Added icons logo
| @@ -1,7 +1,7 @@ | |||||||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||||||
|           package="com.example.immich_mobile"> |           package="com.example.immich_mobile"> | ||||||
|     <application |     <application | ||||||
|             android:label="immich_mobile" |             android:label="Immich" | ||||||
|             android:name="${applicationName}" |             android:name="${applicationName}" | ||||||
|             android:icon="@mipmap/ic_launcher"> |             android:icon="@mipmap/ic_launcher"> | ||||||
|         <activity |         <activity | ||||||
|   | |||||||
| Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 7.1 KiB | 
| Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 4.1 KiB | 
| Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 10 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 17 KiB | 
| Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 23 KiB | 
| Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 115 KiB | 
| Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 1.2 KiB | 
| Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.2 KiB | 
| Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 5.5 KiB | 
| Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 2.1 KiB | 
| Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 5.3 KiB | 
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 8.9 KiB | 
| Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 3.2 KiB | 
| Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 8.1 KiB | 
| Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 7.6 KiB | 
| Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 18 KiB | 
| Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 20 KiB | 
| @@ -5,7 +5,7 @@ | |||||||
|     <key>CFBundleDevelopmentRegion</key> |     <key>CFBundleDevelopmentRegion</key> | ||||||
|     <string>$(DEVELOPMENT_LANGUAGE)</string> |     <string>$(DEVELOPMENT_LANGUAGE)</string> | ||||||
|     <key>CFBundleDisplayName</key> |     <key>CFBundleDisplayName</key> | ||||||
|     <string>Immich Mobile</string> |     <string>Immich</string> | ||||||
|     <key>CFBundleExecutable</key> |     <key>CFBundleExecutable</key> | ||||||
|     <string>$(EXECUTABLE_NAME)</string> |     <string>$(EXECUTABLE_NAME)</string> | ||||||
|     <key>CFBundleIdentifier</key> |     <key>CFBundleIdentifier</key> | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| import 'dart:async'; | import 'dart:async'; | ||||||
|  |  | ||||||
| import 'package:flutter/foundation.dart'; |  | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| /// Build the Scroll Thumb and label using the current configuration | /// Build the Scroll Thumb and label using the current configuration | ||||||
| @@ -166,7 +165,7 @@ class DraggableScrollbar extends StatefulWidget { | |||||||
|     }) { |     }) { | ||||||
|       final scrollThumb = CustomPaint( |       final scrollThumb = CustomPaint( | ||||||
|         key: scrollThumbKey, |         key: scrollThumbKey, | ||||||
|         foregroundPainter: ArrowCustomPainter(Colors.grey), |         foregroundPainter: ArrowCustomPainter(Colors.white), | ||||||
|         child: Material( |         child: Material( | ||||||
|           elevation: 4.0, |           elevation: 4.0, | ||||||
|           child: Container( |           child: Container( | ||||||
| @@ -348,7 +347,7 @@ class _DraggableScrollbarState extends State<DraggableScrollbar> with TickerProv | |||||||
|  |  | ||||||
|   double get barMaxScrollExtent => context.size!.height - widget.heightScrollThumb; |   double get barMaxScrollExtent => context.size!.height - widget.heightScrollThumb; | ||||||
|  |  | ||||||
|   double get barMinScrollExtent => 0.0; |   double get barMinScrollExtent => 0; | ||||||
|  |  | ||||||
|   double get viewMaxScrollExtent => widget.controller.position.maxScrollExtent; |   double get viewMaxScrollExtent => widget.controller.position.maxScrollExtent; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -105,8 +105,8 @@ class ImmichSliverAppBar extends ConsumerWidget { | |||||||
|           statusBarColor: Colors.indigo, |           statusBarColor: Colors.indigo, | ||||||
|  |  | ||||||
|           // Status bar brightness (optional) |           // Status bar brightness (optional) | ||||||
|           statusBarIconBrightness: Brightness.dark, // For Android (dark icons) |           statusBarIconBrightness: Brightness.light, // For Android (dark icons) | ||||||
|           statusBarBrightness: Brightness.light, // For iOS (dark icons) |           statusBarBrightness: Brightness.dark, | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -5,7 +5,6 @@ import 'package:hive_flutter/hive_flutter.dart'; | |||||||
| import 'package:immich_mobile/constants/hive_box.dart'; | import 'package:immich_mobile/constants/hive_box.dart'; | ||||||
| import 'package:immich_mobile/shared/models/immich_asset.model.dart'; | import 'package:immich_mobile/shared/models/immich_asset.model.dart'; | ||||||
| import 'package:immich_mobile/routing/router.dart'; | import 'package:immich_mobile/routing/router.dart'; | ||||||
| import 'package:transparent_image/transparent_image.dart'; |  | ||||||
|  |  | ||||||
| class ThumbnailImage extends StatelessWidget { | class ThumbnailImage extends StatelessWidget { | ||||||
|   final ImmichAsset asset; |   final ImmichAsset asset; | ||||||
| @@ -17,7 +16,6 @@ class ThumbnailImage extends StatelessWidget { | |||||||
|     var box = Hive.box(userInfoBox); |     var box = Hive.box(userInfoBox); | ||||||
|     var thumbnailRequestUrl = |     var thumbnailRequestUrl = | ||||||
|         '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=true'; |         '${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=true'; | ||||||
|  |  | ||||||
|     return GestureDetector( |     return GestureDetector( | ||||||
|       onTap: () { |       onTap: () { | ||||||
|         AutoRouter.of(context).push( |         AutoRouter.of(context).push( | ||||||
| @@ -44,7 +42,10 @@ class ThumbnailImage extends StatelessWidget { | |||||||
|             scale: 0.2, |             scale: 0.2, | ||||||
|             child: CircularProgressIndicator(value: downloadProgress.progress), |             child: CircularProgressIndicator(value: downloadProgress.progress), | ||||||
|           ), |           ), | ||||||
|           errorWidget: (context, url, error) => const Icon(Icons.error), |           errorWidget: (context, url, error) { | ||||||
|  |             debugPrint("Error Loading Thumbnail Widget $error"); | ||||||
|  |             return const Icon(Icons.error); | ||||||
|  |           }, | ||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -84,6 +84,7 @@ class HomePage extends HookConsumerWidget { | |||||||
|           int? currentMonth = DateTime.tryParse(dateTitle)?.month; |           int? currentMonth = DateTime.tryParse(dateTitle)?.month; | ||||||
|           int? previousMonth = DateTime.tryParse(lastGroupDate)?.month; |           int? previousMonth = DateTime.tryParse(lastGroupDate)?.month; | ||||||
|  |  | ||||||
|  |           // Add Monthly Title Group if started at the beginning of the month | ||||||
|           if ((currentMonth! - previousMonth!) != 0) { |           if ((currentMonth! - previousMonth!) != 0) { | ||||||
|             var monthTitleText = DateFormat('MMMM, y').format(DateTime.parse(dateTitle)); |             var monthTitleText = DateFormat('MMMM, y').format(DateTime.parse(dateTitle)); | ||||||
|  |  | ||||||
| @@ -92,10 +93,12 @@ class HomePage extends HookConsumerWidget { | |||||||
|             ); |             ); | ||||||
|           } |           } | ||||||
|  |  | ||||||
|  |           // Add Daily Title Group | ||||||
|           imageGridGroup.add( |           imageGridGroup.add( | ||||||
|             _buildDateGroupTitle(dateTitle), |             DailyTitleText(dateTitle: dateTitle), | ||||||
|           ); |           ); | ||||||
|  |  | ||||||
|  |           // Add Image Group | ||||||
|           imageGridGroup.add( |           imageGridGroup.add( | ||||||
|             ImageGrid(assetGroup: assetGroup), |             ImageGrid(assetGroup: assetGroup), | ||||||
|           ); |           ); | ||||||
| @@ -121,8 +124,9 @@ class HomePage extends HookConsumerWidget { | |||||||
|           //   return Text(scrollLabelText.value); |           //   return Text(scrollLabelText.value); | ||||||
|           // }, |           // }, | ||||||
|           // labelConstraints: const BoxConstraints.tightFor(width: 200.0, height: 30.0), |           // labelConstraints: const BoxConstraints.tightFor(width: 200.0, height: 30.0), | ||||||
|  |           backgroundColor: Theme.of(context).primaryColor, | ||||||
|           controller: _scrollController, |           controller: _scrollController, | ||||||
|           heightScrollThumb: 40.0, |           heightScrollThumb: 48.0, | ||||||
|           child: CustomScrollView( |           child: CustomScrollView( | ||||||
|             controller: _scrollController, |             controller: _scrollController, | ||||||
|             slivers: [ |             slivers: [ | ||||||
| @@ -166,3 +170,41 @@ class MonthlyTitleText extends StatelessWidget { | |||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | class DailyTitleText extends StatelessWidget { | ||||||
|  |   const DailyTitleText({ | ||||||
|  |     Key? key, | ||||||
|  |     required this.dateTitle, | ||||||
|  |   }) : super(key: key); | ||||||
|  |  | ||||||
|  |   final String dateTitle; | ||||||
|  |  | ||||||
|  |   @override | ||||||
|  |   Widget build(BuildContext context) { | ||||||
|  |     var currentYear = DateTime.now().year; | ||||||
|  |     var groupYear = DateTime.parse(dateTitle).year; | ||||||
|  |     var formatDateTemplate = currentYear == groupYear ? 'E, MMM dd' : 'E, MMM dd, yyyy'; | ||||||
|  |     var dateText = DateFormat(formatDateTemplate).format(DateTime.parse(dateTitle)); | ||||||
|  |  | ||||||
|  |     return SliverToBoxAdapter( | ||||||
|  |       child: Padding( | ||||||
|  |         padding: const EdgeInsets.only(top: 24.0, bottom: 24.0, left: 3.0), | ||||||
|  |         child: Row( | ||||||
|  |           children: [ | ||||||
|  |             Padding( | ||||||
|  |               padding: const EdgeInsets.only(left: 8.0, bottom: 5.0, top: 5.0), | ||||||
|  |               child: Text( | ||||||
|  |                 dateText, | ||||||
|  |                 style: const TextStyle( | ||||||
|  |                   fontSize: 14, | ||||||
|  |                   fontWeight: FontWeight.bold, | ||||||
|  |                   color: Colors.black87, | ||||||
|  |                 ), | ||||||
|  |               ), | ||||||
|  |             ), | ||||||
|  |           ], | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ class LoginForm extends HookConsumerWidget { | |||||||
|   Widget build(BuildContext context, WidgetRef ref) { |   Widget build(BuildContext context, WidgetRef ref) { | ||||||
|     final usernameController = useTextEditingController(text: 'testuser@email.com'); |     final usernameController = useTextEditingController(text: 'testuser@email.com'); | ||||||
|     final passwordController = useTextEditingController(text: 'password'); |     final passwordController = useTextEditingController(text: 'password'); | ||||||
|     final serverEndpointController = useTextEditingController(text: 'http://192.168.1.103:3000'); |     final serverEndpointController = useTextEditingController(text: 'http://192.168.1.216:3000'); | ||||||
|  |  | ||||||
|     return Center( |     return Center( | ||||||
|       child: ConstrainedBox( |       child: ConstrainedBox( | ||||||
|   | |||||||
| @@ -3,3 +3,6 @@ build: | |||||||
|  |  | ||||||
| watch: | watch: | ||||||
| 	flutter packages pub run build_runner watch | 	flutter packages pub run build_runner watch | ||||||
|  |  | ||||||
|  | create_app_icon: | ||||||
|  | 	flutter pub run flutter_launcher_icons:main | ||||||
| @@ -15,6 +15,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "3.2.0" |     version: "3.2.0" | ||||||
|  |   archive: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: archive | ||||||
|  |       url: "https://pub.dartlang.org" | ||||||
|  |     source: hosted | ||||||
|  |     version: "3.1.11" | ||||||
|   args: |   args: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
| @@ -321,6 +328,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.18.2" |     version: "0.18.2" | ||||||
|  |   flutter_launcher_icons: | ||||||
|  |     dependency: "direct main" | ||||||
|  |     description: | ||||||
|  |       name: flutter_launcher_icons | ||||||
|  |       url: "https://pub.dartlang.org" | ||||||
|  |     source: hosted | ||||||
|  |     version: "0.9.2" | ||||||
|   flutter_lints: |   flutter_lints: | ||||||
|     dependency: "direct dev" |     dependency: "direct dev" | ||||||
|     description: |     description: | ||||||
| @@ -429,6 +443,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "4.0.0" |     version: "4.0.0" | ||||||
|  |   image: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: image | ||||||
|  |       url: "https://pub.dartlang.org" | ||||||
|  |     source: hosted | ||||||
|  |     version: "3.1.1" | ||||||
|   intl: |   intl: | ||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
| @@ -478,6 +499,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.12.11" |     version: "0.12.11" | ||||||
|  |   material_color_utilities: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: material_color_utilities | ||||||
|  |       url: "https://pub.dartlang.org" | ||||||
|  |     source: hosted | ||||||
|  |     version: "0.1.3" | ||||||
|   meta: |   meta: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
| @@ -576,6 +604,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "3.4.0" |     version: "3.4.0" | ||||||
|  |   petitparser: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: petitparser | ||||||
|  |       url: "https://pub.dartlang.org" | ||||||
|  |     source: hosted | ||||||
|  |     version: "4.4.0" | ||||||
|   photo_manager: |   photo_manager: | ||||||
|     dependency: "direct main" |     dependency: "direct main" | ||||||
|     description: |     description: | ||||||
| @@ -755,7 +790,7 @@ packages: | |||||||
|       name: test_api |       name: test_api | ||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.4.3" |     version: "0.4.8" | ||||||
|   timing: |   timing: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
| @@ -840,6 +875,13 @@ packages: | |||||||
|       url: "https://pub.dartlang.org" |       url: "https://pub.dartlang.org" | ||||||
|     source: hosted |     source: hosted | ||||||
|     version: "0.2.0" |     version: "0.2.0" | ||||||
|  |   xml: | ||||||
|  |     dependency: transitive | ||||||
|  |     description: | ||||||
|  |       name: xml | ||||||
|  |       url: "https://pub.dartlang.org" | ||||||
|  |     source: hosted | ||||||
|  |     version: "5.3.1" | ||||||
|   yaml: |   yaml: | ||||||
|     dependency: transitive |     dependency: transitive | ||||||
|     description: |     description: | ||||||
|   | |||||||
| @@ -26,6 +26,7 @@ dependencies: | |||||||
|   exif: ^3.1.1 |   exif: ^3.1.1 | ||||||
|   transparent_image: ^2.0.0 |   transparent_image: ^2.0.0 | ||||||
|   visibility_detector: ^0.2.2 |   visibility_detector: ^0.2.2 | ||||||
|  |   flutter_launcher_icons: "^0.9.2" | ||||||
|  |  | ||||||
| dev_dependencies: | dev_dependencies: | ||||||
|   flutter_test: |   flutter_test: | ||||||
| @@ -39,3 +40,9 @@ flutter: | |||||||
|   uses-material-design: true |   uses-material-design: true | ||||||
|   assets: |   assets: | ||||||
|     - assets/ |     - assets/ | ||||||
|  |  | ||||||
|  | flutter_icons: | ||||||
|  |   image_path_android: "assets/immich-logo-no-outline.png" | ||||||
|  |   image_path_ios: "assets/immich-logo-no-outline.png" | ||||||
|  |   android: true # can specify file name here e.g. "ic_launcher" | ||||||
|  |   ios: true # can specify file name here e.g. "My-Launcher-Icon | ||||||
|   | |||||||