From e52b9d15b526ee131f14a343d0494d4f82198f72 Mon Sep 17 00:00:00 2001 From: shenlong <139912620+shenlong-tanwen@users.noreply.github.com> Date: Tue, 29 Jul 2025 00:34:03 +0530 Subject: [PATCH] chore: bump dart sdk to 3.8 (#20355) * chore: bump dart sdk to 3.8 * chore: make build * make pigeon * chore: format files --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> --- mobile/lib/constants/colors.dart | 13 +- mobile/lib/constants/enums.dart | 11 +- mobile/lib/constants/filters.dart | 713 +----------------- mobile/lib/constants/locales.dart | 5 +- .../domain/models/asset/base_asset.model.dart | 6 +- .../models/asset/remote_asset.model.dart | 7 +- .../lib/domain/models/device_asset.model.dart | 12 +- mobile/lib/domain/models/log.model.dart | 13 +- mobile/lib/domain/models/memory.model.dart | 20 +- .../domain/models/search_result.model.dart | 15 +- mobile/lib/domain/models/setting.model.dart | 3 +- mobile/lib/domain/models/stack.model.dart | 14 +- mobile/lib/domain/models/timeline.model.dart | 14 +- mobile/lib/domain/models/user.model.dart | 39 +- .../domain/models/user_metadata.model.dart | 49 +- mobile/lib/domain/services/asset.service.dart | 6 +- mobile/lib/domain/services/hash.service.dart | 13 +- .../domain/services/local_sync.service.dart | 60 +- mobile/lib/domain/services/log.service.dart | 11 +- .../lib/domain/services/partner.service.dart | 14 +- .../domain/services/remote_album.service.dart | 33 +- .../lib/domain/services/search.service.dart | 12 +- mobile/lib/domain/services/store.service.dart | 12 +- .../domain/services/sync_stream.service.dart | 109 +-- .../lib/domain/services/timeline.service.dart | 42 +- mobile/lib/domain/services/user.service.dart | 11 +- mobile/lib/domain/utils/background_sync.dart | 75 +- mobile/lib/domain/utils/event_stream.dart | 7 +- mobile/lib/entities/album.entity.dart | 9 +- mobile/lib/entities/album.entity.g.dart | Bin 60066 -> 61737 bytes .../android_device_asset.entity.g.dart | Bin 13566 -> 13417 bytes mobile/lib/entities/asset.entity.dart | 148 ++-- mobile/lib/entities/asset.entity.g.dart | Bin 99183 -> 102334 bytes mobile/lib/entities/backup_album.entity.dart | 18 +- .../lib/entities/backup_album.entity.g.dart | Bin 18667 -> 19009 bytes .../entities/duplicated_asset.entity.g.dart | Bin 12884 -> 12975 bytes mobile/lib/entities/etag.entity.g.dart | Bin 20831 -> 21396 bytes .../entities/ios_device_asset.entity.g.dart | Bin 21487 -> 21638 bytes mobile/lib/extensions/asset_extensions.dart | 10 +- .../lib/extensions/collection_extensions.dart | 14 +- .../lib/extensions/datetime_extensions.dart | 6 +- .../maplibrecontroller_extensions.dart | 18 +- mobile/lib/extensions/scroll_extensions.dart | 22 +- mobile/lib/extensions/string_extensions.dart | 6 +- mobile/lib/extensions/theme_extensions.dart | 10 +- .../lib/extensions/translate_extensions.dart | 6 +- .../entities/asset_face.entity.drift.dart | Bin 40358 -> 41820 bytes .../entities/device_asset.entity.dart | 19 +- .../entities/device_asset.entity.g.dart | Bin 25405 -> 25479 bytes .../infrastructure/entities/exif.entity.dart | 118 +-- .../entities/exif.entity.drift.dart | Bin 62402 -> 64470 bytes .../entities/exif.entity.g.dart | Bin 85708 -> 87909 bytes .../entities/local_album.entity.drift.dart | Bin 21567 -> 22352 bytes .../local_album_asset.entity.drift.dart | Bin 21931 -> 23099 bytes .../entities/local_asset.entity.dart | 26 +- .../entities/local_asset.entity.drift.dart | Bin 32108 -> 33143 bytes .../infrastructure/entities/log.entity.g.dart | Bin 36867 -> 37371 bytes .../entities/memory.entity.drift.dart | Bin 38238 -> 39702 bytes .../entities/memory_asset.entity.drift.dart | Bin 21195 -> 22246 bytes .../entities/merged_asset.drift.dart | Bin 7392 -> 7321 bytes .../entities/partner.entity.drift.dart | Bin 23376 -> 24558 bytes .../entities/person.entity.drift.dart | Bin 34043 -> 35364 bytes .../entities/remote_album.entity.drift.dart | Bin 38567 -> 40090 bytes .../remote_album_asset.entity.drift.dart | Bin 22086 -> 23276 bytes .../remote_album_user.entity.drift.dart | Bin 24035 -> 25305 bytes .../entities/remote_asset.entity.dart | 40 +- .../entities/remote_asset.entity.drift.dart | Bin 52935 -> 54647 bytes .../entities/stack.entity.drift.dart | Bin 22868 -> 23843 bytes .../entities/store.entity.g.dart | Bin 16270 -> 16554 bytes .../infrastructure/entities/user.entity.dart | 56 +- .../entities/user.entity.drift.dart | Bin 25320 -> 26109 bytes .../entities/user.entity.g.dart | Bin 50000 -> 51278 bytes .../entities/user_metadata.entity.drift.dart | Bin 19535 -> 20437 bytes .../repositories/asset_media.repository.dart | 26 +- .../repositories/backup.repository.dart | 18 +- .../repositories/db.repository.dart | 90 +-- .../repositories/db.repository.drift.dart | Bin 12714 -> 11853 bytes .../repositories/db.repository.steps.dart | Bin 60290 -> 60965 bytes .../repositories/exif.repository.dart | 4 +- .../repositories/local_album.repository.dart | 128 ++-- .../repositories/local_asset.repository.dart | 7 +- .../repositories/memory.repository.dart | 70 +- .../repositories/partner.repository.dart | 91 +-- .../repositories/remote_album.repository.dart | 207 ++--- .../repositories/remote_asset.repository.dart | 100 +-- .../repositories/search_api.repository.dart | 9 +- .../repositories/stack.repository.dart | 8 +- .../repositories/store.repository.dart | 34 +- .../repositories/sync_api.repository.dart | 10 +- .../repositories/sync_stream.repository.dart | 226 ++---- .../repositories/timeline.repository.dart | 401 ++++------ .../repositories/user_api.repository.dart | 11 +- .../user_metadata.repository.dart | 20 +- .../infrastructure/utils/user.converter.dart | 100 ++- mobile/lib/main.dart | 83 +- .../album_add_asset_response.model.dart | 15 +- .../lib/models/albums/album_search.model.dart | 6 +- .../albums/album_viewer_page_state.model.dart | 6 +- .../asset_selection_page_result.model.dart | 4 +- mobile/lib/models/asset_selection_state.dart | 15 +- .../models/auth/auxilary_endpoint.model.dart | 40 +- .../models/auth/biometric_status.model.dart | 10 +- .../models/backup/available_album.model.dart | 12 +- .../lib/models/backup/backup_state.model.dart | 5 +- .../backup/success_upload_asset.model.dart | 12 +- .../models/download/download_state.model.dart | 30 +- .../download/livephotos_medatada.model.dart | 30 +- .../models/folder/recursive_folder.model.dart | 6 +- .../lib/models/folder/root_folder.model.dart | 5 +- mobile/lib/models/map/map_marker.model.dart | 19 +- mobile/lib/models/memories/memory.model.dart | 15 +- .../search/search_curated_content.model.dart | 24 +- .../models/search/search_filter.model.dart | 77 +- .../models/search/search_result.model.dart | 15 +- .../server_info/server_config.model.dart | 16 +- .../server_info/server_disk_info.model.dart | 15 +- .../server_info/server_features.model.dart | 15 +- .../server_info/server_version.model.dart | 23 +- .../models/shared_link/shared_link.model.dart | 34 +- .../upload/share_intent_attachment.model.dart | 21 +- ...additional_shared_user_selection.page.dart | 72 +- .../album/album_asset_selection.page.dart | 20 +- .../lib/pages/album/album_control_button.dart | 6 +- mobile/lib/pages/album/album_date_range.dart | 9 +- mobile/lib/pages/album/album_description.dart | 5 +- .../lib/pages/album/album_options.page.dart | 49 +- .../pages/album/album_shared_user_icons.dart | 6 +- .../album_shared_user_selection.page.dart | 63 +- mobile/lib/pages/album/album_title.dart | 18 +- mobile/lib/pages/album/album_viewer.dart | 19 +- mobile/lib/pages/album/album_viewer.page.dart | 4 +- mobile/lib/pages/albums/albums.page.dart | 161 ++-- .../lib/pages/backup/album_preview.page.dart | 27 +- .../backup/backup_album_selection.page.dart | 120 +-- .../pages/backup/backup_controller.page.dart | 148 ++-- .../lib/pages/backup/backup_options.page.dart | 4 +- .../lib/pages/backup/drift_backup.page.dart | 68 +- .../drift_backup_album_selection.page.dart | 143 +--- .../backup/drift_upload_detail.page.dart | 172 +---- .../backup/failed_backup_status.page.dart | 42 +- mobile/lib/pages/common/activities.page.dart | 13 +- mobile/lib/pages/common/app_log.page.dart | 70 +- .../lib/pages/common/app_log_detail.page.dart | 52 +- .../pages/common/change_experience.page.dart | 30 +- .../lib/pages/common/create_album.page.dart | 68 +- mobile/lib/pages/common/download_panel.dart | 58 +- .../common/gallery_stacked_children.dart | 10 +- .../lib/pages/common/gallery_viewer.page.dart | 102 +-- .../pages/common/headers_settings.page.dart | 19 +- .../lib/pages/common/large_leading_tile.dart | 15 +- .../common/native_video_viewer.page.dart | 122 ++- mobile/lib/pages/common/settings.page.dart | 89 +-- .../lib/pages/common/splash_screen.page.dart | 27 +- .../lib/pages/common/tab_controller.page.dart | 60 +- mobile/lib/pages/common/tab_shell.page.dart | 66 +- mobile/lib/pages/editing/crop.page.dart | 55 +- mobile/lib/pages/editing/edit.page.dart | 111 +-- mobile/lib/pages/editing/filter.page.dart | 55 +- mobile/lib/pages/library/archive.page.dart | 9 +- mobile/lib/pages/library/favorite.page.dart | 9 +- .../lib/pages/library/folder/folder.page.dart | 136 +--- mobile/lib/pages/library/library.page.dart | 128 +--- .../lib/pages/library/local_albums.page.dart | 27 +- .../lib/pages/library/locked/locked.page.dart | 45 +- .../pages/library/locked/pin_auth.page.dart | 30 +- .../library/partner/drift_partner.page.dart | 33 +- .../pages/library/partner/partner.page.dart | 34 +- .../library/partner/partner_detail.page.dart | 49 +- .../people/people_collection.page.dart | 25 +- .../places/places_collection.page.dart | 27 +- .../library/shared_link/shared_link.page.dart | 44 +- .../shared_link/shared_link_edit.page.dart | 191 +---- mobile/lib/pages/library/trash.page.dart | 72 +- .../lib/pages/login/change_password.page.dart | 4 +- mobile/lib/pages/login/login.page.dart | 10 +- .../permission_onboarding.page.dart | 70 +- mobile/lib/pages/photos/memory.page.dart | 72 +- mobile/lib/pages/photos/photos.page.dart | 21 +- .../pages/search/all_motion_videos.page.dart | 11 +- mobile/lib/pages/search/all_people.page.dart | 9 +- mobile/lib/pages/search/all_places.page.dart | 15 +- mobile/lib/pages/search/all_videos.page.dart | 5 +- mobile/lib/pages/search/map/map.page.dart | 76 +- .../search/map/map_location_picker.page.dart | 30 +- .../lib/pages/search/person_result.page.dart | 58 +- .../lib/pages/search/recently_taken.page.dart | 11 +- mobile/lib/pages/search/search.page.dart | 272 ++----- .../settings/beta_sync_settings.page.dart | 8 +- .../pages/share_intent/share_intent.page.dart | 147 ++-- mobile/lib/platform/native_sync_api.g.dart | Bin 17170 -> 17039 bytes .../pages/dev/feat_in_development.page.dart | 73 +- .../pages/dev/media_stat.page.dart | 97 +-- .../presentation/pages/drift_album.page.dart | 13 +- .../pages/drift_archive.page.dart | 20 +- .../drift_asset_selection_timeline.page.dart | 33 +- .../pages/drift_create_album.page.dart | 152 +--- .../pages/drift_favorite.page.dart | 20 +- .../pages/drift_library.page.dart | 137 +--- .../pages/drift_local_album.page.dart | 51 +- .../pages/drift_locked_folder.page.dart | 24 +- .../presentation/pages/drift_memory.page.dart | 86 +-- .../pages/drift_partner_detail.page.dart | 54 +- .../presentation/pages/drift_place.page.dart | 40 +- .../pages/drift_place_detail.page.dart | 22 +- .../pages/drift_recently_taken.page.dart | 26 +- .../pages/drift_remote_album.page.dart | 127 +--- .../presentation/pages/drift_trash.page.dart | 28 +- .../pages/drift_user_selection.page.dart | 68 +- .../presentation/pages/drift_video.page.dart | 24 +- .../pages/local_timeline.page.dart | 12 +- .../pages/search/drift_search.page.dart | 287 ++----- .../search/paginated_search.provider.dart | 5 +- .../archive_action_button.widget.dart | 5 +- .../base_action_button.widget.dart | 13 +- .../cast_action_button.widget.dart | 5 +- .../delete_action_button.widget.dart | 9 +- .../delete_local_action_button.widget.dart | 5 +- .../delete_trash_action_button.widget.dart | 11 +- .../edit_location_action_button.widget.dart | 5 +- .../favorite_action_button.widget.dart | 11 +- ...emove_from_album_action_button.widget.dart | 6 +- .../restore_trash_action_button.widget.dart | 17 +- .../stack_action_button.widget.dart | 5 +- .../trash_action_button.widget.dart | 5 +- .../unarchive_action_button.widget.dart | 5 +- .../unfavorite_action_button.widget.dart | 11 +- .../unstack_action_button.widget.dart | 5 +- .../upload_action_button.widget.dart | 5 +- .../widgets/album/album_selector.widget.dart | 309 ++------ .../asset_viewer/asset_stack.provider.dart | 6 +- .../asset_viewer/asset_stack.widget.dart | 34 +- .../asset_viewer/asset_viewer.page.dart | 86 +-- .../asset_viewer/asset_viewer.state.dart | 10 +- .../asset_viewer/bottom_bar.widget.dart | 26 +- .../asset_viewer/bottom_sheet.widget.dart | 32 +- .../bottom_sheet/location_details.widget.dart | 37 +- .../asset_viewer/top_app_bar.widget.dart | 27 +- .../asset_viewer/video_viewer.widget.dart | 123 ++- .../video_viewer_controls.widget.dart | 38 +- .../backup/backup_toggle_button.widget.dart | 72 +- .../archive_bottom_sheet.widget.dart | 12 +- .../base_bottom_sheet.widget.dart | 10 +- .../favorite_bottom_sheet.widget.dart | 12 +- .../general_bottom_sheet.widget.dart | 31 +- .../remote_album_bottom_sheet.widget.dart | 17 +- .../widgets/images/image_provider.dart | 30 +- .../images/local_album_thumbnail.widget.dart | 26 +- .../widgets/images/local_image_provider.dart | 46 +- .../widgets/images/remote_image_provider.dart | 24 +- .../widgets/images/thumb_hash_provider.dart | 19 +- .../widgets/images/thumbnail.widget.dart | 36 +- .../widgets/images/thumbnail_tile.widget.dart | 116 +-- .../memory/memory_bottom_info.widget.dart | 72 +- .../widgets/memory/memory_card.widget.dart | 46 +- .../widgets/memory/memory_lane.widget.dart | 47 +- .../drift_album_option.widget.dart | 48 +- .../widgets/timeline/fixed/row.dart | 12 +- .../widgets/timeline/fixed/segment.model.dart | 53 +- .../timeline/fixed/segment_builder.dart | 3 +- .../widgets/timeline/header.widget.dart | 51 +- .../widgets/timeline/scrubber.widget.dart | 158 +--- .../widgets/timeline/segment.model.dart | 4 +- .../widgets/timeline/segment_builder.dart | 36 +- .../widgets/timeline/timeline.state.dart | 58 +- .../widgets/timeline/timeline.widget.dart | 143 +--- mobile/lib/providers/activity.provider.dart | 9 +- mobile/lib/providers/activity.provider.g.dart | Bin 6008 -> 5862 bytes .../activity_statistics.provider.g.dart | Bin 6026 -> 5873 bytes .../lib/providers/album/album.provider.dart | 34 +- .../album/album_sort_by_options.provider.dart | 28 +- .../album_sort_by_options.provider.g.dart | Bin 1563 -> 1627 bytes .../providers/album/album_title.provider.dart | 4 +- .../album/album_viewer.provider.dart | 29 +- .../album/current_album.provider.g.dart | Bin 954 -> 992 bytes mobile/lib/providers/api.provider.g.dart | Bin 969 -> 975 bytes .../providers/app_life_cycle.provider.dart | 31 +- mobile/lib/providers/asset.provider.dart | 29 +- .../asset_viewer/asset_people.provider.g.dart | Bin 5574 -> 5555 bytes .../current_asset.provider.g.dart | Bin 954 -> 992 bytes .../asset_viewer/download.provider.dart | 59 +- .../share_intent_upload.provider.dart | 27 +- .../video_player_controls_provider.dart | 14 +- .../video_player_value_provider.dart | 40 +- mobile/lib/providers/auth.provider.dart | 44 +- .../lib/providers/backup/backup.provider.dart | 172 ++--- .../backup/backup_album.provider.dart | 4 +- .../backup/backup_verification.provider.dart | 16 +- .../backup_verification.provider.g.dart | Bin 1020 -> 1052 bytes .../backup/drift_backup.provider.dart | 88 +-- .../backup/manual_upload.provider.dart | 95 +-- mobile/lib/providers/cast.provider.dart | 22 +- mobile/lib/providers/folder.provider.dart | 11 +- .../gallery_permission.provider.dart | 5 +- .../providers/image/cache/image_loader.dart | 11 +- .../cache/remote_image_cache_manager.dart | 9 +- .../cache/thumbnail_image_cache_manager.dart | 9 +- .../image/immich_local_image_provider.dart | 12 +- .../immich_local_thumbnail_provider.dart | 24 +- .../image/immich_remote_image_provider.dart | 38 +- .../immich_remote_thumbnail_provider.dart | 38 +- .../lib/providers/immich_logo_provider.g.dart | Bin 1009 -> 1015 bytes .../infrastructure/action.provider.dart | 148 +--- .../infrastructure/album.provider.dart | 5 +- .../asset_viewer/current_asset.provider.dart | 20 +- .../infrastructure/db.provider.g.dart | Bin 908 -> 914 bytes .../infrastructure/person.provider.dart | 4 +- .../infrastructure/remote_album.provider.dart | 102 +-- .../infrastructure/search.provider.dart | 8 +- .../infrastructure/stack.provider.dart | 4 +- .../infrastructure/storage.provider.dart | 4 +- .../infrastructure/store.provider.g.dart | Bin 1583 -> 1589 bytes .../infrastructure/sync.provider.dart | 8 +- .../infrastructure/timeline.provider.dart | 16 +- .../infrastructure/user.provider.dart | 17 +- .../infrastructure/user.provider.g.dart | Bin 2166 -> 2172 bytes mobile/lib/providers/local_auth.provider.dart | 22 +- .../providers/map/map_marker.provider.g.dart | Bin 1020 -> 1026 bytes .../providers/map/map_service.provider.g.dart | Bin 999 -> 1005 bytes .../lib/providers/map/map_state.provider.dart | 45 +- .../providers/map/map_state.provider.g.dart | Bin 974 -> 1006 bytes mobile/lib/providers/network.provider.dart | 4 +- .../notification_permission.provider.dart | 4 +- mobile/lib/providers/partner.provider.dart | 54 +- .../search/paginated_search.provider.dart | 14 +- .../search/paginated_search.provider.g.dart | Bin 1150 -> 1182 bytes .../lib/providers/search/people.provider.dart | 10 +- .../providers/search/people.provider.g.dart | Bin 9230 -> 9013 bytes .../search/search_filter.provider.g.dart | Bin 7004 -> 6961 bytes .../search/search_page_state.provider.dart | 16 +- .../lib/providers/server_info.provider.dart | 85 +-- .../lib/providers/shared_link.provider.dart | 4 +- .../lib/providers/sync_status.provider.dart | 28 +- mobile/lib/providers/tab.provider.dart | 4 +- mobile/lib/providers/theme.provider.dart | 9 +- mobile/lib/providers/timeline.provider.dart | 37 +- .../timeline/multiselect.provider.dart | 63 +- mobile/lib/providers/trash.provider.dart | 8 +- .../upload_profile_image.provider.dart | 34 +- mobile/lib/providers/websocket.provider.dart | 79 +- .../repositories/activity_api.repository.dart | 21 +- mobile/lib/repositories/album.repository.dart | 24 +- .../repositories/album_api.repository.dart | 53 +- .../repositories/album_media.repository.dart | 48 +- mobile/lib/repositories/asset.repository.dart | 78 +- .../repositories/asset_api.repository.dart | 66 +- .../repositories/asset_media.repository.dart | 8 +- .../lib/repositories/auth_api.repository.dart | 13 +- .../repositories/biometric.repository.dart | 9 +- .../lib/repositories/download.repository.dart | 5 +- .../drift_album_api_repository.dart | 50 +- .../repositories/file_media.repository.dart | 49 +- .../repositories/folder_api.repository.dart | 6 +- mobile/lib/repositories/gcast.repository.dart | 10 +- .../lib/repositories/partner.repository.dart | 14 +- .../repositories/partner_api.repository.dart | 22 +- .../repositories/person_api.repository.dart | 20 +- .../repositories/sessions_api.repository.dart | 18 +- .../share_handler.repository.dart | 8 +- .../lib/repositories/timeline.repository.dart | 25 +- .../lib/repositories/upload.repository.dart | 25 +- .../lib/repositories/widget.repository.dart | 5 +- .../lib/routing/app_navigation_observer.dart | 29 +- mobile/lib/routing/duplicate_guard.dart | 4 +- mobile/lib/routing/locked_guard.dart | 10 +- mobile/lib/routing/router.dart | 289 ++----- mobile/lib/routing/router.gr.dart | 549 +++++++------- mobile/lib/services/action.service.dart | 76 +- mobile/lib/services/activity.service.dart | 19 +- mobile/lib/services/album.service.dart | 143 +--- mobile/lib/services/api.service.dart | 16 +- mobile/lib/services/app_settings.service.dart | 69 +- mobile/lib/services/asset.service.dart | 133 +--- mobile/lib/services/auth.service.dart | 5 +- mobile/lib/services/background.service.dart | 105 +-- mobile/lib/services/backup.service.dart | 106 +-- .../services/backup_verification.service.dart | 83 +- mobile/lib/services/deep_link.service.dart | 18 +- mobile/lib/services/download.service.dart | 49 +- mobile/lib/services/entity.service.dart | 10 +- mobile/lib/services/folder.service.dart | 34 +- mobile/lib/services/gcast.service.dart | 47 +- mobile/lib/services/hash.service.dart | 25 +- mobile/lib/services/local_auth.service.dart | 6 +- .../services/local_files_manager.service.dart | 9 +- .../services/local_notification.service.dart | 34 +- mobile/lib/services/memory.service.dart | 29 +- mobile/lib/services/network.service.dart | 5 +- mobile/lib/services/oauth.service.dart | 38 +- mobile/lib/services/partner.service.dart | 16 +- mobile/lib/services/person.service.dart | 14 +- mobile/lib/services/search.service.dart | 6 +- .../lib/services/secure_storage.service.dart | 4 +- mobile/lib/services/server_info.service.dart | 6 +- mobile/lib/services/share.service.dart | 14 +- mobile/lib/services/share_intent_service.dart | 10 +- mobile/lib/services/shared_link.service.dart | 4 +- mobile/lib/services/stack.service.dart | 19 +- mobile/lib/services/sync.service.dart | 251 ++---- mobile/lib/services/timeline.service.dart | 31 +- mobile/lib/services/trash.service.dart | 20 +- mobile/lib/services/upload.service.dart | 58 +- mobile/lib/services/widget.service.dart | 4 +- mobile/lib/theme/color_scheme.dart | 45 +- mobile/lib/theme/dynamic_theme.dart | 10 +- mobile/lib/theme/theme_data.dart | 111 +-- mobile/lib/utils/backup_progress.dart | 6 +- mobile/lib/utils/bootstrap.dart | 5 +- .../lib/utils/cache/custom_image_cache.dart | 6 +- mobile/lib/utils/color_filter_generator.dart | 8 +- mobile/lib/utils/debounce.dart | 20 +- .../utils/draggable_scroll_controller.dart | 14 +- .../utils/hooks/app_settings_update_hook.dart | 9 +- mobile/lib/utils/hooks/blurhash_hook.dart | 8 +- .../lib/utils/hooks/crop_controller_hook.dart | 6 +- mobile/lib/utils/hooks/interval_hook.dart | 11 +- mobile/lib/utils/hooks/timer_hook.dart | 17 +- mobile/lib/utils/http_ssl_cert_override.dart | 6 +- mobile/lib/utils/http_ssl_options.dart | 15 +- mobile/lib/utils/image_url_builder.dart | 40 +- mobile/lib/utils/immich_loading_overlay.dart | 5 +- mobile/lib/utils/isolate.dart | 10 +- mobile/lib/utils/map_utils.dart | 62 +- mobile/lib/utils/migration.dart | 83 +- mobile/lib/utils/openapi_patching.dart | 12 +- mobile/lib/utils/remote_album.utils.dart | 45 +- mobile/lib/utils/selection_handlers.dart | 70 +- mobile/lib/utils/throttle.dart | 10 +- mobile/lib/utils/thumbnail_utils.dart | 11 +- mobile/lib/utils/url_helper.dart | 34 +- mobile/lib/utils/version_compatibility.dart | 7 +- .../activities/activity_text_field.dart | 34 +- .../lib/widgets/activities/activity_tile.dart | 27 +- .../activities/dismissible_activity.dart | 21 +- .../album/add_to_album_bottom_sheet.dart | 62 +- .../album/add_to_album_sliverlist.dart | 11 +- .../album/album_action_filled_button.dart | 27 +- .../widgets/album/album_thumbnail_card.dart | 46 +- .../album/album_thumbnail_listtile.dart | 51 +- .../widgets/album/album_title_text_field.dart | 19 +- .../widgets/album/album_viewer_appbar.dart | 60 +- .../album_viewer_editable_description.dart | 34 +- .../album/album_viewer_editable_title.dart | 47 +- .../album/remote_album_shared_user_icons.dart | 11 +- .../album/shared_album_thumbnail_image.dart | 10 +- .../widgets/asset_grid/asset_drag_region.dart | 16 +- .../asset_grid/asset_grid_data_structure.dart | 60 +- .../asset_grid/control_bottom_app_bar.dart | 110 +-- .../lib/widgets/asset_grid/delete_dialog.dart | 38 +- .../disable_multi_select_button.dart | 16 +- .../asset_grid/draggable_scrollbar.dart | 160 +--- .../draggable_scrollbar_custom.dart | 117 +-- .../asset_grid/group_divider_title.dart | 15 +- .../widgets/asset_grid/immich_asset_grid.dart | 37 +- .../asset_grid/immich_asset_grid_view.dart | 107 +-- .../widgets/asset_grid/multiselect_grid.dart | 165 ++-- .../multiselect_grid_status_indicator.dart | 19 +- .../widgets/asset_grid/thumbnail_image.dart | 171 ++--- .../asset_grid/thumbnail_placeholder.dart | 13 +- .../lib/widgets/asset_grid/upload_dialog.dart | 14 +- .../asset_viewer/advanced_bottom_sheet.dart | 40 +- .../asset_viewer/animated_play_pause.dart | 7 +- .../asset_viewer/bottom_gallery_bar.dart | 69 +- .../lib/widgets/asset_viewer/cast_dialog.dart | 44 +- .../asset_viewer/center_play_button.dart | 10 +- .../custom_video_player_controls.dart | 38 +- .../asset_viewer/description_input.dart | 39 +- .../detail_panel/asset_date_time.dart | 14 +- .../detail_panel/asset_details.dart | 6 +- .../detail_panel/asset_location.dart | 30 +- .../detail_panel/camera_info.dart | 15 +- .../asset_viewer/detail_panel/exif_map.dart | 23 +- .../asset_viewer/detail_panel/file_info.dart | 15 +- .../detail_panel/people_info.dart | 19 +- .../asset_viewer/formatted_duration.dart | 6 +- .../widgets/asset_viewer/gallery_app_bar.dart | 16 +- .../asset_viewer/top_control_app_bar.dart | 56 +- .../widgets/asset_viewer/video_controls.dart | 5 +- .../widgets/asset_viewer/video_position.dart | 23 +- .../lib/widgets/backup/album_info_card.dart | 53 +- .../widgets/backup/album_info_list_tile.dart | 33 +- .../lib/widgets/backup/asset_info_table.dart | 51 +- .../lib/widgets/backup/backup_info_card.dart | 31 +- .../backup/current_backup_asset_info_box.dart | 11 +- .../backup/drift_album_info_list_tile.dart | 29 +- mobile/lib/widgets/backup/error_chip.dart | 5 +- .../lib/widgets/backup/error_chip_text.dart | 6 +- .../backup/icloud_download_progress_bar.dart | 25 +- .../widgets/backup/ios_debug_info_tile.dart | 28 +- .../widgets/backup/upload_progress_bar.dart | 29 +- mobile/lib/widgets/backup/upload_stats.dart | 21 +- .../common/app_bar_dialog/app_bar_dialog.dart | 120 +-- .../app_bar_dialog/app_bar_profile_info.dart | 50 +- .../app_bar_dialog/app_bar_server_info.dart | 57 +- mobile/lib/widgets/common/confirm_dialog.dart | 14 +- .../lib/widgets/common/date_time_picker.dart | 94 +-- .../common/delayed_loading_indicator.dart | 17 +- mobile/lib/widgets/common/drag_sheet.dart | 12 +- .../widgets/common/dropdown_search_menu.dart | 37 +- .../common/fade_in_placeholder_image.dart | 7 +- mobile/lib/widgets/common/immich_app_bar.dart | 72 +- mobile/lib/widgets/common/immich_image.dart | 37 +- .../common/immich_loading_indicator.dart | 32 +- mobile/lib/widgets/common/immich_logo.dart | 6 +- .../widgets/common/immich_sliver_app_bar.dart | 104 +-- .../lib/widgets/common/immich_thumbnail.dart | 48 +- .../lib/widgets/common/immich_title_text.dart | 10 +- mobile/lib/widgets/common/immich_toast.dart | 40 +- .../common/local_album_sliver_app_bar.dart | 8 +- .../lib/widgets/common/location_picker.dart | 48 +- .../common/mesmerizing_sliver_app_bar.dart | 144 +--- .../common/remote_album_sliver_app_bar.dart | 192 +---- .../widgets/common/scaffold_error_body.dart | 12 +- mobile/lib/widgets/common/search_field.dart | 36 +- .../common/selection_sliver_app_bar.dart | 29 +- mobile/lib/widgets/common/share_dialog.dart | 5 +- .../widgets/common/thumbhash_placeholder.dart | 11 +- .../widgets/common/user_circle_avatar.dart | 15 +- .../widgets/forms/change_password_form.dart | 40 +- .../lib/widgets/forms/login/email_input.dart | 12 +- .../lib/widgets/forms/login/loading_icon.dart | 10 +- .../lib/widgets/forms/login/login_button.dart | 14 +- .../lib/widgets/forms/login/login_form.dart | 110 +-- .../forms/login/o_auth_login_button.dart | 5 +- .../widgets/forms/login/password_input.dart | 16 +- .../forms/login/server_endpoint_input.dart | 7 +- mobile/lib/widgets/forms/pin_input.dart | 34 +- .../widgets/forms/pin_registration_form.dart | 32 +- .../widgets/forms/pin_verification_form.dart | 10 +- mobile/lib/widgets/map/map_app_bar.dart | 56 +- mobile/lib/widgets/map/map_asset_grid.dart | 86 +-- mobile/lib/widgets/map/map_bottom_sheet.dart | 10 +- .../map_settings/map_settings_list_tile.dart | 12 +- .../map_settings_time_dropdown.dart | 57 +- .../map/map_settings/map_theme_picker.dart | 15 +- .../lib/widgets/map/map_theme_override.dart | 6 +- mobile/lib/widgets/map/map_thumbnail.dart | 6 +- .../map/positioned_asset_marker_icon.dart | 50 +- .../widgets/memories/memory_bottom_info.dart | 62 +- mobile/lib/widgets/memories/memory_card.dart | 57 +- .../lib/widgets/memories/memory_epilogue.dart | 38 +- mobile/lib/widgets/memories/memory_lane.dart | 48 +- .../memories/memory_progress_indicator.dart | 15 +- mobile/lib/widgets/photo_view/photo_view.dart | 100 +-- .../photo_view/photo_view_gallery.dart | 39 +- .../src/controller/photo_view_controller.dart | 35 +- .../photo_view_controller_delegate.dart | 48 +- .../photo_view_scalestate_controller.dart | 5 +- .../photo_view/src/core/photo_view_core.dart | 80 +- .../src/core/photo_view_gesture_detector.dart | 35 +- .../src/core/photo_view_hit_corners.dart | 5 +- .../src/photo_view_default_widgets.dart | 14 +- .../photo_view/src/photo_view_wrappers.dart | 27 +- .../src/utils/ignorable_change_notifier.dart | 6 +- .../src/utils/photo_view_utils.dart | 25 +- .../widgets/search/curated_people_row.dart | 34 +- .../widgets/search/curated_places_row.dart | 4 +- mobile/lib/widgets/search/explore_grid.dart | 28 +- .../widgets/search/person_name_edit_form.dart | 29 +- .../search/search_filter/camera_picker.dart | 49 +- .../search/search_filter/common/dropdown.dart | 4 +- .../search_filter/display_option_picker.dart | 27 +- .../filter_bottom_sheet_scaffold.dart | 5 +- .../search/search_filter/location_picker.dart | 53 +- .../search/search_filter/people_picker.dart | 18 +- .../search_filter/search_filter_chip.dart | 38 +- .../widgets/search/search_map_thumbnail.dart | 16 +- .../widgets/search/search_row_section.dart | 5 +- .../lib/widgets/search/search_row_title.dart | 17 +- .../widgets/search/thumbnail_with_info.dart | 7 +- .../search/thumbnail_with_info_container.dart | 11 +- .../widgets/settings/advanced_settings.dart | 5 +- .../asset_list_group_settings.dart | 24 +- .../asset_list_layout_settings.dart | 4 +- .../asset_list_settings.dart | 9 +- .../asset_viewer_settings.dart | 14 +- .../image_viewer_quality_setting.dart | 9 +- .../video_viewer_settings.dart | 4 +- .../backup_settings/background_settings.dart | 103 ++- .../backup_settings/backup_settings.dart | 18 +- .../beta_sync_settings.dart | 160 +--- .../beta_sync_settings/entity_count_tile.dart | 37 +- .../settings/beta_timeline_list_tile.dart | 91 +-- .../custome_proxy_headers_settings.dart | 8 +- .../widgets/settings/language_settings.dart | 104 +-- .../settings/local_storage_settings.dart | 19 +- .../networking_settings/endpoint_input.dart | 19 +- .../external_network_preference.dart | 62 +- .../local_network_preference.dart | 88 +-- .../networking_settings.dart | 129 +--- .../settings/notification_setting.dart | 22 +- .../preference_settings/haptic_setting.dart | 4 +- .../preference_setting.dart | 14 +- .../primary_color_setting.dart | 43 +- .../preference_settings/theme_setting.dart | 4 +- .../settings/settings_button_list_tile.dart | 11 +- .../lib/widgets/settings/settings_card.dart | 22 +- .../settings/settings_radio_list_tile.dart | 14 +- .../settings/settings_slider_list_tile.dart | 7 +- .../settings/settings_sub_page_scaffold.dart | 12 +- .../widgets/settings/settings_sub_title.dart | 10 +- .../settings/settings_switch_list_tile.dart | 13 +- .../settings/ssl_client_cert_settings.dart | 54 +- .../widgets/shared_link/shared_link_item.dart | 72 +- mobile/pubspec.lock | 2 +- mobile/pubspec.yaml | 2 +- .../domain/services/hash_service_test.dart | 15 +- .../domain/services/log_service_test.dart | 33 +- .../domain/services/store_service_test.dart | 20 +- .../services/sync_stream_service_test.dart | 157 ++-- .../domain/services/user_service_test.dart | 18 +- .../test/drift/main/generated/schema_v1.dart | Bin 188331 -> 193664 bytes .../test/drift/main/generated/schema_v2.dart | Bin 188331 -> 193664 bytes .../test/drift/main/generated/schema_v3.dart | Bin 188224 -> 193552 bytes .../test/drift/main/generated/schema_v4.dart | Bin 202557 -> 208286 bytes mobile/test/fixtures/album.stub.dart | 29 +- mobile/test/fixtures/sync_stream.stub.dart | 32 +- .../local_album_repository_test.dart | 39 +- .../repositories/store_repository_test.dart | 31 +- .../sync_api_repository_test.dart | 174 ++--- mobile/test/mock_http_override.dart | 9 +- .../activity/activities_page_test.dart | 199 ++--- .../activity/activity_provider_test.dart | 123 +-- .../activity_statistics_provider_test.dart | 33 +- .../activity/activity_text_field_test.dart | 91 +-- .../modules/activity/activity_tile_test.dart | 84 +-- .../activity/dismissible_activity_test.dart | 28 +- .../album_sort_by_options_provider_test.dart | 184 +---- .../extensions/asset_extensions_test.dart | 21 +- .../extensions/builtin_extensions_test.dart | 9 +- .../home/asset_grid_data_structure_test.dart | 30 +- .../modules/map/map_theme_override_test.dart | 9 +- .../modules/shared/sync_service_test.dart | 79 +- .../test/modules/utils/async_mutex_test.dart | 28 +- .../modules/utils/thumbnail_utils_test.dart | 21 +- .../utils/version_compatibility_test.dart | 5 +- .../test/pages/search/search.page_test.dart | 40 +- mobile/test/services/album.service_test.dart | 90 +-- mobile/test/services/asset.service_test.dart | 8 +- mobile/test/services/auth.service_test.dart | 84 +-- mobile/test/services/entity.service_test.dart | 54 +- mobile/test/services/hash_service_test.dart | 100 +-- mobile/test/test_utils.dart | 27 +- mobile/test/widget_tester_extensions.dart | 5 +- 643 files changed, 6519 insertions(+), 18431 deletions(-) diff --git a/mobile/lib/constants/colors.dart b/mobile/lib/constants/colors.dart index 1614a308e..069ed519c 100644 --- a/mobile/lib/constants/colors.dart +++ b/mobile/lib/constants/colors.dart @@ -1,17 +1,6 @@ import 'package:flutter/material.dart'; -enum ImmichColorPreset { - indigo, - deepPurple, - pink, - red, - orange, - yellow, - lime, - green, - cyan, - slateGray, -} +enum ImmichColorPreset { indigo, deepPurple, pink, red, orange, yellow, lime, green, cyan, slateGray } const ImmichColorPreset defaultColorPreset = ImmichColorPreset.indigo; const String defaultColorPresetName = "indigo"; diff --git a/mobile/lib/constants/enums.dart b/mobile/lib/constants/enums.dart index febc71032..6ec0ce37e 100644 --- a/mobile/lib/constants/enums.dart +++ b/mobile/lib/constants/enums.dart @@ -1,13 +1,6 @@ -enum SortOrder { - asc, - desc, -} +enum SortOrder { asc, desc } -enum TextSearchType { - context, - filename, - description, -} +enum TextSearchType { context, filename, description } enum AssetVisibilityEnum { timeline, hidden, archive, locked } diff --git a/mobile/lib/constants/filters.dart b/mobile/lib/constants/filters.dart index 61597f08d..e77bcfbf1 100644 --- a/mobile/lib/constants/filters.dart +++ b/mobile/lib/constants/filters.dart @@ -2,511 +2,49 @@ import 'package:flutter/material.dart'; const List filters = [ //Original - ColorFilter.matrix([ - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]), //Vintage - ColorFilter.matrix([ - 0.8, - 0.1, - 0.1, - 0, - 20, - 0.1, - 0.8, - 0.1, - 0, - 20, - 0.1, - 0.1, - 0.8, - 0, - 20, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.8, 0.1, 0.1, 0, 20, 0.1, 0.8, 0.1, 0, 20, 0.1, 0.1, 0.8, 0, 20, 0, 0, 0, 1, 0]), //Mood - ColorFilter.matrix([ - 1.2, - 0.1, - 0.1, - 0, - 10, - 0.1, - 1, - 0.1, - 0, - 10, - 0.1, - 0.1, - 1, - 0, - 10, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.2, 0.1, 0.1, 0, 10, 0.1, 1, 0.1, 0, 10, 0.1, 0.1, 1, 0, 10, 0, 0, 0, 1, 0]), //Crisp - ColorFilter.matrix([ - 1.2, - 0, - 0, - 0, - 0, - 0, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.2, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1, 0]), //Cool - ColorFilter.matrix([ - 0.9, - 0, - 0.2, - 0, - 0, - 0, - 1, - 0.1, - 0, - 0, - 0.1, - 0, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.9, 0, 0.2, 0, 0, 0, 1, 0.1, 0, 0, 0.1, 0, 1.2, 0, 0, 0, 0, 0, 1, 0]), //Blush - ColorFilter.matrix([ - 1.1, - 0.1, - 0.1, - 0, - 10, - 0.1, - 1, - 0.1, - 0, - 10, - 0.1, - 0.1, - 1, - 0, - 5, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.1, 0.1, 0.1, 0, 10, 0.1, 1, 0.1, 0, 10, 0.1, 0.1, 1, 0, 5, 0, 0, 0, 1, 0]), //Sunkissed - ColorFilter.matrix([ - 1.3, - 0, - 0.1, - 0, - 15, - 0, - 1.1, - 0.1, - 0, - 10, - 0, - 0, - 0.9, - 0, - 5, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.3, 0, 0.1, 0, 15, 0, 1.1, 0.1, 0, 10, 0, 0, 0.9, 0, 5, 0, 0, 0, 1, 0]), //Fresh - ColorFilter.matrix([ - 1.2, - 0, - 0, - 0, - 20, - 0, - 1.2, - 0, - 0, - 20, - 0, - 0, - 1.1, - 0, - 20, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.2, 0, 0, 0, 20, 0, 1.2, 0, 0, 20, 0, 0, 1.1, 0, 20, 0, 0, 0, 1, 0]), //Classic - ColorFilter.matrix([ - 1.1, - 0, - -0.1, - 0, - 10, - -0.1, - 1.1, - 0.1, - 0, - 5, - 0, - -0.1, - 1.1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.1, 0, -0.1, 0, 10, -0.1, 1.1, 0.1, 0, 5, 0, -0.1, 1.1, 0, 0, 0, 0, 0, 1, 0]), //Lomo-ish - ColorFilter.matrix([ - 1.5, - 0, - 0.1, - 0, - 0, - 0, - 1.45, - 0, - 0, - 0, - 0.1, - 0, - 1.3, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.5, 0, 0.1, 0, 0, 0, 1.45, 0, 0, 0, 0.1, 0, 1.3, 0, 0, 0, 0, 0, 1, 0]), //Nashville - ColorFilter.matrix([ - 1.2, - 0.15, - -0.15, - 0, - 15, - 0.1, - 1.1, - 0.1, - 0, - 10, - -0.05, - 0.2, - 1.25, - 0, - 5, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.2, 0.15, -0.15, 0, 15, 0.1, 1.1, 0.1, 0, 10, -0.05, 0.2, 1.25, 0, 5, 0, 0, 0, 1, 0]), //Valencia - ColorFilter.matrix([ - 1.15, - 0.1, - 0.1, - 0, - 20, - 0.1, - 1.1, - 0, - 0, - 10, - 0.1, - 0.1, - 1.2, - 0, - 5, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.15, 0.1, 0.1, 0, 20, 0.1, 1.1, 0, 0, 10, 0.1, 0.1, 1.2, 0, 5, 0, 0, 0, 1, 0]), //Clarendon - ColorFilter.matrix([ - 1.2, - 0, - 0, - 0, - 10, - 0, - 1.25, - 0, - 0, - 10, - 0, - 0, - 1.3, - 0, - 10, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.2, 0, 0, 0, 10, 0, 1.25, 0, 0, 10, 0, 0, 1.3, 0, 10, 0, 0, 0, 1, 0]), //Moon - ColorFilter.matrix([ - 0.33, - 0.33, - 0.33, - 0, - 0, - 0.33, - 0.33, - 0.33, - 0, - 0, - 0.33, - 0.33, - 0.33, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.33, 0.33, 0.33, 0, 0, 0.33, 0.33, 0.33, 0, 0, 0.33, 0.33, 0.33, 0, 0, 0, 0, 0, 1, 0]), //Willow - ColorFilter.matrix([ - 0.5, - 0.5, - 0.5, - 0, - 20, - 0.5, - 0.5, - 0.5, - 0, - 20, - 0.5, - 0.5, - 0.5, - 0, - 20, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.5, 0.5, 0.5, 0, 20, 0.5, 0.5, 0.5, 0, 20, 0.5, 0.5, 0.5, 0, 20, 0, 0, 0, 1, 0]), //Kodak - ColorFilter.matrix([ - 1.3, - 0.1, - -0.1, - 0, - 10, - 0, - 1.25, - 0.1, - 0, - 10, - 0, - -0.1, - 1.1, - 0, - 5, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.3, 0.1, -0.1, 0, 10, 0, 1.25, 0.1, 0, 10, 0, -0.1, 1.1, 0, 5, 0, 0, 0, 1, 0]), //Frost - ColorFilter.matrix([ - 0.8, - 0.2, - 0.1, - 0, - 0, - 0.2, - 1.1, - 0.1, - 0, - 0, - 0.1, - 0.1, - 1.2, - 0, - 10, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.8, 0.2, 0.1, 0, 0, 0.2, 1.1, 0.1, 0, 0, 0.1, 0.1, 1.2, 0, 10, 0, 0, 0, 1, 0]), //Night Vision - ColorFilter.matrix([ - 0.1, - 0.95, - 0.2, - 0, - 0, - 0.1, - 1.5, - 0.1, - 0, - 0, - 0.2, - 0.7, - 0, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.1, 0.95, 0.2, 0, 0, 0.1, 1.5, 0.1, 0, 0, 0.2, 0.7, 0, 0, 0, 0, 0, 0, 1, 0]), //Sunset - ColorFilter.matrix([ - 1.5, - 0.2, - 0, - 0, - 0, - 0.1, - 0.9, - 0.1, - 0, - 0, - -0.1, - -0.2, - 1.3, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.5, 0.2, 0, 0, 0, 0.1, 0.9, 0.1, 0, 0, -0.1, -0.2, 1.3, 0, 0, 0, 0, 0, 1, 0]), //Noir - ColorFilter.matrix([ - 1.3, - -0.3, - 0.1, - 0, - 0, - -0.1, - 1.2, - -0.1, - 0, - 0, - 0.1, - -0.2, - 1.3, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.3, -0.3, 0.1, 0, 0, -0.1, 1.2, -0.1, 0, 0, 0.1, -0.2, 1.3, 0, 0, 0, 0, 0, 1, 0]), //Dreamy - ColorFilter.matrix([ - 1.1, - 0.1, - 0.1, - 0, - 0, - 0.1, - 1.1, - 0.1, - 0, - 0, - 0.1, - 0.1, - 1.1, - 0, - 15, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.1, 0.1, 0.1, 0, 0, 0.1, 1.1, 0.1, 0, 0, 0.1, 0.1, 1.1, 0, 15, 0, 0, 0, 1, 0]), //Sepia - ColorFilter.matrix([ - 0.393, - 0.769, - 0.189, - 0, - 0, - 0.349, - 0.686, - 0.168, - 0, - 0, - 0.272, - 0.534, - 0.131, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0]), //Radium ColorFilter.matrix([ 1.438, @@ -554,212 +92,23 @@ const List filters = [ 0, ]), //Purple Haze - ColorFilter.matrix([ - 1.3, - 0, - 1.2, - 0, - 0, - 0, - 1.1, - 0, - 0, - 0, - 0.2, - 0, - 1.3, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.3, 0, 1.2, 0, 0, 0, 1.1, 0, 0, 0, 0.2, 0, 1.3, 0, 0, 0, 0, 0, 1, 0]), //Lemonade - ColorFilter.matrix([ - 1.2, - 0.1, - 0, - 0, - 0, - 0, - 1.1, - 0.2, - 0, - 0, - 0.1, - 0, - 0.7, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.2, 0.1, 0, 0, 0, 0, 1.1, 0.2, 0, 0, 0.1, 0, 0.7, 0, 0, 0, 0, 0, 1, 0]), //Caramel - ColorFilter.matrix([ - 1.6, - 0.2, - 0, - 0, - 0, - 0.1, - 1.3, - 0.1, - 0, - 0, - 0, - 0.1, - 0.9, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.6, 0.2, 0, 0, 0, 0.1, 1.3, 0.1, 0, 0, 0, 0.1, 0.9, 0, 0, 0, 0, 0, 1, 0]), //Peachy - ColorFilter.matrix([ - 1.3, - 0.5, - 0, - 0, - 0, - 0.2, - 1.1, - 0.3, - 0, - 0, - 0.1, - 0.1, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.3, 0.5, 0, 0, 0, 0.2, 1.1, 0.3, 0, 0, 0.1, 0.1, 1.2, 0, 0, 0, 0, 0, 1, 0]), //Neon - ColorFilter.matrix([ - 1, - 0, - 1, - 0, - 0, - 0, - 2, - 0, - 0, - 0, - 0, - 0, - 3, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0]), //Cold Morning - ColorFilter.matrix([ - 0.9, - 0.1, - 0.2, - 0, - 0, - 0, - 1, - 0.1, - 0, - 0, - 0.1, - 0, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.9, 0.1, 0.2, 0, 0, 0, 1, 0.1, 0, 0, 0.1, 0, 1.2, 0, 0, 0, 0, 0, 1, 0]), //Lush - ColorFilter.matrix([ - 0.9, - 0.2, - 0, - 0, - 0, - 0, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1.1, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.9, 0.2, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.1, 0, 0, 0, 0, 0, 1, 0]), //Urban Neon - ColorFilter.matrix([ - 1.1, - 0, - 0.3, - 0, - 0, - 0, - 0.9, - 0.3, - 0, - 0, - 0.3, - 0.1, - 1.2, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([1.1, 0, 0.3, 0, 0, 0, 0.9, 0.3, 0, 0, 0.3, 0.1, 1.2, 0, 0, 0, 0, 0, 1, 0]), //Monochrome - ColorFilter.matrix([ - 0.6, - 0.2, - 0.2, - 0, - 0, - 0.2, - 0.6, - 0.2, - 0, - 0, - 0.2, - 0.2, - 0.7, - 0, - 0, - 0, - 0, - 0, - 1, - 0, - ]), + ColorFilter.matrix([0.6, 0.2, 0.2, 0, 0, 0.2, 0.6, 0.2, 0, 0, 0.2, 0.2, 0.7, 0, 0, 0, 0, 0, 1, 0]), ]; const List filterNames = [ diff --git a/mobile/lib/constants/locales.dart b/mobile/lib/constants/locales.dart index 601a83b56..f3c24384b 100644 --- a/mobile/lib/constants/locales.dart +++ b/mobile/lib/constants/locales.dart @@ -51,7 +51,4 @@ const Map locales = { const String translationsPath = 'assets/i18n'; -const List localesNotSupportedByOverpass = [ - Locale('el', 'GR'), - Locale('sr', 'Cyrl'), -]; +const List localesNotSupportedByOverpass = [Locale('el', 'GR'), Locale('sr', 'Cyrl')]; diff --git a/mobile/lib/domain/models/asset/base_asset.model.dart b/mobile/lib/domain/models/asset/base_asset.model.dart index 7cd4caab6..4d40be2d3 100644 --- a/mobile/lib/domain/models/asset/base_asset.model.dart +++ b/mobile/lib/domain/models/asset/base_asset.model.dart @@ -9,11 +9,7 @@ enum AssetType { audio, } -enum AssetState { - local, - remote, - merged, -} +enum AssetState { local, remote, merged } sealed class BaseAsset { final String name; diff --git a/mobile/lib/domain/models/asset/remote_asset.model.dart b/mobile/lib/domain/models/asset/remote_asset.model.dart index db3e53cd2..864825516 100644 --- a/mobile/lib/domain/models/asset/remote_asset.model.dart +++ b/mobile/lib/domain/models/asset/remote_asset.model.dart @@ -1,11 +1,6 @@ part of 'base_asset.model.dart'; -enum AssetVisibility { - timeline, - hidden, - archive, - locked, -} +enum AssetVisibility { timeline, hidden, archive, locked } // Model for an asset stored in the server class RemoteAsset extends BaseAsset { diff --git a/mobile/lib/domain/models/device_asset.model.dart b/mobile/lib/domain/models/device_asset.model.dart index b0949ccc9..a404f5a9e 100644 --- a/mobile/lib/domain/models/device_asset.model.dart +++ b/mobile/lib/domain/models/device_asset.model.dart @@ -5,11 +5,7 @@ class DeviceAsset { final Uint8List hash; final DateTime modifiedTime; - const DeviceAsset({ - required this.assetId, - required this.hash, - required this.modifiedTime, - }); + const DeviceAsset({required this.assetId, required this.hash, required this.modifiedTime}); @override bool operator ==(covariant DeviceAsset other) { @@ -28,11 +24,7 @@ class DeviceAsset { return 'DeviceAsset(assetId: $assetId, hash: $hash, modifiedTime: $modifiedTime)'; } - DeviceAsset copyWith({ - String? assetId, - Uint8List? hash, - DateTime? modifiedTime, - }) { + DeviceAsset copyWith({String? assetId, Uint8List? hash, DateTime? modifiedTime}) { return DeviceAsset( assetId: assetId ?? this.assetId, hash: hash ?? this.hash, diff --git a/mobile/lib/domain/models/log.model.dart b/mobile/lib/domain/models/log.model.dart index f58cae806..9902ca04c 100644 --- a/mobile/lib/domain/models/log.model.dart +++ b/mobile/lib/domain/models/log.model.dart @@ -1,16 +1,5 @@ /// Log levels according to dart logging [Level] -enum LogLevel { - all, - finest, - finer, - fine, - config, - info, - warning, - severe, - shout, - off, -} +enum LogLevel { all, finest, finer, fine, config, info, warning, severe, shout, off } class LogMessage { final String message; diff --git a/mobile/lib/domain/models/memory.model.dart b/mobile/lib/domain/models/memory.model.dart index 39a6d4518..40117c5ac 100644 --- a/mobile/lib/domain/models/memory.model.dart +++ b/mobile/lib/domain/models/memory.model.dart @@ -13,28 +13,18 @@ enum MemoryTypeEnum { class MemoryData { final int year; - const MemoryData({ - required this.year, - }); + const MemoryData({required this.year}); - MemoryData copyWith({ - int? year, - }) { - return MemoryData( - year: year ?? this.year, - ); + MemoryData copyWith({int? year}) { + return MemoryData(year: year ?? this.year); } Map toMap() { - return { - 'year': year, - }; + return {'year': year}; } factory MemoryData.fromMap(Map map) { - return MemoryData( - year: map['year'] as int, - ); + return MemoryData(year: map['year'] as int); } String toJson() => json.encode(toMap()); diff --git a/mobile/lib/domain/models/search_result.model.dart b/mobile/lib/domain/models/search_result.model.dart index e8c942943..bae8b8e82 100644 --- a/mobile/lib/domain/models/search_result.model.dart +++ b/mobile/lib/domain/models/search_result.model.dart @@ -5,21 +5,12 @@ class SearchResult { final List assets; final int? nextPage; - const SearchResult({ - required this.assets, - this.nextPage, - }); + const SearchResult({required this.assets, this.nextPage}); int get totalAssets => assets.length; - SearchResult copyWith({ - List? assets, - int? nextPage, - }) { - return SearchResult( - assets: assets ?? this.assets, - nextPage: nextPage ?? this.nextPage, - ); + SearchResult copyWith({List? assets, int? nextPage}) { + return SearchResult(assets: assets ?? this.assets, nextPage: nextPage ?? this.nextPage); } @override diff --git a/mobile/lib/domain/models/setting.model.dart b/mobile/lib/domain/models/setting.model.dart index 150545eba..f427d9328 100644 --- a/mobile/lib/domain/models/setting.model.dart +++ b/mobile/lib/domain/models/setting.model.dart @@ -8,8 +8,7 @@ enum Setting { loadOriginalVideo(StoreKey.loadOriginalVideo, false), preferRemoteImage(StoreKey.preferRemoteImage, false), advancedTroubleshooting(StoreKey.advancedTroubleshooting, false), - enableBackup(StoreKey.enableBackup, false), - ; + enableBackup(StoreKey.enableBackup, false); const Setting(this.storeKey, this.defaultValue); diff --git a/mobile/lib/domain/models/stack.model.dart b/mobile/lib/domain/models/stack.model.dart index 0db65d105..d5ccf5558 100644 --- a/mobile/lib/domain/models/stack.model.dart +++ b/mobile/lib/domain/models/stack.model.dart @@ -14,13 +14,7 @@ class Stack { required this.primaryAssetId, }); - Stack copyWith({ - String? id, - DateTime? createdAt, - DateTime? updatedAt, - String? ownerId, - String? primaryAssetId, - }) { + Stack copyWith({String? id, DateTime? createdAt, DateTime? updatedAt, String? ownerId, String? primaryAssetId}) { return Stack( id: id ?? this.id, createdAt: createdAt ?? this.createdAt, @@ -63,11 +57,7 @@ class StackResponse { final String primaryAssetId; final List assetIds; - const StackResponse({ - required this.id, - required this.primaryAssetId, - required this.assetIds, - }); + const StackResponse({required this.id, required this.primaryAssetId, required this.assetIds}); @override bool operator ==(covariant StackResponse other) { diff --git a/mobile/lib/domain/models/timeline.model.dart b/mobile/lib/domain/models/timeline.model.dart index 3751500f0..d4cc5ab5c 100644 --- a/mobile/lib/domain/models/timeline.model.dart +++ b/mobile/lib/domain/models/timeline.model.dart @@ -1,18 +1,8 @@ import 'package:immich_mobile/domain/utils/event_stream.dart'; -enum GroupAssetsBy { - day, - month, - auto, - none; -} +enum GroupAssetsBy { day, month, auto, none } -enum HeaderType { - none, - month, - day, - monthAndDay; -} +enum HeaderType { none, month, day, monthAndDay } class Bucket { final int assetCount; diff --git a/mobile/lib/domain/models/user.model.dart b/mobile/lib/domain/models/user.model.dart index 9af8abadc..1e83fa498 100644 --- a/mobile/lib/domain/models/user.model.dart +++ b/mobile/lib/domain/models/user.model.dart @@ -74,22 +74,21 @@ quotaSizeInBytes: $quotaSizeInBytes, bool? isPartnerSharedWith, int? quotaUsageInBytes, int? quotaSizeInBytes, - }) => - UserDto( - id: id ?? this.id, - email: email ?? this.email, - name: name ?? this.name, - isAdmin: isAdmin ?? this.isAdmin, - updatedAt: updatedAt ?? this.updatedAt, - profileImagePath: profileImagePath ?? this.profileImagePath, - avatarColor: avatarColor ?? this.avatarColor, - memoryEnabled: memoryEnabled ?? this.memoryEnabled, - inTimeline: inTimeline ?? this.inTimeline, - isPartnerSharedBy: isPartnerSharedBy ?? this.isPartnerSharedBy, - isPartnerSharedWith: isPartnerSharedWith ?? this.isPartnerSharedWith, - quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, - quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, - ); + }) => UserDto( + id: id ?? this.id, + email: email ?? this.email, + name: name ?? this.name, + isAdmin: isAdmin ?? this.isAdmin, + updatedAt: updatedAt ?? this.updatedAt, + profileImagePath: profileImagePath ?? this.profileImagePath, + avatarColor: avatarColor ?? this.avatarColor, + memoryEnabled: memoryEnabled ?? this.memoryEnabled, + inTimeline: inTimeline ?? this.inTimeline, + isPartnerSharedBy: isPartnerSharedBy ?? this.isPartnerSharedBy, + isPartnerSharedWith: isPartnerSharedWith ?? this.isPartnerSharedWith, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + ); @override bool operator ==(covariant UserDto other) { @@ -143,13 +142,7 @@ class PartnerUserDto { this.profileImagePath, }); - PartnerUserDto copyWith({ - String? id, - String? email, - String? name, - bool? inTimeline, - String? profileImagePath, - }) { + PartnerUserDto copyWith({String? id, String? email, String? name, bool? inTimeline, String? profileImagePath}) { return PartnerUserDto( id: id ?? this.id, email: email ?? this.email, diff --git a/mobile/lib/domain/models/user_metadata.model.dart b/mobile/lib/domain/models/user_metadata.model.dart index 8b7ca1ffa..1c371a9d3 100644 --- a/mobile/lib/domain/models/user_metadata.model.dart +++ b/mobile/lib/domain/models/user_metadata.model.dart @@ -24,17 +24,17 @@ enum AvatarColor { const AvatarColor(this.value); Color toColor({bool isDarkTheme = false}) => switch (this) { - AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF), - AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182), - AvatarColor.red => const Color.fromARGB(255, 239, 68, 68), - AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8), - AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246), - AvatarColor.green => const Color.fromARGB(255, 22, 163, 74), - AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234), - AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12), - AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99), - AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6), - }; + AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF), + AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182), + AvatarColor.red => const Color.fromARGB(255, 239, 68, 68), + AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8), + AvatarColor.blue => const Color.fromARGB(255, 59, 130, 246), + AvatarColor.green => const Color.fromARGB(255, 22, 163, 74), + AvatarColor.purple => const Color.fromARGB(255, 147, 51, 234), + AvatarColor.orange => const Color.fromARGB(255, 234, 88, 12), + AvatarColor.gray => const Color.fromARGB(255, 75, 85, 99), + AvatarColor.amber => const Color.fromARGB(255, 217, 119, 6), + }; } class Onboarding { @@ -193,17 +193,9 @@ class License { final String activationKey; final String licenseKey; - const License({ - required this.activatedAt, - required this.activationKey, - required this.licenseKey, - }); + const License({required this.activatedAt, required this.activationKey, required this.licenseKey}); - License copyWith({ - DateTime? activatedAt, - String? activationKey, - String? licenseKey, - }) { + License copyWith({DateTime? activatedAt, String? activationKey, String? licenseKey}) { return License( activatedAt: activatedAt ?? this.activatedAt, activationKey: activationKey ?? this.activationKey, @@ -255,16 +247,11 @@ class UserMetadata { final Preferences? preferences; final License? license; - const UserMetadata({ - required this.userId, - required this.key, - this.onboarding, - this.preferences, - this.license, - }) : assert( - onboarding != null || preferences != null || license != null, - 'One of onboarding, preferences and license must be provided', - ); + const UserMetadata({required this.userId, required this.key, this.onboarding, this.preferences, this.license}) + : assert( + onboarding != null || preferences != null || license != null, + 'One of onboarding, preferences and license must be provided', + ); UserMetadata copyWith({ String? userId, diff --git a/mobile/lib/domain/services/asset.service.dart b/mobile/lib/domain/services/asset.service.dart index 5006e2d45..c8cc61314 100644 --- a/mobile/lib/domain/services/asset.service.dart +++ b/mobile/lib/domain/services/asset.service.dart @@ -13,9 +13,9 @@ class AssetService { const AssetService({ required RemoteAssetRepository remoteAssetRepository, required DriftLocalAssetRepository localAssetRepository, - }) : _remoteAssetRepository = remoteAssetRepository, - _localAssetRepository = localAssetRepository, - _platform = const LocalPlatform(); + }) : _remoteAssetRepository = remoteAssetRepository, + _localAssetRepository = localAssetRepository, + _platform = const LocalPlatform(); Stream watchAsset(BaseAsset asset) { final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id; diff --git a/mobile/lib/domain/services/hash.service.dart b/mobile/lib/domain/services/hash.service.dart index 3bbb75b00..2eb9aec4d 100644 --- a/mobile/lib/domain/services/hash.service.dart +++ b/mobile/lib/domain/services/hash.service.dart @@ -25,19 +25,16 @@ class HashService { required NativeSyncApi nativeSyncApi, this.batchSizeLimit = kBatchHashSizeLimit, this.batchFileLimit = kBatchHashFileLimit, - }) : _localAlbumRepository = localAlbumRepository, - _localAssetRepository = localAssetRepository, - _storageRepository = storageRepository, - _nativeSyncApi = nativeSyncApi; + }) : _localAlbumRepository = localAlbumRepository, + _localAssetRepository = localAssetRepository, + _storageRepository = storageRepository, + _nativeSyncApi = nativeSyncApi; Future hashAssets() async { final Stopwatch stopwatch = Stopwatch()..start(); // Sorted by backupSelection followed by isCloud final localAlbums = await _localAlbumRepository.getAll( - sortBy: { - SortLocalAlbumsBy.backupSelection, - SortLocalAlbumsBy.isIosSharedAlbum, - }, + sortBy: {SortLocalAlbumsBy.backupSelection, SortLocalAlbumsBy.isIosSharedAlbum}, ); for (final album in localAlbums) { diff --git a/mobile/lib/domain/services/local_sync.service.dart b/mobile/lib/domain/services/local_sync.service.dart index 420476105..cb1bb4061 100644 --- a/mobile/lib/domain/services/local_sync.service.dart +++ b/mobile/lib/domain/services/local_sync.service.dart @@ -21,9 +21,9 @@ class LocalSyncService { required DriftLocalAlbumRepository localAlbumRepository, required NativeSyncApi nativeSyncApi, Platform? platform, - }) : _localAlbumRepository = localAlbumRepository, - _nativeSyncApi = nativeSyncApi, - _platform = platform ?? const LocalPlatform(); + }) : _localAlbumRepository = localAlbumRepository, + _nativeSyncApi = nativeSyncApi, + _platform = platform ?? const LocalPlatform(); Future sync({bool full = false}) async { final Stopwatch stopwatch = Stopwatch()..start(); @@ -70,9 +70,7 @@ class LocalSyncService { for (final album in cloudAlbums) { final dbAlbum = dbAlbums.firstWhereOrNull((a) => a.id == album.id); if (dbAlbum == null) { - _log.warning( - "Cloud album ${album.name} not found in local database. Skipping sync.", - ); + _log.warning("Cloud album ${album.name} not found in local database. Skipping sync."); continue; } await updateAlbum(dbAlbum, album); @@ -120,10 +118,7 @@ class LocalSyncService { final assets = album.assetCount > 0 ? await _nativeSyncApi.getAssetsForAlbum(album.id) : []; - await _localAlbumRepository.upsert( - album, - toUpsert: assets.toLocalAssets(), - ); + await _localAlbumRepository.upsert(album, toUpsert: assets.toLocalAssets()); _log.fine("Successfully added device album ${album.name}"); } catch (e, s) { _log.warning("Error while adding device album", e, s); @@ -146,9 +141,7 @@ class LocalSyncService { _log.fine("Syncing device album ${dbAlbum.name}"); if (_albumsEqual(deviceAlbum, dbAlbum)) { - _log.fine( - "Device album ${dbAlbum.name} has not changed. Skipping sync.", - ); + _log.fine("Device album ${dbAlbum.name} has not changed. Skipping sync."); return false; } @@ -172,10 +165,7 @@ class LocalSyncService { @visibleForTesting // The [deviceAlbum] is expected to be refreshed before calling this method // with modified time and asset count - Future checkAddition( - LocalAlbum dbAlbum, - LocalAlbum deviceAlbum, - ) async { + Future checkAddition(LocalAlbum dbAlbum, LocalAlbum deviceAlbum) async { try { _log.fine("Fast syncing device album ${dbAlbum.name}"); // Assets has been modified @@ -189,9 +179,7 @@ class LocalSyncService { // Early return if no new assets were found if (newAssetsCount == 0) { - _log.fine( - "No new assets found despite album having changes. Proceeding to full sync for ${dbAlbum.name}", - ); + _log.fine("No new assets found despite album having changes. Proceeding to full sync for ${dbAlbum.name}"); return false; } @@ -201,10 +189,7 @@ class LocalSyncService { return false; } - final newAssets = await _nativeSyncApi.getAssetsForAlbum( - deviceAlbum.id, - updatedTimeCond: updatedTime, - ); + final newAssets = await _nativeSyncApi.getAssetsForAlbum(deviceAlbum.id, updatedTimeCond: updatedTime); await _localAlbumRepository.upsert( deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection), @@ -229,9 +214,7 @@ class LocalSyncService { final assetsInDb = dbAlbum.assetCount > 0 ? await _localAlbumRepository.getAssets(dbAlbum.id) : []; if (deviceAlbum.assetCount == 0) { - _log.fine( - "Device album ${deviceAlbum.name} is empty. Removing assets from DB.", - ); + _log.fine("Device album ${deviceAlbum.name} is empty. Removing assets from DB."); await _localAlbumRepository.upsert( deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection), toDelete: assetsInDb.map((a) => a.id), @@ -239,18 +222,11 @@ class LocalSyncService { return true; } - final updatedDeviceAlbum = deviceAlbum.copyWith( - backupSelection: dbAlbum.backupSelection, - ); + final updatedDeviceAlbum = deviceAlbum.copyWith(backupSelection: dbAlbum.backupSelection); if (dbAlbum.assetCount == 0) { - _log.fine( - "Device album ${deviceAlbum.name} is empty. Adding assets to DB.", - ); - await _localAlbumRepository.upsert( - updatedDeviceAlbum, - toUpsert: assetsInDevice, - ); + _log.fine("Device album ${deviceAlbum.name} is empty. Adding assets to DB."); + await _localAlbumRepository.upsert(updatedDeviceAlbum, toUpsert: assetsInDevice); return true; } @@ -282,18 +258,12 @@ class LocalSyncService { ); if (assetsToUpsert.isEmpty && assetsToDelete.isEmpty) { - _log.fine( - "No asset changes detected in album ${deviceAlbum.name}. Updating metadata.", - ); + _log.fine("No asset changes detected in album ${deviceAlbum.name}. Updating metadata."); _localAlbumRepository.upsert(updatedDeviceAlbum); return true; } - await _localAlbumRepository.upsert( - updatedDeviceAlbum, - toUpsert: assetsToUpsert, - toDelete: assetsToDelete, - ); + await _localAlbumRepository.upsert(updatedDeviceAlbum, toUpsert: assetsToUpsert, toDelete: assetsToDelete); return true; } catch (e, s) { diff --git a/mobile/lib/domain/services/log.service.dart b/mobile/lib/domain/services/log.service.dart index 72fb4d9bf..ff72ec550 100644 --- a/mobile/lib/domain/services/log.service.dart +++ b/mobile/lib/domain/services/log.service.dart @@ -61,11 +61,7 @@ class LogService { return instance; } - LogService._( - this._logRepository, - this._storeRepository, - this._shouldBuffer, - ) { + LogService._(this._logRepository, this._storeRepository, this._shouldBuffer) { _logSubscription = Logger.root.onRecord.listen(_handleLogRecord); } @@ -89,10 +85,7 @@ class LogService { if (_shouldBuffer) { _msgBuffer.add(record); - _flushTimer ??= Timer( - const Duration(seconds: 5), - () => unawaited(flushBuffer()), - ); + _flushTimer ??= Timer(const Duration(seconds: 5), () => unawaited(flushBuffer())); } else { unawaited(_logRepository.insert(record)); } diff --git a/mobile/lib/domain/services/partner.service.dart b/mobile/lib/domain/services/partner.service.dart index 11299b9d6..7733b5be6 100644 --- a/mobile/lib/domain/services/partner.service.dart +++ b/mobile/lib/domain/services/partner.service.dart @@ -7,10 +7,7 @@ class DriftPartnerService { final DriftPartnerRepository _driftPartnerRepository; final PartnerApiRepository _partnerApiRepository; - const DriftPartnerService( - this._driftPartnerRepository, - this._partnerApiRepository, - ); + const DriftPartnerService(this._driftPartnerRepository, this._partnerApiRepository); Future> getSharedWith(String userId) { return _driftPartnerRepository.getSharedWith(userId); @@ -20,9 +17,7 @@ class DriftPartnerService { return _driftPartnerRepository.getSharedBy(userId); } - Future> getAvailablePartners( - String currentUserId, - ) async { + Future> getAvailablePartners(String currentUserId) async { final otherUsers = await _driftPartnerRepository.getAvailablePartners(currentUserId); final currentPartners = await _driftPartnerRepository.getSharedBy(currentUserId); final available = otherUsers.where((user) { @@ -39,10 +34,7 @@ class DriftPartnerService { return; } - await _partnerApiRepository.update( - partnerId, - inTimeline: !partner.inTimeline, - ); + await _partnerApiRepository.update(partnerId, inTimeline: !partner.inTimeline); await _driftPartnerRepository.toggleShowInTimeline(partner, userId); } diff --git a/mobile/lib/domain/services/remote_album.service.dart b/mobile/lib/domain/services/remote_album.service.dart index 6c3b2e32a..f6c596f24 100644 --- a/mobile/lib/domain/services/remote_album.service.dart +++ b/mobile/lib/domain/services/remote_album.service.dart @@ -26,11 +26,7 @@ class RemoteAlbumService { return _repository.get(albumId); } - List sortAlbums( - List albums, - RemoteAlbumSortMode sortMode, { - bool isReverse = false, - }) { + List sortAlbums(List albums, RemoteAlbumSortMode sortMode, {bool isReverse = false}) { return sortMode.sortFn(albums, isReverse); } @@ -69,16 +65,8 @@ class RemoteAlbumService { return filtered; } - Future createAlbum({ - required String title, - required List assetIds, - String? description, - }) async { - final album = await _albumApiRepository.createDriftAlbum( - title, - description: description, - assetIds: assetIds, - ); + Future createAlbum({required String title, required List assetIds, String? description}) async { + final album = await _albumApiRepository.createDriftAlbum(title, description: description, assetIds: assetIds); await _repository.create(album, assetIds); @@ -120,14 +108,8 @@ class RemoteAlbumService { return _repository.getAssets(albumId); } - Future addAssets({ - required String albumId, - required List assetIds, - }) async { - final album = await _albumApiRepository.addAssets( - albumId, - assetIds, - ); + Future addAssets({required String albumId, required List assetIds}) async { + final album = await _albumApiRepository.addAssets(albumId, assetIds); await _repository.addAssets(albumId, album.added); @@ -140,10 +122,7 @@ class RemoteAlbumService { await _repository.deleteAlbum(albumId); } - Future addUsers({ - required String albumId, - required List userIds, - }) async { + Future addUsers({required String albumId, required List userIds}) async { await _albumApiRepository.addUsers(albumId, userIds); return _repository.addUsers(albumId, userIds); diff --git a/mobile/lib/domain/services/search.service.dart b/mobile/lib/domain/services/search.service.dart index 052a2ca9d..6ccc5a97b 100644 --- a/mobile/lib/domain/services/search.service.dart +++ b/mobile/lib/domain/services/search.service.dart @@ -83,10 +83,10 @@ extension on AssetResponseDto { extension on AssetTypeEnum { AssetType toAssetType() => switch (this) { - AssetTypeEnum.IMAGE => AssetType.image, - AssetTypeEnum.VIDEO => AssetType.video, - AssetTypeEnum.AUDIO => AssetType.audio, - AssetTypeEnum.OTHER => AssetType.other, - _ => throw Exception('Unknown AssetType value: $this'), - }; + AssetTypeEnum.IMAGE => AssetType.image, + AssetTypeEnum.VIDEO => AssetType.video, + AssetTypeEnum.AUDIO => AssetType.audio, + AssetTypeEnum.OTHER => AssetType.other, + _ => throw Exception('Unknown AssetType value: $this'), + }; } diff --git a/mobile/lib/domain/services/store.service.dart b/mobile/lib/domain/services/store.service.dart index bd839a18e..dc845b70f 100644 --- a/mobile/lib/domain/services/store.service.dart +++ b/mobile/lib/domain/services/store.service.dart @@ -24,16 +24,12 @@ class StoreService { } // TODO: Replace the implementation with the one from create after removing the typedef - static Future init({ - required IsarStoreRepository storeRepository, - }) async { + static Future init({required IsarStoreRepository storeRepository}) async { _instance ??= await create(storeRepository: storeRepository); return _instance!; } - static Future create({ - required IsarStoreRepository storeRepository, - }) async { + static Future create({required IsarStoreRepository storeRepository}) async { final instance = StoreService._(storeRepository: storeRepository); await instance._populateCache(); instance._storeUpdateSubscription = instance._listenForChange(); @@ -48,8 +44,8 @@ class StoreService { } StreamSubscription _listenForChange() => _storeRepository.watchAll().listen((event) { - _cache[event.key.id] = event.value; - }); + _cache[event.key.id] = event.value; + }); /// Disposes the store and cancels the subscription. To reuse the store call init() again void dispose() async { diff --git a/mobile/lib/domain/services/sync_stream.service.dart b/mobile/lib/domain/services/sync_stream.service.dart index a98500825..c21a9cade 100644 --- a/mobile/lib/domain/services/sync_stream.service.dart +++ b/mobile/lib/domain/services/sync_stream.service.dart @@ -18,9 +18,9 @@ class SyncStreamService { required SyncApiRepository syncApiRepository, required SyncStreamRepository syncStreamRepository, bool Function()? cancelChecker, - }) : _syncApiRepository = syncApiRepository, - _syncStreamRepository = syncStreamRepository, - _cancelChecker = cancelChecker; + }) : _syncApiRepository = syncApiRepository, + _syncStreamRepository = syncStreamRepository, + _cancelChecker = cancelChecker; bool get isCancelled => _cancelChecker?.call() ?? false; @@ -34,9 +34,7 @@ class SyncStreamService { Future handleWsAssetUploadReadyV1Batch(List batchData) async { if (batchData.isEmpty) return; - _logger.info( - 'Processing batch of ${batchData.length} AssetUploadReadyV1 events', - ); + _logger.info('Processing batch of ${batchData.length} AssetUploadReadyV1 events'); final List assets = []; final List exifs = []; @@ -65,22 +63,12 @@ class SyncStreamService { } if (assets.isNotEmpty && exifs.isNotEmpty) { - await _syncStreamRepository.updateAssetsV1( - assets, - debugLabel: 'websocket-batch', - ); - await _syncStreamRepository.updateAssetsExifV1( - exifs, - debugLabel: 'websocket-batch', - ); + await _syncStreamRepository.updateAssetsV1(assets, debugLabel: 'websocket-batch'); + await _syncStreamRepository.updateAssetsExifV1(exifs, debugLabel: 'websocket-batch'); _logger.info('Successfully processed ${assets.length} assets in batch'); } } catch (error, stackTrace) { - _logger.severe( - "Error processing AssetUploadReadyV1 websocket batch events", - error, - stackTrace, - ); + _logger.severe("Error processing AssetUploadReadyV1 websocket batch events", error, stackTrace); } } @@ -114,10 +102,7 @@ class SyncStreamService { batch.clear(); } - Future _handleSyncData( - SyncEntityType type, - Iterable data, - ) async { + Future _handleSyncData(SyncEntityType type, Iterable data) async { _logger.fine("Processing sync data for $type of length ${data.length}"); switch (type) { case SyncEntityType.userV1: @@ -135,30 +120,15 @@ class SyncStreamService { case SyncEntityType.assetExifV1: return _syncStreamRepository.updateAssetsExifV1(data.cast()); case SyncEntityType.partnerAssetV1: - return _syncStreamRepository.updateAssetsV1( - data.cast(), - debugLabel: 'partner', - ); + return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'partner'); case SyncEntityType.partnerAssetBackfillV1: - return _syncStreamRepository.updateAssetsV1( - data.cast(), - debugLabel: 'partner backfill', - ); + return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'partner backfill'); case SyncEntityType.partnerAssetDeleteV1: - return _syncStreamRepository.deleteAssetsV1( - data.cast(), - debugLabel: "partner", - ); + return _syncStreamRepository.deleteAssetsV1(data.cast(), debugLabel: "partner"); case SyncEntityType.partnerAssetExifV1: - return _syncStreamRepository.updateAssetsExifV1( - data.cast(), - debugLabel: 'partner', - ); + return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'partner'); case SyncEntityType.partnerAssetExifBackfillV1: - return _syncStreamRepository.updateAssetsExifV1( - data.cast(), - debugLabel: 'partner backfill', - ); + return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'partner backfill'); case SyncEntityType.albumV1: return _syncStreamRepository.updateAlbumsV1(data.cast()); case SyncEntityType.albumDeleteV1: @@ -166,39 +136,21 @@ class SyncStreamService { case SyncEntityType.albumUserV1: return _syncStreamRepository.updateAlbumUsersV1(data.cast()); case SyncEntityType.albumUserBackfillV1: - return _syncStreamRepository.updateAlbumUsersV1( - data.cast(), - debugLabel: 'backfill', - ); + return _syncStreamRepository.updateAlbumUsersV1(data.cast(), debugLabel: 'backfill'); case SyncEntityType.albumUserDeleteV1: return _syncStreamRepository.deleteAlbumUsersV1(data.cast()); case SyncEntityType.albumAssetV1: - return _syncStreamRepository.updateAssetsV1( - data.cast(), - debugLabel: 'album', - ); + return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'album'); case SyncEntityType.albumAssetBackfillV1: - return _syncStreamRepository.updateAssetsV1( - data.cast(), - debugLabel: 'album backfill', - ); + return _syncStreamRepository.updateAssetsV1(data.cast(), debugLabel: 'album backfill'); case SyncEntityType.albumAssetExifV1: - return _syncStreamRepository.updateAssetsExifV1( - data.cast(), - debugLabel: 'album', - ); + return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'album'); case SyncEntityType.albumAssetExifBackfillV1: - return _syncStreamRepository.updateAssetsExifV1( - data.cast(), - debugLabel: 'album backfill', - ); + return _syncStreamRepository.updateAssetsExifV1(data.cast(), debugLabel: 'album backfill'); case SyncEntityType.albumToAssetV1: return _syncStreamRepository.updateAlbumToAssetsV1(data.cast()); case SyncEntityType.albumToAssetBackfillV1: - return _syncStreamRepository.updateAlbumToAssetsV1( - data.cast(), - debugLabel: 'backfill', - ); + return _syncStreamRepository.updateAlbumToAssetsV1(data.cast(), debugLabel: 'backfill'); case SyncEntityType.albumToAssetDeleteV1: return _syncStreamRepository.deleteAlbumToAssetsV1(data.cast()); // No-op. SyncAckV1 entities are checkpoints in the sync stream @@ -218,28 +170,15 @@ class SyncStreamService { case SyncEntityType.stackDeleteV1: return _syncStreamRepository.deleteStacksV1(data.cast()); case SyncEntityType.partnerStackV1: - return _syncStreamRepository.updateStacksV1( - data.cast(), - debugLabel: 'partner', - ); + return _syncStreamRepository.updateStacksV1(data.cast(), debugLabel: 'partner'); case SyncEntityType.partnerStackBackfillV1: - return _syncStreamRepository.updateStacksV1( - data.cast(), - debugLabel: 'partner backfill', - ); + return _syncStreamRepository.updateStacksV1(data.cast(), debugLabel: 'partner backfill'); case SyncEntityType.partnerStackDeleteV1: - return _syncStreamRepository.deleteStacksV1( - data.cast(), - debugLabel: 'partner', - ); + return _syncStreamRepository.deleteStacksV1(data.cast(), debugLabel: 'partner'); case SyncEntityType.userMetadataV1: - return _syncStreamRepository.updateUserMetadatasV1( - data.cast(), - ); + return _syncStreamRepository.updateUserMetadatasV1(data.cast()); case SyncEntityType.userMetadataDeleteV1: - return _syncStreamRepository.deleteUserMetadatasV1( - data.cast(), - ); + return _syncStreamRepository.deleteUserMetadatasV1(data.cast()); case SyncEntityType.personV1: return _syncStreamRepository.updatePeopleV1(data.cast()); case SyncEntityType.personDeleteV1: diff --git a/mobile/lib/domain/services/timeline.service.dart b/mobile/lib/domain/services/timeline.service.dart index 7e982558b..7c22fb786 100644 --- a/mobile/lib/domain/services/timeline.service.dart +++ b/mobile/lib/domain/services/timeline.service.dart @@ -11,27 +11,19 @@ import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/infrastructure/repositories/timeline.repository.dart'; import 'package:immich_mobile/utils/async_mutex.dart'; -typedef TimelineAssetSource = Future> Function( - int index, - int count, -); +typedef TimelineAssetSource = Future> Function(int index, int count); typedef TimelineBucketSource = Stream> Function(); -typedef TimelineQuery = ({ - TimelineAssetSource assetSource, - TimelineBucketSource bucketSource, -}); +typedef TimelineQuery = ({TimelineAssetSource assetSource, TimelineBucketSource bucketSource}); class TimelineFactory { final DriftTimelineRepository _timelineRepository; final SettingsService _settingsService; - const TimelineFactory({ - required DriftTimelineRepository timelineRepository, - required SettingsService settingsService, - }) : _timelineRepository = timelineRepository, - _settingsService = settingsService; + const TimelineFactory({required DriftTimelineRepository timelineRepository, required SettingsService settingsService}) + : _timelineRepository = timelineRepository, + _settingsService = settingsService; GroupAssetsBy get groupBy { final group = GroupAssetsBy.values[_settingsService.get(Setting.groupAssetsBy)]; @@ -75,17 +67,11 @@ class TimelineService { int _totalAssets = 0; int get totalAssets => _totalAssets; - TimelineService(TimelineQuery query) - : this._( - assetSource: query.assetSource, - bucketSource: query.bucketSource, - ); + TimelineService(TimelineQuery query) : this._(assetSource: query.assetSource, bucketSource: query.bucketSource); - TimelineService._({ - required TimelineAssetSource assetSource, - required TimelineBucketSource bucketSource, - }) : _assetSource = assetSource, - _bucketSource = bucketSource { + TimelineService._({required TimelineAssetSource assetSource, required TimelineBucketSource bucketSource}) + : _assetSource = assetSource, + _bucketSource = bucketSource { _bucketSubscription = _bucketSource().listen((buckets) { _mutex.run(() async { final totalAssets = buckets.fold(0, (acc, bucket) => acc + bucket.assetCount); @@ -103,10 +89,7 @@ class TimelineService { count = kTimelineAssetLoadBatchSize; } else { offset = _bufferOffset; - count = math.min( - _buffer.length, - totalAssets - _bufferOffset, - ); + count = math.min(_buffer.length, totalAssets - _bufferOffset); } _buffer = await _assetSource(offset, count); _bufferOffset = offset; @@ -134,10 +117,7 @@ class TimelineService { // make sure to load a meaningful amount of data (and not only the requested slice) // otherwise, each call to [loadAssets] would result in DB call trashing performance // fills small requests to [kTimelineAssetLoadBatchSize], adds some legroom into the opposite scroll direction for large requests - final len = math.max( - kTimelineAssetLoadBatchSize, - count + kTimelineAssetLoadOppositeSize, - ); + final len = math.max(kTimelineAssetLoadBatchSize, count + kTimelineAssetLoadOppositeSize); // when scrolling forward, start shortly before the requested offset // when scrolling backward, end shortly after the requested offset to guard against the user scrolling // in the other direction a tiny bit resulting in another required load from the DB diff --git a/mobile/lib/domain/services/user.service.dart b/mobile/lib/domain/services/user.service.dart index 14fed9fb9..3e948fe0f 100644 --- a/mobile/lib/domain/services/user.service.dart +++ b/mobile/lib/domain/services/user.service.dart @@ -18,9 +18,9 @@ class UserService { required IsarUserRepository isarUserRepository, required UserApiRepository userApiRepository, required StoreService storeService, - }) : _isarUserRepository = isarUserRepository, - _userApiRepository = userApiRepository, - _storeService = storeService; + }) : _isarUserRepository = isarUserRepository, + _userApiRepository = userApiRepository, + _storeService = storeService; UserDto getMyUser() { return _storeService.get(StoreKey.currentUser); @@ -44,10 +44,7 @@ class UserService { Future createProfileImage(String name, Uint8List image) async { try { - final path = await _userApiRepository.createProfileImage( - name: name, - data: image, - ); + final path = await _userApiRepository.createProfileImage(name: name, data: image); final updatedUser = getMyUser().copyWith(profileImagePath: path); await _storeService.put(StoreKey.currentUser, updatedUser); await _isarUserRepository.update(updatedUser); diff --git a/mobile/lib/domain/utils/background_sync.dart b/mobile/lib/domain/utils/background_sync.dart index 1524c412f..1944591c9 100644 --- a/mobile/lib/domain/utils/background_sync.dart +++ b/mobile/lib/domain/utils/background_sync.dart @@ -66,23 +66,21 @@ class BackgroundSyncManager { // We use a ternary operator to avoid [_deviceAlbumSyncTask] from being // captured by the closure passed to [runInIsolateGentle]. _deviceAlbumSyncTask = full - ? runInIsolateGentle( - computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true), - ) - : runInIsolateGentle( - computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false), - ); + ? runInIsolateGentle(computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true)) + : runInIsolateGentle(computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false)); - return _deviceAlbumSyncTask!.whenComplete(() { - _deviceAlbumSyncTask = null; - onLocalSyncComplete?.call(); - }).catchError((error) { - onLocalSyncError?.call(error.toString()); - _deviceAlbumSyncTask = null; - }); + return _deviceAlbumSyncTask! + .whenComplete(() { + _deviceAlbumSyncTask = null; + onLocalSyncComplete?.call(); + }) + .catchError((error) { + onLocalSyncError?.call(error.toString()); + _deviceAlbumSyncTask = null; + }); } -// No need to cancel the task, as it can also be run when the user logs out + // No need to cancel the task, as it can also be run when the user logs out Future hashAssets() { if (_hashTask != null) { return _hashTask!.future; @@ -90,17 +88,17 @@ class BackgroundSyncManager { onHashingStart?.call(); - _hashTask = runInIsolateGentle( - computation: (ref) => ref.read(hashServiceProvider).hashAssets(), - ); + _hashTask = runInIsolateGentle(computation: (ref) => ref.read(hashServiceProvider).hashAssets()); - return _hashTask!.whenComplete(() { - onHashingComplete?.call(); - _hashTask = null; - }).catchError((error) { - onHashingError?.call(error.toString()); - _hashTask = null; - }); + return _hashTask! + .whenComplete(() { + onHashingComplete?.call(); + _hashTask = null; + }) + .catchError((error) { + onHashingError?.call(error.toString()); + _hashTask = null; + }); } Future syncRemote() { @@ -110,16 +108,16 @@ class BackgroundSyncManager { onRemoteSyncStart?.call(); - _syncTask = runInIsolateGentle( - computation: (ref) => ref.read(syncStreamServiceProvider).sync(), - ); - return _syncTask!.whenComplete(() { - onRemoteSyncComplete?.call(); - _syncTask = null; - }).catchError((error) { - onRemoteSyncError?.call(error.toString()); - _syncTask = null; - }); + _syncTask = runInIsolateGentle(computation: (ref) => ref.read(syncStreamServiceProvider).sync()); + return _syncTask! + .whenComplete(() { + onRemoteSyncComplete?.call(); + _syncTask = null; + }) + .catchError((error) { + onRemoteSyncError?.call(error.toString()); + _syncTask = null; + }); } Future syncWebsocketBatch(List batchData) { @@ -133,9 +131,6 @@ class BackgroundSyncManager { } } -Cancelable _handleWsAssetUploadReadyV1Batch( - List batchData, -) => - runInIsolateGentle( - computation: (ref) => ref.read(syncStreamServiceProvider).handleWsAssetUploadReadyV1Batch(batchData), - ); +Cancelable _handleWsAssetUploadReadyV1Batch(List batchData) => runInIsolateGentle( + computation: (ref) => ref.read(syncStreamServiceProvider).handleWsAssetUploadReadyV1Batch(batchData), +); diff --git a/mobile/lib/domain/utils/event_stream.dart b/mobile/lib/domain/utils/event_stream.dart index 008ddef18..5967fdca5 100644 --- a/mobile/lib/domain/utils/event_stream.dart +++ b/mobile/lib/domain/utils/event_stream.dart @@ -28,12 +28,7 @@ class EventStream { void Function()? onDone, bool? cancelOnError, }) { - return where().listen( - onData, - onError: onError, - onDone: onDone, - cancelOnError: cancelOnError, - ); + return where().listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError); } /// Closes the stream controller diff --git a/mobile/lib/entities/album.entity.dart b/mobile/lib/entities/album.entity.dart index a7cb612d6..2ca0d50dc 100644 --- a/mobile/lib/entities/album.entity.dart +++ b/mobile/lib/entities/album.entity.dart @@ -113,10 +113,7 @@ class Album { modifiedAt.isAtSameMomentAs(other.modifiedAt) && isAtSameMomentAs(startDate, other.startDate) && isAtSameMomentAs(endDate, other.endDate) && - isAtSameMomentAs( - lastModifiedAssetTimestamp, - other.lastModifiedAssetTimestamp, - ) && + isAtSameMomentAs(lastModifiedAssetTimestamp, other.lastModifiedAssetTimestamp) && shared == other.shared && activityEnabled == other.activityEnabled && owner.value == other.owner.value && @@ -169,9 +166,7 @@ class Album { a.thumbnail.value = await db.assets.where().remoteIdEqualTo(dto.albumThumbnailAssetId).findFirst(); } if (dto.albumUsers.isNotEmpty) { - final users = await db.users.getAllById( - dto.albumUsers.map((e) => e.user.id).toList(growable: false), - ); + final users = await db.users.getAllById(dto.albumUsers.map((e) => e.user.id).toList(growable: false)); a.sharedUsers.addAll(users.cast()); } if (dto.assets.isNotEmpty) { diff --git a/mobile/lib/entities/album.entity.g.dart b/mobile/lib/entities/album.entity.g.dart index 546101baca6add4070c3d97cbcc55cd3064ac788..e6ecde7f9a53f99942ce29a103ec9d24a2ef5219 100644 GIT binary patch delta 5721 zcma)AeQ*Dh$K{%r=2CX1yg(caefppVul7j+% z+;K-mkLkx#EoVI`-f&e>DC~@m%;+$Fj9(0TH|Kbxo>y*UxI6!#&MWJ_EPbo z0r8GM#_&DjRZA?+hq;}Q$RBM&l-o24q8j4;1;3H-w`=%VAH%Z*4?CjKh)`WvWP<6u zyxd2n01aCweB z65Ye{?UZChmvH={R+z0T75+fIn;i*^!mYCR|0dMN#jQj*jC>F zTt|V>(kNzd&f|a?Kxt8S{nUep@SmF z3}=@(VRW&>O8uOPB*g81h)YBwy$YllHXpiIS&A8c(d>byrUoeUIiSs34|g|LD7Zpc zxx`|>Un-bY6wmfY<1AW)=$`(~$+jW#%aa}S(vu!)PH;XkdV z#Ow4?q14D$(J)~fg4N9q10EMlGRC{y+X~X(xaq=(pj7;R5`=1 zEOQvx)F+ruX7|D^&h+e}$7UG%iIbdK;$tnZMB{m$o1pfR15Vz0*ouTfE)pf=2aBXe zLwW$0hMn-{a(9VZMJT<{+}H{817#3sE2>*Jm|!A3QMp_1Wa4a3xS!2v&Ud@R$lP(v z^Y?9yu(Q1u-dJvhk#;+LvBoJjK!@rW4#uC+(Bt2~%wG(D>ez-ESk~!==`L+O2=PJZjub>Se0r!L4fW2-qZsPaa6L@^bdeO> zC+0G+t*ewJLvu{8ejOvINy$R`@D4#EskzC*39h}OaikO>fV zFUl6)-`3;#m>X%xLMU7t<>E}3i$P#y6mzv|EDO_VmHV3-5RVs@=U{BzV;KL~xV#hJ z{?ZKwJ7K?PJ4Qf_G2K;dRvUw+lhui;!PynWz~8sk8i6f=0;ucO6_+u-vxu4FRM zVs~wPRzs`hi29lYK6l>*4V-LMggg;;Woy*~J-aZnxJR{kOkp$@DF;MKI71IiU^KPK z&fYaCST!kz_?j*@7VGI_xW(!zuu3@wsQq9% zV~3|bewg2A(`>5gGc*Y+x9e*`#b&LA8gXEFSn~x)vPTE)N?p34B-oqsRF-QE;e;Q8 zxHQSRqR3M1gv~5Tre`9Cg!!KlBsv5BV4q%|5!j%X(&gC+M|SC@IfJ*WyYbkOEN1|B z_gi7p$WvH4ks4@|JS7 zY?Z1dN+jHfImyGz!q|%`?l48Bjw@xnK(x@WbfZOf zT416U`hKmKLuRZ}lEc8nLfCSMB!?=(H+%-$0#r!oY_vXEK`JKSa5cR2BuNglkk&p$ zki;yUzdWs%MV0X5iVM(czdfRtM%4&<>ClaXzF`;mNASi%@|ckz=3|s3ky%Iu<3BuVkN&mrHxr4oqM(t z{(aP7`UJ})>Ag^*6~f3QX&4!Pp%h$`aurJNh6?(hM+pO`5xDa?{g9y|4N6Fr*!ig; zENy7O7r|<&cdf6sydFgr%Y(43=V9%3-aw#HlF{22$l{aSv;MT6(mF4CH2PZtZ4g3x%~Ko{{yakPBs7l delta 4615 zcma)ASx{3~7@o_P5E29=VNGY*zr#zpjV{_I_N#T8kv`-A=!_W>Y@usy9s^6Idu$6B2{l= zQdGVt$P(hNV*@WLgz9` zp-wfk-*DF-4jV#=R2Yi=Di)DVl%v^HKxSdSsfA{LnA0>s#icAjOIZcvTASTjVQ-=B z8HkE$X6YKvGag zciEiuO4u7;2i2x%QAsSXgk!XLC@NSGrYI&KMi$i|6H=fv#R#i&wXi-r9M)$fKtqlS z_AHD=CR7;b$ryF%F$kTH42(kPcuvtYsOMg9=~s-UkZxANiwrStCOz+tEM^c!7P8zY znS9vdJwwKEBE!U>S!~UeMIJL#G_Sx7is9mQkmWXK$<`jqQe#Wuijhx(AWs@R9W2g{ zhKgJ@8^F$NQZax$3!~lvR6@l7@~D!AE5;}oyBP&{7Z3WOQ)52T1h?{{VaK*$XfM{n zUwPpW7NCMW%78LPZ7hbyB?c6sV#-O^w0F@Y8x5e!*2}i(@h7@Or`WMzkIS+ecN9S&v;N1vCV*Up^%93Ry)NU_)u5gmIzpGl@@1 zjIJU^;*k<#e#t}5CnIVS1|Qx;duXnC^<#JniO6ClnRiMLfw|l01Fc&X8pRj6JAr%` z?1!ns7`RZf0nEF6>`pGDoXu^tLtfitH|2EFcB{7_(t*=ugl0#a%!N*AXd}2oWis&s z+{K1-w62_DV~m9OqLo#=CZsnK;_Je=6qQwIpt!QZBgI+?BfTmTm;F!mtrBxEAp&JP zQV^qpqUytvOe--iu00^hv=Sq(_FJKPu?FAScGvC-cv06Tv+I*hI>D|LFtu)2W|JJP z*sxn>kAO1N#sESv1TRl-$km1wI7ac!b71#o987$U-fGH2(UCx(ZfTOmd9W!{PWZmw zCipVgWaj*kNJwZDL##vyz&9uiPkvl&;d z(LFYIOHf8tTW8i1ly~p2>tck4GHoZ|_lw;C+xEAkQBoRgNR^H{rapBxvo+5NQljBo zs^fJH{L!QP|C{Q0pI$go?6%=P`8DN9I3`pdz8^hN4NSgqLpWO)^_@F>$O{Kb;d=i; z(fe(2l48PW?)J;VAs_TYCwE*F?2(~N;Xpc9L}-(5BlrTss!s3Z3dl=M{5xFncp-b< z4c5EIo9S*6nQ7SRc>WgQ_D)|kNUK;d*wViDB?YrBPN@nojUMERMVUejRlxA(&62Bw z+=nM;V(6@_mElD5$QnpZ)x(X#2za({tB^J~W40u9#Lya;_(<#n%8c&aVjoaukbC** z0NXHo2ARZ~R|7vCxOa)I0Ha^;Rc_xOc;7?~gdqy}xO0=nw5=cBE-av>N?0z1ik%OC5r$)+P;fM}D zclhU~kNGz9Xe8G)rbZqJ#}liUB4u#lsC*_6Q0CUL81W9q%f62&?i0xT;p456N_}`L zf?p1S7stJ490@@U&qsAiW6r}{U~pQun1Qj)elY)% z0bJuNnWf_<0-Da~;my+(aN~?sOOowYCuyOrth3A=l*^uVyMQ ze;$xaqCZ6_hl6(F{|{y?e_$*buG|b@KAgA{gv@2At3wg^`}f;Rv}*22$e*B<@N81Y m9J%+1@IshplP2#~%!l2-TD|D3px)nduu43vG1nf`f&T#vE>Wid diff --git a/mobile/lib/entities/android_device_asset.entity.g.dart b/mobile/lib/entities/android_device_asset.entity.g.dart index eaa7658565f1cb2193ce3b35cd2eb37b6eb4a70e..9034709b8e1cea850f11fb5b323035525b5e6dbd 100644 GIT binary patch delta 1281 zcma)5O=uHA6eclLlh!1gq)9eun#qrwMz?9IC>Z={DXl~*c&H~EWX-PKDeERpHkK$N zf=9u_6K{pKAR-l$0yxy+m0?|pCH_rCd!zshSl z$8jtcP@YGsa9t{(T1FP?a)w7*vr3M|x=@=TQSNF}lcsT9%knOSZu2hvrsJE9p$EE3 ztsu+8V$WfHx#znBe4G!)4mja??}-d$nW!j=RMv1sJta0tEnGf>$`yqs7Da?b5&*;b zX^x)m^Vy-`ZU&UfqEsu;zo=2IwnF&iF6rZ*cXmDO%h>b@f5Ha8_z>I)JcWy1CoKEi z@XXD?WPb#HA`b47eJ<>Uu|!}WLRnZyUV^;e1A{@;z~2wDz=ZuCbVE=Yq~*(0fYM*w zScvj^;Q^b07i=0HMWS#%9EZ1&lpP_+GpEg8n=Jk8ge|lm2HAcBa{-EYC~SpcVa;3I z3)ITkRcwXfAaX1XN1{()GpdcZo0ho-(;72Uj7E^}mU|=ulBYbk( z^!M>MmLji)6RiTnVPkqDxp3F?WO$iSQl?K8NuASV;@4V3;*s?PpWPQ=Bjtw=$ywIK z6Q{SJ?Z8BRNnMFsQP%{eP8d%btCiHjB5ILoqwus;ug}PWIz$ERRPQJ_1-Vpj!b(*|Jjt$n0ZEl8xE+$5aKQR2bKu9#Ag;v_6c4O->3leW8 z#(0o#xS7Ze6EDX80V+354Dn!M;z2ojSwc)a8TGxg*%op54sGB2zVGMz{e0f1@2m7v zex7ZEdb_h-77A<*?zH#Ev|33lu;UfJJcGWn3pGugkSkicn?)muo@;4+v8_&cjRlsy z)`-ADM@oO#@vV(ufgpV_?Q}xQ)dNpmN!W2kI@oc6l?8Y`OyZDEy89dsmW8-y6+Q>L zhLqxMv0Okq_Tg}`YN=#jO2Tqv5`Ix$l&E{WA25Kv+nXftyVDoLZ%C5caNk2=Q1JVM z@G0Sj$9-M!AmfEuH0MGdc(#=!TtOoLb?PD$?Pq#8;#SMMU4y z0JsCsV3XnCEi(vphKA$8ewYeI5h!siVu^Hum+_;B6EaK~&d>q0V~HL+Vuu~Wihj2@ z08{xmY=pKj-$HnWz91`_SRN~?f~?6!H7hPxd1a=^b;FZ^78pSXE5uydvHb zRqbL~O^&k0b zBZG(MpJm?xn~560b5Y86WE)XxopZyh47JYz*E>0=!iz*GFRDwLWco!bS4DHC91?}S zu!I2;v3Uf*a5;0kJ^4VOnfD{cvb>9e)`L2L2pP%Nn841A;Y>OfLW8h7{H7!}pB8ugobe z+&Ggd6B iHAz&@)y4%59`#=WF7Ja{?h2OVeeSezF}Y66JAMQ7rjKX< diff --git a/mobile/lib/entities/asset.entity.dart b/mobile/lib/entities/asset.entity.dart index f5c577a06..0d549457a 100644 --- a/mobile/lib/entities/asset.entity.dart +++ b/mobile/lib/entities/asset.entity.dart @@ -19,30 +19,30 @@ part 'asset.entity.g.dart'; @Collection(inheritance: false) class Asset { Asset.remote(AssetResponseDto remote) - : remoteId = remote.id, - checksum = remote.checksum, - fileCreatedAt = remote.fileCreatedAt, - fileModifiedAt = remote.fileModifiedAt, - updatedAt = remote.updatedAt, - durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0, - type = remote.type.toAssetType(), - fileName = remote.originalFileName, - height = remote.exifInfo?.exifImageHeight?.toInt(), - width = remote.exifInfo?.exifImageWidth?.toInt(), - livePhotoVideoId = remote.livePhotoVideoId, - ownerId = fastHash(remote.ownerId), - exifInfo = remote.exifInfo == null ? null : ExifDtoConverter.fromDto(remote.exifInfo!), - isFavorite = remote.isFavorite, - isArchived = remote.isArchived, - isTrashed = remote.isTrashed, - isOffline = remote.isOffline, - // workaround to nullify stackPrimaryAssetId for the parent asset until we refactor the mobile app - // stack handling to properly handle it - stackPrimaryAssetId = remote.stack?.primaryAssetId == remote.id ? null : remote.stack?.primaryAssetId, - stackCount = remote.stack?.assetCount ?? 0, - stackId = remote.stack?.id, - thumbhash = remote.thumbhash, - visibility = getVisibility(remote.visibility); + : remoteId = remote.id, + checksum = remote.checksum, + fileCreatedAt = remote.fileCreatedAt, + fileModifiedAt = remote.fileModifiedAt, + updatedAt = remote.updatedAt, + durationInSeconds = remote.duration.toDuration()?.inSeconds ?? 0, + type = remote.type.toAssetType(), + fileName = remote.originalFileName, + height = remote.exifInfo?.exifImageHeight?.toInt(), + width = remote.exifInfo?.exifImageWidth?.toInt(), + livePhotoVideoId = remote.livePhotoVideoId, + ownerId = fastHash(remote.ownerId), + exifInfo = remote.exifInfo == null ? null : ExifDtoConverter.fromDto(remote.exifInfo!), + isFavorite = remote.isFavorite, + isArchived = remote.isArchived, + isTrashed = remote.isTrashed, + isOffline = remote.isOffline, + // workaround to nullify stackPrimaryAssetId for the parent asset until we refactor the mobile app + // stack handling to properly handle it + stackPrimaryAssetId = remote.stack?.primaryAssetId == remote.id ? null : remote.stack?.primaryAssetId, + stackCount = remote.stack?.assetCount ?? 0, + stackId = remote.stack?.id, + thumbhash = remote.thumbhash, + visibility = getVisibility(remote.visibility); Asset({ this.id = Isar.autoIncrement, @@ -127,11 +127,7 @@ class Asset { @Index(unique: false, replace: false, type: IndexType.hash) String? localId; - @Index( - unique: true, - replace: false, - composite: [CompositeIndex("checksum", type: IndexType.hash)], - ) + @Index(unique: true, replace: false, composite: [CompositeIndex("checksum", type: IndexType.hash)]) int ownerId; DateTime fileCreatedAt; @@ -447,33 +443,32 @@ class Asset { int? stackCount, String? thumbhash, AssetVisibilityEnum? visibility, - }) => - Asset( - id: id ?? this.id, - checksum: checksum ?? this.checksum, - remoteId: remoteId ?? this.remoteId, - localId: localId ?? this.localId, - ownerId: ownerId ?? this.ownerId, - fileCreatedAt: fileCreatedAt ?? this.fileCreatedAt, - fileModifiedAt: fileModifiedAt ?? this.fileModifiedAt, - updatedAt: updatedAt ?? this.updatedAt, - durationInSeconds: durationInSeconds ?? this.durationInSeconds, - type: type ?? this.type, - width: width ?? this.width, - height: height ?? this.height, - fileName: fileName ?? this.fileName, - livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId, - isFavorite: isFavorite ?? this.isFavorite, - isArchived: isArchived ?? this.isArchived, - isTrashed: isTrashed ?? this.isTrashed, - isOffline: isOffline ?? this.isOffline, - exifInfo: exifInfo ?? this.exifInfo, - stackId: stackId ?? this.stackId, - stackPrimaryAssetId: stackPrimaryAssetId ?? this.stackPrimaryAssetId, - stackCount: stackCount ?? this.stackCount, - thumbhash: thumbhash ?? this.thumbhash, - visibility: visibility ?? this.visibility, - ); + }) => Asset( + id: id ?? this.id, + checksum: checksum ?? this.checksum, + remoteId: remoteId ?? this.remoteId, + localId: localId ?? this.localId, + ownerId: ownerId ?? this.ownerId, + fileCreatedAt: fileCreatedAt ?? this.fileCreatedAt, + fileModifiedAt: fileModifiedAt ?? this.fileModifiedAt, + updatedAt: updatedAt ?? this.updatedAt, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + type: type ?? this.type, + width: width ?? this.width, + height: height ?? this.height, + fileName: fileName ?? this.fileName, + livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId, + isFavorite: isFavorite ?? this.isFavorite, + isArchived: isArchived ?? this.isArchived, + isTrashed: isTrashed ?? this.isTrashed, + isOffline: isOffline ?? this.isOffline, + exifInfo: exifInfo ?? this.exifInfo, + stackId: stackId ?? this.stackId, + stackPrimaryAssetId: stackPrimaryAssetId ?? this.stackPrimaryAssetId, + stackCount: stackCount ?? this.stackCount, + thumbhash: thumbhash ?? this.thumbhash, + visibility: visibility ?? this.visibility, + ); Future put(Isar db) async { await db.assets.put(this); @@ -494,10 +489,7 @@ class Asset { return compareByChecksum(a, b); } - static int compareByOwnerChecksumCreatedModified( - Asset a, - Asset b, - ) { + static int compareByOwnerChecksumCreatedModified(Asset a, Asset b) { final int ownerIdOrder = a.ownerId.compareTo(b.ownerId); if (ownerIdOrder != 0) return ownerIdOrder; final int checksumOrder = compareByChecksum(a, b); @@ -539,11 +531,11 @@ class Asset { } static getVisibility(AssetVisibility visibility) => switch (visibility) { - AssetVisibility.archive => AssetVisibilityEnum.archive, - AssetVisibility.hidden => AssetVisibilityEnum.hidden, - AssetVisibility.locked => AssetVisibilityEnum.locked, - AssetVisibility.timeline || _ => AssetVisibilityEnum.timeline, - }; + AssetVisibility.archive => AssetVisibilityEnum.archive, + AssetVisibility.hidden => AssetVisibilityEnum.hidden, + AssetVisibility.locked => AssetVisibilityEnum.locked, + AssetVisibility.timeline || _ => AssetVisibilityEnum.timeline, + }; } enum AssetType { @@ -556,21 +548,17 @@ enum AssetType { extension AssetTypeEnumHelper on AssetTypeEnum { AssetType toAssetType() => switch (this) { - AssetTypeEnum.IMAGE => AssetType.image, - AssetTypeEnum.VIDEO => AssetType.video, - AssetTypeEnum.AUDIO => AssetType.audio, - AssetTypeEnum.OTHER => AssetType.other, - _ => throw Exception(), - }; + AssetTypeEnum.IMAGE => AssetType.image, + AssetTypeEnum.VIDEO => AssetType.video, + AssetTypeEnum.AUDIO => AssetType.audio, + AssetTypeEnum.OTHER => AssetType.other, + _ => throw Exception(), + }; } /// Describes where the information of this asset came from: /// only from the local device, only from the remote server or merged from both -enum AssetState { - local, - remote, - merged, -} +enum AssetState { local, remote, merged } extension AssetsHelper on IsarCollection { Future deleteAllByRemoteId(Iterable ids) => ids.isEmpty ? Future.value(0) : remote(ids).deleteAll(); @@ -579,13 +567,9 @@ extension AssetsHelper on IsarCollection { Future> getAllByLocalId(Iterable ids) => ids.isEmpty ? Future.value([]) : local(ids).findAll(); Future getByRemoteId(String id) => where().remoteIdEqualTo(id).findFirst(); - QueryBuilder remote( - Iterable ids, - ) => + QueryBuilder remote(Iterable ids) => where().anyOf(ids, (q, String e) => q.remoteIdEqualTo(e)); - QueryBuilder local( - Iterable ids, - ) { + QueryBuilder local(Iterable ids) { return where().anyOf(ids, (q, String e) => q.localIdEqualTo(e)); } } diff --git a/mobile/lib/entities/asset.entity.g.dart b/mobile/lib/entities/asset.entity.g.dart index b558690813e3f240ffe04e66d39797ddc15c17a8..be5b427d017464cae1b15836c89fd5055872d2a6 100644 GIT binary patch literal 102334 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%0Ap25UyTKb0WTGNe~bYR4nK|uktR|7(qe}-Uwy~ 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 b5M0V^fNvJ$ObhZ*=S7pmfNyGRvJd|cCG{)z delta 7694 zcmbVRc~q3w6+e%Cm>GsaVAzBY!m6l1BrdfT6r!jg=%iwlWt0&{V1{LofO;(Pw5e8W z;D+;Iw816mN!q3^qi{?$RTGn1gGKZ3B>LN5YyOTv-`F=%S zn6C5AOb>*ehFECV8GzD;`8rzd)+V4dls-#r2u^$u%5b`U#z2(jTQV1A!#+(Ioc=<~ z&vxYp?jUBhrYvk%>PD-r%2`9aFu1))!<6;ut`PnE2p$_uuCIfFkn6GG7&35k%UC06 zaK<>!^}P}F&>8m?U7Uzau1@M>U$`7+KxxpC{1$CaL}LOcI&JmVI-A{^2G6A&nTCy| zIGi=srj+Sa2CpLtITL z(O_N_>g^Xu?Fgr7U_W!~5WLxUNoFC1F`niFSdT0R_P$!Cp9?Iuw;IlrB=g7|i=iG8G z@@~39fjRJ}0=-d)ew|~brA`ri_xwm+1db=sV2P?7ak!I2VGe-*%#Tonnq_=e7%^;! zhhqt$^|TrZ>x3o#(6KN=Pf@r{QA{_K?K-VE6&4pqaCu7j$BLsBeDUt|aNHa(+2K%$ za)&&N8g_@nv4kD+EIxGuKvQAaYRC2QVj9q>P+hmK9jU&aB*ieZ-9IcF2WD37`1B3DfIaCrZD@N9q z8cP{Rl@(oD%XCB!A`}7d_G#e323=Pz4o!DBv~5hpOXarb!LHf>NLqQAM&2k1j##5S zv#wMf1av=Pc+#d-|AgJYi|4G6rX0>h_(63z7h(D02Wwsh<0pxp*PXPw2aI5X0M?M%dAy*RplZYz8dNr4ow}rN(`v@|88+~8 zUxPu{9_seB1YU3L5&I{HW81n#zKKv*ZhJK19Akz(IhMJuVnnBsIEOOVErQ=9+LZ8HKNreOiI%>^))z+9mgkF$ ztkbcHEiAc_LKxaiGZiIA7C`HkpwX3+a_Zn#eWbe*hbm%j^pwMUx;sVbDMx+ilkU>NX4Rx&OD7L5_pFw>vGzB5ca`M9z;>A%Qh59hsT)#s zO zuJ937iQ27|tg>PE2s3oHW^atU*usXMGbAwbVCbknBpu?L!ihfqhC{}$zvl~Wa|r> zC<)c=lcJuEmykZ=Vc&3WNew!m~dVZaH%FL#Ej9 zs9NO78l3|Rz&Udvmnr0Ui62Pf#v9H^jurv1ek97Av;onH@9G@zLV~jrj9E+EC6p-N z9WbKiFy9%7)AoyOS5O+c{Rx{U3gk(;fXv9HrK3Fb$vmOziNnkOCQ1+t^9e$*hBLm9 z>?&siC&G+Zi=g<^VXnxUM@Cq9EtpFfaGOmeb@b+)QT7}4>E&OKw%_pcg>)jZy7G-Eoj3}g zQUpIc$n_f;=005LpLyXAgDVj%0n?b-IDXQp` z^b1u(Px8@C3<-)$WHHg35E5MjlhfOH^*R@JWI);eEQW;6pSBi zbDNv3PIFs>+5-fcq^BR6P!M|-5S#h*-Y~S&eIlq+bSAW&zqhM191-XoDLw&JQ;55; z(3R0hLobO!BRrVUN5(RlB$~Ec@KgzE=ucyi`;kIrwuYV)i=}YM-2v;ZrjZZ<6^HqwwgexRj2v6j$1?*%~8j^l#D;Vp?A<4(Kf^cm- za)0(Spr?)G7NX?-t_kSloB-~BJN)ZpLH~I>+T*1drtz@8|8^rf=dF&>)#WGz76$l3 zS}jFyX-Bi@V{1@=I=TNRttbL{z|OsZVm)B=s&=$aeHuJHM8SmG7-s1Zb4^SAiW>Y? Yo+{rTyOG*;C@};-ruT3CHOfT)18;ukp#T5? diff --git a/mobile/lib/entities/backup_album.entity.dart b/mobile/lib/entities/backup_album.entity.dart index 1e96c0452..ad2a5d671 100644 --- a/mobile/lib/entities/backup_album.entity.dart +++ b/mobile/lib/entities/backup_album.entity.dart @@ -14,21 +14,9 @@ class BackupAlbum { Id get isarId => fastHash(id); - BackupAlbum copyWith({ - String? id, - DateTime? lastBackup, - BackupSelection? selection, - }) { - return BackupAlbum( - id ?? this.id, - lastBackup ?? this.lastBackup, - selection ?? this.selection, - ); + BackupAlbum copyWith({String? id, DateTime? lastBackup, BackupSelection? selection}) { + return BackupAlbum(id ?? this.id, lastBackup ?? this.lastBackup, selection ?? this.selection); } } -enum BackupSelection { - none, - select, - exclude; -} +enum BackupSelection { none, select, exclude } diff --git a/mobile/lib/entities/backup_album.entity.g.dart b/mobile/lib/entities/backup_album.entity.g.dart index 23d00e43cadbe92b17f1cfbf8572d25bb3af7f5e..ed9850311941b20cfab4ebd165f1e80ed25b9249 100644 GIT binary patch delta 1674 zcmb7DPfXKL98Pg_vOiFu+X~y*V~ll+C2k{tAx09!z@iBzKr|snDl0e{-RO!$iDV=m zG{zA2^I*IHH}y1a)Po0OOt_JF^5nrp4<;s};bOSx>&n*hXA1Au_rBlvzVCZqzb_H* z9uoPjBXx;*7YegT;HLO4Br=IO!vZompy3Ly5f^kDWebj9PxzZ8AdplQZ zd_2QT3Rb^Dmr-|jVGr(Gyk_lGerDMuVArW$I%F;h`$1F zFW6~$z}ZbGZq=2GHbGy53)W~FI(-2Z)DLNQ9SqmM)NnA}+5)p}?sDLbh8H^Us>@d% z{96Z{>`-*KGqE}UVk|mzr2rhzx_-PE_Ha#N7^*{TL5F(FK#G$%>CC;&;%>t_3#RX^Eg&+a%W|ELDcMd^mLn8GEI zZWgPKZg9yNTzrPX@1#CKZOfQ8gP*|t|Djs=95R9{V6);{6&SZWdr4!$x1$}m7rM=` zMFq+jWbH9r1ClU9grO`YGBgJ@E(+e%#o%Xz)HrnosfOzzvd}2ihbk!-T-2ephU|xa zuS2R8QBk{UqE$qZ`Q-R5Z46t4d@F4&V`-hGYkE0}A4*K|+bJEuSQQMgcAYVj!T(W` z%Sb)k*yK$5JfF!7UE_q{L7BA>_Ap~Vt0z8cen5>u#r-peY$U6VDKRufo%_ZR#^N)4 zk{^>2DWOl~aU5bnzUpSMcyyS2mfI+OKCSvIO7R?$U!T%0ew@OHUI~6wY8lD1}z~pe=*F3`5(gB|wP{RwIfJoWy`ZV&Xz@Xh$6#+R}$ciH4OM z6O0_=MoCEAs4LBAlwdT3Na7zbBrc3`V{}1?2@4a&duOH(DP?vu-#Opo+;eB~KK1h+ z_5Ama-A1H7QY?ZxgZfKc7#AZb<&$C%H#kk{OiGGh)Ig=xV5TZ@-OV8Et6WvMs-{Y_ z-lj1j1hX}C6?YEx_8Q?%tw(uT`-|F-5T6!OM-s9uMl(_(ejs)o%Sh3KD4LLih>syD z7DRnQ^h!2)SRTucqr}){T*{$Ipv;U?UH_D-#U!{6^YAhF8ae@Hn+aY!JneGgnwW~{ zNG=6J*<`ZxGY1o$z3|Ltg(nuvCdMA+k7cf+p-4t2gAV^FR(o3>YE{nL2PonORva{} zJ6NC_Y2bqltkt(G(8y3Q<#SR-n0B{74d;N5Zk8fu24Tka1}3~TB-}N?(QbI)c5SNY zZ+Zo*9ZVT?o&F9l_Oz&dD-P34k5ScULk_IZ772Mgv+%*gZXxgpJ%mFo%od29+0}^9 zX>|wCRYA^*xdBhYB67i+>nzMOTXjyiT3q?gq>#yosd#B`H>(++V4I4Zn%bg;aW$y2 z5#;mb+O@e=crWDVhG$l;Y{P3akRyf9p%I;QAkc;PZo#7xbMV3tu%95b6kj`k=?4+1Z7m}8x%kABN zRK&?*=O;A`0k#V>ADYs`1j7D;8@w9`rA7UJP&|293)|sucQr(u#Xk{7ub3fYJ==)qUL4XR6kJak-V}0UfVXMvjddi1Gq|`yVRNqecJ# diff --git a/mobile/lib/entities/duplicated_asset.entity.g.dart b/mobile/lib/entities/duplicated_asset.entity.g.dart index 8965d47c97e330f6f7451c4784aa39d15eec3426..6cf08ad9ccebe21bbdb83898a44e7778cb18c328 100644 GIT binary patch delta 1033 zcma)5O=#0#7$#wbE~_qWq={|Xy-n+qVjT4(^e_?pq3A(bL5AQKNm#>bTGO;L=MQ*R z1mBBO@U9-51o7ZOgyG492f?d53{RrBorZpC;`%w)VJ^wX_dL)0yzl$uv-#3m6-JKQ zW)&(rIL1}03a)CKst(>#n;dE#!>yCAsgCE`&O%w|0B-3VUK;u3&&J-dn2YE9>G&9n zXE`}RE^8*(W`KIgrDHl*hGo26DfrL0_Y69TMf|~w_*96?&DM3xt%6PTYo-p}c6)F{ zBQ@vW*|)*^4gLt@uOw9l*HRxNZW4RietawN3?L-a_*EFk??N6wXeAbaaHXIkUOw<- z)HY9D>l)2^3t#8&juKPhgImP{ZsxMs6D2&IoeXK`aZVM`PQRgm>&hYAkmMm?(KgRn zold=BIND5qKF~9oT?=0&MMlS;*$f_sSxWBtq_T$``Uk&J;K!NBq$W|Fu4+=yDW1$~ zlC+iopH`$CNnY delta 1088 zcmaKrO=uHA6vs*0YE2ruX48#{`Iy9*WHBt!gF?Ji+gev^L>nkY3T~Zgv#{BuyBn(( z!F#11-cb*F5xl6dB6#dULg-4JLDKGJcV^%Fzu%kppO@qde#H)7 z@FDw=aS0U*?n0Gnq=dAbjB`6%#+?S;5_L(d&@VwZG+AABe)2TyUIC_u|BWKFN(>Q~ z;Kl*YTpoGi&Dx3@kucE&>ospD=IbjfIx+O?#Ux8Izmm49azD~3fk}0Q%ci0hXHX8lg zJUkUP1+=p1-GeQ~*O8y_Eb5eem*?8RLp(=;Grb6mgFSCZnxQYq zMzx3hek?N>>Y&@Liu;rP#?yn7EV!?UEl`qs1YAT9Bj;tsAlg)2#j+vSRiP#sH>*U? z`(T^)g;Ga)d+<9jqCQh=z}b_Rx(_{gOH!KD%el6<+o$jLAnN71(Vb~cgN|#DOskQP zM;q>718_XY(BXzUgN@rnwk>DrJ)q50s*-D55rfQSVLH0lHTMA;(T;{S`+))-FANZ{ qC^v&~_?&z0`oRh6_k?X?^EQ8XgyxvPg-Opo=Z?Xz1U4TRS?_-;hf59s diff --git a/mobile/lib/entities/etag.entity.g.dart b/mobile/lib/entities/etag.entity.g.dart index afabca4aeaa4eff46ca26e66a7f368588daba6a8..b1abba6bb7fac4c7e0def9502120f2adc5bac7d2 100644 GIT binary patch delta 1830 zcma)6O-vI(6i%_JP_VT8lAFP4Z}`uj{jodXg{&pLE$cr4W9kanYfwN`TdogBZ!mEeVzIe5 z(nEOaxRrxoyCtAvzE2{UwE8A8}*1O|22czBOD5@O~qO*3)kY&e)qFivJR84OQE zZ7hEx3M{@XVsD*8# z6+`6k+gQy*lnol_HTE4+DGDuAD=<UTm`GA?-8hcs}!PkdN&DF zwl_>rq%Vlpz3Y*}s;lr(3(sCfrXY;*T#b0jf}5;u#*O|BpYD$mk>LUvkEjma2Q(H#2YEH*aa#TSnqac$iF(H-799ayE)JR0EuG}&qk-!Y&CehY7JHz02xlSDl#F=sK zB}ZuEGz*UOs`Qye$;&VD2^b=Wsb(t@Ob%VY=JbRsqx(OQ#M17(B{)8mv=JqeQ zA!T-fRjJaf`a@a0FH|I(M_sQPsTLocbTd9R-2NYBMQep|Kn{g&3`y!WevmrOlGOcMZB5r)Xa!#N0SP%|sb*IFN`j9n7^vAUr;6tHQd`tWE~P2`-=u zY>1zmkUhPr=@H&H*|4oA(CaDm>Kmaq$nlPrBdAw#PLmpgh*61Jql#lRW5n3Np;ryw zf1rihQoElcyEtv8DiYx^cifaq4UaYBnlg{#o9Qx#5lP{?Uq%QUiF>fya|s)RIsw+e z=T!63@6C%?v$x=mgT|6e!EGu={Vgf{=rjKXUAMl%&mohbOLl1a3()f6n>vTFWP2dE zn>c4Jwj37DJ%g3mUx?hPB6RuCbCG*7I@11?cc)P3Y!Mu`QR%dB=PTB3Iv*n8GM7L+ zT?aI0<54zpg=FiH@Af>7+bOQ3ethXFp)-yJ;=ySqX5+PUfq0yWM)s>myEA!FxZB+* zoN^fS;mN&>>iHhFw&vx0SUtgPSe(2x#fzPu8DSp{KK9n~H*M<7U=`Roa!-_ZbqR)F zR|lr=rYQGPtR$tu8}~Awe~wXj2f0sg2)71;MYT0}tFzt9U~+_yPKc_zhn*UX36rQ{ z@G6DQW^_`V@hpiZQIue;9=k7^q7;K3+7SAiaVVMqJN4G|mUrP`CI2_fcfglkJGoi@ E2N$ftk^lez diff --git a/mobile/lib/entities/ios_device_asset.entity.g.dart b/mobile/lib/entities/ios_device_asset.entity.g.dart index ffed338c916fb62a57f89cae70a0e118fff3d193..8d8fec945b87ae14b05d931ae621f6066cd3efcd 100644 GIT binary patch delta 2266 zcma)8U1%It6lRvJNw(QKyPHjSHv4lo$^N97mR(eA)^^jRUDJj9l0fk%w$sko8Qe^l z*@-m-sjVUiT9qS$57NgHXeBZaKAN@k(h(`2zaVLO2Z5F< zxHM-8SHcU%FFn7zjCF2^F*d`S3>E8x{~|Hi7fr#n1ACzqW#MFWz=cy>3BL+=qpWw% ztlAP@PdwSrMHN+)-kGvnZ#L|0p}d4U|C%B$nDM{G0$bt_!PEc|&%%R58g9h<;BLGZ zHj*CrCmw+7sZKZ@ZHH_!Kt%i+IzqubpeG0vLWOwR^-(x=mS*qP_YrHF7kI|JxI zfQr3ZjO-#7Hjb%O5KahdC%U_=d6GA8&iH|KF4(c#IdeSTG-txrC)BY|27gqa!c{j? zGZ*+Hz3|8QDka=9Q5>2KWVJSAOqbqwdvsY+$Ck;z2?&#~7{k*aF$~$Bw+w#vw(Ea8 C{LEkg delta 1995 zcma)7T}TvB6lTnytz6eyU3cBTyX(5U+Nx_mmR8zomMfNpKLuemI+HuKPTS6C1cg0C zP?T_j>LKtgBC=p0`X!?$p{S>zAbJua$dY;}2<+b38OPl*YhHGC&Ue1^opZl?@3~vl z*PGP6!fZf!c{v=@fWk15>vW2z5^MvC3Usm?zg73264?$;5JM{veqd|1li(u+Uz_@d z5Kj-`lw^Qo0_vv>7C}sM{9r0rftk*Pqzl>aD2dH=Q6`xgp*|%HSMn;QXLV94k) zpeTblCWK%z-wH3RDbDKYo%;HXsgn8D&(>2n{C^`p*^MscMCBiwP4+cP!I{P#UvU zQRMe==`5wP!dqP7e4qeMM=en5bigL3mr}Fy;l8twNLgjF!sLc}7)Id)=c4j6Bbw~LvCer*V5Sqn_uy3`<9x*kyll4O_4p7fgKKMwf@s z;1Wb9c6#+hM8L_aSJ1TCBUk9f=2A^|1;48%la(H+;o-r0do9ZkiZRXCVse<({>2xG z0@Zw&RN56jhzUxAVGW+1oDm>-2DMe7TlT*XiCfLi}sZE@;6 zAfrwRT`=o*l|8(GJzZaBa~wYqA7)sUe`c-qKlttIGe)GaXquPkLHe<-I7_k8<$4dc zgav+W_GxzdQulD)Ggs?v>420y7-ARrSvLWyCo+LOu)E=tYzh+5o5H8nEF|m0FD3f)u=!XVSqJ8@+lk@l34g63jK}gFWzmTVV-8UGm|N z60|6?NnV*Dm>NYGjd*0rrxCj*mrx#RX0!>eR?d*X{Ov-HMcMCtEraqXaT80R`nM+( zwwh?Uwna&yF on List { - List uniqueConsecutive({ - int Function(E a, E b)? compare, - void Function(E a, E b)? onDuplicate, - }) { + List uniqueConsecutive({int Function(E a, E b)? compare, void Function(E a, E b)? onDuplicate}) { compare ??= (E a, E b) => a == b ? 0 : 1; int i = 1, j = 1; for (; i < length; i++) { @@ -45,9 +42,7 @@ extension IntListExtension on Iterable { extension AssetListExtension on Iterable { /// Returns the assets that are already available in the Immich server - Iterable remoteOnly({ - void Function()? errorCallback, - }) { + Iterable remoteOnly({void Function()? errorCallback}) { final bool onlyRemote = every((e) => e.isRemote); if (!onlyRemote) { if (errorCallback != null) errorCallback(); @@ -58,10 +53,7 @@ extension AssetListExtension on Iterable { /// Returns the assets that are owned by the user passed to the [owner] param /// If [owner] is null, an empty list is returned - Iterable ownedOnly( - UserDto? owner, { - void Function()? errorCallback, - }) { + Iterable ownedOnly(UserDto? owner, {void Function()? errorCallback}) { if (owner == null) return []; final isarUserId = fastHash(owner.id); final bool onlyOwned = every((e) => e.ownerId == isarUserId); diff --git a/mobile/lib/extensions/datetime_extensions.dart b/mobile/lib/extensions/datetime_extensions.dart index 7e5498027..0bc95565a 100644 --- a/mobile/lib/extensions/datetime_extensions.dart +++ b/mobile/lib/extensions/datetime_extensions.dart @@ -47,11 +47,7 @@ extension DateRangeFormatting on DateTime { /// - Date range of this year: "Mar 23-May 31" /// - Date range of other year: "Aug 28 - Sep 30, 2023" /// - Date range over multiple years: "Apr 17, 2021 - Apr 9, 2022" - static String formatDateRange( - DateTime startDate, - DateTime endDate, - Locale? locale, - ) { + static String formatDateRange(DateTime startDate, DateTime endDate, Locale? locale) { final now = DateTime.now(); final currentYear = now.year; final localeString = locale?.toString() ?? 'en_US'; diff --git a/mobile/lib/extensions/maplibrecontroller_extensions.dart b/mobile/lib/extensions/maplibrecontroller_extensions.dart index 42d5e2c1d..e1f32a4d8 100644 --- a/mobile/lib/extensions/maplibrecontroller_extensions.dart +++ b/mobile/lib/extensions/maplibrecontroller_extensions.dart @@ -13,9 +13,7 @@ extension MapMarkers on MapLibreMapController { Future addGeoJSONSourceForMarkers(List markers) async { return addSource( MapUtils.defaultSourceId, - GeojsonSourceProperties( - data: MapUtils.generateGeoJsonForMarkers(markers.toList()), - ), + GeojsonSourceProperties(data: MapUtils.generateGeoJsonForMarkers(markers.toList())), ); } @@ -73,23 +71,13 @@ extension MapMarkers on MapLibreMapController { try { final ByteData bytes = await rootBundle.load("assets/location-pin.png"); await addImage("mapMarker", bytes.buffer.asUint8List()); - return addSymbol( - SymbolOptions( - geometry: centre, - iconImage: "mapMarker", - iconSize: 0.15, - iconAnchor: "bottom", - ), - ); + return addSymbol(SymbolOptions(geometry: centre, iconImage: "mapMarker", iconSize: 0.15, iconAnchor: "bottom")); } finally { // no-op } } - Future getBoundsFromPoint( - Point point, - double distance, - ) async { + Future getBoundsFromPoint(Point point, double distance) async { final southWestPx = Point(point.x - distance, point.y + distance); final northEastPx = Point(point.x + distance, point.y - distance); diff --git a/mobile/lib/extensions/scroll_extensions.dart b/mobile/lib/extensions/scroll_extensions.dart index 2752d0b77..169032ff5 100644 --- a/mobile/lib/extensions/scroll_extensions.dart +++ b/mobile/lib/extensions/scroll_extensions.dart @@ -10,11 +10,7 @@ class FastScrollPhysics extends ScrollPhysics { } @override - SpringDescription get spring => const SpringDescription( - mass: 1, - stiffness: 402.49984375, - damping: 40, - ); + SpringDescription get spring => const SpringDescription(mass: 1, stiffness: 402.49984375, damping: 40); } class FastClampingScrollPhysics extends ClampingScrollPhysics { @@ -27,12 +23,12 @@ class FastClampingScrollPhysics extends ClampingScrollPhysics { @override SpringDescription get spring => const SpringDescription( - // When swiping between videos on Android, the placeholder of the first opened video - // can briefly be seen and cause a flicker effect if the video begins to initialize - // before the animation finishes - probably a bug in PhotoViewGallery's animation handling - // Making the animation faster is not just stylistic, but also helps to avoid this flicker - mass: 1, - stiffness: 1601.2499609375, - damping: 80, - ); + // When swiping between videos on Android, the placeholder of the first opened video + // can briefly be seen and cause a flicker effect if the video begins to initialize + // before the animation finishes - probably a bug in PhotoViewGallery's animation handling + // Making the animation faster is not just stylistic, but also helps to avoid this flicker + mass: 1, + stiffness: 1601.2499609375, + damping: 80, + ); } diff --git a/mobile/lib/extensions/string_extensions.dart b/mobile/lib/extensions/string_extensions.dart index 65660c04e..6cd6e1e4b 100644 --- a/mobile/lib/extensions/string_extensions.dart +++ b/mobile/lib/extensions/string_extensions.dart @@ -1,10 +1,6 @@ extension StringExtension on String { String capitalize() { - return split(" ") - .map( - (str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1), - ) - .join(" "); + return split(" ").map((str) => str.isEmpty ? str : str[0].toUpperCase() + str.substring(1)).join(" "); } } diff --git a/mobile/lib/extensions/theme_extensions.dart b/mobile/lib/extensions/theme_extensions.dart index 6da8ac1fe..332dc58fc 100644 --- a/mobile/lib/extensions/theme_extensions.dart +++ b/mobile/lib/extensions/theme_extensions.dart @@ -7,16 +7,10 @@ extension ImmichColorSchemeExtensions on ColorScheme { extension ColorExtensions on Color { Color lighten({double amount = 0.1}) { - return Color.alphaBlend( - Colors.white.withValues(alpha: amount), - this, - ); + return Color.alphaBlend(Colors.white.withValues(alpha: amount), this); } Color darken({double amount = 0.1}) { - return Color.alphaBlend( - Colors.black.withValues(alpha: amount), - this, - ); + return Color.alphaBlend(Colors.black.withValues(alpha: amount), this); } } diff --git a/mobile/lib/extensions/translate_extensions.dart b/mobile/lib/extensions/translate_extensions.dart index d8a2810e7..cfd8c8cd1 100644 --- a/mobile/lib/extensions/translate_extensions.dart +++ b/mobile/lib/extensions/translate_extensions.dart @@ -29,11 +29,7 @@ extension TextTranslateExtension on Text { } } -String _translateHelper( - BuildContext? context, - String key, [ - Map? args, -]) { +String _translateHelper(BuildContext? context, String key, [Map? args]) { if (key.isEmpty) { return ''; } diff --git a/mobile/lib/infrastructure/entities/asset_face.entity.drift.dart b/mobile/lib/infrastructure/entities/asset_face.entity.drift.dart index 140af60de10be1ee66b00ea42ad250c7cbd813d2..092fcc58599f3b97abd3460effdd0400039a51da 100644 GIT binary patch delta 6213 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 hash; final DateTime modifiedTime; - const DeviceAssetEntity({ - required this.assetId, - required this.hash, - required this.modifiedTime, - }); + const DeviceAssetEntity({required this.assetId, required this.hash, required this.modifiedTime}); - DeviceAsset toModel() => DeviceAsset( - assetId: assetId, - hash: Uint8List.fromList(hash), - modifiedTime: modifiedTime, - ); + DeviceAsset toModel() => DeviceAsset(assetId: assetId, hash: Uint8List.fromList(hash), modifiedTime: modifiedTime); - static DeviceAssetEntity fromDto(DeviceAsset dto) => DeviceAssetEntity( - assetId: dto.assetId, - hash: dto.hash, - modifiedTime: dto.modifiedTime, - ); + static DeviceAssetEntity fromDto(DeviceAsset dto) => + DeviceAssetEntity(assetId: dto.assetId, hash: dto.hash, modifiedTime: dto.modifiedTime); } diff --git a/mobile/lib/infrastructure/entities/device_asset.entity.g.dart b/mobile/lib/infrastructure/entities/device_asset.entity.g.dart index a66f8288ef2f497e1f7aac311dc11af1d2059c03..87ae54ad40dc02bac48aacb2f527876493f2b31d 100644 GIT binary patch delta 2339 zcma)7-A`L(7*AOlYv-T{Eu|myrSyZc4(URjbYn7PE`-9mwR|WmaOgRu#~e=K^we1m zPM4_5Zrpg{oe_-}Xe8Bm;)R(e;ssuiEZdDY#`q7Y$u7Lnn0VgvQC^^c=juK0`Tc&+ z^Lw7>yzlp0hWCCleC0OYV(A#_2_v3bWMW7NQiTE|4%5Lf5=%?+&TxSeQu3<1APOwM z5DJ@-{0PAuRmcTnC?VvR7(py0GdX6F>cnD^9We#8Piej+GI6#bDq8T+xLk)tSHfm# zsP<2TNsWL|8fJ{PPZM>9#>$Sm2!&zxM3;2u#K>`onjG*)ebkTBd?C+qOh#n$`~|us z`(ZN|Q6|q}(lCu!It&-gZfUN8KVGYtfQMF8hu%=vkDINq-qS2OZM`*+w3nK>{7puP zVHzqf$sX|%-o6@#0egcq)%v(bI^*&iqzSjj0GW{%xYzdis?!9&xa;AruL-6+c9@I= zVAbP*cfA&P5N|$)Pzat}N@4{#gO)M;Bh(6?_-s$3S1GP2mwQ^Pe|iTw(Y~?jw7|7s z5S*a~DEsU%>UF}eJ}><1>!?8pVvhbjpUvRzu*;uKFc+zVZl4uaLai8DcFg}@=zi5* zLCcO-IPIS@;vPdeFb4Nr0a!zJFU!-+Yh&6tX%nEk!>@$3^?+P6-I`CcWd_t`-EYkY z{UOicmJWpMSg9IBwQ>shuC02l{+E}F6qm}waP+oG84x`6urb;Wf1O5PJZ}Rj(y28x z3txx7BT#F7epv5!RYm5yza^0E&v*|++IxN{kdf7(YKL3B)|2|b5e(v=B3q~B3A2LP&bOFYUQ{!H0oNQ@p0^NEdaF14-FPT;BW^5tnPV0iUW_w^LMlh` zorme@gRn;j#xHIY(eMyp!~sK~M~BD&*HN*>G5msQf$-fN_fFxDsraWi_H)yEJ?`c(R>T+MN>1XSgEGC^4lW zn;F+@H#txt>ozpb{%oY07jGNj&Xre)^2vR7k$q?JEvKDKWY=vheMMj>kr9->$#;hW zI;8#Lu#;?m6H8Z0a0pv(`X07?oBTjzjhl`UM>YNI=<5Uv|2vxr$5Yk(1s3x(n`Id~ z#V#_W(;?Y2-aFE7;<}&o+d&FeoFA#C``@Dm)7O3`oM8VLak&2$`S9+L9LYBg@L_5T zvg6wjop>afCPxfLF~{)maq36O`_elG_~PYFSekyM?w*<~!&|mm_~*td+)w`v@6SAt M#%8HwAkE+X4=?EBJpcdz delta 2398 zcmah~U2NNA6jin~KTXZzlJRv5;UfAP+2PC8+#`iftw)3~Ve75hs z=bm%!jeYJr)s1gepLeO@rrMzDhk%A~@TXVk5n?h&W|QbDl;g7ux7626pdTdEE-^C# zQ`#&kQhH!O7ZB!k2Q{#x*$%f_hq?)| z%S47{=@idoxKZjfM=mp|F(Q>=`-n-3U?@;U+97Pxs(RpLk`RuWrZww|25}m4M_{;6b-3X7 z!?i#QXgoG>b?e}XZwG_|ItY7h5Z+hmY3%Wx-Kk_O=@Y8@jS$nSw44!;nQWR#=-7t z7VWZ{7)L29HikUa6D39%cH5i@)gHo{iq zm~2)RwYxBLysI&mUZy#Iiq7SdX_E6d0F&lg0fr5{y60|ju7zOj*%n?5q5+%Z92nz{ z2+b|=>5@GJ!DsWdbjQ|+!p7ht?)cum1q5LC_e<%@;)+12?!*L%>q4^dBFW}tU7r_! zN?2T7Hf>6zRqa`Uu51GP;mNoGck7pRQ?jg-$Z#n(Pthf|qcL0I%Yp}77vC{hVN?-C z(ojzma#A?3{~htgekaZ+X> z0i;~I0uoFA;^m*q(s8i9bm#nlaPiQa;%LpYw{h_=vv=`v ExifInfo( - id: dto.assetId, - fileSize: dto.fileSize, - dateTimeOriginal: dto.dateTimeOriginal, - timeZone: dto.timeZone, - make: dto.make, - model: dto.model, - lens: dto.lens, - f: dto.f, - mm: dto.mm, - iso: dto.iso?.toInt(), - exposureSeconds: dto.exposureSeconds, - lat: dto.latitude, - long: dto.longitude, - city: dto.city, - state: dto.state, - country: dto.country, - description: dto.description, - orientation: dto.orientation, - ); + id: dto.assetId, + fileSize: dto.fileSize, + dateTimeOriginal: dto.dateTimeOriginal, + timeZone: dto.timeZone, + make: dto.make, + model: dto.model, + lens: dto.lens, + f: dto.f, + mm: dto.mm, + iso: dto.iso?.toInt(), + exposureSeconds: dto.exposureSeconds, + lat: dto.latitude, + long: dto.longitude, + city: dto.city, + state: dto.state, + country: dto.country, + description: dto.description, + orientation: dto.orientation, + ); domain.ExifInfo toDto() => domain.ExifInfo( - assetId: id, - fileSize: fileSize, - description: description, - orientation: orientation, - timeZone: timeZone, - dateTimeOriginal: dateTimeOriginal, - isFlipped: ExifDtoConverter.isOrientationFlipped(orientation), - latitude: lat, - longitude: long, - city: city, - state: state, - country: country, - make: make, - model: model, - lens: lens, - f: f, - mm: mm, - iso: iso?.toInt(), - exposureSeconds: exposureSeconds, - ); + assetId: id, + fileSize: fileSize, + description: description, + orientation: orientation, + timeZone: timeZone, + dateTimeOriginal: dateTimeOriginal, + isFlipped: ExifDtoConverter.isOrientationFlipped(orientation), + latitude: lat, + longitude: long, + city: city, + state: state, + country: country, + make: make, + model: model, + lens: lens, + f: f, + mm: mm, + iso: iso?.toInt(), + exposureSeconds: exposureSeconds, + ); } class RemoteExifEntity extends Table with DriftDefaultsMixin { @@ -148,24 +148,24 @@ class RemoteExifEntity extends Table with DriftDefaultsMixin { extension RemoteExifEntityDataDomainEx on RemoteExifEntityData { domain.ExifInfo toDto() => domain.ExifInfo( - fileSize: fileSize, - dateTimeOriginal: dateTimeOriginal, - timeZone: timeZone, - make: make, - model: model, - iso: iso, - city: city, - state: state, - country: country, - description: description, - orientation: orientation, - latitude: latitude, - longitude: longitude, - f: fNumber?.toDouble(), - mm: focalLength?.toDouble(), - lens: lens, - width: width?.toDouble(), - height: height?.toDouble(), - isFlipped: ExifDtoConverter.isOrientationFlipped(orientation), - ); + fileSize: fileSize, + dateTimeOriginal: dateTimeOriginal, + timeZone: timeZone, + make: make, + model: model, + iso: iso, + city: city, + state: state, + country: country, + description: description, + orientation: orientation, + latitude: latitude, + longitude: longitude, + f: fNumber?.toDouble(), + mm: focalLength?.toDouble(), + lens: lens, + width: width?.toDouble(), + height: height?.toDouble(), + isFlipped: ExifDtoConverter.isOrientationFlipped(orientation), + ); } diff --git a/mobile/lib/infrastructure/entities/exif.entity.drift.dart b/mobile/lib/infrastructure/entities/exif.entity.drift.dart index 10712948eaac2a2885ddca079129f82658305e8e..d45d6e8ef6b0058dc09c7c0222011b7cdbd8a8dd 100644 GIT binary patch delta 9759 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 diff --git a/mobile/lib/infrastructure/entities/exif.entity.g.dart b/mobile/lib/infrastructure/entities/exif.entity.g.dart index 989338abffffb87d6ad349ddfa4d75bb95a888c0..d2f9ebda277d4acb74af0123bcc973dca4d29175 100644 GIT binary patch literal 87909 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 TS~7vOh(&C3Ea>PM-);Rrg@%L@ diff --git a/mobile/lib/infrastructure/entities/local_album.entity.drift.dart b/mobile/lib/infrastructure/entities/local_album.entity.drift.dart index 06f65e25d8605e8eb76056f4de4a4e56233571f8..5be349c8e09674eb0cc4606042afd0e3dd3d9207 100644 GIT binary patch delta 3044 zcmb7GYiv_x7*4yjYrEd)dOKaaeckDL8SU9xw#t}W2VP*477z_lgR{_sR=SS09f24x zBpRb=j65-F3{gXj7^AW@{?K?~8ly%HXdw6tG5SaO!HkI-jhF8`r>E`4MLo%OzJBlf zJ@4&#-|xJCRCV%o)v@!c7BXr;JmosHK@YRqjL8Wv2GkxrpLSx}V^Bv8c-AwFKhtJ> z(c(Ci)*zTMXZg%B0$2c3QkxK1pR=I8FcRhrZQr!*|wx zb_fr&IV9m*ZKQ#?*p`%pI+JthNoH=b&49x?o+;?3v!&f)X==IEvnC$T>#fx_`rDT{ zzDhQ+$;6>(FycoIVJHp9o8%9)uc9*Mcz@%N&p0UgB|BXg@c7Iqr2w+Sb;0!)IVoGH zo;9gjmZiX9*f~>}n=VReJ-1>x<}&dscB#(dzKU4Pm8CT+`;#`0hSi^7oH+2lO{=EM z1sf01?qj5R&5@8_0hS+Sxxd5B^p1CQ;%J9gUS3th46`a{?S4TfmIO}!ZOCOVq}&-OFLO-KA5|an#=3&>1857zoa( z-MH6g#G+k`wZx&$?Vyo$`$#3bqd*BqNQA5*<+(j#i8(7j)p5sbDqL{t0`)CL6p+rX zX&k2kPI+Chx!lfW%3*4rKG@`O;69fQH@Nz+&10hLLHgbxt^al<5qC$V^(QS(?01Ky zwUE)$h7|M+;NA!s9m7xVm2h)z%y)Y6X=f0-xCA)wASS#7qIU)Ea~kjmXTF>hCQlSY zo}gs-InU^SF{tukd_t#@gRpYsGNwOkq<_G7bt_Xx!Pkvn>`ulZd}#AyRf=PDnRf{C zizoz|cMwnl;e!s2v4_5gw1h~s=}-BBN@1@|8HFxQbd?FtvNxt+M4}K=1tMu`ql&w$R+3T(%axua{Ta! zWSlvxC`@H#4Yqd)yKGa5Yk?oY&wMW)37HWNI2wiZ2L2GLU+NOFj07?Nl6%!N3gLsijQm@UXOe5M4Jxty=U}wO#HOP(Zqs(Gojrv zGgF`iI?u;&D%=5ID1oh^2qRtA+d<%!sQ zki2_2a>!9pZUktM{+f9K?ufTtrc;EyFccXMliMUS>_TKYkgqB4Zezeju-j{csA?k!{R6T@=pd%sClX>wKV%L3r#5Jg@Y~BTbvtl@sz{aXwCVpl@fJ1CC}E)C2?1NA9E6~_CJl4 zaSNVGSZi&^C5Vx>>2@UsJUkG+Sj8%}U|lKV$BUT`SmG-sq;Gf|{0TRTaic-Op(-ab z9G;4=H%jSbVbKTXxPT`UcFN#UpQ0;^BL3#z5m+{Pa94s^aM1BU{ltffrbhZY(O>hk zCbrf{RreB^RVUFi*okWflemA7lLl7xnZbuuZn?xIads|W5_6<-SH3JrA5|ksFK$Wt zurJBua57+(B((xC_o^q7W2)L9U$FUDtLcQw%+}dL*nm4Yj`p3QsgBdD7nS-L?=H_2 zmHOcRVR?R54-dc8vJ_8G@g}M6B>|6&zB(#9uasD!zVf@#0@u=^c2j;@Of@$Hj*P`L zjN2&)^s?>ESm^B-)W|pE3gSjrl75WkxvR=?sw!}1lHue~{$_UmFAtef;=YO)JwGM4J&lc&_`dki>`cFG^Q2hs#b w(meL8_u~7si+*Vbsn2d4zrj(>WVFjtx1fYZ$3Dk*f41YxnNJ)$7YCEXNpOq0w(fGHT&575`gA?ibzJ)d zT0+zc#P(w<>-I1xUKtu|dG$1BZaQgelJy{9i+kFjFl`5op(r773%DUy2SxI|fh<_|I4 zv^RruK_kN^{}Fprn800@FfMU6$To?-`|zgmFZg4x16TXJ=rel^!h{v4y9k1IGlooF z^{#C9vpYOw+NYl1Hd%4S&Z)Gt`O|traK@ZtuRrwmW6SKunF%9)WuC#s?g;$7qAGQ$ zm!mX-)22R3-%V*=JnB?Y+WRdJ>QpAp3=5`v9C(5B*_Q z$9qOq8Z$tn#r{pXM*HM-iZ#6bmKa{QIoq=BlKv)N>{zgmVat(Mp%2kWX=f{zo%e=_ zbW)M()fUU=!rGd$R9US_}N8o>o4k17f1Q&wc$L3Xp{^5AQ>Au1oU6xG5KC^hT$v&#qFVO+2U@oTpe?tacd zs;f9>^drQX?1IWn$j3=*y&*MI?FsH_9rNuiE{3$nVYiZ?dM)(bjpse0 z`u$x)Kfbb`;G2PNdY(qZ8&~Ns?&BURZ<8$u8*O;so6v3I368_K+m51-$7g*mobY*Y z))&RGi9VbThLPXn#2pKEJiDhGeSQq8dV!+Tng1IUS&@V+=qI-nbDVKA9`OKK`~8;~ijg4%O~ zpVB!9Sz*;tmXwO78}AMVaW&JAK;~l*hvu9sJGQ7yENl-C9l+-@G4y1|aWNagC~enf zHi}(iRy>yFd9re&jZ9QfWz4w7vjmGst1Q&LD@y=Aq zxOk$Lf-WD$JELWT5D{Qs@S!o5X8c_&b|O=RH^$t!Ha3*F$rL)scQ@rD3dLDE)sQkf zB9>0UEDP9J2;hNyo6Xai@u0S?36{t6jPk&Euzh~~J{|s6GP^gL(usAMW|k;NkG~r1u+DqnGCC~N+nw7k Y&hxhkZQzzE%zTOc3<~X^FMUJ*A=#%Yd;kCd diff --git a/mobile/lib/infrastructure/entities/local_album_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/local_album_asset.entity.drift.dart index e8f94fa74b48389152981e76a85df218d6fc5f13..78da361f62f28a4fc39203070dfe4b015fae7a24 100644 GIT binary patch delta 3499 zcmc&%Z){Ul6i>UZEpJ=bcJ0=6?fSZPrLQa9>&Di0-8we@4z{@gY68Jo=mSd17;P88 z!60Y|1mlFCQ4`RBF@k{@NQqG~0wyK~BZ7%W{UAf*CkcNNVkF^%_rBM4-2!962VU}W z?>qP0dw%D4?z#88Q>SF-&&kfLl*`#xTytA-=DAteDc9gEZ^RKfLs~n&l82`Z%UKqD zUZvC+@N%A7!IB3X^Zagx_Jr*zVIZ0m`}8};dpjaYVY#qgNC*S#gk%dD!k(ZL9|qmn z7pk0AgKZK5DKG$O7TvFF5C9Jrk{^_xx4l*+Y!8k{WMLfT@u%Dxf5?`Z^_vy@_6l^Z9j+{P?L zjtOouURtqjw#&G7C>D#%eojGvXv=3>@b6N8;3o1CH8P?oUZZa@8a0jFwPL1 zx3m@%>Pm6nV8@RJeX)dW67Q7BPFoM&vpMl)bro9mdK}YM;Yv-Rip$V?qb7(4`eIzx zM>D`JxM|T$1Kwwx|K!MT=s7$fyiJGPXY53`ZRulRTd>ew1Ky-fpDg`WhSgPOEGe;I zv{;Lv-+-$olQoA^mdyzOB`Ler_F28<4+#R*A%Pg-Dx^SoxjC6Y6lOTo<^+Slz($uI zJ6&eG0psR}j;W!tXOKLkrhC4R9$CyKD97gY1=O9f;dr$I}Gi;kT{alweGg~dr?rBt$%r8RB*D!Sz;`&iv1wQvVNsu@& z^&0#^_6E_GY6VaI7`=mKEzmU@)Aoj>jCN#UDrCa0WGa#pIChu{ab~U^WBCe|C?u82 zU4J=#n5)92CL4MiRM1xDW2}kG=@Xg17%h#KtSsa&5$92TKA@C2Ae&QhxSoNgsa#Yd zLY!`#oil;KML#o>Njg{p;d>}^n@Cs0c9%XVeF$;Z1*mM8G2HV51cyczXB zfj6W68G3_gpoIE>>j4!;0!Hv;tN`|5Ix1l1(53^+>K zk4X7f9dh7au#voC9?LxpUTSX3q_3K^7Mi?yWWVE5y9EwUJ?tc7KMDCY;;s#c7-n5O zl1yUjA}b17<{G>!X>Hg!uzm}zF{KBCWbmq6iM^q!oJ@bc<$Lh0<`OBBXOmTgRA+QH z#STwf0Owmdmn7|vNn)0b#ABq8jrK$~XX?-Ok$94Hakk9~KFnfyxE=3=n+hZb#0mvh z!gD7Ximx5oJYgt8j8Mt{Hd2BW^Qv5BbYUAg$bE~< zIvOEL(;A6g;^1!!>mH?E&5UbtcD%B}l1?l-B5Rh2NeEkqVhJJ2rZ&cs-V7a*`jjCl zR&*%czQitbiX=YNyG_Y01LNM|i=~wk@xLtXPT%hQT8^LHCi;6dOJaep_iNWm1-yOE k^z(fiWf}<>`BQo!5+5Re4Si<(xx5tr^cmC4isSPC07;g^+yDRo delta 2775 zcmcguYiyHM7*5-@Yrn0#bX&Ks?RMI=Ys-2ctaNKTHehUvs{_YHFpRJCn-q4l?c&(P z&0C@pKz$-HF;O6dKZp>E2=Rw#L=!LqCjKF2f`&+x5PwKCCSK0>ecfPV6Mm>o+VAq7 z^YnS%_dU-!AD)yPJt{fTBULbje!{rqH^VC{z+R~yhy3MICxi3S$lPeF%z&7z5|gq3 zA>3%18;qw&!s~8jQ`{P^k4ticTe(z7z{INsWjI?W$M<0iZr2%b(PYLk8Pi}F!i1zo zhPkBM(i@LCXYSK%te?BU&EzF`qTI{=Q3DkKN=JUJSERZS5S#Dg%97!&4|hy z`Dc|o5qCJ67>3|lp&q-#T5QhU54%!>&*gflr56X8Qv60IN97(&D$k=`<->&P>wAEM zc_Ofy5r7pUFrF@{5>So#^P;L59+kskHOC`M99ULYhp49@Gg@#;fB?%^e@%MLO`9 zrwGl~3f%H4@vcKBu~3bCLOhtV7U5Qv5xsQ&#i~4<)#{-xx8M)020s%&W#=&&Fj4Y~ zK_}}wHtehlcrWoF&{fn>z5HSooFM5s*7N^)eBdb&YKle zg)2tQJc7hzJ*c44`2^8Y80f#5|3QnIxua#NLJgN%b3Z*9kI5wcKPoY7(!gc?FDkLg zRsx4D{XbPeZ?*ip6`)JE1yOgta@vKlyRLGMKWl*aDFr?=uTT@_g1DVjpMlvabqn_b9O4XUBeDM6wGLUM)7c$`I;N z;V)kSiv3ksQg1-GJQrK)71-jhVEC!RGA4LYY8C90;Gn-k?Yzr2XG0CIRpNKQdJbGL z*Us^7OD&es;#_?#F8bxT>M`&enA*;Z&F)kjT7sq2N>?tvDkUL&+)$EM-(2izEX0KX-Nu?2>S0Pe=d$CQCLO#%4K_Au>HAVV@3Ljz z)nRFlRD*Xy27D3P12)_| zz4adnoA85-K$T<123IZCIfb4=C+(zl&YF8s! zLKFpa@MwLWfWUXyugx1vXKLc^;dlLx!M>poOisPTNlzm>6tyYv{;~@q4}!@Sy~@U> zQe3(tZbR?#rMTYWun;1?>rKRMPQvyl=s_eNWe4aPqL1xQaeU!%V|gv|SD4{ku^eYw z8)>!vY+XDXw?8&AAmXwDCjb1vm^)Tb%*+Y;iyJEgB&%yYHZ;^v5~+^C6qigV1|KJ3 zkrP_m-Yn|PO6lU#tU&UYwl;X%gBV}cZR}-5KGQ+5rwP?ZX+g4zps<~GOZ&AYUF>k^ zk#v%xJ4t-!AUlxQ8X<93#N?-qi_vDWU%QiBUt$!|j)TQB*(b!E^tMFGoh84^(S-61qlk1JG0#hL zdunKKdSQ-(iB=)@a93t$^b;vwZ?5DQx>Athpl6_gXhY_$)%qNqUTe!ttxZUj(^*E> Q`bz9rUzvGn{d>~C0sIVCQ~&?~ diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.dart b/mobile/lib/infrastructure/entities/local_asset.entity.dart index 204d5d6a8..e5519cfac 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.dart @@ -22,17 +22,17 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { extension LocalAssetEntityDataDomainEx on LocalAssetEntityData { LocalAsset toDto() => LocalAsset( - id: id, - name: name, - checksum: checksum, - type: type, - createdAt: createdAt, - updatedAt: updatedAt, - durationInSeconds: durationInSeconds, - isFavorite: isFavorite, - height: height, - width: width, - remoteId: null, - orientation: orientation, - ); + id: id, + name: name, + checksum: checksum, + type: type, + createdAt: createdAt, + updatedAt: updatedAt, + durationInSeconds: durationInSeconds, + isFavorite: isFavorite, + height: height, + width: width, + remoteId: null, + orientation: orientation, + ); } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart index e9c5961aa50a840c12a9a47b44c4d3bda9840cce..329401d5db45639454f1e17d4dcb33407db48cfb 100644 GIT binary patch delta 4846 zcmcIoYiyI(8CD!8@g=bx$Co(q<@gpSajlo&8JQiAiYB3zi0;k=aK>x6dYDJ9HF zJwB1D)P(+>sOeB7zq=5PL=WQ6wZ8T0SBObcr$7g>@*R`7kQY6ipHUx7WM@Jdw5Cv4k!EC%!CJw5|iq&Fg z>bUNRRAi$beq*5!*i?h5O$a+g$c8K#4JH$A8s+O!mXilX$7M^gPH2$m(PT6pNeF9J z`}->^B=mK-(uym78%}tgxNDYS$!2A}!g_Pw=E9*`0}{5zTr=FRt;CI5GZVdC+mc4B zW<7M$Yi9^f)^&u$>U}-oMD(%f!RTT%eju9Y%xI=WLF=1-C)HYvTMi@Yy;7BkPDnRi zsW#z7uTe1ShSw&~l5x)B$5N#(pG2ndry84uB*W9QQP!?Cq@5&|7NU#HApVz9STE&O zxFXZ-ls(hZ86qJrbXv=CvAPr=*~$%BDb7%ROxVD6y9Ihuhu_*uFhtsgH=B}dU|k^9 z+3#DVQCKgyo6_$>jM{zK^%w3ox(?8%469Nle)BZJ+e9YN{}t2VzUcc$j%GQt;zSMU z>c+Wz3m!OBkUGsc;4x#XvkFhp=cv<)4?G0_@HE3yU5@)s7j&*_w9XISl;?8|rr(9L8Z|PLKNB@XUy_2iOcugmtU~kmekf=1{Eq^5~DH*oWWA3h5 zj_0f%R>;S!L@4BwRx^(4w0vr%3mJE7w@C@9R^YVP#)_@-Kh&CTi@4b|nh zSSX4T?|I7$c=i0n+n7&RFxFYoQn!N|lsZ{AkcUunrCQ+d#KUt@4+Ftea|>KPk1MxD zNO(3z8!0kOnYf~Z;n@UT;%0pX7KV!Q6i{_k$dZdo0v*A6AKDCVJn*?O)l}po#KX>E zK>@Gp4Tx+zgBtQXDB@J3RhvO%)EeJ%EIEUa!650bMrnx&zxVeu7x-}T99WEolhH^h z$^8h{&vXdBG1&}pGR&!LZxgrJX3hvJKCRbcrqK;|gEN=%ymk-f8`L7rOAC>;n%nRp zQR4Fkm&k%N)BnnX4;q!s0u4{!ax9XZ$@uN3Be?*auUw?{;H1O@nN>s3}4Y=ZB3Oz+MV?NZP2Ongk z9l?G!LAW`r)%hyhlKeBsHAQ!Dr?(t;0)>clm*u+qrJh!- zcJINJUOB$$E{7@5mm`h`b})iwGV2LP#kIgLF_#ln!J4v3!NE0pF&1oH%XlqlXOJb6 zJOpXHzXp5Ovh51B;Q0{2@5W2<%a8-NLl!&}^2&v5Glwu9aH6^AeZg>5uMwW!;97{6 zdj0rSuL-}HP~a|QV6GSUiT=r82qS%doa(EbGQz7H_IxO|MMVjwD zql2t}Iepfg?61gX;kEuUo`tvie}aiYHKvA)GNIp?#r6Rcez?6*k;zJp9dGV!#=G0) zIiAp9k0K)=h}d))c6uV%Gi&q=1aOApjW^2S7%11JE00av@hsEzf#4b@(MZlQg?4Na zO#OJ9E@uWcRn2E+d!JDWE34&U2ZB2L6-)8!oH}Xh3{-vcaP9}#fSl~&y}#t(2FAuTpBU) z(zr45KAu=^%GJ}wKkmuT){?&Xsl@A0&GsuS%y!Z zH2eDK8NW9+7Y&egV=YI>js+@mn%=N4ND4sg1kc;m^cG%4-$7LdnNK+Sn}L~K!nM=$ z^RoexJ0~c@;W3?@)e*mc=hc===oRtum>qu@v*7+%9bDse*gL)rKNxSr<4Z1lPKQJO zgab7b*0NZno&GRE0s)>frVW>u3^+RB$7Hnue_t};485-ZbD}(@ovh1u5Z3CxoB_Ut z#b|<_8lvu-nl8r+VJ%KgTb-O;G>B|YwAdRpHy;8u|jmRY<53etfD_bIq9Rra6*mAL?wEBfs|+pXobR7cNI&>ga{fJuTt(=w8<$I(u;Di0Y|@5z-4>}|g_~{zx;;uH zWiq5ZdPX|$sbR})Pd!4@GK9TGyy`SFQg4YJGbMH9kN9?~_!CJk#?3<0Y{KDYqgchQ zl3Lt!)Mepq+2y}zF~mcG`=j%VT-PL@iZ2}PA@LYhc-bi!nbWIcdQ~&?(R5l+`+jL< z=G&zYN^nzd#LGq_s>@99mn~zus!mD>F01PCb{WBGg$qseKdz|5q$w+QS~1K-I!!@g z*J(u!CX|hglrc4lNJ{)jQ;*+hObFNJcQR2WQmSS=r}E-eRS@gtPSlp$*!EVlSJ=K@ zKFD6rnF9s1CUpo7y#<8Owg|&mn?2sl3uyCR=he72 zd!82`DtezM)#5`Pi-2R3k*D;bTm%HfjK=V+j0V<;H*4B(sY8*eHk%|u+!$fKj!9c7 z(+<6XpxUlh5N?I%7Gh~^vzT$E*^B|39Zv*>D!xfiB)Bl^USME6qk3 ziB0>Fw3v;Ak512XK4A+Xog}@O7f?onHF97vFO3#78nS{!HJM4SkfRMxvww zM;qLdNAM;w;%#d+ZY(L0SW#fsXTx`WCVbXVkJo+m7;>3$)MbHbK!b3j124Puc({?^ zU#f*7N?SApDEKGbms;xfn&Q_?)5B0k8#-OXvf8n$3}?o z?(vi8d_0=wV&jzSC$rJ{G)K#dv{_I+UWVYdI()AqfQPpY*L&Eky~~Ddeqd{}$>IyV zpY2oUYmf0T)M72mWfA+=LO9iOUv^dt)|GobGbt|0bFn_2ni#^*wyWT84L0P-ktlyx z%~Wd$S6V$d-sYmX9&~T7+Kj!JjBUd1Xz=7n_l*1FwiXd)nb)%%kMVPYt?PBA2;S#n zAr**Q4dqjdxsYaKWACsqGqrPE{OBA%#_>_ooed33l)~%DG78vZJKT1Pou%F*I3(>C zaH-!=vn9V-TWCHCnaWv%hdRD#p<3dxts1_lBu=$>vDR53iinD4aE_b#Mtbp>P-B1Z zY;sVzJZ&pzF(yKp<&8MEvs#3y_Il#!J<+8^D$cXY4WYNI6!tE^iy4}Z%;s2I!NnGD zbg5`57o#m@KHXVSSY07c6SrgD`I__ z-qq1^Ty1sYWKTUV^z_ou62cl#7~brKux`q}K@!&a8L3dGMJb`8im$oSs2r%Hmm;}| zZDKbRwz6M7+&D6*w-(7Fn{%R5cs*>v+3@dhtha^ah-=e{#5{?ohZfRYil^5f(w!X$ zc%}D@hL8wzfYqyCa0QokTk%Yv4!S+<_*>sTZKTk{f)GW;S9Xo!cApd1cDb~Xf_nva z+3qa+(cQiZiZ3`TF!AECF=)+m>8_X+@KS^1LZOnE1Vp33&L+vW^%6u&b>j5@2%C6h$vpn z8XvyD_hj2xG?}{<`bq2r4MlvWhtRna&Bu8yduI%1Pu_hgZZ^Jxsi9{zx$rWj0XpSk z-lxWEAQ`Qdvv_)@Ff!cN9_9Hc&0egZ0#4I;EZ)N^g=$aIjEKns6!!P%8J0pA&Qm@I zbR%J08rI_0h>|hz|+YVzHY(DSQEuH3VP0s z8SvVe?@rvDw=z0frqDkgx~l|U8dt%6$bfgpEq4mxu`UBsR3+|w=5S)xfW*WX?a0Lj zHzq2iR4}}1$w>FzlH%}8S=CyKJH8lCaWTTr#nS-3`K$L>kHlQt-$Z|XmR zk}XD|5RWI!tPSzpqzRcx1FlXIdJ1d?7S$5{Zoug33LZT$g|Dr(NqlE(zFGpyL380` zeCNPwqhc7-bi_ znO+wH&f44sQ7*b5y6N+t>U>w^=Tz<{<_3SnD2zp_cYzO+O@SiaJ?tKA#ifG^EUq~4 zH2r5*LU@P%2VIqj(5{?uY4J?73Hkv8y*%m=;&k{Z+5r7@J$`V)iWg4k5t$BRcCZp3 zobcdkqZv)B=FI!kfs!s!3|SKgiYHAVnc~uP{FAWI-eS%Y`!*z~L*YMXR3(93Cn3vT!B-NvRS%Y=D9!hJlB&){ias^u@ zVcd{fabdX@e~@YMr)3pgHTZB@OFz%6ph#?EnA( diff --git a/mobile/lib/infrastructure/entities/log.entity.g.dart b/mobile/lib/infrastructure/entities/log.entity.g.dart index 9300cf15c56c2641070501dd5fae706f453703f9..02fa817a08aa0e75101776b9b19d5d07ca0c6234 100644 GIT binary patch delta 3514 zcma)9?@t?b98Swhw`P<==`SqyfI(YVa4inC(-E2A)Dqds!kh_k&>M6++R|Q!OSieQ z%q?4VlaGlpG10j{z{QIRbN(2weIaNJi7%YSn8i05qsGJ~#{2eq*H7E;75b*V-t&BZ z_4z#a?S&8Y4{qvj4I7;CSeWSxFbQ^^3o~hNj1$;6pYaA@!C;3s44)JLdrN?ME|Xzr zIT^6sA22b@*?g#kTy=gX2k*N*V$Qmv+aZ510YKL>25;KzEqrp3ONR-X$)-~BM_9MbltG^mGxqCx zLxBy!@i?ShD`i)m;!5kF4$in7@Sd#+9PU;~^>;&5de4q@!%wYFsfLf?NZTxG7|a94BsaL)d$)Q~GJ`Cgv2&XQdtSdevVj*mDvA zr;=_hV5C<=PgZ@X6z9|L{F-yCsac{bS4ahE2TpRDoYZA^ZZrRAQ2E@j?3!UF!Yk z3c&Q(9GmbxD^bSc^PF5+0GeErFq*WWG$s3Kgu8=QA}(YD?P}DB^my1}$dW_RLc-vI zZ&7~Pm1H1IRf=hL4jo4<$+?}xx$%IMC!D&)-NW%R3e!>xZZGmT-$CODL)*a*4}Ol) zDRb2TA9~?a1Xd=d0si;J-w>Egi~woVDmT2QVoNnwke;(qnTEE1(}~6+5k~!2P|?K1 z=>*^p5mX;{Z;rtF;Gn(&@Q}DnUb~_Xp_Nu@-0-je3;W5(P;Qvl@`UN%tf7iCx32LT+6;| y5a)9jbmCuUF6zXy=bT13zlVplOJ-o4uo6)zgZmCJpli|H#j4F3a%xp)Qu delta 2998 zcma)8T})GF7*0D&6M@ib^E7B9FW=OIPeg0C&U&21))oiy zm<_?{s^5i#^9Kh!ba>#S+Mw`;o3hu$xyd+vo@T>LHq8Zve`>3r*+&quJeeEdSe8!l z43|AX6;U=O)kmZ_HblfIf}uhLtk&;@<(yAQH{7;4kqwrcoeHvumu15kX$1;<)kFq8D#g7Ela7*<*U#UW60S)RVYM`C$c*?$VMN1Gf4 zmTj+w)sDRgx*i#`69f#jvdBcBh{|z;);l^~AlXq4uKNl2b&-TC&)327iCys2w+-%f z_~3(KFEB3z)PQ%1JJA2qUid5BY!0~W{|f3R{MLZufem;txJUF3M7?sGUesbhP36@V znc&GBpFhd)Q!qjKlsZFg0b>astz$Gx8Qnf^_Z!{tT`dN$!P5FeGQj`i+V zE5)7*q1UyyR)3yk3v>_B)>fJ#kq?))H0T>ki5H1(*#eIvFNYZowPZx5RvW4lhFZ_a zBr5qD;*pDT15pt!)_x>UMN0k^s(y0P(p(cM{rZbJqw-JOWghdpj(tuC~GZvT`M( zo=&`=0!)L3CY4GBaYmU^?=Mg}j;({m#rZX;9Ut;98P8)2hiJoleq zlzBpc3gg*5#)_9`iAs3TQz&yH4IF;qp!U>jN``wKE_im_txl{PUll{iqYAgj7Zrla zu?biizpAifv^KrEDi55LLr;%p;QmY&bOj|R>ePb#xF8mPHW=hn`kt_mj|+5xd`h4= zozJTxG>xJvsVoX6_u<64(il!*+L)+|49Y}K(j{GJ-#_)8cENXkp=k~H_3r7|58>G zPbri^K%1N@AQ@yKB3)wjMHdsBxu6d?;g@NT9hD*cn}5fKf9DGGwyn589g9?8yZL diff --git a/mobile/lib/infrastructure/entities/memory.entity.drift.dart b/mobile/lib/infrastructure/entities/memory.entity.drift.dart index cb88651ba411fe8e85481617810d9f434e885d3a..f5f18695a567e552612cc75f5efc69b8c3835329 100644 GIT binary patch delta 6170 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 KW#3s?(ESUM&(bsi delta 5079 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 LWGuD}e<1%GZ~i)} delta 2458 zcmc&$ZD?Cn80IEzn%?vy-%DV9ncXU;LF;6NGm15ps2I0V^#I6OBWwVR!Y4!sag z?)iA$=Y7t5o^!uD#aw=!IWweCv4lQ-ARZIG*v?`~Q4jaH4cdUET4Wd8QD_v+h>eo>W3fK!K#FjTh?@#4 zeA`%bRS9-Nat9ulvOaz?of236=aZ>vNyOnQBVMZdbdfy)q6%Pub>f&Vh&q)~nMu2G zRrL{u>+}e#Yzlr7OI=1>t*$Fh@v1+>FX|vXwU-vz&x$K&Ol`PctHCR5Z8cp@llxfD zVV~xWwJ_w#UUeF`>!xHJ#*OFAF6{O+6fW1FVQ|F4!Q>PnMD)1QXsO}TDL2&;uhyDr z_$Z7URm?n=OzUw$+px&B=@#6iufMnp@=nkPj4py7 zS~yJj)M(_b3{Uei7xS9n2O-+F;3r)J1DnZZaYr4T5-eJfLr=hnVt>L z7_?}M81JDN!*34u-%!*UTH)0-+=u3jsS_SsVojQTINq);Tr|JW;C8be24?^}!$p3@ zJS+Pbm)RLgf~+YbE`+L93t1(1;IQ6l`jen#QSCIc4*NJAWo^e!AG;zhS1uYGZboc4 z>vUovq{eYRfggDhhxB|==nEkg##%d+g#00Q!k&MiQfu!ek1>q}3A+|koEA4)ENc|S zU#m@gdR#P5f%puCQzY>}s7`$R15^Cyf1vgi7x@QuJ*uu)AI`ZsG)K8rR(IaZVw1;D ze>S=NWwT^_L1<$t@Lmf7F*|KL@nmcSzbcH7r(g9(pcMmXikg)qox*NnHv+XT7;;8SsJMv3m7Ug&95L^=MbA@uI?^EyY~}XCh#_3+GCpM=eNlJR;y|$b^ny8*1Cv z!{5VVA=p6s4AivV41SHJ4pZUnjvQ0h-!J6y$vj;(&tgw!u%`G%ucmi8ThSD*!MScH zZ96a#*3xrog{IwB#9IyvSf&9^){lX_YltaM$6aaVze0-l?2}_c{F>R zcr<9ESBIt8mJ47k*g_Abo)&=`PA^A`z(LzyS_GqL^6+v26g+(oGbKcVv3`yfT*+Kc z%8#a9*g4RR<$e!ONU3i!lXi(DIh~=GZaR^ikwmgLIh~W}{Y>DGw_$tSiClaG-ik-5 z^ta;SRlpj-H6zW;WuGV^r&=j$spD_MW(LEIyKr)_i^1|xh?EO(J~cNtO)|OB*_@Qk zXJ)5JUx^k%8(!8jkO9ZxBK2b<#R8~^|S diff --git a/mobile/lib/infrastructure/entities/merged_asset.drift.dart b/mobile/lib/infrastructure/entities/merged_asset.drift.dart index 7f56b25d4e1dcfdfbc0576edb24e2ce299bef644..75f8de2de006abdc154416722349b169d5c7506b 100644 GIT binary patch delta 701 zcmaix&r2IY7>1#{DDE$7vzx>uw1Xna)(}a8NmCO`OKB?>ddRtlsafMfV&Z0^h^*Iw zhf;WZX?wA>HxCxlTPyw_^->SL7Ch;pP-iygQWOUU=9_uvn}=t9mEM=WQt7rr_;~Ji zSh>nPceOrG)~T0Glda$YTN07ee2KTC1mC4M!@)MM7vvm#IWZ&-dHGL@y~yi6-N3dM28=Q||^%e3&!yaU&a@!TzhRm=4IVLQ{L?bP70 z9W#y>s)c2>gimS_Kh+duZKjY}_FB#AT4N9tC|+wL<2kfec30VaD#gJ;R{YAtqS(Tu~+~|8KX-pPVF&e^cC$mg2BeFwIU)@S4X(SPPf6T4lCo>GO-kX za$VEk;SUo*L-7xny({)@e2h%vbyP=mM8ls*@tUqZ8oe)LH!+Tb#Q2cUKfzbd0jf2` AVgLXD delta 658 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 C1rz)L delta 4446 zcmcIodrX_x6_>#_#`uNt13xeq4A=(a2bA&%U`t!-!)wawH;sjN-fQr6^;?$LG4{^&HVt=eQ#|EZE~(Wb4^rm%ZIKlmUp zwX16B)BV14?mg#sf9KqD@Aai;a{m3ToU6th{Kae1$O-**Pe;ZR;b_D;BgboBE5?o5 zB3Q*r+FG%YBSxgoVu*1^r^7KWM0O@(;m9Ep2~KiuId13Jac;&6U%eTB7h9l}l;X+U z#R|N!v<_OOO;7%C>|BRpaH-E4W$EgnEMx7l{GiHRt2HT8&wy5ladc zUNTf-PF)Cd8Cj*P=jG3>kazJiW4T4p*N$khgO?vt72;yKQJ^#8y2?j&MJTc7<5I;+ z|JPLtTsDWv6@4`5sMmcaRQdA{=|4BHhI*Nk zV_neAG~dMt3pWVpL8_dWvs1;rMz(i~g>MZ|0CzR(z6ujd78v9iKE=kl$Q} z?ah)L(uV%#N}O(X(I*eDH`l;m)nK;8gl0+~+qfbv&caw`a|?AvC#EMOEy5mp&uH}V z2p8)K4YF8M6fU|);a-DI<|4s38QdVp#SM1+W`h-dt!jL_;UrGBHo+q|E?``x|IMU+J;{|uRl!8g*Ia0B}y+AWYHdU8XPI$@ay3F9hBh~mu zuK_>qkm25@&8XX4PZNjEK*J7JtHDbhOv-TYryF7FSbKX~p>-7mQm}0?P_VINlvR7LA1yJWempZt*)PduX5{|^vKhV+ z#R^7(J(Y}+o(6#zIW?C$8S*iN{ZVga%Ew{;ytsaz9PN0}!+##Nr#LShk4{8mt4Ysu z@M7kv5x>~#qy(fTtLBlRXqg_G=f}3K%=58uEOB@f&CP7~-Pz`|J9zOZ%h}b~vsM>7 z9drpmgP$nLPWLHmCgrHBSPuGU5kUy=XV^9ypoJ>S;LtOL_HI(LZxf?&> z<U}{R1NHXci*lm)SE@|XwVDAkOh@Pc1#Qwh#8aEGE~LexiU0VIGUj& z>)Nubhu2=(^_Y^n&nAf*>fKGe(b(=vEbK1EPj`1G#gFxf3e%i0^t&3zlG zM-zj9z_1#DLwXz;wyrUdjOh7ZZx1VRd)T*rj{>@+)5~oH;gQ-kdZs3A#)l(P{Ogcz ze*anyZ|&h>DFjPkB>C0-gE@GI%hS(fFPw?P;W*vg_|*CMKpCYtqrwYOBkVy7T7zbq z)lW~EFcGxj$)Jrc6n@x>gytpLoKF5acpw+GoLQDhWb|=1%pdMeE^?oee;iDK-eN2yb1%+O3av3SOgErUuNnB0ilJ~OK4 zEa;l6#ix^vI5$^}u85ZcO-@DrD5??6iI$w8N3c>nQ}lAoMG_=Hcom+QtnOhoB2(2{ zRu5iQtsX1T91BiNbEE~ebLC0P(VAR44WyuIk?f}ICYho|;GHr$-2&I_J^hCONkx<_ zhw)}&AP?kt30jX=;=u7zoIGBWeC2q)*p!JY{kLEjgVCA_V|xJib4$>8q7XG=9i+2` z=of3@m{lW6+sh{ucuHJ^@!2B$!K1<1SuNk{Pin9!wy!N# D-gj>7 diff --git a/mobile/lib/infrastructure/entities/remote_album.entity.drift.dart b/mobile/lib/infrastructure/entities/remote_album.entity.drift.dart index bc13c8cb5cdeb1897cc39093f8e128f7136e68e6..30a6d0b535868f3c50836190283eaa2c0a0e015b 100644 GIT binary patch delta 5987 zcmc&&du&_P8JANh@hgt)`2EVYW51-`XCy6Y z!^BEENK^7d+F(qCjnN_%nqsC63A!TK7%FTq9zmEE15RHe|>f4eyI`&Fkv_{j3)LTm@!ArB~U|*E;h8GKT!{L~f;)ZAB-O(a}hP zZPST&bB$PNcVX|i74Njm@P4~lnx143vf1a`Wc6NlBr&l+8V|bqBD*=I>3%Z2dxXHG zb}~a#`=gQWXkua{NhfeJ?_5DfD;2~U`AH}wdo6FVz`P z<}|}xpu;aE58`&I3d2$pI;1ucmAnNr$_N6oLG%=srFZ4I{B|g4-OmOF)&dia(KSaM+^2tNHclQP}91bqV~Xh zTvQi|S(hvn88D^}=#~lcgt>;O0^bjK@JhfUl3lIoK}{u8j2$SpFE!yRs>IV*Pi(<$ zK?fE_bJHuNte0zKG6q+)PK;>Fv7mM1g4WDRNOcScn?~`Ft`K)P1LV0H&+7De%jw6S z78Q+;F5_fZ*26TyYmq4N>UK}WMk3L8bw-L|yfWC0262EnD8qS+4~u3cdRIG9;8)~M zvtb{1>WC>N>J3Wla_KSabvOhHXt)H%_~@~uDqkzc>y|e7jip5A8hpAonD6641;%g1 zd#mlJH5DSqG|F$pf?rh{KW8(CEgQf5W-7c^V)AA;bJ)^;gN=kxSffh)&DwuG+EsF~ z>tjsVP^`d)9P0!W6HJ_Q_<2_GgJsV9 zzaAF3(d+$RFzAYV7SER%ajJBEnmM*5{9MLPdf046Oz*cb%rz2%5}2N7uo_KyG%ZN; zqG2UTj5Q=FRD4oYcxzE+G2(u22|0oFh`3ZM$XP{HcjB^P3y!W05V|`tklJ zdD5TxKZL6?i1rE<#z^{;^Xq0pMoy{_J}gjh_t&!9pNW+RyT`_oIMJ@h6YY$k3UJ}0 zCL2x{Dsf4#z@M8e^pwc7=V~-~tV4#A9o6J-#%CQ244s{%dT`<1&c>w`1Tn9nS8)z0 zWzM(TZA_+M@G;d~$&kH+Q!A<$MTDEVc)M9c_$iZTr1?tVQjJl+BtZz_Db30Bc!Lg| zAqmtQ{FrJeVA~xV0-5#&u^e~Sd)fZNtduR(E^Wy6FW0Z;W!JIK*-!&{cChW@+BzvU z!rv;j0X$r5L~ElJs?B1&R$GcAjioq6{_#02-f2|g!^Sl*Hm${(IxAkS^VzQrn(CxK zzN%EQ&+>XwB@(sM4N`U!Uj#UtBZRB2oWocKFRuT}<+ z*J$x_Qz=fgkVCy$$<|uzUP#3zW*e)UKf*okBGCq%_2^RN8xtbh5Y^H_S*QMR>JE&&lboBNCv~-)J?Ghls&hFKI|H-bz-9abK&3J|3o~zYwl9 zoUI#Ra<*CV;^rG-a<*070Mn7SA{Ghto$`V>`%BE#-h#j<8&Lb}_ zlv(346CQ1s;M8pj*yIwLhv(Y8n4B`scSw+|vCurHqoXwrn&w=yl4Q69O*SLW=jc(` z$+bW0u;Y)nwBValX1e%DXT6f8M=dG-21de(1kUa?r9SNZk;v(ZMLZm?Fs-wrkuB`& z4CTdOcqBpJY|d>nV__(t)TD>DnkC8j1p6L=KWypCR6 zJg)2z!+aS7_S@9dfPps0NehwbNaqpj!%Kw;NAwRbt@|jojnm%SjR=y5(ctg%pvFN5s9OL>iK5JZ0=9`|s|u znoLG|c%i;9Cq>PEE}C*4MM*YciTT2b{SlIl#9n7K8D>I4D48iCl=T7_yueog1HC;3 z)N~Q=g|WLvqw&ogli1i_=<$0!>}cOj5-g7+7%Fyb#HsCNa*mvA3|RkP+5Q|p?a9v} z;ZP4~-RYdVjz4*2%Y$3RDp%k;I|4;n4Z=Ws@$Qai1y|&Qx9i=RfL_I98c!jS7Gt?2 zT~ytxKrQXM!008mAf62RCB(#7oV-3^|2At)Y&2QRIhe|L z*a9{UW1Y-8$kd}Pw$V1UVHTjm3Cu7l5pgD!sEuWay&+D8o6e6bKzbS=ffB`iiokU+9}hSHGED?Q-1J@6?gx2=82y{=JR> zHuk%v+2EG#p^-|)$UDnsj`pXD+d#U zyEkREoZkH?+6IboYL^NJ2b_3(z)IHmmx1`_z&eyi7;I0fF%WU$Si}Z*WTimrT;zdV zmUU>0n(e%=wkG4T(LHrsh1M014#p;_n{YV#Je1V#-J@uI1W1?JTe^?weX$41I*5Ji!NeWJ(tYp_v*>dYRKO~c- zvHKiYoHpbAp_Rhzp(&=7W<*eN$bv*{B^F}3CE)Pum`~(@o0oe4#g7O z7oykpStaRV{AJ3J?NrR^;2E{)(zDzmo@H1(Vqx=XX4Gw7CP5Dj3Tm2s$10w%Aa&Lp5BZs!uvA3vR=2@b}`_O&I(Ml zQ`s|RCbS9VQ#Nd!GO=M#m-#w8FeSq?#|`)inT<3W@$nS-vU?x^b)6Pn2aFgwP>Q#P zG+3Nd;oWI9-ZC}v!2kn?X_!(yIHsOP5ja&PJFue4LAJ zX1Iu7fxGXq;^t0!9(jGE(}-v9DoDMS(8tqa2VN6b0BsB%Iwa-doxWxq&2z%uWV%c~ z5u=p|GCMl;(r9>^B}+Ow1wmgGO?WVwUziau_A3~K_PeQ?f8^KM8Fo9*Mk5J^3s!Z8 z6YMSQI2&i9V{Brn0`^rU=x(-3$QlNxC#l#Wsy;z0!Ni*;(tFXioHsP8J*>(B5b^g@!~&rOFl*L99GvmP+FnFfTcpS)5o;5 zrZv%7oHv%C(5%9buEf!LFFvSrq0OSh#rj&25AzN? z-l-_TDa+2ZWe!BG<||l7W6)Nw_}UgeTI3*FRM)UFr9p%0%Koofnw)nW&y9Nls-0S# zb6Rk))Gq`n75iMe5&^~|%%yNpBk-SMXs{U)(9BqcNhbw`7Dt`xG<}sYP6a;2_qeN4 zps9j(0-Tf{nj!0b8g#kC-%wyn+!dH08jjp#zRsW?6D-%0*v7kBlgO441=?E(8tmdY=o2Z?eN|cMDpq0{qlU8&>xgW1bWm zt(s)dfPw^hB_65wW6)A2z;V7;N<`O+8HR$g1z)VvB`0rKlP9?RwSW@mv?fdiN^$5m zMUttiNnxSgrAtqgB%i6)ioT&Bv=*4~bfXT#wO>EO=z6KAMUeAwun;4j^8Z7CGP@Wd z?mlvp^?wkk{VJtAb5P-7as)7|td|^2^fYre)}g%7hF2V#)UcEU*bGUN8K?40gtXAq zfW51i;U^Pj%5bcy3#X(d*sn6+RG}H785=^)QjITN^O{oUnir2PGb9f-9~PmqMS=3A zHpE)Y62?2Hz;1GozbaAS z;D=o&a1aN6*KYUuH}` zxGW)3wzhf`e3)l_3<*VNUyV!{kv?pqzZ|dk%kX-ii#(0cFL&TC%N00il?pW?(Br|& z%e{nVz#mpw@H?pj!Ic(5(_!xl3x2SoSngxO31+BSflpVsVC%2Eity&NU^zY{kjw~r zaG>TZ!XF&4VTLHVMELJly75Ji44OeB4h*W%Ft`gR2b(hu-^D>EZj&;&YnxS0docQ= zeHewWqp>*`?v6$xiI`wq-9Y|U(l(NAWp!VM`>CehWX&x<6_L)(!$mxPCOpNFZZEQu zc8|<>cq&1g$a5ohvQOHx`f+-b4W~DFB(%T8=fmFAOK@WY&JTG?h!{F?9fI)0ty)|h zb`?h0#8{l0;kj58RGedNb-5>pcomss=O2ue;NKfHcz&%1&xKrKkH<$%MBp|xm0U0u zX9*l49Xyd6Bt^Wj%#$XC!u++x`q$|MvEg;)g2)%vr9{roL@p7jfd5<7Wu7$oy2ZAv zFQS%8W80!^ybm=aHQ2OKj%U_ax`;;wYUrBbA^TV1$7@Ykx`CW;!)t&IZju+LH~bbx zm7(~uxbpE?64uK+S3SH8@!_R()$qFk50?mq$9V4B9KR#PMrj9sHFyYe{DPaPjIE(S zzE6;TEEGV^#ww^b1qvxdV{y`0k~|az3|=nEw|YGS<*E@7U`>K6AAkKcl{m@nv0Fu?qYhC+ z23S7q$J3D|&_){IWY^;?YX{hBoMbIJCX@qo%Id>l#0~Fwxh|BoSr9>^Ha^}jOutX3 zvq;QN+cx(jwz&rvZXG__;)0lCikT3? zi+rhh2Uic@gbRJ$dYt22xX3y2ELTjxF*I@al7aBd($pQ+&qQ{R?QvtR3`vM^#`$xp z*)~SF`mKtyy(so2t96b?Tf5c!qsWJa)Stf$1B-&FJ7?R{&y>GN)_|nu@+=9qzayl9^diI^~(PqF5wrr=jGBmNre>JRgLcx($B z=_2kQC8ayp!#wdQiPa1NWiI)Oju&$5zNl4Blax9j`O1t_g!i`EaNB!F|OlF43e$3#vaEYo+uAz{3!_SwJFBgRv;tj%cey<5H-mMq%>Ih#>K4TQ(7rY|* zE`K5qziA*X$Bb6V#|Q+xLb~}da)`ml+dR%I0&OA@i)Mg^U2{`7zQ>t7v%NLXn7hgG zcx-w(;q)$i$ABB=^vRyN7qi;n-BpB^U3DEfE3%l)tszYMTTNR|HK7F~OUI+6$9is; zMV+FOD6m7^G~0&r?IwJ<%Xo$MNGhdKY-6xzpT$F$akW()Q=_xfLKY5E|F@-T<(GFI z;Va8MlX5(?Xv2>domgnM;*&)?p6W8ecE1&M_XqL!E*-|_P0)8&;K;ld$L7oNx4mvs z%Zv+qYM^r zCMKC;%3NMv{G>{Dq|cP@)RE#(Z8Uk}&KqULOcSZ!q;T#@1Ml-wDohSffd{HwOEfL{8^&IHt3CtjXu;3&OJr#mC&w3)`56$R>yR!va%gGZe*uyGWFP(Q!7JqKYYGPJjDk=J%HW$C*tm2YFq>G@!f!E9H zWNhBE7+3MwTESyomA{}+x$>tuGW?jEBf~$q7!l`T24~(SJNj?*vMiJ7; z;ZJ>SnTPD)5H-6Iw^n1P#wXwDCb3T3tZu>?YWdD;z#*p{rFxCJSY1LyExXNq_)qUb z6orI_@3#Y1C*~&m zmrqx63r@HmMEdb$Z?OnLJ*z2@RKT}-Xeft?4gPA-&xsKXA7c@?#6nwx})(0#Dr6kSO-5u}^*9&MVw-RCJ=R)O z`Cpo49rrgFW@I?c*&TubXZ$OLP?iTemCTb^9zR&qj8}t=I2t7QJm8*p&t#0380V7= zzjY*);ge)dE|VJEL=x$NkuAN+ov{1080N}wBRXGb@428JgIoo61+AEJRNz?9f;;s2 zRWNRxwKk>3vl2}YfYX7rxNwLb29;FRNGm@P+c80)MK`agJ}~OEO6+TyL`#!a7Da;7 z=XX7mm9c@Wlm6A>&O$S8%FAGEwF^&cdpWh&3gbnsPSiAT*xjl`y0u;!FBG1(kP4U8 z6|$g!W~iDrIr`h;!q+`*I#h-X64LMhj92)6I5eLKFZcL=JbckTwg%dPVuXHYgp{re@ zCWIyWx)#oGB&J5eQGz;QmdAFY!_~N>*iru9ctnQQ#cd9H(_u+4Ff^1Vsci3Hme1r^ zR>p|Lmu~T$#RqEz6hp3;cE5_xCFpM2mh{{`!B>{-Dh7(|C7`~02CxJBx<8SQAhy(G zm3W9Xp-arz=Q8}p)Tp3xX6c93z6_s8PM0@~ciLnG(H_TL|Lc4F4?>x6xkovT%>UeT zR;G}u+2LgdyRg0K%9Puj%KD_b#N4xgEbMDX(bIcOqI{#*R4!45dbw3-2zl>vZ7EK9 zgzBXt$pjOKRpuQST;85Py2@ULZ~9&N>-{gvO6UdioL`5*H5@I^Z1m=8D=sWG(#kh4 Ke{s$BlK%nJqIS^$ delta 2430 zcmcIlYitx%6wbc4vt`-tmTf!x=p~` z0YWmlVPVwg>`V81r^i{oe^7W}`oge~UL|C5gIQcw{)E%2Lon!U*sCf=w~oPnwI36V z12@z`>{IEetw=GD=Fp(Ih`82>%{q(R*@xSzQdBU-k{dryz+J6?zM>%BEc$r{WW5CU zO=%F#x>6N|;u?^$Rbsuyf}G8SJsJm|FW&GdcpUt^Z$;4jM*STb4pp>|oJ!tbnY#>Rjlf1&JqQ4K3pZaY=O2+r=6_!lxFY7ww1F=6)> z6Y{Vk*tJ+Gsp1z$bXyKohRtZAsn{5B;F4d1@tOrVVyTt@&5~Ck%@+L0ETD5W3|2R; zv6WPyAg+46NYy$)s?78oQ4k`^6hoiwzrQ2NKAcFSa;UV@P&R@I&Xn(R^!yK!PH@gSIg2;v@gzOrGGUu5_ut6+HkX`} z+P{&rM|-bmVX~G*B*8vVq!{G95&9DG_~M#ZEsb@H%F&vvr>_l%lUA7ZUdZ_IhT9-H4O*6?mtyOv@2ILspAUF$Y>>a|H-J0zTAe#JL9ZtO14^Yaa%` z-B^wCxD`j@^U)sPfgj?jdtES9Q~_^7OA~B|L0OBfi5mQtbVwC?GU=H*GYo!D66h9L z!7Yl@S3EOzs5w2BdppDiSlF`?pM`W1M5nJFucV&Ah~A2nw-~uZCEA-V7NQayZDAR= zi_c_)Y)9IKJ1tSX*vvTzDcJf3(k?II2M1{TP51Caw1IBo2Qz|K>^M7G7vfl}17Eea zK(@3T6;>UbOUr5cCY#*&qNR97kiq`kP$38}1rXr`R zjw@|%VQ0G;Xiwov`>TdNz7VQg$np}?v1M)aM?K^n@8MJjdw=zh9VYzRajawtPCU83 zQGrj>OW0M0R2N$$DkGBIfL}WObNW^1H+Ow0!&99a+E)DC<_a<@jN}GJg*3@NJCN~B z5!z0B{^z|GaO?EAwYC>myWgdJ7T{=)>OQ9vJ$5Kpbm!UL^K#UMohp*%vwU8+>PaPp ZHLm>LHJfGkz3)E3f?dnzqia8s{|)a@|Cs;) diff --git a/mobile/lib/infrastructure/entities/remote_album_user.entity.drift.dart b/mobile/lib/infrastructure/entities/remote_album_user.entity.drift.dart index 7ec1151a8a703faf80df884c13be55c4d175088c..f8167ddf94b17d39bdda0ddd1e8b192283e42ef8 100644 GIT binary patch delta 3855 zcmcgvYfPKh8J4jzwlUZkU+@KUY{13_J{xm0#)NRmg*1i$(UQ3BkeN;9%G_+zGHvOo zw3|9@ZTeK5rfO~Jx;0gWMC<&hl&V{$R*JT)U8YD=FIw0pb(^$mNS&4++tAMWF2>N7 zY+aR4vd-~2@AtmX`#k5I_k4f6B75ge+2#++%E$oL6!mx{uExXiYJAkuh+7?cY@N~K zP{<>{;Ooa1%bIagZr*R&7&qdQTnpBQ<37Cog>q$^hR_Gw@?Im~OReTp3&|YcXA=QM zT^VhjX?0?xpTiqbr&^jLSXYE1xs|05R4TWU$+HQ_ z%WqT_o$)Y!TmA$Vl{P%oZN#sYCOoAKA|I%!m7Fsp;ql?3ZNSN;lR}8%aOq#nSY0?* zu>qAz51Y!0e^%7X*o(*TE!8hDr4C5xKcs&BHb~T!floy;UdfSzkx)&3HJ=&(vb*p`gF#oyIU&sXU5NWnV1sz*n{I6T4G3De3ZGzz zgvEiUycT>|n-QVf@qJ_U0dNJHRG$sL=J*2X|ZNj90b3Ru)HF>ohWLI zTWcg?enPXfQ9;_U+N(vZiPV?SO-P9_Y#B5D#%QMgdO|)y9%j-)-^bI$s$?S3?sY>e zm8lDhUVVv7YgRq3*$vpT+wiw$7hS$)-0w{0_lc#55zbIGZkAQz z1*H~i5e5D4#)ABj_eQ{M6}0_pk0A8JucQ(Z%@&P740&1%wN_+gp zuW5wf>k1{k{CV(${%-n{HmM2~(LR2IuD3bG&8b3d`vhMq%*+@W7VHfT5SR^CKrc4dAn>1AM{8|Kh3q{7{Utu4aLOj?*C zB#}uca;fBaVqUy<&LuKA+Qm!5HrzL)#cu`){ysQ_zQethLhAf_#q!}!7OzH#w~|X` z_lJ`Y`Mq8?@fo7s9184-rW^iRcQJo2yUg*a34DAk2R1C_u`%qHGZL;1w$NMbKZgAn z>v!UpF`Y^hvM@a|D8u8U-4*=3fZARktrKn`e;Iw!QVcsIk{V0p6O^FGj~p$!z`IAj zvwK#}2yBRU%ST5_?ZWu$(dR{hJH}0o$prN#2AmydIwW@W9FbhuZ_+ULT=L_gAF2E>j#0(;$4{?b8iG@G8w zPcLUq(=QM%y}*Bd2#mAHRy!|4(IKrLuA*~XnRdK-ib!md-xMYVKZzDfWaYmwh+S4`O!}`Lh)@+nI3kniZDEt+HBfF1t8? zBDc6uWQ<<@COkzag*PW+GSRicz#FpI#iJPGlf9f!Y$Q=iQ4?uUP+G|3rAdpL^@IZS z`__7FPbzUaq{n95jHanZd>FTv(_@3Ku;n%r9+<46hwS`PVj)d&N}s1{!mkKwRJb}d zRu02i5Bko!3-_FTR;CoopEBM6Z`_HuFIOmHTC delta 3191 zcmcgvZERat8J54|_&V{o9mlbgW7qM=;@sGd+kE*WPD7)#P1Yu%K|t!=)Hkh*W2d%5 z+qt3e3(%yN^+83W(po@hKc;D!jF6^ntvYE!z+lpf5S3^%io_2jC?6U~o7Qsf^+(ez zL8>&cWZmO)&w1YGea`#7=k@J(B!7HEvi^d!i6Qh819zky=Tj}TDde*}9qZ%+U4%bV;&bUD$pqOkuE@{u zOMHRP9pj5p!7Q$hnT2iFCS1Z}g(bLts0kje9Wgnx$0t%Fq`11m7g%>Hy%=bWOWY#0 z^62N;6+S(~7gw_-%qf0@KQWi_tlExH+=NzT2p+Wy8;U4m@n$)jN&7KvbKa%G`Vm@47lD;$3BWAK@KsxxO9NRmMfJelFlh z{CLLNgC4!6a!d17iA?bSPJ1{0Vrz!n)}|1SfgtF%AZSxTp|j#mU9-sZp+SRx>y{8P zTQTN$;DTO@qB)>&i$l#ve*FwnRY9^cJ3&X^RzdIa~GLoLdx-~zE#cP6! zmToE?cxbRAWmMn;ixD5&cgZNCC|Ok9Qp40BX79q+oxOP3=|fBBAXYp<>PpmQ$JNd@ z>W&t-O$#+{JzIDQ?x%X5jMueJiy#u-vuJkYR>j?!Te9+;^|a)YjcO_CX`?#+SmYS@ zJ4OBe7HPt-h75RBZ>{NAKl*i}2EXhGd`d?I2j!xceZq*!;4*F1w4rO>ro-u=0ez0D zw)Y2`@QK}7)7Ofsz8yHOHdC-BoKtIX&S68sQ`Pzdha8>uR@`@VK^t%*NHx(0g1GBw zYH0t>&s1{{<*UOTi{(>s@L#pAL|v~-|Bu2hyA8M-`riuMh6gSK&bt-3WAch)#_#@2 z#kNpXBQ`?XCl{P1UJ{wU7U$;DI+M?r=7fSc#pSr;d|~_I>Va&upMJaWoK+{(+lPr= zxG-wPJ(|l+tR4482PHn}dmR`~hEQT%cs{uYMC+mk4R|MDk&*P`B`vWKvHJRJ)nvF@ zg?+fy_fsL_jl*&;QjvE&eli>?GYVjA|{-SJhgR~3O6EV{4Ubj*csV9 zs`T+fy(DmYO?Yv)4=;zD!kvWsyEO>MjWi3%o(<>+%oX22QPL8R`-&y5L^n~Yw+2H> z@fW>T{X^ZjIHUwO>Rc+5_67)-&Cq@$JtOIBn(jL_#7VSYGJ$XL2;sXhRjKX;@y& z=d&bJoXkRE4{6%I^jekISG!Gpt>@jW@A;@jwXzRnSRIMd^t;#Q(n zaRMZLHpeYzj>XBzVm?!=w5{-Iq+5O$r(Ec^U>Y)RTnRmRAcVaxLCj1>xkTh4~DsRnCDxg^KqGw@OWoqF^ olI9wjGX8b63%`&VBnkXp=4Tpa%D8#ZT{)lnXWb8Hg~}%R57TJU^Z)<= diff --git a/mobile/lib/infrastructure/entities/remote_asset.entity.dart b/mobile/lib/infrastructure/entities/remote_asset.entity.dart index cb14e2501..7ee2e76ff 100644 --- a/mobile/lib/infrastructure/entities/remote_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/remote_asset.entity.dart @@ -5,11 +5,7 @@ import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/utils/asset.mixin.dart'; import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; -@TableIndex( - name: 'UQ_remote_asset_owner_checksum', - columns: {#checksum, #ownerId}, - unique: true, -) +@TableIndex(name: 'UQ_remote_asset_owner_checksum', columns: {#checksum, #ownerId}, unique: true) @TableIndex(name: 'idx_remote_asset_checksum', columns: {#checksum}) class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { const RemoteAssetEntity(); @@ -40,21 +36,21 @@ class RemoteAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin extension RemoteAssetEntityDataDomainEx on RemoteAssetEntityData { RemoteAsset toDto() => RemoteAsset( - id: id, - name: name, - ownerId: ownerId, - checksum: checksum, - type: type, - createdAt: createdAt, - updatedAt: updatedAt, - durationInSeconds: durationInSeconds, - isFavorite: isFavorite, - height: height, - width: width, - thumbHash: thumbHash, - visibility: visibility, - livePhotoVideoId: livePhotoVideoId, - localId: null, - stackId: stackId, - ); + id: id, + name: name, + ownerId: ownerId, + checksum: checksum, + type: type, + createdAt: createdAt, + updatedAt: updatedAt, + durationInSeconds: durationInSeconds, + isFavorite: isFavorite, + height: height, + width: width, + thumbHash: thumbHash, + visibility: visibility, + livePhotoVideoId: livePhotoVideoId, + localId: null, + stackId: stackId, + ); } diff --git a/mobile/lib/infrastructure/entities/remote_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/remote_asset.entity.drift.dart index 543ed659857d6e99404966b7cc4b7fa9eac4392c..6bd416b259b971af6efe202cae74ee0e6dc98ebc 100644 GIT binary patch delta 8184 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 delta 6748 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 diff --git a/mobile/lib/infrastructure/entities/store.entity.g.dart b/mobile/lib/infrastructure/entities/store.entity.g.dart index b97b5b0a28ce11a5754a99e632296ef9ba3c5c3d..7da92cf77848903ff849f9cff946342c2ea18672 100644 GIT binary patch delta 1379 zcma)+&u7g}^F(w)f z@=UxbN86Z4LgK|k#fukB{0B^o7d&XvM9=E%vds=iiF=vN%;)>&z3-cuN4NKPb-kZ+ zOFWlF%PgvutCcJg6MRj&QWjd31dF7t2A(Q3%i?AHmlo=^4LD~IPO@f%wplam8;1S% zi8-T7sNbrHS;TWJYBd_8Ul_PAz=6Zwx7t4HA>=XYd9D-Yp*L>S~{-iaG^(V0F3>QiCf)fs^-!9?gQ=<%i`|+;m2skw4I#UxaPf6AKP@Q?5Wk zBjGiZ3Sgwm_<{|wj#HGjlwvttrUGY`0bWoS;Zl$Srw0gGI242To*>+#18_I(gFPy* zQ0v|{K^=OdQ>i`Q0YT{^5hYHS_Q7j9PN5^q6z7zjQz=&6f`%LZ5+VK&pbafSNW!7t zts)Mc8P)^B7=(!RxD9u7b(SL-_E@I4AV=Ok?Kws0;kUB{U%U=tH_aP6WFi#d4-MZ! zj|o!q=U;Lay(7qxM{BAY&unxiZ-iG%HW;Sv6PkQ_ zmIfRdw@pp6QI@2NSc4L~L+E=MtySMM;fYpRiNXs_c)oItkm4r+28_pibO90xqQmW# gDuISWK^dLb(6Ps-zjOA73CgU{$yxhfb1(IO0bDhc+W-In delta 1091 zcmZ`(O=#0#7^Yo|TWO_TYMQpT{nE8|>z|$83Y!CAu9tyKL{B5w&}F1)mu702qTakH zs}BS5RuE*OFf8I__;c~HgJNm5Zd1?f)o3Rm3)bDyTK@f_jC1<>i`E>0v+|vXi3kW&y`xXUl0H$38QW zkZZR@wMeA0K}E=By*?P~v^=3Pcd7gzg|CrSM18M^f}Q!vRU0ZERwu_U?{<_ZGv24O zIN|5u$i!_kSoVLQolw4;g1jkWqi_w8B#$L7h__KcTAq1qhrMvJJGdN8;&wDNl&c1w z;LddX*xVQH6V}r`zFnTh=X3&x^i3BxxnG3V@FO0vxp1FP_M?oQ5VXTGzE6>Xgct48 zteX%?(Jmb6`5_;(^vp22H57JL7j{V%1x-|uk3BMV4C1}uW6w+-M{_N5(AA;GN9kzB z4IK-dA16~jtCq%;p=B`XMI+JfkK9d*7%G89Gnud!|4Du{yI$gsgL&~TwQqJm3bQfu ztM5jSV^B%Lx~xy1UPDv6(_7I5RYNYfgT-uu`hR=}e6EdyTzq8yc|H&zWJOaYrP8y` z*ymeVI1|LT%ylfE9bKO)utBrFE@;$GWr!iTD9JQ&v8I$IO{yvRs-WFi6C2Ym^ajs> zoef)+>N{<3cHQcMuX`AZB$YDwt!}(ISM9pdpTp!3SU**n&eQWhC&v4Cf+4Vk(4439 IckY$_A3ljwGynhq diff --git a/mobile/lib/infrastructure/entities/user.entity.dart b/mobile/lib/infrastructure/entities/user.entity.dart index b0c1e6e86..ab5b9a562 100644 --- a/mobile/lib/infrastructure/entities/user.entity.dart +++ b/mobile/lib/infrastructure/entities/user.entity.dart @@ -43,36 +43,36 @@ class User { }); static User fromDto(UserDto dto) => User( - id: dto.id, - updatedAt: dto.updatedAt, - email: dto.email, - name: dto.name, - isAdmin: dto.isAdmin, - isPartnerSharedBy: dto.isPartnerSharedBy, - isPartnerSharedWith: dto.isPartnerSharedWith, - profileImagePath: dto.profileImagePath ?? "", - avatarColor: dto.avatarColor, - memoryEnabled: dto.memoryEnabled, - inTimeline: dto.inTimeline, - quotaUsageInBytes: dto.quotaUsageInBytes, - quotaSizeInBytes: dto.quotaSizeInBytes, - ); + id: dto.id, + updatedAt: dto.updatedAt, + email: dto.email, + name: dto.name, + isAdmin: dto.isAdmin, + isPartnerSharedBy: dto.isPartnerSharedBy, + isPartnerSharedWith: dto.isPartnerSharedWith, + profileImagePath: dto.profileImagePath ?? "", + avatarColor: dto.avatarColor, + memoryEnabled: dto.memoryEnabled, + inTimeline: dto.inTimeline, + quotaUsageInBytes: dto.quotaUsageInBytes, + quotaSizeInBytes: dto.quotaSizeInBytes, + ); UserDto toDto() => UserDto( - id: id, - email: email, - name: name, - isAdmin: isAdmin, - updatedAt: updatedAt, - profileImagePath: profileImagePath.isEmpty ? null : profileImagePath, - avatarColor: avatarColor, - memoryEnabled: memoryEnabled, - inTimeline: inTimeline, - isPartnerSharedBy: isPartnerSharedBy, - isPartnerSharedWith: isPartnerSharedWith, - quotaUsageInBytes: quotaUsageInBytes, - quotaSizeInBytes: quotaSizeInBytes, - ); + id: id, + email: email, + name: name, + isAdmin: isAdmin, + updatedAt: updatedAt, + profileImagePath: profileImagePath.isEmpty ? null : profileImagePath, + avatarColor: avatarColor, + memoryEnabled: memoryEnabled, + inTimeline: inTimeline, + isPartnerSharedBy: isPartnerSharedBy, + isPartnerSharedWith: isPartnerSharedWith, + quotaUsageInBytes: quotaUsageInBytes, + quotaSizeInBytes: quotaSizeInBytes, + ); } class UserEntity extends Table with DriftDefaultsMixin { diff --git a/mobile/lib/infrastructure/entities/user.entity.drift.dart b/mobile/lib/infrastructure/entities/user.entity.drift.dart index 32be96951829bdb9dc0255b3575d3f6a41ea6476..2c3c8a1f9ca9198acbcef16143aa7756dbec2fc9 100644 GIT binary patch delta 3629 zcmb_fZERcR6_yh_u^q?p_xHzZCywoWIC1kqKAN~82~G3Sr7bC~(=6P?rd)6w659ww zyQLCLn}k-Bhi$($#Ke#`RGQ9HfA9lo2!6Fwn6w|0Kr9Hx2xHTzwn;;x?0xU`y>{BP zTc<^e-h0nE?>Wyo?{kjd`{_H1udXS!o>eHc_?FwHCl3^|%Xxk^8+k@c2rkT7aDGmW z{^2@&f6j=vlLqW6bb|c7xjMX>G~&&}W^A0+pmW}cEteLvRZ5s98j+Y$%rC27HIwHB`=&G!`Nrp5V7 zn&PbFkh1WRVc%< zFIo7dC2C=0AnB*_>1-+|JTv;VT3uCi8L|3QOiggv7RQE7jWvg3Q>m|N)8cVQOk8{v zj)Penf>!u!9`P|=@)e;gUJAN}-DiT1Iw=P8O8sjD|D_lNKMPv*6&8dHW6R^j&x1zh zVAJl`$Xd)Q?dY|eFmAQ?>Q`gk_a=bwI%H3bn`gQ=rrfaD5Kq}LfL z@vr#2{cVL!eiennXrTBmI=xtPw%|w35&B<`?W78yI6LXH6=7F9U0Kui;|I} z4Oc|4^G_TUWY?>0m~b}>Ii8P_piy4 z25dR(ZCsX)sZlPIS>l!-AJ`wG2$*gt4Kj6wfVLb3DuHGOY@$8yRsRpbf9-4gPr&iD z|C&xb1zPGs?RgwixUoybk+K=^W7O(VFfMs;JYYx8VJmTI)zQMZwCZp%F2NKuGa}Ko zgBByA#mhn3C6s*+2Q9UwGVJB1T`tbB41hi0XuwT(sZeWos05qhzk)wi1jBqPEE;kd zp39|EN4b@>D0qa+e6+SCP=)jB3u}GNDEpoE>u2Ec@VJ)g!+)gpORQeIF zkjam(W^?&Qdr${6y1qqTPM@gi!jl`qTQq`igK+af` zRwx#Ip_QhUsS|z)X3}|%46zgpVhVy(O5i>mi$p@m~fQ$LbY@xA`d{--)`^^t1#cC|W$?#Aj^$ ztnJEp8QfZ7HP0;;a@^VUBA;DcdODxZ-3!b=wbu(Uy|G{!W+HZ|xpc80jP4@T5;Mh@ z(j5SQo1#~t(=~N+1u0P!V-|WhC*@hfw#2*esor^MMWoJYXVJq%MUzfGKWhdT;=em}#+vUgKrwnj)2XUy|gAck| zG(rn7^k9yE*d1a342yCVN)Ue2JuUm&?2Y30J$lUcG@{Vs$7eAEUhN6udXE>6^;Edr z?48F#FTvp%BVOnY;%cuC$9r4LF^iw~jw_%aXu#D$11|U1swF-kG3eCMQMVu^hbQ~m z?r5nOMp@Z*x35F8-3;sK;HKV8(om@I$@RBOcDF^xc7Lr_iXIK%^C=f@^tbMd6yF%I z$mPNEKtix$jdN(wVJp>=wVe!+I(&25g_{G+p#^_#*HF`TjU12C&W-O4R%(6N9W+!T z8eZ@e?FW@rRnKT~Y}o8hiM!X+YXyEiog(>1`CLq7J=OcMKJ3INb5_Q3{9@RP_DQ!| zGKO)^&L}Q?2}~_KRoqCdRaMi|z?Ct(?y=lzR$@8c9rFo2T#VmuQkg{RpUAIM!Y2sp zHE@S*LDmcORs0DMaY;5(!+j`xH*{IY=qP)TUr8s3Ogif11J|gMj*SFHk~Woi135S0 zF!QMa8iXVgVs=8j%M$_oZlW1CCkUmt3Ew8C9!5zW?92C?1_XTVoaQ4iUaHc9P2!(h)wzeuA!_3>9yj z+^lA2_hHh8pCr}zBmJ;?BdJwOrnvZ!1D_^cRM7zQybJfAFhP6Df`{fC>DL>*X?c{$ Mo-!6M%@5Z88>1ip2mk;8 delta 2873 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 KLp7h|E%+bhgHHbd delta 3167 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 delta 2626 zcmcImZERcB8P>HOf802Zoy6bv^>J*+_a=^GH%SxX#EzQ?(%`0_V-lz|H}OsD)=h(b z1C$U1Y^`%H@@h1-2r562107aqfhVzduPHr zx}7T!GkI7puPSu$XZ?_wD37YjaS|dqsZUK%OJ)8tN-ibGiDR_GJBFELevXwO+i97~&(( zjUUKw7v6Mrd|%&ZoBE6P)_?ZbUxgOD8f<~mAHXGxjkTxTPYW*SqM{+}7l!H2OFKNk ziO7$7aZ?z;eL5!^8&{JemP2X067s>G54ecdi>xBqGgfa=vG!FcrM1jiS}4cE$5>IH zB@y_$Jv`CKhG}D7A4IuZ#JTPn{JndYzg?)Xg+i2}EVwUX!;we;KaaRzj(Ko@*xey7 zQ_7l>%jE@m@fa=nH6G!p6VFpOpNJUIAMK|<3l2wn?nFGa(}9g>+Z~8)NXG`vqQcsQ zHjo^5;!LauuLlK-n=~_*dL#I>w-=p#ZnH$>DmjqhG2a)#slEWLiFW+D z?+J`2#v5EaVDaiGJ&pu>@KV-~$AUaOp$NRfRw^Arl%~>0MWZy0cWtIp!27~(O_e5( z&t`aju`E}s1Yw=0_Pb=7s~aG=HsG^}@jC6t5l+pA3DK5^O2v4B$mNn;Rf==+amu|* za=FU*{1<}(b5)xcbdlR8;>%PXed$3Ot#B%d=R6&FJv|YQQ^Nco5UdhtExbG^7$_+w za4qF`H0p_cNj_3ikKlYdfYaMrfgJ-BSTHrn_i@imE7Q{E3rzr*?!=D=+aqyJ@NFg| z%$l{?8on4zqH`#X>vub92Z!Puo*o`DZ(3W!#;^w;55LrYs2-(ViYhZ^$LZ};_~Z5) zczeX>Zz$I%K(5{)dn(FO=}~+>@`||mT{~Mvk&9v}m7K1WmelQ&yN{6ypZwZSDC%Exoi6ISNz zZeK4nDI1`7h_sC1%ETu)yCZ34K2aqJ*R%J)J=BkxTpO;;5v=D#8fGWn$+c`%!Ef?q zj7^?uc0RdOIdOcpO7Aw9pX|b|Ne4Y@=Kp9c=G|>leN0OkdX#m%JK@L1hy}I$A1G~Y zJxTQh!yTug%!+X2dvG;tv}mU44)55mIXp6D!>*|zp=s+{qb3@6D;o4?Gd^6LYGoAp z&sJA^E}N?tbDa$FWH5w1lV&VM>{uzd@k~L0kuuWdLYIk-Vdg31sSwtt+ws$&o06uj z_V#qD1%IQrHp6VNMrO}(w+r~ny#jus7q}cQ=zC3@rfP}8TO5lz%yTvfbN6os+=|O{ KrrMP`H}`LV7zHT+ diff --git a/mobile/lib/infrastructure/repositories/asset_media.repository.dart b/mobile/lib/infrastructure/repositories/asset_media.repository.dart index e8bf9ace4..6c81c7ff7 100644 --- a/mobile/lib/infrastructure/repositories/asset_media.repository.dart +++ b/mobile/lib/infrastructure/repositories/asset_media.repository.dart @@ -6,21 +6,13 @@ import 'package:photo_manager/photo_manager.dart'; class AssetMediaRepository { const AssetMediaRepository(); - Future getThumbnail( - String id, { - int quality = 80, - Size size = const Size.square(256), - }) => - AssetEntity( - id: id, - // The below fields are not used in thumbnailDataWithSize but are required - // to create an AssetEntity instance. It is faster to create a dummy AssetEntity - // instance than to fetch the asset from the device first. - typeInt: AssetType.image.index, - width: size.width.toInt(), - height: size.height.toInt(), - ).thumbnailDataWithSize( - ThumbnailSize(size.width.toInt(), size.height.toInt()), - quality: quality, - ); + Future getThumbnail(String id, {int quality = 80, Size size = const Size.square(256)}) => AssetEntity( + id: id, + // The below fields are not used in thumbnailDataWithSize but are required + // to create an AssetEntity instance. It is faster to create a dummy AssetEntity + // instance than to fetch the asset from the device first. + typeInt: AssetType.image.index, + width: size.width.toInt(), + height: size.height.toInt(), + ).thumbnailDataWithSize(ThumbnailSize(size.width.toInt(), size.height.toInt()), quality: quality); } diff --git a/mobile/lib/infrastructure/repositories/backup.repository.dart b/mobile/lib/infrastructure/repositories/backup.repository.dart index aaba90de5..ce38ff931 100644 --- a/mobile/lib/infrastructure/repositories/backup.repository.dart +++ b/mobile/lib/infrastructure/repositories/backup.repository.dart @@ -24,9 +24,7 @@ class DriftBackupRepository extends DriftDatabaseRepository { useColumns: false, ), ]) - ..where( - _db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.excluded), - ); + ..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.excluded)); } Future getTotalCount() async { @@ -79,9 +77,7 @@ class DriftBackupRepository extends DriftDatabaseRepository { Future getBackupCount(String userId) async { final query = _db.localAlbumAssetEntity.selectOnly(distinct: true) - ..addColumns( - [_db.localAlbumAssetEntity.assetId], - ) + ..addColumns([_db.localAlbumAssetEntity.assetId]) ..join([ innerJoin( _db.localAlbumEntity, @@ -112,9 +108,7 @@ class DriftBackupRepository extends DriftDatabaseRepository { Future> getCandidates(String userId) async { final selectedAlbumIds = _db.localAlbumEntity.selectOnly(distinct: true) ..addColumns([_db.localAlbumEntity.id]) - ..where( - _db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected), - ); + ..where(_db.localAlbumEntity.backupSelection.equalsValue(BackupSelection.selected)); final query = _db.localAssetEntity.select() ..where( @@ -138,11 +132,7 @@ class DriftBackupRepository extends DriftDatabaseRepository { ) & lae.id.isNotInQuery(_getExcludedSubquery()), ) - ..orderBy( - [ - (localAsset) => OrderingTerm.desc(localAsset.createdAt), - ], - ); + ..orderBy([(localAsset) => OrderingTerm.desc(localAsset.createdAt)]); return query.map((localAsset) => localAsset.toDto()).get(); } diff --git a/mobile/lib/infrastructure/repositories/db.repository.dart b/mobile/lib/infrastructure/repositories/db.repository.dart index 15fce4d64..7f6374ed2 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.dart @@ -59,66 +59,58 @@ class IsarDatabaseRepository implements IDatabaseRepository { PersonEntity, AssetFaceEntity, ], - include: { - 'package:immich_mobile/infrastructure/entities/merged_asset.drift', - }, + include: {'package:immich_mobile/infrastructure/entities/merged_asset.drift'}, ) class Drift extends $Drift implements IDatabaseRepository { Drift([QueryExecutor? executor]) - : super( - executor ?? - driftDatabase( - name: 'immich', - native: const DriftNativeOptions(shareAcrossIsolates: true), - ), - ); + : super(executor ?? driftDatabase(name: 'immich', native: const DriftNativeOptions(shareAcrossIsolates: true))); @override int get schemaVersion => 4; @override MigrationStrategy get migration => MigrationStrategy( - onUpgrade: (m, from, to) async { - // Run migration steps without foreign keys and re-enable them later - await customStatement('PRAGMA foreign_keys = OFF'); + onUpgrade: (m, from, to) async { + // Run migration steps without foreign keys and re-enable them later + await customStatement('PRAGMA foreign_keys = OFF'); - await m.runMigrationSteps( - from: from, - to: to, - steps: migrationSteps( - from1To2: (m, v2) async { - for (final entity in v2.entities) { - await m.drop(entity); - await m.create(entity); - } - }, - from2To3: (m, v3) async { - // Removed foreign key constraint on stack.primaryAssetId - await m.alterTable(TableMigration(v3.stackEntity)); - }, - from3To4: (m, v4) async { - // Thumbnail path column got removed from person_entity - await m.alterTable(TableMigration(v4.personEntity)); - // asset_face_entity is added - await m.create(v4.assetFaceEntity); - }, - ), - ); - - if (kDebugMode) { - // Fail if the migration broke foreign keys - final wrongFKs = await customSelect('PRAGMA foreign_key_check').get(); - assert(wrongFKs.isEmpty, '${wrongFKs.map((e) => e.data)}'); - } - - await customStatement('PRAGMA foreign_keys = ON;'); - }, - beforeOpen: (details) async { - await customStatement('PRAGMA foreign_keys = ON'); - await customStatement('PRAGMA synchronous = NORMAL'); - await customStatement('PRAGMA journal_mode = WAL'); - }, + await m.runMigrationSteps( + from: from, + to: to, + steps: migrationSteps( + from1To2: (m, v2) async { + for (final entity in v2.entities) { + await m.drop(entity); + await m.create(entity); + } + }, + from2To3: (m, v3) async { + // Removed foreign key constraint on stack.primaryAssetId + await m.alterTable(TableMigration(v3.stackEntity)); + }, + from3To4: (m, v4) async { + // Thumbnail path column got removed from person_entity + await m.alterTable(TableMigration(v4.personEntity)); + // asset_face_entity is added + await m.create(v4.assetFaceEntity); + }, + ), ); + + if (kDebugMode) { + // Fail if the migration broke foreign keys + final wrongFKs = await customSelect('PRAGMA foreign_key_check').get(); + assert(wrongFKs.isEmpty, '${wrongFKs.map((e) => e.data)}'); + } + + await customStatement('PRAGMA foreign_keys = ON;'); + }, + beforeOpen: (details) async { + await customStatement('PRAGMA foreign_keys = ON'); + await customStatement('PRAGMA synchronous = NORMAL'); + await customStatement('PRAGMA journal_mode = WAL'); + }, + ); } class DriftDatabaseRepository implements IDatabaseRepository { diff --git a/mobile/lib/infrastructure/repositories/db.repository.drift.dart b/mobile/lib/infrastructure/repositories/db.repository.drift.dart index f5962f09ab09c5ed9a62e1186922d7a026c4f875..296b87900ed54e08d58f66622c0d5848a5c9cd6f 100644 GIT binary patch delta 1848 zcmb_dJ#W)c6jg)N#�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 QWv~tgl4t+{k1vD&06rUy*8l(j diff --git a/mobile/lib/infrastructure/repositories/db.repository.steps.dart b/mobile/lib/infrastructure/repositories/db.repository.steps.dart index 57c90f731d78192b8882bf19d22aa2a5dac6a4b1..5bf20780f4cad769dad32d0028f0c3e491c5af51 100644 GIT binary patch literal 60965 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 E2W1r*O#lD@ literal 60290 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 VtrJ&8-onK~wn%Hkzi)w(|35&X>7W1r diff --git a/mobile/lib/infrastructure/repositories/exif.repository.dart b/mobile/lib/infrastructure/repositories/exif.repository.dart index 726e51b77..0ede30680 100644 --- a/mobile/lib/infrastructure/repositories/exif.repository.dart +++ b/mobile/lib/infrastructure/repositories/exif.repository.dart @@ -33,9 +33,7 @@ class IsarExifRepository extends IsarDatabaseRepository { Future> updateAll(List exifInfos) { return transaction(() async { - await _db.exifInfos.putAll( - exifInfos.map(entity.ExifInfo.fromDto).toList(), - ); + await _db.exifInfos.putAll(exifInfos.map(entity.ExifInfo.fromDto).toList()); return exifInfos; }); } diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index c1e5724b4..feb25925f 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -14,8 +14,8 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { final Drift _db; final Platform _platform; const DriftLocalAlbumRepository(this._db, {Platform? platform}) - : _platform = platform ?? const LocalPlatform(), - super(_db); + : _platform = platform ?? const LocalPlatform(), + super(_db); Future> getAll({Set sortBy = const {}}) { final assetCount = _db.localAlbumAssetEntity.assetId.count(); @@ -34,41 +34,32 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { if (sortBy.isNotEmpty) { final orderings = []; for (final sort in sortBy) { - orderings.add( - switch (sort) { - SortLocalAlbumsBy.id => OrderingTerm.asc(_db.localAlbumEntity.id), - SortLocalAlbumsBy.backupSelection => OrderingTerm.asc(_db.localAlbumEntity.backupSelection), - SortLocalAlbumsBy.isIosSharedAlbum => OrderingTerm.asc(_db.localAlbumEntity.isIosSharedAlbum), - SortLocalAlbumsBy.name => OrderingTerm.asc(_db.localAlbumEntity.name), - SortLocalAlbumsBy.assetCount => OrderingTerm.desc(assetCount), - }, - ); + orderings.add(switch (sort) { + SortLocalAlbumsBy.id => OrderingTerm.asc(_db.localAlbumEntity.id), + SortLocalAlbumsBy.backupSelection => OrderingTerm.asc(_db.localAlbumEntity.backupSelection), + SortLocalAlbumsBy.isIosSharedAlbum => OrderingTerm.asc(_db.localAlbumEntity.isIosSharedAlbum), + SortLocalAlbumsBy.name => OrderingTerm.asc(_db.localAlbumEntity.name), + SortLocalAlbumsBy.assetCount => OrderingTerm.desc(assetCount), + }); } query.orderBy(orderings); } - return query - .map( - (row) => row.readTable(_db.localAlbumEntity).toDto(assetCount: row.read(assetCount) ?? 0), - ) - .get(); + return query.map((row) => row.readTable(_db.localAlbumEntity).toDto(assetCount: row.read(assetCount) ?? 0)).get(); } Future delete(String albumId) => transaction(() async { - // Remove all assets that are only in this particular album - // We cannot remove all assets in the album because they might be in other albums in iOS - // That is not the case on Android since asset <-> album has one:one mapping - final assetsToDelete = _platform.isIOS ? await _getUniqueAssetsInAlbum(albumId) : await getAssetIds(albumId); - await _deleteAssets(assetsToDelete); + // Remove all assets that are only in this particular album + // We cannot remove all assets in the album because they might be in other albums in iOS + // That is not the case on Android since asset <-> album has one:one mapping + final assetsToDelete = _platform.isIOS ? await _getUniqueAssetsInAlbum(albumId) : await getAssetIds(albumId); + await _deleteAssets(assetsToDelete); - // All the other assets that are still associated will be unlinked automatically on-cascade - await _db.managers.localAlbumEntity.filter((a) => a.id.equals(albumId)).delete(); - }); + // All the other assets that are still associated will be unlinked automatically on-cascade + await _db.managers.localAlbumEntity.filter((a) => a.id.equals(albumId)).delete(); + }); - Future syncDeletes( - String albumId, - Iterable assetIdsToKeep, - ) async { + Future syncDeletes(String albumId, Iterable assetIdsToKeep) async { if (assetIdsToKeep.isEmpty) { return Future.value(); } @@ -77,12 +68,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { deleteSmt.where((localAsset) { final subQuery = _db.localAlbumAssetEntity.selectOnly() ..addColumns([_db.localAlbumAssetEntity.assetId]) - ..join([ - innerJoin( - _db.localAlbumEntity, - _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id), - ), - ]); + ..join([innerJoin(_db.localAlbumEntity, _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id))]); subQuery.where( _db.localAlbumEntity.id.equals(albumId) & _db.localAlbumAssetEntity.assetId.isNotIn(assetIdsToKeep), ); @@ -109,12 +95,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { if (toUpsert.isNotEmpty) { await _upsertAssets(toUpsert); await _db.localAlbumAssetEntity.insertAll( - toUpsert.map( - (a) => LocalAlbumAssetEntityCompanion.insert( - assetId: a.id, - albumId: localAlbum.id, - ), - ), + toUpsert.map((a) => LocalAlbumAssetEntityCompanion.insert(assetId: a.id, albumId: localAlbum.id)), mode: InsertMode.insertOrIgnore, ); } @@ -162,10 +143,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { final subQuery = _db.localAlbumAssetEntity.selectOnly() ..addColumns([_db.localAlbumAssetEntity.assetId]) ..join([ - innerJoin( - _db.localAlbumEntity, - _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id), - ), + innerJoin(_db.localAlbumEntity, _db.localAlbumAssetEntity.albumId.equalsExp(_db.localAlbumEntity.id)), ]); subQuery.where(_db.localAlbumEntity.marker_.isNotNull()); return localAsset.id.isInQuery(subQuery); @@ -178,16 +156,12 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { } Future> getAssets(String albumId) { - final query = _db.localAlbumAssetEntity.select().join( - [ - innerJoin( - _db.localAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - ), - ], - ) - ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) - ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]); + final query = + _db.localAlbumAssetEntity.select().join([ + innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)), + ]) + ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) + ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]); return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get(); } @@ -224,11 +198,8 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { batch.insertAll( _db.localAlbumAssetEntity, albumIds.cast().nonNulls.map( - (albumId) => LocalAlbumAssetEntityCompanion.insert( - assetId: assetId, - albumId: albumId, - ), - ), + (albumId) => LocalAlbumAssetEntityCompanion.insert(assetId: assetId, albumId: albumId), + ), onConflict: DoNothing(), ); }); @@ -237,18 +208,12 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { } Future> getAssetsToHash(String albumId) { - final query = _db.localAlbumAssetEntity.select().join( - [ - innerJoin( - _db.localAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - ), - ], - ) - ..where( - _db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAssetEntity.checksum.isNull(), - ) - ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]); + final query = + _db.localAlbumAssetEntity.select().join([ + innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)), + ]) + ..where(_db.localAlbumAssetEntity.albumId.equals(albumId) & _db.localAssetEntity.checksum.isNull()) + ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]); return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get(); } @@ -275,10 +240,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { batch.insert<$LocalAssetEntityTable, LocalAssetEntityData>( _db.localAssetEntity, companion, - onConflict: DoUpdate( - (_) => companion, - where: (old) => old.updatedAt.isNotValue(asset.updatedAt), - ), + onConflict: DoUpdate((_) => companion, where: (old) => old.updatedAt.isNotValue(asset.updatedAt)), ); } }); @@ -351,15 +313,13 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { } Future getThumbnail(String albumId) async { - final query = _db.localAlbumAssetEntity.select().join([ - innerJoin( - _db.localAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - ), - ]) - ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) - ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]) - ..limit(1); + final query = + _db.localAlbumAssetEntity.select().join([ + innerJoin(_db.localAssetEntity, _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id)), + ]) + ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) + ..orderBy([OrderingTerm.asc(_db.localAssetEntity.id)]) + ..limit(1); final results = await query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get(); diff --git a/mobile/lib/infrastructure/repositories/local_asset.repository.dart b/mobile/lib/infrastructure/repositories/local_asset.repository.dart index 17521e1cb..58adac30d 100644 --- a/mobile/lib/infrastructure/repositories/local_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_asset.repository.dart @@ -16,14 +16,11 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository { _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum), useColumns: false, ), - ]) - ..where(_db.localAssetEntity.id.equals(id)); + ])..where(_db.localAssetEntity.id.equals(id)); return query.map((row) { final asset = row.readTable(_db.localAssetEntity).toDto(); - return asset.copyWith( - remoteId: row.read(_db.remoteAssetEntity.id), - ); + return asset.copyWith(remoteId: row.read(_db.remoteAssetEntity.id)); }).watchSingleOrNull(); } diff --git a/mobile/lib/infrastructure/repositories/memory.repository.dart b/mobile/lib/infrastructure/repositories/memory.repository.dart index 3663b75bf..2a52faf2d 100644 --- a/mobile/lib/infrastructure/repositories/memory.repository.dart +++ b/mobile/lib/infrastructure/repositories/memory.repository.dart @@ -13,30 +13,21 @@ class DriftMemoryRepository extends DriftDatabaseRepository { final now = DateTime.now(); final localUtc = DateTime.utc(now.year, now.month, now.day, 0, 0, 0); - final query = _db.select(_db.memoryEntity).join([ - leftOuterJoin( - _db.memoryAssetEntity, - _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id), - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) & - _db.remoteAssetEntity.deletedAt.isNull() & - _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline), - ), - ]) - ..where(_db.memoryEntity.ownerId.equals(ownerId)) - ..where(_db.memoryEntity.deletedAt.isNull()) - ..where( - _db.memoryEntity.showAt.isSmallerOrEqualValue(localUtc), - ) - ..where( - _db.memoryEntity.hideAt.isBiggerOrEqualValue(localUtc), - ) - ..orderBy([ - OrderingTerm.desc(_db.memoryEntity.memoryAt), - OrderingTerm.asc(_db.remoteAssetEntity.createdAt), - ]); + final query = + _db.select(_db.memoryEntity).join([ + leftOuterJoin(_db.memoryAssetEntity, _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id)), + leftOuterJoin( + _db.remoteAssetEntity, + _db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) & + _db.remoteAssetEntity.deletedAt.isNull() & + _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline), + ), + ]) + ..where(_db.memoryEntity.ownerId.equals(ownerId)) + ..where(_db.memoryEntity.deletedAt.isNull()) + ..where(_db.memoryEntity.showAt.isSmallerOrEqualValue(localUtc)) + ..where(_db.memoryEntity.hideAt.isBiggerOrEqualValue(localUtc)) + ..orderBy([OrderingTerm.desc(_db.memoryEntity.memoryAt), OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]); final rows = await query.get(); @@ -59,24 +50,19 @@ class DriftMemoryRepository extends DriftDatabaseRepository { } Future get(String memoryId) async { - final query = _db.select(_db.memoryEntity).join([ - leftOuterJoin( - _db.memoryAssetEntity, - _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id), - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) & - _db.remoteAssetEntity.deletedAt.isNull() & - _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline), - ), - ]) - ..where(_db.memoryEntity.id.equals(memoryId)) - ..where(_db.memoryEntity.deletedAt.isNull()) - ..orderBy([ - OrderingTerm.desc(_db.memoryEntity.memoryAt), - OrderingTerm.asc(_db.remoteAssetEntity.createdAt), - ]); + final query = + _db.select(_db.memoryEntity).join([ + leftOuterJoin(_db.memoryAssetEntity, _db.memoryAssetEntity.memoryId.equalsExp(_db.memoryEntity.id)), + leftOuterJoin( + _db.remoteAssetEntity, + _db.remoteAssetEntity.id.equalsExp(_db.memoryAssetEntity.assetId) & + _db.remoteAssetEntity.deletedAt.isNull() & + _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline), + ), + ]) + ..where(_db.memoryEntity.id.equals(memoryId)) + ..where(_db.memoryEntity.deletedAt.isNull()) + ..orderBy([OrderingTerm.desc(_db.memoryEntity.memoryAt), OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]); final rows = await query.get(); diff --git a/mobile/lib/infrastructure/repositories/partner.repository.dart b/mobile/lib/infrastructure/repositories/partner.repository.dart index 9e78b1b65..b12061ad2 100644 --- a/mobile/lib/infrastructure/repositories/partner.repository.dart +++ b/mobile/lib/infrastructure/repositories/partner.repository.dart @@ -9,24 +9,13 @@ class DriftPartnerRepository extends DriftDatabaseRepository { Future> getPartners(String userId) { final query = _db.select(_db.partnerEntity).join([ - innerJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById), - ), - ]) - ..where( - _db.partnerEntity.sharedWithId.equals(userId), - ); + innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)), + ])..where(_db.partnerEntity.sharedWithId.equals(userId)); return query.map((row) { final user = row.readTable(_db.userEntity); final partner = row.readTable(_db.partnerEntity); - return PartnerUserDto( - id: user.id, - email: user.email, - name: user.name, - inTimeline: partner.inTimeline, - ); + return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline); }).get(); } @@ -35,60 +24,33 @@ class DriftPartnerRepository extends DriftDatabaseRepository { final query = _db.select(_db.userEntity)..where((row) => row.id.equals(currentUserId).not()); return query.map((user) { - return PartnerUserDto( - id: user.id, - email: user.email, - name: user.name, - inTimeline: false, - ); + return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: false); }).get(); } // Get users who are sharing their photos WITH the current user Future> getSharedWith(String partnerId) { final query = _db.select(_db.partnerEntity).join([ - innerJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById), - ), - ]) - ..where( - _db.partnerEntity.sharedWithId.equals(partnerId), - ); + innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)), + ])..where(_db.partnerEntity.sharedWithId.equals(partnerId)); return query.map((row) { final user = row.readTable(_db.userEntity); final partner = row.readTable(_db.partnerEntity); - return PartnerUserDto( - id: user.id, - email: user.email, - name: user.name, - inTimeline: partner.inTimeline, - ); + return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline); }).get(); } // Get users who the current user is sharing their photos TO Future> getSharedBy(String userId) { final query = _db.select(_db.partnerEntity).join([ - innerJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.partnerEntity.sharedWithId), - ), - ]) - ..where( - _db.partnerEntity.sharedById.equals(userId), - ); + innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedWithId)), + ])..where(_db.partnerEntity.sharedById.equals(userId)); return query.map((row) { final user = row.readTable(_db.userEntity); final partner = row.readTable(_db.partnerEntity); - return PartnerUserDto( - id: user.id, - email: user.email, - name: user.name, - inTimeline: partner.inTimeline, - ); + return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline); }).get(); } @@ -108,35 +70,24 @@ class DriftPartnerRepository extends DriftDatabaseRepository { Future getPartner(String partnerId, String userId) { final query = _db.select(_db.partnerEntity).join([ - innerJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById), - ), - ]) - ..where( - _db.partnerEntity.sharedById.equals(partnerId) & _db.partnerEntity.sharedWithId.equals(userId), - ); + innerJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.partnerEntity.sharedById)), + ])..where(_db.partnerEntity.sharedById.equals(partnerId) & _db.partnerEntity.sharedWithId.equals(userId)); return query.map((row) { final user = row.readTable(_db.userEntity); final partner = row.readTable(_db.partnerEntity); - return PartnerUserDto( - id: user.id, - email: user.email, - name: user.name, - inTimeline: partner.inTimeline, - ); + return PartnerUserDto(id: user.id, email: user.email, name: user.name, inTimeline: partner.inTimeline); }).getSingleOrNull(); } Future toggleShowInTimeline(PartnerUserDto partner, String userId) { return _db.partnerEntity.update().replace( - PartnerEntityCompanion( - sharedById: Value(partner.id), - sharedWithId: Value(userId), - inTimeline: Value(!partner.inTimeline), - ), - ); + PartnerEntityCompanion( + sharedById: Value(partner.id), + sharedWithId: Value(userId), + inTimeline: Value(!partner.inTimeline), + ), + ); } Future create(String partnerId, String userId) { @@ -150,8 +101,6 @@ class DriftPartnerRepository extends DriftDatabaseRepository { } Future delete(String partnerId, String userId) { - return _db.partnerEntity.deleteWhere( - (t) => t.sharedById.equals(userId) & t.sharedWithId.equals(partnerId), - ); + return _db.partnerEntity.deleteWhere((t) => t.sharedById.equals(userId) & t.sharedWithId.equals(partnerId)); } } diff --git a/mobile/lib/infrastructure/repositories/remote_album.repository.dart b/mobile/lib/infrastructure/repositories/remote_album.repository.dart index f60caceb4..79f3d78fd 100644 --- a/mobile/lib/infrastructure/repositories/remote_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_album.repository.dart @@ -16,9 +16,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { final Drift _db; const DriftRemoteAlbumRepository(this._db) : super(_db); - Future> getAll({ - Set sortBy = const {SortRemoteAlbumsBy.updatedAt}, - }) { + Future> getAll({Set sortBy = const {SortRemoteAlbumsBy.updatedAt}}) { final assetCount = _db.remoteAlbumAssetEntity.assetId.count(); final query = _db.remoteAlbumEntity.select().join([ @@ -32,11 +30,7 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), useColumns: false, ), - leftOuterJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), - useColumns: false, - ), + leftOuterJoin(_db.userEntity, _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), useColumns: false), ]); query ..where(_db.remoteAssetEntity.deletedAt.isNull()) @@ -47,22 +41,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { if (sortBy.isNotEmpty) { final orderings = []; for (final sort in sortBy) { - orderings.add( - switch (sort) { - SortRemoteAlbumsBy.id => OrderingTerm.asc(_db.remoteAlbumEntity.id), - SortRemoteAlbumsBy.updatedAt => OrderingTerm.desc(_db.remoteAlbumEntity.updatedAt), - }, - ); + orderings.add(switch (sort) { + SortRemoteAlbumsBy.id => OrderingTerm.asc(_db.remoteAlbumEntity.id), + SortRemoteAlbumsBy.updatedAt => OrderingTerm.desc(_db.remoteAlbumEntity.updatedAt), + }); } query.orderBy(orderings); } return query .map( - (row) => row.readTable(_db.remoteAlbumEntity).toDto( - assetCount: row.read(assetCount) ?? 0, - ownerName: row.read(_db.userEntity.name)!, - ), + (row) => row + .readTable(_db.remoteAlbumEntity) + .toDto(assetCount: row.read(assetCount) ?? 0, ownerName: row.read(_db.userEntity.name)!), ) .get(); } @@ -70,42 +61,39 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { Future get(String albumId) { final assetCount = _db.remoteAlbumAssetEntity.assetId.count(); - final query = _db.remoteAlbumEntity.select().join([ - leftOuterJoin( - _db.remoteAlbumAssetEntity, - _db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id), - useColumns: false, - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), - useColumns: false, - ), - leftOuterJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), - useColumns: false, - ), - ]) - ..where(_db.remoteAlbumEntity.id.equals(albumId) & _db.remoteAssetEntity.deletedAt.isNull()) - ..addColumns([assetCount]) - ..addColumns([_db.userEntity.name]) - ..groupBy([_db.remoteAlbumEntity.id]); + final query = + _db.remoteAlbumEntity.select().join([ + leftOuterJoin( + _db.remoteAlbumAssetEntity, + _db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id), + useColumns: false, + ), + leftOuterJoin( + _db.remoteAssetEntity, + _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), + useColumns: false, + ), + leftOuterJoin( + _db.userEntity, + _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), + useColumns: false, + ), + ]) + ..where(_db.remoteAlbumEntity.id.equals(albumId) & _db.remoteAssetEntity.deletedAt.isNull()) + ..addColumns([assetCount]) + ..addColumns([_db.userEntity.name]) + ..groupBy([_db.remoteAlbumEntity.id]); return query .map( - (row) => row.readTable(_db.remoteAlbumEntity).toDto( - assetCount: row.read(assetCount) ?? 0, - ownerName: row.read(_db.userEntity.name)!, - ), + (row) => row + .readTable(_db.remoteAlbumEntity) + .toDto(assetCount: row.read(assetCount) ?? 0, ownerName: row.read(_db.userEntity.name)!), ) .getSingleOrNull(); } - Future create( - RemoteAlbum album, - List assetIds, - ) async { + Future create(RemoteAlbum album, List assetIds) async { await _db.transaction(() async { final entity = RemoteAlbumEntityCompanion( id: Value(album.id), @@ -123,17 +111,11 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { if (assetIds.isNotEmpty) { final albumAssets = assetIds.map( - (assetId) => RemoteAlbumAssetEntityCompanion( - albumId: Value(album.id), - assetId: Value(assetId), - ), + (assetId) => RemoteAlbumAssetEntityCompanion(albumId: Value(album.id), assetId: Value(assetId)), ); await _db.batch((batch) { - batch.insertAll( - _db.remoteAlbumAssetEntity, - albumAssets, - ); + batch.insertAll(_db.remoteAlbumAssetEntity, albumAssets); }); } }); @@ -141,38 +123,30 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { Future update(RemoteAlbum album) async { await _db.remoteAlbumEntity.update().replace( - RemoteAlbumEntityCompanion( - id: Value(album.id), - name: Value(album.name), - ownerId: Value(album.ownerId), - createdAt: Value(album.createdAt), - updatedAt: Value(album.updatedAt), - description: Value(album.description), - thumbnailAssetId: Value(album.thumbnailAssetId), - isActivityEnabled: Value(album.isActivityEnabled), - order: Value(album.order), - ), - ); + RemoteAlbumEntityCompanion( + id: Value(album.id), + name: Value(album.name), + ownerId: Value(album.ownerId), + createdAt: Value(album.createdAt), + updatedAt: Value(album.updatedAt), + description: Value(album.description), + thumbnailAssetId: Value(album.thumbnailAssetId), + isActivityEnabled: Value(album.isActivityEnabled), + order: Value(album.order), + ), + ); } Future removeAssets(String albumId, List assetIds) { - return _db.remoteAlbumAssetEntity.deleteWhere( - (tbl) => tbl.albumId.equals(albumId) & tbl.assetId.isIn(assetIds), - ); + return _db.remoteAlbumAssetEntity.deleteWhere((tbl) => tbl.albumId.equals(albumId) & tbl.assetId.isIn(assetIds)); } FutureOr<(DateTime, DateTime)> getDateRange(String albumId) { final query = _db.remoteAlbumAssetEntity.selectOnly() ..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId)) - ..addColumns([ - _db.remoteAssetEntity.createdAt.min(), - _db.remoteAssetEntity.createdAt.max(), - ]) + ..addColumns([_db.remoteAssetEntity.createdAt.min(), _db.remoteAssetEntity.createdAt.max()]) ..join([ - innerJoin( - _db.remoteAssetEntity, - _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), - ), + innerJoin(_db.remoteAssetEntity, _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId)), ]); return query.map((row) { @@ -183,8 +157,9 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { } Future> getSharedUsers(String albumId) async { - final albumUserRows = - await (_db.select(_db.remoteAlbumUserEntity)..where((row) => row.albumId.equals(albumId))).get(); + final albumUserRows = await (_db.select( + _db.remoteAlbumUserEntity, + )..where((row) => row.albumId.equals(albumId))).get(); if (albumUserRows.isEmpty) { return []; @@ -214,29 +189,19 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { Future> getAssets(String albumId) { final query = _db.remoteAlbumAssetEntity.select().join([ - innerJoin( - _db.remoteAssetEntity, - _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), - ), - ]) - ..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId)); + innerJoin(_db.remoteAssetEntity, _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId)), + ])..where(_db.remoteAlbumAssetEntity.albumId.equals(albumId)); return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get(); } Future addAssets(String albumId, List assetIds) async { final albumAssets = assetIds.map( - (assetId) => RemoteAlbumAssetEntityCompanion( - albumId: Value(albumId), - assetId: Value(assetId), - ), + (assetId) => RemoteAlbumAssetEntityCompanion(albumId: Value(albumId), assetId: Value(assetId)), ); await _db.batch((batch) { - batch.insertAll( - _db.remoteAlbumAssetEntity, - albumAssets, - ); + batch.insertAll(_db.remoteAlbumAssetEntity, albumAssets); }); return assetIds.length; @@ -252,47 +217,41 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository { ); return _db.batch((batch) { - batch.insertAll( - _db.remoteAlbumUserEntity, - albumUsers, - ); + batch.insertAll(_db.remoteAlbumUserEntity, albumUsers); }); } Future deleteAlbum(String albumId) async { return _db.transaction(() async { - await _db.remoteAlbumEntity.deleteWhere( - (table) => table.id.equals(albumId), - ); + await _db.remoteAlbumEntity.deleteWhere((table) => table.id.equals(albumId)); }); } Stream watchAlbum(String albumId) { - final query = _db.remoteAlbumEntity.select().join([ - leftOuterJoin( - _db.remoteAlbumAssetEntity, - _db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id), - useColumns: false, - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), - useColumns: false, - ), - leftOuterJoin( - _db.userEntity, - _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), - useColumns: false, - ), - ]) - ..where(_db.remoteAlbumEntity.id.equals(albumId)) - ..addColumns([_db.userEntity.name]) - ..groupBy([_db.remoteAlbumEntity.id]); + final query = + _db.remoteAlbumEntity.select().join([ + leftOuterJoin( + _db.remoteAlbumAssetEntity, + _db.remoteAlbumAssetEntity.albumId.equalsExp(_db.remoteAlbumEntity.id), + useColumns: false, + ), + leftOuterJoin( + _db.remoteAssetEntity, + _db.remoteAssetEntity.id.equalsExp(_db.remoteAlbumAssetEntity.assetId), + useColumns: false, + ), + leftOuterJoin( + _db.userEntity, + _db.userEntity.id.equalsExp(_db.remoteAlbumEntity.ownerId), + useColumns: false, + ), + ]) + ..where(_db.remoteAlbumEntity.id.equals(albumId)) + ..addColumns([_db.userEntity.name]) + ..groupBy([_db.remoteAlbumEntity.id]); return query.map((row) { - final album = row.readTable(_db.remoteAlbumEntity).toDto( - ownerName: row.read(_db.userEntity.name)!, - ); + final album = row.readTable(_db.remoteAlbumEntity).toDto(ownerName: row.read(_db.userEntity.name)!); return album; }).watchSingleOrNull(); } diff --git a/mobile/lib/infrastructure/repositories/remote_asset.repository.dart b/mobile/lib/infrastructure/repositories/remote_asset.repository.dart index 212b9b7f3..1ab62b344 100644 --- a/mobile/lib/infrastructure/repositories/remote_asset.repository.dart +++ b/mobile/lib/infrastructure/repositories/remote_asset.repository.dart @@ -30,17 +30,16 @@ class RemoteAssetRepository extends DriftDatabaseRepository { } SingleOrNullSelectable _assetSelectable(String id) { - final query = _db.remoteAssetEntity.select().addColumns([ - _db.localAssetEntity.id, - ]).join([ - leftOuterJoin( - _db.localAssetEntity, - _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), - useColumns: false, - ), - ]) - ..where(_db.remoteAssetEntity.id.equals(id)) - ..limit(1); + final query = + _db.remoteAssetEntity.select().addColumns([_db.localAssetEntity.id]).join([ + leftOuterJoin( + _db.localAssetEntity, + _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), + useColumns: false, + ), + ]) + ..where(_db.remoteAssetEntity.id.equals(id)) + ..limit(1); return query.map((row) { final asset = row.readTable(_db.remoteAssetEntity).toDto(); @@ -57,17 +56,16 @@ class RemoteAssetRepository extends DriftDatabaseRepository { } Stream watchAsset(String id) { - final query = _db.remoteAssetEntity.select().addColumns([ - _db.localAssetEntity.id, - ]).join([ - leftOuterJoin( - _db.localAssetEntity, - _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), - useColumns: false, - ), - ]) - ..where(_db.remoteAssetEntity.id.equals(id)) - ..limit(1); + final query = + _db.remoteAssetEntity.select().addColumns([_db.localAssetEntity.id]).join([ + leftOuterJoin( + _db.localAssetEntity, + _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), + useColumns: false, + ), + ]) + ..where(_db.remoteAssetEntity.id.equals(id)) + ..limit(1); return query.map((row) { final asset = row.readTable(_db.remoteAssetEntity).toDto(); @@ -81,9 +79,7 @@ class RemoteAssetRepository extends DriftDatabaseRepository { } final query = _db.remoteAssetEntity.select() - ..where( - (row) => row.stackId.equals(asset.stackId!) & row.id.equals(asset.id).not(), - ) + ..where((row) => row.stackId.equals(asset.stackId!) & row.id.equals(asset.id).not()) ..orderBy([(row) => OrderingTerm.desc(row.createdAt)]); return query.map((row) => row.toDto()).get(); @@ -102,24 +98,22 @@ class RemoteAssetRepository extends DriftDatabaseRepository { "asset", ); - final query = asset.selectOnly().join([ - innerJoin( - _db.remoteExifEntity, - _db.remoteExifEntity.assetId.equalsExp(asset.ref(_db.remoteAssetEntity.id)), - useColumns: false, - ), - ]) - ..addColumns([ - _db.remoteExifEntity.city, - _db.remoteExifEntity.assetId, - ]) - ..where( - _db.remoteExifEntity.city.isNotNull() & - asset.ref(_db.remoteAssetEntity.deletedAt).isNull() & - asset.ref(_db.remoteAssetEntity.visibility).equals(AssetVisibility.timeline.index), - ) - ..groupBy([_db.remoteExifEntity.city]) - ..orderBy([OrderingTerm.asc(_db.remoteExifEntity.city)]); + final query = + asset.selectOnly().join([ + innerJoin( + _db.remoteExifEntity, + _db.remoteExifEntity.assetId.equalsExp(asset.ref(_db.remoteAssetEntity.id)), + useColumns: false, + ), + ]) + ..addColumns([_db.remoteExifEntity.city, _db.remoteExifEntity.assetId]) + ..where( + _db.remoteExifEntity.city.isNotNull() & + asset.ref(_db.remoteAssetEntity.deletedAt).isNull() & + asset.ref(_db.remoteAssetEntity.visibility).equals(AssetVisibility.timeline.index), + ) + ..groupBy([_db.remoteExifEntity.city]) + ..orderBy([OrderingTerm.asc(_db.remoteExifEntity.city)]); return query.map((row) { final assetId = row.read(_db.remoteExifEntity.assetId); @@ -185,10 +179,7 @@ class RemoteAssetRepository extends DriftDatabaseRepository { for (final id in ids) { batch.update( _db.remoteExifEntity, - RemoteExifEntityCompanion( - latitude: Value(location.latitude), - longitude: Value(location.longitude), - ), + RemoteExifEntityCompanion(latitude: Value(location.latitude), longitude: Value(location.longitude)), where: (e) => e.assetId.equals(id), ); } @@ -205,23 +196,14 @@ class RemoteAssetRepository extends DriftDatabaseRepository { await _db.stackEntity.deleteWhere((row) => row.id.isIn(stackIds)); await _db.batch((batch) { - final companion = StackEntityCompanion( - ownerId: Value(userId), - primaryAssetId: Value(stack.primaryAssetId), - ); + final companion = StackEntityCompanion(ownerId: Value(userId), primaryAssetId: Value(stack.primaryAssetId)); - batch.insert( - _db.stackEntity, - companion.copyWith(id: Value(stack.id)), - onConflict: DoUpdate((_) => companion), - ); + batch.insert(_db.stackEntity, companion.copyWith(id: Value(stack.id)), onConflict: DoUpdate((_) => companion)); for (final assetId in stack.assetIds) { batch.update( _db.remoteAssetEntity, - RemoteAssetEntityCompanion( - stackId: Value(stack.id), - ), + RemoteAssetEntityCompanion(stackId: Value(stack.id)), where: (e) => e.id.equals(assetId), ); } diff --git a/mobile/lib/infrastructure/repositories/search_api.repository.dart b/mobile/lib/infrastructure/repositories/search_api.repository.dart index 441219a02..129746120 100644 --- a/mobile/lib/infrastructure/repositories/search_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/search_api.repository.dart @@ -66,12 +66,5 @@ class SearchApiRepository extends ApiRepository { String? state, String? make, String? model, - }) => - _api.getSearchSuggestions( - type, - country: country, - state: state, - make: make, - model: model, - ); + }) => _api.getSearchSuggestions(type, country: country, state: state, make: make, model: model); } diff --git a/mobile/lib/infrastructure/repositories/stack.repository.dart b/mobile/lib/infrastructure/repositories/stack.repository.dart index cdac5fe4a..28f7496f9 100644 --- a/mobile/lib/infrastructure/repositories/stack.repository.dart +++ b/mobile/lib/infrastructure/repositories/stack.repository.dart @@ -18,12 +18,6 @@ class DriftStackRepository extends DriftDatabaseRepository { extension on StackEntityData { Stack toDto() { - return Stack( - id: id, - createdAt: createdAt, - updatedAt: updatedAt, - ownerId: ownerId, - primaryAssetId: primaryAssetId, - ); + return Stack(id: id, createdAt: createdAt, updatedAt: updatedAt, ownerId: ownerId, primaryAssetId: primaryAssetId); } } diff --git a/mobile/lib/infrastructure/repositories/store.repository.dart b/mobile/lib/infrastructure/repositories/store.repository.dart index 990c2ad65..6467767aa 100644 --- a/mobile/lib/infrastructure/repositories/store.repository.dart +++ b/mobile/lib/infrastructure/repositories/store.repository.dart @@ -23,11 +23,7 @@ class IsarStoreRepository extends IsarDatabaseRepository { .filter() .anyOf(validStoreKeys, (query, id) => query.idEqualTo(id)) .watch(fireImmediately: true) - .asyncExpand( - (entities) => Stream.fromFutures( - entities.map((e) async => _toUpdateEvent(e)), - ), - ); + .asyncExpand((entities) => Stream.fromFutures(entities.map((e) async => _toUpdateEvent(e)))); } Future delete(StoreKey key) async { @@ -68,14 +64,17 @@ class IsarStoreRepository extends IsarDatabaseRepository { return StoreDto(key, value); } - Future _toValue(StoreKey key, StoreValue entity) async => switch (key.type) { - const (int) => entity.intValue, - const (String) => entity.strValue, - const (bool) => entity.intValue == 1, - const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!), - const (UserDto) => entity.strValue == null ? null : await IsarUserRepository(_db).getByUserId(entity.strValue!), - _ => null, - } as T?; + Future _toValue(StoreKey key, StoreValue entity) async => + switch (key.type) { + const (int) => entity.intValue, + const (String) => entity.strValue, + const (bool) => entity.intValue == 1, + const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!), + const (UserDto) => + entity.strValue == null ? null : await IsarUserRepository(_db).getByUserId(entity.strValue!), + _ => null, + } + as T?; Future _fromValue(StoreKey key, T value) async { final (int? intValue, String? strValue) = switch (key.type) { @@ -83,13 +82,8 @@ class IsarStoreRepository extends IsarDatabaseRepository { const (String) => (null, value as String), const (bool) => ((value as bool) ? 1 : 0, null), const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null), - const (UserDto) => ( - null, - (await IsarUserRepository(_db).update(value as UserDto)).id, - ), - _ => throw UnsupportedError( - "Unsupported primitive type: ${key.type} for key: ${key.name}", - ), + const (UserDto) => (null, (await IsarUserRepository(_db).update(value as UserDto)).id), + _ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"), }; return StoreValue(key.id, intValue: intValue, strValue: strValue); } diff --git a/mobile/lib/infrastructure/repositories/sync_api.repository.dart b/mobile/lib/infrastructure/repositories/sync_api.repository.dart index 6727f19c6..78b2a9d95 100644 --- a/mobile/lib/infrastructure/repositories/sync_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_api.repository.dart @@ -27,10 +27,7 @@ class SyncApiRepository { final client = httpClient ?? http.Client(); final endpoint = "${_api.apiClient.basePath}/sync/stream"; - final headers = { - 'Content-Type': 'application/json', - 'Accept': 'application/jsonlines+json', - }; + final headers = {'Content-Type': 'application/json', 'Accept': 'application/jsonlines+json'}; final headerParams = {}; await _api.applyToParams([], headerParams); @@ -78,10 +75,7 @@ class SyncApiRepository { if (response.statusCode != 200) { final errorBody = await response.stream.bytesToString(); - throw ApiException( - response.statusCode, - 'Failed to get sync stream: $errorBody', - ); + throw ApiException(response.statusCode, 'Failed to get sync stream: $errorBody'); } await for (final chunk in response.stream.transform(utf8.decoder)) { diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index 54bc01cfa..64b0661e1 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -42,16 +42,9 @@ class SyncStreamRepository extends DriftDatabaseRepository { try { await _db.batch((batch) { for (final user in data) { - final companion = UserEntityCompanion( - name: Value(user.name), - email: Value(user.email), - ); + final companion = UserEntityCompanion(name: Value(user.name), email: Value(user.email)); - batch.insert( - _db.userEntity, - companion.copyWith(id: Value(user.id)), - onConflict: DoUpdate((_) => companion), - ); + batch.insert(_db.userEntity, companion.copyWith(id: Value(user.id)), onConflict: DoUpdate((_) => companion)); } }); } catch (error, stack) { @@ -66,10 +59,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { for (final partner in data) { batch.delete( _db.partnerEntity, - PartnerEntityCompanion( - sharedById: Value(partner.sharedById), - sharedWithId: Value(partner.sharedWithId), - ), + PartnerEntityCompanion(sharedById: Value(partner.sharedById), sharedWithId: Value(partner.sharedWithId)), ); } }); @@ -87,10 +77,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { batch.insert( _db.partnerEntity, - companion.copyWith( - sharedById: Value(partner.sharedById), - sharedWithId: Value(partner.sharedWithId), - ), + companion.copyWith(sharedById: Value(partner.sharedById), sharedWithId: Value(partner.sharedWithId)), onConflict: DoUpdate((_) => companion), ); } @@ -101,24 +88,16 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future deleteAssetsV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future deleteAssetsV1(Iterable data, {String debugLabel = 'user'}) async { try { - await _db.remoteAssetEntity.deleteWhere( - (row) => row.id.isIn(data.map((e) => e.assetId)), - ); + await _db.remoteAssetEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.assetId))); } catch (error, stack) { _logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stack); rethrow; } } - Future updateAssetsV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future updateAssetsV1(Iterable data, {String debugLabel = 'user'}) async { try { await _db.batch((batch) { for (final asset in data) { @@ -152,10 +131,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future updateAssetsExifV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future updateAssetsExifV1(Iterable data, {String debugLabel = 'user'}) async { try { await _db.batch((batch) { for (final exif in data) { @@ -191,20 +167,14 @@ class SyncStreamRepository extends DriftDatabaseRepository { } }); } catch (error, stack) { - _logger.severe( - 'Error: updateAssetsExifV1 - $debugLabel', - error, - stack, - ); + _logger.severe('Error: updateAssetsExifV1 - $debugLabel', error, stack); rethrow; } } Future deleteAlbumsV1(Iterable data) async { try { - await _db.remoteAlbumEntity.deleteWhere( - (row) => row.id.isIn(data.map((e) => e.albumId)), - ); + await _db.remoteAlbumEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.albumId))); } catch (error, stack) { _logger.severe('Error: deleteAlbumsV1', error, stack); rethrow; @@ -245,10 +215,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { for (final album in data) { batch.delete( _db.remoteAlbumUserEntity, - RemoteAlbumUserEntityCompanion( - albumId: Value(album.albumId), - userId: Value(album.userId), - ), + RemoteAlbumUserEntityCompanion(albumId: Value(album.albumId), userId: Value(album.userId)), ); } }); @@ -258,49 +225,32 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future updateAlbumUsersV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future updateAlbumUsersV1(Iterable data, {String debugLabel = 'user'}) async { try { await _db.batch((batch) { for (final album in data) { - final companion = RemoteAlbumUserEntityCompanion( - role: Value(album.role.toAlbumUserRole()), - ); + final companion = RemoteAlbumUserEntityCompanion(role: Value(album.role.toAlbumUserRole())); batch.insert( _db.remoteAlbumUserEntity, - companion.copyWith( - albumId: Value(album.albumId), - userId: Value(album.userId), - ), + companion.copyWith(albumId: Value(album.albumId), userId: Value(album.userId)), onConflict: DoUpdate((_) => companion), ); } }); } catch (error, stack) { - _logger.severe( - 'Error: updateAlbumUsersV1 - $debugLabel', - error, - stack, - ); + _logger.severe('Error: updateAlbumUsersV1 - $debugLabel', error, stack); rethrow; } } - Future deleteAlbumToAssetsV1( - Iterable data, - ) async { + Future deleteAlbumToAssetsV1(Iterable data) async { try { await _db.batch((batch) { for (final album in data) { batch.delete( _db.remoteAlbumAssetEntity, - RemoteAlbumAssetEntityCompanion( - albumId: Value(album.albumId), - assetId: Value(album.assetId), - ), + RemoteAlbumAssetEntityCompanion(albumId: Value(album.albumId), assetId: Value(album.assetId)), ); } }); @@ -310,10 +260,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future updateAlbumToAssetsV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future updateAlbumToAssetsV1(Iterable data, {String debugLabel = 'user'}) async { try { await _db.batch((batch) { for (final album in data) { @@ -322,19 +269,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { assetId: Value(album.assetId), ); - batch.insert( - _db.remoteAlbumAssetEntity, - companion, - onConflict: DoNothing(), - ); + batch.insert(_db.remoteAlbumAssetEntity, companion, onConflict: DoNothing()); } }); } catch (error, stack) { - _logger.severe( - 'Error: updateAlbumToAssetsV1 - $debugLabel', - error, - stack, - ); + _logger.severe('Error: updateAlbumToAssetsV1 - $debugLabel', error, stack); rethrow; } } @@ -371,9 +310,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { Future deleteMemoriesV1(Iterable data) async { try { - await _db.memoryEntity.deleteWhere( - (row) => row.id.isIn(data.map((e) => e.memoryId)), - ); + await _db.memoryEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.memoryId))); } catch (error, stack) { _logger.severe('Error: deleteMemoriesV1', error, stack); rethrow; @@ -384,16 +321,9 @@ class SyncStreamRepository extends DriftDatabaseRepository { try { await _db.batch((batch) { for (final asset in data) { - final companion = MemoryAssetEntityCompanion( - memoryId: Value(asset.memoryId), - assetId: Value(asset.assetId), - ); + final companion = MemoryAssetEntityCompanion(memoryId: Value(asset.memoryId), assetId: Value(asset.assetId)); - batch.insert( - _db.memoryAssetEntity, - companion, - onConflict: DoNothing(), - ); + batch.insert(_db.memoryAssetEntity, companion, onConflict: DoNothing()); } }); } catch (error, stack) { @@ -402,18 +332,13 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future deleteMemoryAssetsV1( - Iterable data, - ) async { + Future deleteMemoryAssetsV1(Iterable data) async { try { await _db.batch((batch) { for (final asset in data) { batch.delete( _db.memoryAssetEntity, - MemoryAssetEntityCompanion( - memoryId: Value(asset.memoryId), - assetId: Value(asset.assetId), - ), + MemoryAssetEntityCompanion(memoryId: Value(asset.memoryId), assetId: Value(asset.assetId)), ); } }); @@ -423,10 +348,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future updateStacksV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future updateStacksV1(Iterable data, {String debugLabel = 'user'}) async { try { await _db.batch((batch) { for (final stack in data) { @@ -450,36 +372,24 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future deleteStacksV1( - Iterable data, { - String debugLabel = 'user', - }) async { + Future deleteStacksV1(Iterable data, {String debugLabel = 'user'}) async { try { - await _db.stackEntity.deleteWhere( - (row) => row.id.isIn(data.map((e) => e.stackId)), - ); + await _db.stackEntity.deleteWhere((row) => row.id.isIn(data.map((e) => e.stackId))); } catch (error, stack) { _logger.severe('Error: deleteStacksV1 - $debugLabel', error, stack); rethrow; } } - Future updateUserMetadatasV1( - Iterable data, - ) async { + Future updateUserMetadatasV1(Iterable data) async { try { await _db.batch((batch) { for (final userMetadata in data) { - final companion = UserMetadataEntityCompanion( - value: Value(userMetadata.value as Map), - ); + final companion = UserMetadataEntityCompanion(value: Value(userMetadata.value as Map)); batch.insert( _db.userMetadataEntity, - companion.copyWith( - userId: Value(userMetadata.userId), - key: Value(userMetadata.key.toUserMetadataKey()), - ), + companion.copyWith(userId: Value(userMetadata.userId), key: Value(userMetadata.key.toUserMetadataKey())), onConflict: DoUpdate((_) => companion), ); } @@ -490,9 +400,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future deleteUserMetadatasV1( - Iterable data, - ) async { + Future deleteUserMetadatasV1(Iterable data) async { try { await _db.batch((batch) { for (final userMetadata in data) { @@ -540,16 +448,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { } } - Future deletePeopleV1( - Iterable data, - ) async { + Future deletePeopleV1(Iterable data) async { try { await _db.batch((batch) { for (final person in data) { - batch.deleteWhere( - _db.personEntity, - (row) => row.id.equals(person.personId), - ); + batch.deleteWhere(_db.personEntity, (row) => row.id.equals(person.personId)); } }); } catch (error, stack) { @@ -591,10 +494,7 @@ class SyncStreamRepository extends DriftDatabaseRepository { try { await _db.batch((batch) { for (final assetFace in data) { - batch.deleteWhere( - _db.assetFaceEntity, - (row) => row.id.equals(assetFace.assetFaceId), - ); + batch.deleteWhere(_db.assetFaceEntity, (row) => row.id.equals(assetFace.assetFaceId)); } }); } catch (error, stack) { @@ -606,54 +506,54 @@ class SyncStreamRepository extends DriftDatabaseRepository { extension on AssetTypeEnum { AssetType toAssetType() => switch (this) { - AssetTypeEnum.IMAGE => AssetType.image, - AssetTypeEnum.VIDEO => AssetType.video, - AssetTypeEnum.AUDIO => AssetType.audio, - AssetTypeEnum.OTHER => AssetType.other, - _ => throw Exception('Unknown AssetType value: $this'), - }; + AssetTypeEnum.IMAGE => AssetType.image, + AssetTypeEnum.VIDEO => AssetType.video, + AssetTypeEnum.AUDIO => AssetType.audio, + AssetTypeEnum.OTHER => AssetType.other, + _ => throw Exception('Unknown AssetType value: $this'), + }; } extension on AssetOrder { AlbumAssetOrder toAlbumAssetOrder() => switch (this) { - AssetOrder.asc => AlbumAssetOrder.asc, - AssetOrder.desc => AlbumAssetOrder.desc, - _ => throw Exception('Unknown AssetOrder value: $this'), - }; + AssetOrder.asc => AlbumAssetOrder.asc, + AssetOrder.desc => AlbumAssetOrder.desc, + _ => throw Exception('Unknown AssetOrder value: $this'), + }; } extension on MemoryType { MemoryTypeEnum toMemoryType() => switch (this) { - MemoryType.onThisDay => MemoryTypeEnum.onThisDay, - _ => throw Exception('Unknown MemoryType value: $this'), - }; + MemoryType.onThisDay => MemoryTypeEnum.onThisDay, + _ => throw Exception('Unknown MemoryType value: $this'), + }; } extension on api.AlbumUserRole { AlbumUserRole toAlbumUserRole() => switch (this) { - api.AlbumUserRole.editor => AlbumUserRole.editor, - api.AlbumUserRole.viewer => AlbumUserRole.viewer, - _ => throw Exception('Unknown AlbumUserRole value: $this'), - }; + api.AlbumUserRole.editor => AlbumUserRole.editor, + api.AlbumUserRole.viewer => AlbumUserRole.viewer, + _ => throw Exception('Unknown AlbumUserRole value: $this'), + }; } extension on api.AssetVisibility { AssetVisibility toAssetVisibility() => switch (this) { - api.AssetVisibility.timeline => AssetVisibility.timeline, - api.AssetVisibility.hidden => AssetVisibility.hidden, - api.AssetVisibility.archive => AssetVisibility.archive, - api.AssetVisibility.locked => AssetVisibility.locked, - _ => throw Exception('Unknown AssetVisibility value: $this'), - }; + api.AssetVisibility.timeline => AssetVisibility.timeline, + api.AssetVisibility.hidden => AssetVisibility.hidden, + api.AssetVisibility.archive => AssetVisibility.archive, + api.AssetVisibility.locked => AssetVisibility.locked, + _ => throw Exception('Unknown AssetVisibility value: $this'), + }; } extension on api.UserMetadataKey { UserMetadataKey toUserMetadataKey() => switch (this) { - api.UserMetadataKey.onboarding => UserMetadataKey.onboarding, - api.UserMetadataKey.preferences => UserMetadataKey.preferences, - api.UserMetadataKey.license => UserMetadataKey.license, - _ => throw Exception('Unknown UserMetadataKey value: $this'), - }; + api.UserMetadataKey.onboarding => UserMetadataKey.onboarding, + api.UserMetadataKey.preferences => UserMetadataKey.preferences, + api.UserMetadataKey.license => UserMetadataKey.license, + _ => throw Exception('Unknown UserMetadataKey value: $this'), + }; } extension on String { diff --git a/mobile/lib/infrastructure/repositories/timeline.repository.dart b/mobile/lib/infrastructure/repositories/timeline.repository.dart index 772fb74f8..a2c14a363 100644 --- a/mobile/lib/infrastructure/repositories/timeline.repository.dart +++ b/mobile/lib/infrastructure/repositories/timeline.repository.dart @@ -21,9 +21,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { Stream> watchTimelineUserIds(String userId) { final query = _db.partnerEntity.selectOnly() ..addColumns([_db.partnerEntity.sharedById]) - ..where( - _db.partnerEntity.inTimeline.equals(true) & _db.partnerEntity.sharedWithId.equals(userId), - ); + ..where(_db.partnerEntity.inTimeline.equals(true) & _db.partnerEntity.sharedWithId.equals(userId)); return query .map((row) => row.read(_db.partnerEntity.sharedById)!) @@ -33,25 +31,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository { } TimelineQuery main(List userIds, GroupAssetsBy groupBy) => ( - bucketSource: () => _watchMainBucket( - userIds, - groupBy: groupBy, - ), - assetSource: (offset, count) => _getMainBucketAssets( - userIds, - offset: offset, - count: count, - ), - ); + bucketSource: () => _watchMainBucket(userIds, groupBy: groupBy), + assetSource: (offset, count) => _getMainBucketAssets(userIds, offset: offset, count: count), + ); - Stream> _watchMainBucket( - List userIds, { - GroupAssetsBy groupBy = GroupAssetsBy.day, - }) { + Stream> _watchMainBucket(List userIds, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { if (groupBy == GroupAssetsBy.none) { - throw UnsupportedError( - "GroupAssetsBy.none is not supported for watchMainBucket", - ); + throw UnsupportedError("GroupAssetsBy.none is not supported for watchMainBucket"); } return _db.mergedAssetDrift @@ -64,11 +50,7 @@ class DriftTimelineRepository extends DriftDatabaseRepository { .throttle(const Duration(seconds: 3), trailing: true); } - Future> _getMainBucketAssets( - List userIds, { - required int offset, - required int count, - }) { + Future> _getMainBucketAssets(List userIds, {required int offset, required int count}) { return _db.mergedAssetDrift .mergedAsset(userIds, limit: (_) => Limit(count, offset)) .map( @@ -109,21 +91,11 @@ class DriftTimelineRepository extends DriftDatabaseRepository { } TimelineQuery localAlbum(String albumId, GroupAssetsBy groupBy) => ( - bucketSource: () => _watchLocalAlbumBucket( - albumId, - groupBy: groupBy, - ), - assetSource: (offset, count) => _getLocalAlbumBucketAssets( - albumId, - offset: offset, - count: count, - ), - ); + bucketSource: () => _watchLocalAlbumBucket(albumId, groupBy: groupBy), + assetSource: (offset, count) => _getLocalAlbumBucketAssets(albumId, offset: offset, count: count), + ); - Stream> _watchLocalAlbumBucket( - String albumId, { - GroupAssetsBy groupBy = GroupAssetsBy.day, - }) { + Stream> _watchLocalAlbumBucket(String albumId, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { if (groupBy == GroupAssetsBy.none) { return _db.localAlbumAssetEntity .count(where: (row) => row.albumId.equals(albumId)) @@ -134,22 +106,23 @@ class DriftTimelineRepository extends DriftDatabaseRepository { final assetCountExp = _db.localAssetEntity.id.count(); final dateExp = _db.localAssetEntity.createdAt.dateFmt(groupBy); - final query = _db.localAssetEntity.selectOnly().join([ - innerJoin( - _db.localAlbumAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - useColumns: false, - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum), - useColumns: false, - ), - ]) - ..addColumns([assetCountExp, dateExp]) - ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) - ..groupBy([dateExp]) - ..orderBy([OrderingTerm.desc(dateExp)]); + final query = + _db.localAssetEntity.selectOnly().join([ + innerJoin( + _db.localAlbumAssetEntity, + _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), + useColumns: false, + ), + leftOuterJoin( + _db.remoteAssetEntity, + _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum), + useColumns: false, + ), + ]) + ..addColumns([assetCountExp, dateExp]) + ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) + ..groupBy([dateExp]) + ..orderBy([OrderingTerm.desc(dateExp)]); return query.map((row) { final timeline = row.read(dateExp)!.dateFmt(groupBy); @@ -158,54 +131,37 @@ class DriftTimelineRepository extends DriftDatabaseRepository { }).watch(); } - Future> _getLocalAlbumBucketAssets( - String albumId, { - required int offset, - required int count, - }) { - final query = _db.localAssetEntity.select().join( - [ - innerJoin( - _db.localAlbumAssetEntity, - _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), - useColumns: false, - ), - leftOuterJoin( - _db.remoteAssetEntity, - _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum), - useColumns: false, - ), - ], - ) - ..addColumns([_db.remoteAssetEntity.id]) - ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) - ..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)]) - ..limit(count, offset: offset); + Future> _getLocalAlbumBucketAssets(String albumId, {required int offset, required int count}) { + final query = + _db.localAssetEntity.select().join([ + innerJoin( + _db.localAlbumAssetEntity, + _db.localAlbumAssetEntity.assetId.equalsExp(_db.localAssetEntity.id), + useColumns: false, + ), + leftOuterJoin( + _db.remoteAssetEntity, + _db.localAssetEntity.checksum.equalsExp(_db.remoteAssetEntity.checksum), + useColumns: false, + ), + ]) + ..addColumns([_db.remoteAssetEntity.id]) + ..where(_db.localAlbumAssetEntity.albumId.equals(albumId)) + ..orderBy([OrderingTerm.desc(_db.localAssetEntity.createdAt)]) + ..limit(count, offset: offset); return query.map((row) { final asset = row.readTable(_db.localAssetEntity).toDto(); - return asset.copyWith( - remoteId: row.read(_db.remoteAssetEntity.id), - ); + return asset.copyWith(remoteId: row.read(_db.remoteAssetEntity.id)); }).get(); } TimelineQuery remoteAlbum(String albumId, GroupAssetsBy groupBy) => ( - bucketSource: () => _watchRemoteAlbumBucket( - albumId, - groupBy: groupBy, - ), - assetSource: (offset, count) => _getRemoteAlbumBucketAssets( - albumId, - offset: offset, - count: count, - ), - ); + bucketSource: () => _watchRemoteAlbumBucket(albumId, groupBy: groupBy), + assetSource: (offset, count) => _getRemoteAlbumBucketAssets(albumId, offset: offset, count: count), + ); - Stream> _watchRemoteAlbumBucket( - String albumId, { - GroupAssetsBy groupBy = GroupAssetsBy.day, - }) { + Stream> _watchRemoteAlbumBucket(String albumId, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { if (groupBy == GroupAssetsBy.none) { return _db.remoteAlbumAssetEntity .count(where: (row) => row.albumId.equals(albumId)) @@ -213,56 +169,53 @@ class DriftTimelineRepository extends DriftDatabaseRepository { .watch() .map((results) => results.isNotEmpty ? results.first : []) .handleError((error) { - return []; - }); + return []; + }); } - return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))).watch().switchMap((albums) { - if (albums.isEmpty) { - return Stream.value([]); - } + return (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))) + .watch() + .switchMap((albums) { + if (albums.isEmpty) { + return Stream.value([]); + } - final album = albums.first; - final isAscending = album.order == AlbumAssetOrder.asc; - final assetCountExp = _db.remoteAssetEntity.id.count(); - final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy); + final album = albums.first; + final isAscending = album.order == AlbumAssetOrder.asc; + final assetCountExp = _db.remoteAssetEntity.id.count(); + final dateExp = _db.remoteAssetEntity.createdAt.dateFmt(groupBy); - final query = _db.remoteAssetEntity.selectOnly() - ..addColumns([assetCountExp, dateExp]) - ..join([ - innerJoin( - _db.remoteAlbumAssetEntity, - _db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id), - useColumns: false, - ), - ]) - ..where( - _db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId), - ) - ..groupBy([dateExp]); + final query = _db.remoteAssetEntity.selectOnly() + ..addColumns([assetCountExp, dateExp]) + ..join([ + innerJoin( + _db.remoteAlbumAssetEntity, + _db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id), + useColumns: false, + ), + ]) + ..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId)) + ..groupBy([dateExp]); - if (isAscending) { - query.orderBy([OrderingTerm.asc(dateExp)]); - } else { - query.orderBy([OrderingTerm.desc(dateExp)]); - } + if (isAscending) { + query.orderBy([OrderingTerm.asc(dateExp)]); + } else { + query.orderBy([OrderingTerm.desc(dateExp)]); + } - return query.map((row) { - final timeline = row.read(dateExp)!.dateFmt(groupBy); - final assetCount = row.read(assetCountExp)!; - return TimeBucket(date: timeline, assetCount: assetCount); - }).watch(); - }).handleError((error) { - // If there's an error (e.g., album was deleted), return empty buckets - return []; - }); + return query.map((row) { + final timeline = row.read(dateExp)!.dateFmt(groupBy); + final assetCount = row.read(assetCountExp)!; + return TimeBucket(date: timeline, assetCount: assetCount); + }).watch(); + }) + .handleError((error) { + // If there's an error (e.g., album was deleted), return empty buckets + return []; + }); } - Future> _getRemoteAlbumBucketAssets( - String albumId, { - required int offset, - required int count, - }) async { + Future> _getRemoteAlbumBucketAssets(String albumId, {required int offset, required int count}) async { final albumData = await (_db.remoteAlbumEntity.select()..where((row) => row.id.equals(albumId))).getSingleOrNull(); // If album doesn't exist (was deleted), return empty list @@ -272,17 +225,13 @@ class DriftTimelineRepository extends DriftDatabaseRepository { final isAscending = albumData.order == AlbumAssetOrder.asc; - final query = _db.remoteAssetEntity.select().join( - [ - innerJoin( - _db.remoteAlbumAssetEntity, - _db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id), - useColumns: false, - ), - ], - )..where( - _db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId), - ); + final query = _db.remoteAssetEntity.select().join([ + innerJoin( + _db.remoteAlbumAssetEntity, + _db.remoteAlbumAssetEntity.assetId.equalsExp(_db.remoteAssetEntity.id), + useColumns: false, + ), + ])..where(_db.remoteAssetEntity.deletedAt.isNull() & _db.remoteAlbumAssetEntity.albumId.equals(albumId)); if (isAscending) { query.orderBy([OrderingTerm.asc(_db.remoteAssetEntity.createdAt)]); @@ -296,69 +245,57 @@ class DriftTimelineRepository extends DriftDatabaseRepository { } TimelineQuery fromAssets(List assets) => ( - bucketSource: () => Stream.value(_generateBuckets(assets.length)), - assetSource: (offset, count) => Future.value(assets.skip(offset).take(count).toList()), - ); + bucketSource: () => Stream.value(_generateBuckets(assets.length)), + assetSource: (offset, count) => Future.value(assets.skip(offset).take(count).toList()), + ); TimelineQuery remote(String ownerId, GroupAssetsBy groupBy) => _remoteQueryBuilder( - filter: (row) => - row.deletedAt.isNull() & row.visibility.equalsValue(AssetVisibility.timeline) & row.ownerId.equals(ownerId), - groupBy: groupBy, - ); + filter: (row) => + row.deletedAt.isNull() & row.visibility.equalsValue(AssetVisibility.timeline) & row.ownerId.equals(ownerId), + groupBy: groupBy, + ); TimelineQuery favorite(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( - filter: (row) => row.deletedAt.isNull() & row.isFavorite.equals(true) & row.ownerId.equals(userId), - groupBy: groupBy, - ); + filter: (row) => row.deletedAt.isNull() & row.isFavorite.equals(true) & row.ownerId.equals(userId), + groupBy: groupBy, + ); TimelineQuery trash(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( - filter: (row) => row.deletedAt.isNotNull() & row.ownerId.equals(userId), - groupBy: groupBy, - joinLocal: true, - ); + filter: (row) => row.deletedAt.isNotNull() & row.ownerId.equals(userId), + groupBy: groupBy, + joinLocal: true, + ); TimelineQuery archived(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( - filter: (row) => - row.deletedAt.isNull() & row.ownerId.equals(userId) & row.visibility.equalsValue(AssetVisibility.archive), - groupBy: groupBy, - ); + filter: (row) => + row.deletedAt.isNull() & row.ownerId.equals(userId) & row.visibility.equalsValue(AssetVisibility.archive), + groupBy: groupBy, + ); TimelineQuery locked(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( - filter: (row) => - row.deletedAt.isNull() & row.visibility.equalsValue(AssetVisibility.locked) & row.ownerId.equals(userId), - groupBy: groupBy, - ); + filter: (row) => + row.deletedAt.isNull() & row.visibility.equalsValue(AssetVisibility.locked) & row.ownerId.equals(userId), + groupBy: groupBy, + ); TimelineQuery video(String userId, GroupAssetsBy groupBy) => _remoteQueryBuilder( - filter: (row) => - row.deletedAt.isNull() & - row.type.equalsValue(AssetType.video) & - row.visibility.equalsValue(AssetVisibility.timeline) & - row.ownerId.equals(userId), - groupBy: groupBy, - ); + filter: (row) => + row.deletedAt.isNull() & + row.type.equalsValue(AssetType.video) & + row.visibility.equalsValue(AssetVisibility.timeline) & + row.ownerId.equals(userId), + groupBy: groupBy, + ); TimelineQuery place(String place, GroupAssetsBy groupBy) => ( - bucketSource: () => _watchPlaceBucket( - place, - groupBy: groupBy, - ), - assetSource: (offset, count) => _getPlaceBucketAssets( - place, - offset: offset, - count: count, - ), - ); + bucketSource: () => _watchPlaceBucket(place, groupBy: groupBy), + assetSource: (offset, count) => _getPlaceBucketAssets(place, offset: offset, count: count), + ); - Stream> _watchPlaceBucket( - String place, { - GroupAssetsBy groupBy = GroupAssetsBy.day, - }) { + Stream> _watchPlaceBucket(String place, {GroupAssetsBy groupBy = GroupAssetsBy.day}) { if (groupBy == GroupAssetsBy.none) { // TODO: implement GroupAssetBy for place - throw UnsupportedError( - "GroupAssetsBy.none is not supported for watchPlaceBucket", - ); + throw UnsupportedError("GroupAssetsBy.none is not supported for watchPlaceBucket"); } final assetCountExp = _db.remoteAssetEntity.id.count(); @@ -388,27 +325,22 @@ class DriftTimelineRepository extends DriftDatabaseRepository { }).watch(); } - Future> _getPlaceBucketAssets( - String place, { - required int offset, - required int count, - }) { - final query = _db.remoteAssetEntity.select().join( - [ - innerJoin( - _db.remoteExifEntity, - _db.remoteExifEntity.assetId.equalsExp(_db.remoteAssetEntity.id), - useColumns: false, - ), - ], - ) - ..where( - _db.remoteAssetEntity.deletedAt.isNull() & - _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) & - _db.remoteExifEntity.city.equals(place), - ) - ..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)]) - ..limit(count, offset: offset); + Future> _getPlaceBucketAssets(String place, {required int offset, required int count}) { + final query = + _db.remoteAssetEntity.select().join([ + innerJoin( + _db.remoteExifEntity, + _db.remoteExifEntity.assetId.equalsExp(_db.remoteAssetEntity.id), + useColumns: false, + ), + ]) + ..where( + _db.remoteAssetEntity.deletedAt.isNull() & + _db.remoteAssetEntity.visibility.equalsValue(AssetVisibility.timeline) & + _db.remoteExifEntity.city.equals(place), + ) + ..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)]) + ..limit(count, offset: offset); return query.map((row) => row.readTable(_db.remoteAssetEntity).toDto()).get(); } @@ -419,12 +351,8 @@ class DriftTimelineRepository extends DriftDatabaseRepository { }) { return ( bucketSource: () => _watchRemoteBucket(filter: filter, groupBy: groupBy), - assetSource: (offset, count) => _getRemoteAssets( - filter: filter, - offset: offset, - count: count, - joinLocal: joinLocal, - ), + assetSource: (offset, count) => + _getRemoteAssets(filter: filter, offset: offset, count: count, joinLocal: joinLocal), ); } @@ -460,17 +388,18 @@ class DriftTimelineRepository extends DriftDatabaseRepository { bool joinLocal = false, }) { if (joinLocal) { - final query = _db.remoteAssetEntity.select().join([ - leftOuterJoin( - _db.localAssetEntity, - _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), - useColumns: false, - ), - ]) - ..addColumns([_db.localAssetEntity.id]) - ..where(filter(_db.remoteAssetEntity)) - ..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)]) - ..limit(count, offset: offset); + final query = + _db.remoteAssetEntity.select().join([ + leftOuterJoin( + _db.localAssetEntity, + _db.remoteAssetEntity.checksum.equalsExp(_db.localAssetEntity.checksum), + useColumns: false, + ), + ]) + ..addColumns([_db.localAssetEntity.id]) + ..where(filter(_db.remoteAssetEntity)) + ..orderBy([OrderingTerm.desc(_db.remoteAssetEntity.createdAt)]) + ..limit(count, offset: offset); return query.map((row) { final asset = row.readTable(_db.remoteAssetEntity).toDto(); @@ -507,9 +436,7 @@ extension on Expression { return switch (groupBy) { GroupAssetsBy.day || GroupAssetsBy.auto => localTimeExp.date, GroupAssetsBy.month => localTimeExp.strftime("%Y-%m"), - GroupAssetsBy.none => throw ArgumentError( - "GroupAssetsBy.none is not supported for date formatting", - ), + GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"), }; } } @@ -519,9 +446,7 @@ extension on String { final format = switch (groupBy) { GroupAssetsBy.day || GroupAssetsBy.auto => "y-M-d", GroupAssetsBy.month => "y-M", - GroupAssetsBy.none => throw ArgumentError( - "GroupAssetsBy.none is not supported for date formatting", - ), + GroupAssetsBy.none => throw ArgumentError("GroupAssetsBy.none is not supported for date formatting"), }; try { return DateFormat(format).parse(this); diff --git a/mobile/lib/infrastructure/repositories/user_api.repository.dart b/mobile/lib/infrastructure/repositories/user_api.repository.dart index 0ee3deb4b..d21a1b71a 100644 --- a/mobile/lib/infrastructure/repositories/user_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/user_api.repository.dart @@ -17,15 +17,8 @@ class UserApiRepository extends ApiRepository { return UserConverter.fromAdminDto(adminDto, preferenceDto); } - Future createProfileImage({ - required String name, - required Uint8List data, - }) async { - final res = await checkNull( - _api.createProfileImage( - MultipartFile.fromBytes('file', data, filename: name), - ), - ); + Future createProfileImage({required String name, required Uint8List data}) async { + final res = await checkNull(_api.createProfileImage(MultipartFile.fromBytes('file', data, filename: name))); return res.profileImagePath; } diff --git a/mobile/lib/infrastructure/repositories/user_metadata.repository.dart b/mobile/lib/infrastructure/repositories/user_metadata.repository.dart index 81a4cd794..7205c7f73 100644 --- a/mobile/lib/infrastructure/repositories/user_metadata.repository.dart +++ b/mobile/lib/infrastructure/repositories/user_metadata.repository.dart @@ -18,20 +18,8 @@ class DriftUserMetadataRepository extends DriftDatabaseRepository { extension on UserMetadataEntityData { UserMetadata toDto() => switch (key) { - UserMetadataKey.onboarding => UserMetadata( - userId: userId, - key: key, - onboarding: Onboarding.fromMap(value), - ), - UserMetadataKey.preferences => UserMetadata( - userId: userId, - key: key, - preferences: Preferences.fromMap(value), - ), - UserMetadataKey.license => UserMetadata( - userId: userId, - key: key, - license: License.fromMap(value), - ), - }; + UserMetadataKey.onboarding => UserMetadata(userId: userId, key: key, onboarding: Onboarding.fromMap(value)), + UserMetadataKey.preferences => UserMetadata(userId: userId, key: key, preferences: Preferences.fromMap(value)), + UserMetadataKey.license => UserMetadata(userId: userId, key: key, license: License.fromMap(value)), + }; } diff --git a/mobile/lib/infrastructure/utils/user.converter.dart b/mobile/lib/infrastructure/utils/user.converter.dart index eb7b24737..19958beab 100644 --- a/mobile/lib/infrastructure/utils/user.converter.dart +++ b/mobile/lib/infrastructure/utils/user.converter.dart @@ -6,63 +6,59 @@ import 'package:openapi/api.dart'; abstract final class UserConverter { /// Base user dto used where the complete user object is not required static UserDto fromSimpleUserDto(UserResponseDto dto) => UserDto( - id: dto.id, - email: dto.email, - name: dto.name, - isAdmin: false, - updatedAt: DateTime.now(), - profileImagePath: dto.profileImagePath, - avatarColor: dto.avatarColor.toAvatarColor(), - ); + id: dto.id, + email: dto.email, + name: dto.name, + isAdmin: false, + updatedAt: DateTime.now(), + profileImagePath: dto.profileImagePath, + avatarColor: dto.avatarColor.toAvatarColor(), + ); - static UserDto fromAdminDto( - UserAdminResponseDto adminDto, [ - UserPreferencesResponseDto? preferenceDto, - ]) => - UserDto( - id: adminDto.id, - email: adminDto.email, - name: adminDto.name, - isAdmin: adminDto.isAdmin, - updatedAt: adminDto.updatedAt, - profileImagePath: adminDto.profileImagePath, - avatarColor: adminDto.avatarColor.toAvatarColor(), - memoryEnabled: preferenceDto?.memories.enabled ?? true, - inTimeline: false, - isPartnerSharedBy: false, - isPartnerSharedWith: false, - quotaUsageInBytes: adminDto.quotaUsageInBytes ?? 0, - quotaSizeInBytes: adminDto.quotaSizeInBytes ?? 0, - ); + static UserDto fromAdminDto(UserAdminResponseDto adminDto, [UserPreferencesResponseDto? preferenceDto]) => UserDto( + id: adminDto.id, + email: adminDto.email, + name: adminDto.name, + isAdmin: adminDto.isAdmin, + updatedAt: adminDto.updatedAt, + profileImagePath: adminDto.profileImagePath, + avatarColor: adminDto.avatarColor.toAvatarColor(), + memoryEnabled: preferenceDto?.memories.enabled ?? true, + inTimeline: false, + isPartnerSharedBy: false, + isPartnerSharedWith: false, + quotaUsageInBytes: adminDto.quotaUsageInBytes ?? 0, + quotaSizeInBytes: adminDto.quotaSizeInBytes ?? 0, + ); static UserDto fromPartnerDto(PartnerResponseDto dto) => UserDto( - id: dto.id, - email: dto.email, - name: dto.name, - isAdmin: false, - updatedAt: DateTime.now(), - profileImagePath: dto.profileImagePath, - avatarColor: dto.avatarColor.toAvatarColor(), - memoryEnabled: false, - inTimeline: dto.inTimeline ?? false, - isPartnerSharedBy: false, - isPartnerSharedWith: false, - quotaUsageInBytes: 0, - quotaSizeInBytes: 0, - ); + id: dto.id, + email: dto.email, + name: dto.name, + isAdmin: false, + updatedAt: DateTime.now(), + profileImagePath: dto.profileImagePath, + avatarColor: dto.avatarColor.toAvatarColor(), + memoryEnabled: false, + inTimeline: dto.inTimeline ?? false, + isPartnerSharedBy: false, + isPartnerSharedWith: false, + quotaUsageInBytes: 0, + quotaSizeInBytes: 0, + ); } extension on UserAvatarColor { AvatarColor toAvatarColor() => switch (this) { - UserAvatarColor.red => AvatarColor.red, - UserAvatarColor.green => AvatarColor.green, - UserAvatarColor.blue => AvatarColor.blue, - UserAvatarColor.purple => AvatarColor.purple, - UserAvatarColor.orange => AvatarColor.orange, - UserAvatarColor.pink => AvatarColor.pink, - UserAvatarColor.amber => AvatarColor.amber, - UserAvatarColor.yellow => AvatarColor.yellow, - UserAvatarColor.gray => AvatarColor.gray, - UserAvatarColor.primary || _ => AvatarColor.primary, - }; + UserAvatarColor.red => AvatarColor.red, + UserAvatarColor.green => AvatarColor.green, + UserAvatarColor.blue => AvatarColor.blue, + UserAvatarColor.purple => AvatarColor.purple, + UserAvatarColor.orange => AvatarColor.orange, + UserAvatarColor.pink => AvatarColor.pink, + UserAvatarColor.amber => AvatarColor.amber, + UserAvatarColor.yellow => AvatarColor.yellow, + UserAvatarColor.gray => AvatarColor.gray, + UserAvatarColor.primary || _ => AvatarColor.primary, + }; } diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index e52f29841..63220295f 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -50,10 +50,7 @@ void main() async { runApp( ProviderScope( - overrides: [ - dbProvider.overrideWithValue(db), - isarProvider.overrideWithValue(db), - ], + overrides: [dbProvider.overrideWithValue(db), isarProvider.overrideWithValue(db)], child: const MainWidget(), ), ); @@ -100,23 +97,15 @@ Future initApp() async { globalConfig: (Config.holdingQueue, (1000, 1000, 1000)), ); - await FileDownloader().trackTasksInGroup( - kDownloadGroupLivePhoto, - markDownloadedComplete: false, - ); + await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false); await FileDownloader().trackTasks(); - LicenseRegistry.addLicense( - () async* { - for (final license in nonPubLicenses.entries) { - yield LicenseEntryWithLineBreaks( - [license.key], - license.value, - ); - } - }, - ); + LicenseRegistry.addLicense(() async* { + for (final license in nonPubLicenses.entries) { + yield LicenseEntryWithLineBreaks([license.key], license.value); + } + }); } class ImmichApp extends ConsumerStatefulWidget { @@ -160,9 +149,7 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); // Sets the navigation bar color - SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle( - systemNavigationBarColor: Colors.transparent, - ); + SystemUiOverlayStyle overlayStyle = const SystemUiOverlayStyle(systemNavigationBarColor: Colors.transparent); if (Platform.isAndroid) { // Android 8 does not support transparent app bars final info = await DeviceInfoPlugin().androidInfo; @@ -177,40 +164,22 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve void _configureFileDownloaderNotifications() { FileDownloader().configureNotificationForGroup( kDownloadGroupImage, - running: TaskNotification( - 'downloading_media'.tr(), - '${'file_name'.tr()}: {filename}', - ), - complete: TaskNotification( - 'download_finished'.tr(), - '${'file_name'.tr()}: {filename}', - ), + running: TaskNotification('downloading_media'.tr(), '${'file_name'.tr()}: {filename}'), + complete: TaskNotification('download_finished'.tr(), '${'file_name'.tr()}: {filename}'), progressBar: true, ); FileDownloader().configureNotificationForGroup( kDownloadGroupVideo, - running: TaskNotification( - 'downloading_media'.tr(), - '${'file_name'.tr()}: {filename}', - ), - complete: TaskNotification( - 'download_finished'.tr(), - '${'file_name'.tr()}: {filename}', - ), + running: TaskNotification('downloading_media'.tr(), '${'file_name'.tr()}: {filename}'), + complete: TaskNotification('download_finished'.tr(), '${'file_name'.tr()}: {filename}'), progressBar: true, ); FileDownloader().configureNotificationForGroup( kManualUploadGroup, - running: TaskNotification( - 'uploading_media'.tr(), - '${'file_name'.tr()}: {displayName}', - ), - complete: TaskNotification( - 'upload_finished'.tr(), - '${'file_name'.tr()}: {displayName}', - ), + running: TaskNotification('uploading_media'.tr(), '${'file_name'.tr()}: {displayName}'), + complete: TaskNotification('upload_finished'.tr(), '${'file_name'.tr()}: {displayName}'), progressBar: true, ); } @@ -222,19 +191,13 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve final isColdStart = currentRouteName == null || currentRouteName == SplashScreenRoute.name; if (deepLink.uri.scheme == "immich") { - final proposedRoute = await deepLinkHandler.handleScheme( - deepLink, - isColdStart, - ); + final proposedRoute = await deepLinkHandler.handleScheme(deepLink, isColdStart); return proposedRoute; } if (deepLink.uri.host == "my.immich.app") { - final proposedRoute = await deepLinkHandler.handleMyImmichApp( - deepLink, - isColdStart, - ); + final proposedRoute = await deepLinkHandler.handleMyImmichApp(deepLink, isColdStart); return proposedRoute; } @@ -275,9 +238,7 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve final immichTheme = ref.watch(immichThemeProvider); return ProviderScope( - overrides: [ - localeProvider.overrideWithValue(context.locale), - ], + overrides: [localeProvider.overrideWithValue(context.locale)], child: MaterialApp.router( title: 'Immich', debugShowCheckedModeBanner: true, @@ -285,14 +246,8 @@ class ImmichAppState extends ConsumerState with WidgetsBindingObserve supportedLocales: context.supportedLocales, locale: context.locale, themeMode: ref.watch(immichThemeModeProvider), - darkTheme: getThemeData( - colorScheme: immichTheme.dark, - locale: context.locale, - ), - theme: getThemeData( - colorScheme: immichTheme.light, - locale: context.locale, - ), + darkTheme: getThemeData(colorScheme: immichTheme.dark, locale: context.locale), + theme: getThemeData(colorScheme: immichTheme.light, locale: context.locale), routerConfig: router.config( deepLinkBuilder: _deepLinkBuilder, navigatorObservers: () => [AppNavigationObserver(ref: ref), HeroController()], diff --git a/mobile/lib/models/albums/album_add_asset_response.model.dart b/mobile/lib/models/albums/album_add_asset_response.model.dart index fbc8a4d56..38dd989af 100644 --- a/mobile/lib/models/albums/album_add_asset_response.model.dart +++ b/mobile/lib/models/albums/album_add_asset_response.model.dart @@ -7,15 +7,9 @@ class AlbumAddAssetsResponse { List alreadyInAlbum; int successfullyAdded; - AlbumAddAssetsResponse({ - required this.alreadyInAlbum, - required this.successfullyAdded, - }); + AlbumAddAssetsResponse({required this.alreadyInAlbum, required this.successfullyAdded}); - AlbumAddAssetsResponse copyWith({ - List? alreadyInAlbum, - int? successfullyAdded, - }) { + AlbumAddAssetsResponse copyWith({List? alreadyInAlbum, int? successfullyAdded}) { return AlbumAddAssetsResponse( alreadyInAlbum: alreadyInAlbum ?? this.alreadyInAlbum, successfullyAdded: successfullyAdded ?? this.successfullyAdded, @@ -23,10 +17,7 @@ class AlbumAddAssetsResponse { } Map toMap() { - return { - 'alreadyInAlbum': alreadyInAlbum, - 'successfullyAdded': successfullyAdded, - }; + return {'alreadyInAlbum': alreadyInAlbum, 'successfullyAdded': successfullyAdded}; } String toJson() => json.encode(toMap()); diff --git a/mobile/lib/models/albums/album_search.model.dart b/mobile/lib/models/albums/album_search.model.dart index ac4eedbff..4f69e7e2e 100644 --- a/mobile/lib/models/albums/album_search.model.dart +++ b/mobile/lib/models/albums/album_search.model.dart @@ -1,5 +1 @@ -enum QuickFilterMode { - all, - sharedWithMe, - myAlbums, -} +enum QuickFilterMode { all, sharedWithMe, myAlbums } diff --git a/mobile/lib/models/albums/album_viewer_page_state.model.dart b/mobile/lib/models/albums/album_viewer_page_state.model.dart index 823226b4a..70427899a 100644 --- a/mobile/lib/models/albums/album_viewer_page_state.model.dart +++ b/mobile/lib/models/albums/album_viewer_page_state.model.dart @@ -11,11 +11,7 @@ class AlbumViewerPageState { required this.editDescriptionText, }); - AlbumViewerPageState copyWith({ - bool? isEditAlbum, - String? editTitleText, - String? editDescriptionText, - }) { + AlbumViewerPageState copyWith({bool? isEditAlbum, String? editTitleText, String? editDescriptionText}) { return AlbumViewerPageState( isEditAlbum: isEditAlbum ?? this.isEditAlbum, editTitleText: editTitleText ?? this.editTitleText, diff --git a/mobile/lib/models/albums/asset_selection_page_result.model.dart b/mobile/lib/models/albums/asset_selection_page_result.model.dart index d921ac63c..cc750f397 100644 --- a/mobile/lib/models/albums/asset_selection_page_result.model.dart +++ b/mobile/lib/models/albums/asset_selection_page_result.model.dart @@ -4,9 +4,7 @@ import 'package:immich_mobile/entities/asset.entity.dart'; class AssetSelectionPageResult { final Set selectedAssets; - const AssetSelectionPageResult({ - required this.selectedAssets, - }); + const AssetSelectionPageResult({required this.selectedAssets}); @override bool operator ==(Object other) { if (identical(this, other)) return true; diff --git a/mobile/lib/models/asset_selection_state.dart b/mobile/lib/models/asset_selection_state.dart index c022ec3a3..aded3064c 100644 --- a/mobile/lib/models/asset_selection_state.dart +++ b/mobile/lib/models/asset_selection_state.dart @@ -13,12 +13,7 @@ class AssetSelectionState { this.selectedCount = 0, }); - AssetSelectionState copyWith({ - bool? hasRemote, - bool? hasLocal, - bool? hasMerged, - int? selectedCount, - }) { + AssetSelectionState copyWith({bool? hasRemote, bool? hasLocal, bool? hasMerged, int? selectedCount}) { return AssetSelectionState( hasRemote: hasRemote ?? this.hasRemote, hasLocal: hasLocal ?? this.hasLocal, @@ -28,10 +23,10 @@ class AssetSelectionState { } AssetSelectionState.fromSelection(Set selection) - : hasLocal = selection.any((e) => e.storage == AssetState.local), - hasMerged = selection.any((e) => e.storage == AssetState.merged), - hasRemote = selection.any((e) => e.storage == AssetState.remote), - selectedCount = selection.length; + : hasLocal = selection.any((e) => e.storage == AssetState.local), + hasMerged = selection.any((e) => e.storage == AssetState.merged), + hasRemote = selection.any((e) => e.storage == AssetState.remote), + selectedCount = selection.length; @override String toString() => diff --git a/mobile/lib/models/auth/auxilary_endpoint.model.dart b/mobile/lib/models/auth/auxilary_endpoint.model.dart index e876097d6..c7f472e11 100644 --- a/mobile/lib/models/auth/auxilary_endpoint.model.dart +++ b/mobile/lib/models/auth/auxilary_endpoint.model.dart @@ -5,19 +5,10 @@ class AuxilaryEndpoint { final String url; final AuxCheckStatus status; - const AuxilaryEndpoint({ - required this.url, - required this.status, - }); + const AuxilaryEndpoint({required this.url, required this.status}); - AuxilaryEndpoint copyWith({ - String? url, - AuxCheckStatus? status, - }) { - return AuxilaryEndpoint( - url: url ?? this.url, - status: status ?? this.status, - ); + AuxilaryEndpoint copyWith({String? url, AuxCheckStatus? status}) { + return AuxilaryEndpoint(url: url ?? this.url, status: status ?? this.status); } @override @@ -34,10 +25,7 @@ class AuxilaryEndpoint { int get hashCode => url.hashCode ^ status.hashCode; Map toMap() { - return { - 'url': url, - 'status': status.toMap(), - }; + return {'url': url, 'status': status.toMap()}; } factory AuxilaryEndpoint.fromMap(Map map) { @@ -55,9 +43,7 @@ class AuxilaryEndpoint { class AuxCheckStatus { final String name; - const AuxCheckStatus({ - required this.name, - }); + const AuxCheckStatus({required this.name}); const AuxCheckStatus._(this.name); static const loading = AuxCheckStatus._('loading'); @@ -75,24 +61,16 @@ class AuxCheckStatus { @override int get hashCode => name.hashCode; - AuxCheckStatus copyWith({ - String? name, - }) { - return AuxCheckStatus( - name: name ?? this.name, - ); + AuxCheckStatus copyWith({String? name}) { + return AuxCheckStatus(name: name ?? this.name); } Map toMap() { - return { - 'name': name, - }; + return {'name': name}; } factory AuxCheckStatus.fromMap(Map map) { - return AuxCheckStatus( - name: map['name'] as String, - ); + return AuxCheckStatus(name: map['name'] as String); } String toJson() => json.encode(toMap()); diff --git a/mobile/lib/models/auth/biometric_status.model.dart b/mobile/lib/models/auth/biometric_status.model.dart index 223b28327..ad2b06be0 100644 --- a/mobile/lib/models/auth/biometric_status.model.dart +++ b/mobile/lib/models/auth/biometric_status.model.dart @@ -5,18 +5,12 @@ class BiometricStatus { final List availableBiometrics; final bool canAuthenticate; - const BiometricStatus({ - required this.availableBiometrics, - required this.canAuthenticate, - }); + const BiometricStatus({required this.availableBiometrics, required this.canAuthenticate}); @override String toString() => 'BiometricStatus(availableBiometrics: $availableBiometrics, canAuthenticate: $canAuthenticate)'; - BiometricStatus copyWith({ - List? availableBiometrics, - bool? canAuthenticate, - }) { + BiometricStatus copyWith({List? availableBiometrics, bool? canAuthenticate}) { return BiometricStatus( availableBiometrics: availableBiometrics ?? this.availableBiometrics, canAuthenticate: canAuthenticate ?? this.canAuthenticate, diff --git a/mobile/lib/models/backup/available_album.model.dart b/mobile/lib/models/backup/available_album.model.dart index 96a19cf60..502d0b66b 100644 --- a/mobile/lib/models/backup/available_album.model.dart +++ b/mobile/lib/models/backup/available_album.model.dart @@ -4,17 +4,9 @@ class AvailableAlbum { final Album album; final int assetCount; final DateTime? lastBackup; - const AvailableAlbum({ - required this.album, - required this.assetCount, - this.lastBackup, - }); + const AvailableAlbum({required this.album, required this.assetCount, this.lastBackup}); - AvailableAlbum copyWith({ - Album? album, - int? assetCount, - DateTime? lastBackup, - }) { + AvailableAlbum copyWith({Album? album, int? assetCount, DateTime? lastBackup}) { return AvailableAlbum( album: album ?? this.album, assetCount: assetCount ?? this.assetCount, diff --git a/mobile/lib/models/backup/backup_state.model.dart b/mobile/lib/models/backup/backup_state.model.dart index 39554736d..635d925c3 100644 --- a/mobile/lib/models/backup/backup_state.model.dart +++ b/mobile/lib/models/backup/backup_state.model.dart @@ -148,10 +148,7 @@ class BackUpState { collectionEquals(other.selectedBackupAlbums, selectedBackupAlbums) && collectionEquals(other.excludedBackupAlbums, excludedBackupAlbums) && collectionEquals(other.allUniqueAssets, allUniqueAssets) && - collectionEquals( - other.selectedAlbumsBackupAssetsIds, - selectedAlbumsBackupAssetsIds, - ) && + collectionEquals(other.selectedAlbumsBackupAssetsIds, selectedAlbumsBackupAssetsIds) && other.currentUploadAsset == currentUploadAsset; } diff --git a/mobile/lib/models/backup/success_upload_asset.model.dart b/mobile/lib/models/backup/success_upload_asset.model.dart index ca49450a3..da1e104ba 100644 --- a/mobile/lib/models/backup/success_upload_asset.model.dart +++ b/mobile/lib/models/backup/success_upload_asset.model.dart @@ -5,17 +5,9 @@ class SuccessUploadAsset { final String remoteAssetId; final bool isDuplicate; - const SuccessUploadAsset({ - required this.candidate, - required this.remoteAssetId, - required this.isDuplicate, - }); + const SuccessUploadAsset({required this.candidate, required this.remoteAssetId, required this.isDuplicate}); - SuccessUploadAsset copyWith({ - BackupCandidate? candidate, - String? remoteAssetId, - bool? isDuplicate, - }) { + SuccessUploadAsset copyWith({BackupCandidate? candidate, String? remoteAssetId, bool? isDuplicate}) { return SuccessUploadAsset( candidate: candidate ?? this.candidate, remoteAssetId: remoteAssetId ?? this.remoteAssetId, diff --git a/mobile/lib/models/download/download_state.model.dart b/mobile/lib/models/download/download_state.model.dart index b2bd389bc..82d4e3125 100644 --- a/mobile/lib/models/download/download_state.model.dart +++ b/mobile/lib/models/download/download_state.model.dart @@ -10,17 +10,9 @@ class DownloadInfo { // enum final TaskStatus status; - const DownloadInfo({ - required this.fileName, - required this.progress, - required this.status, - }); + const DownloadInfo({required this.fileName, required this.progress, required this.status}); - DownloadInfo copyWith({ - String? fileName, - double? progress, - TaskStatus? status, - }) { + DownloadInfo copyWith({String? fileName, double? progress, TaskStatus? status}) { return DownloadInfo( fileName: fileName ?? this.fileName, progress: progress ?? this.progress, @@ -29,11 +21,7 @@ class DownloadInfo { } Map toMap() { - return { - 'fileName': fileName, - 'progress': progress, - 'status': status.index, - }; + return {'fileName': fileName, 'progress': progress, 'status': status.index}; } factory DownloadInfo.fromMap(Map map) { @@ -67,17 +55,9 @@ class DownloadState { final TaskStatus downloadStatus; final Map taskProgress; final bool showProgress; - const DownloadState({ - required this.downloadStatus, - required this.taskProgress, - required this.showProgress, - }); + const DownloadState({required this.downloadStatus, required this.taskProgress, required this.showProgress}); - DownloadState copyWith({ - TaskStatus? downloadStatus, - Map? taskProgress, - bool? showProgress, - }) { + DownloadState copyWith({TaskStatus? downloadStatus, Map? taskProgress, bool? showProgress}) { return DownloadState( downloadStatus: downloadStatus ?? this.downloadStatus, taskProgress: taskProgress ?? this.taskProgress, diff --git a/mobile/lib/models/download/livephotos_medatada.model.dart b/mobile/lib/models/download/livephotos_medatada.model.dart index 9c0c7ae4e..f77a1514a 100644 --- a/mobile/lib/models/download/livephotos_medatada.model.dart +++ b/mobile/lib/models/download/livephotos_medatada.model.dart @@ -1,43 +1,25 @@ // ignore_for_file: public_member_api_docs, sort_constructors_first import 'dart:convert'; -enum LivePhotosPart { - video, - image, -} +enum LivePhotosPart { video, image } class LivePhotosMetadata { // enum LivePhotosPart part; String id; - LivePhotosMetadata({ - required this.part, - required this.id, - }); + LivePhotosMetadata({required this.part, required this.id}); - LivePhotosMetadata copyWith({ - LivePhotosPart? part, - String? id, - }) { - return LivePhotosMetadata( - part: part ?? this.part, - id: id ?? this.id, - ); + LivePhotosMetadata copyWith({LivePhotosPart? part, String? id}) { + return LivePhotosMetadata(part: part ?? this.part, id: id ?? this.id); } Map toMap() { - return { - 'part': part.index, - 'id': id, - }; + return {'part': part.index, 'id': id}; } factory LivePhotosMetadata.fromMap(Map map) { - return LivePhotosMetadata( - part: LivePhotosPart.values[map['part'] as int], - id: map['id'] as String, - ); + return LivePhotosMetadata(part: LivePhotosPart.values[map['part'] as int], id: map['id'] as String); } String toJson() => json.encode(toMap()); diff --git a/mobile/lib/models/folder/recursive_folder.model.dart b/mobile/lib/models/folder/recursive_folder.model.dart index 62ec670fe..33ac0f4cb 100644 --- a/mobile/lib/models/folder/recursive_folder.model.dart +++ b/mobile/lib/models/folder/recursive_folder.model.dart @@ -3,9 +3,5 @@ import 'package:immich_mobile/models/folder/root_folder.model.dart'; class RecursiveFolder extends RootFolder { final String name; - const RecursiveFolder({ - required this.name, - required super.path, - required super.subfolders, - }); + const RecursiveFolder({required this.name, required super.path, required super.subfolders}); } diff --git a/mobile/lib/models/folder/root_folder.model.dart b/mobile/lib/models/folder/root_folder.model.dart index 567093ecd..d4b791b91 100644 --- a/mobile/lib/models/folder/root_folder.model.dart +++ b/mobile/lib/models/folder/root_folder.model.dart @@ -4,8 +4,5 @@ class RootFolder { final List subfolders; final String path; - const RootFolder({ - required this.subfolders, - required this.path, - }); + const RootFolder({required this.subfolders, required this.path}); } diff --git a/mobile/lib/models/map/map_marker.model.dart b/mobile/lib/models/map/map_marker.model.dart index 781eae792..0f425306f 100644 --- a/mobile/lib/models/map/map_marker.model.dart +++ b/mobile/lib/models/map/map_marker.model.dart @@ -4,24 +4,13 @@ import 'package:openapi/api.dart'; class MapMarker { final LatLng latLng; final String assetRemoteId; - const MapMarker({ - required this.latLng, - required this.assetRemoteId, - }); + const MapMarker({required this.latLng, required this.assetRemoteId}); - MapMarker copyWith({ - LatLng? latLng, - String? assetRemoteId, - }) { - return MapMarker( - latLng: latLng ?? this.latLng, - assetRemoteId: assetRemoteId ?? this.assetRemoteId, - ); + MapMarker copyWith({LatLng? latLng, String? assetRemoteId}) { + return MapMarker(latLng: latLng ?? this.latLng, assetRemoteId: assetRemoteId ?? this.assetRemoteId); } - MapMarker.fromDto(MapMarkerResponseDto dto) - : latLng = LatLng(dto.lat, dto.lon), - assetRemoteId = dto.id; + MapMarker.fromDto(MapMarkerResponseDto dto) : latLng = LatLng(dto.lat, dto.lon), assetRemoteId = dto.id; @override String toString() => 'MapMarker(latLng: $latLng, assetRemoteId: $assetRemoteId)'; diff --git a/mobile/lib/models/memories/memory.model.dart b/mobile/lib/models/memories/memory.model.dart index fb85d70b9..8a9db5d51 100644 --- a/mobile/lib/models/memories/memory.model.dart +++ b/mobile/lib/models/memories/memory.model.dart @@ -7,19 +7,10 @@ import 'package:immich_mobile/entities/asset.entity.dart'; class Memory { final String title; final List assets; - const Memory({ - required this.title, - required this.assets, - }); + const Memory({required this.title, required this.assets}); - Memory copyWith({ - String? title, - List? assets, - }) { - return Memory( - title: title ?? this.title, - assets: assets ?? this.assets, - ); + Memory copyWith({String? title, List? assets}) { + return Memory(title: title ?? this.title, assets: assets ?? this.assets); } @override diff --git a/mobile/lib/models/search/search_curated_content.model.dart b/mobile/lib/models/search/search_curated_content.model.dart index 7ecb5af45..6e4a08387 100644 --- a/mobile/lib/models/search/search_curated_content.model.dart +++ b/mobile/lib/models/search/search_curated_content.model.dart @@ -14,30 +14,14 @@ class SearchCuratedContent { /// The id to lookup the asset from the server final String id; - const SearchCuratedContent({ - required this.label, - required this.id, - this.subtitle, - }); + const SearchCuratedContent({required this.label, required this.id, this.subtitle}); - SearchCuratedContent copyWith({ - String? label, - String? subtitle, - String? id, - }) { - return SearchCuratedContent( - label: label ?? this.label, - subtitle: subtitle ?? this.subtitle, - id: id ?? this.id, - ); + SearchCuratedContent copyWith({String? label, String? subtitle, String? id}) { + return SearchCuratedContent(label: label ?? this.label, subtitle: subtitle ?? this.subtitle, id: id ?? this.id); } Map toMap() { - return { - 'label': label, - 'subtitle': subtitle, - 'id': id, - }; + return {'label': label, 'subtitle': subtitle, 'id': id}; } factory SearchCuratedContent.fromMap(Map map) { diff --git a/mobile/lib/models/search/search_filter.model.dart b/mobile/lib/models/search/search_filter.model.dart index 1c2167faa..7f27b4d33 100644 --- a/mobile/lib/models/search/search_filter.model.dart +++ b/mobile/lib/models/search/search_filter.model.dart @@ -8,30 +8,14 @@ class SearchLocationFilter { String? country; String? state; String? city; - SearchLocationFilter({ - this.country, - this.state, - this.city, - }); + SearchLocationFilter({this.country, this.state, this.city}); - SearchLocationFilter copyWith({ - String? country, - String? state, - String? city, - }) { - return SearchLocationFilter( - country: country ?? this.country, - state: state ?? this.state, - city: city ?? this.city, - ); + SearchLocationFilter copyWith({String? country, String? state, String? city}) { + return SearchLocationFilter(country: country ?? this.country, state: state ?? this.state, city: city ?? this.city); } Map toMap() { - return { - 'country': country, - 'state': state, - 'city': city, - }; + return {'country': country, 'state': state, 'city': city}; } factory SearchLocationFilter.fromMap(Map map) { @@ -64,26 +48,14 @@ class SearchLocationFilter { class SearchCameraFilter { String? make; String? model; - SearchCameraFilter({ - this.make, - this.model, - }); + SearchCameraFilter({this.make, this.model}); - SearchCameraFilter copyWith({ - String? make, - String? model, - }) { - return SearchCameraFilter( - make: make ?? this.make, - model: model ?? this.model, - ); + SearchCameraFilter copyWith({String? make, String? model}) { + return SearchCameraFilter(make: make ?? this.make, model: model ?? this.model); } Map toMap() { - return { - 'make': make, - 'model': model, - }; + return {'make': make, 'model': model}; } factory SearchCameraFilter.fromMap(Map map) { @@ -115,19 +87,10 @@ class SearchCameraFilter { class SearchDateFilter { DateTime? takenBefore; DateTime? takenAfter; - SearchDateFilter({ - this.takenBefore, - this.takenAfter, - }); + SearchDateFilter({this.takenBefore, this.takenAfter}); - SearchDateFilter copyWith({ - DateTime? takenBefore, - DateTime? takenAfter, - }) { - return SearchDateFilter( - takenBefore: takenBefore ?? this.takenBefore, - takenAfter: takenAfter ?? this.takenAfter, - ); + SearchDateFilter copyWith({DateTime? takenBefore, DateTime? takenAfter}) { + return SearchDateFilter(takenBefore: takenBefore ?? this.takenBefore, takenAfter: takenAfter ?? this.takenAfter); } Map toMap() { @@ -167,17 +130,9 @@ class SearchDisplayFilters { bool isNotInAlbum = false; bool isArchive = false; bool isFavorite = false; - SearchDisplayFilters({ - required this.isNotInAlbum, - required this.isArchive, - required this.isFavorite, - }); + SearchDisplayFilters({required this.isNotInAlbum, required this.isArchive, required this.isFavorite}); - SearchDisplayFilters copyWith({ - bool? isNotInAlbum, - bool? isArchive, - bool? isFavorite, - }) { + SearchDisplayFilters copyWith({bool? isNotInAlbum, bool? isArchive, bool? isFavorite}) { return SearchDisplayFilters( isNotInAlbum: isNotInAlbum ?? this.isNotInAlbum, isArchive: isArchive ?? this.isArchive, @@ -186,11 +141,7 @@ class SearchDisplayFilters { } Map toMap() { - return { - 'isNotInAlbum': isNotInAlbum, - 'isArchive': isArchive, - 'isFavorite': isFavorite, - }; + return {'isNotInAlbum': isNotInAlbum, 'isArchive': isArchive, 'isFavorite': isFavorite}; } factory SearchDisplayFilters.fromMap(Map map) { diff --git a/mobile/lib/models/search/search_result.model.dart b/mobile/lib/models/search/search_result.model.dart index 458a9b4ab..02553869b 100644 --- a/mobile/lib/models/search/search_result.model.dart +++ b/mobile/lib/models/search/search_result.model.dart @@ -6,19 +6,10 @@ class SearchResult { final List assets; final int? nextPage; - const SearchResult({ - required this.assets, - this.nextPage, - }); + const SearchResult({required this.assets, this.nextPage}); - SearchResult copyWith({ - List? assets, - int? nextPage, - }) { - return SearchResult( - assets: assets ?? this.assets, - nextPage: nextPage ?? this.nextPage, - ); + SearchResult copyWith({List? assets, int? nextPage}) { + return SearchResult(assets: assets ?? this.assets, nextPage: nextPage ?? this.nextPage); } @override diff --git a/mobile/lib/models/server_info/server_config.model.dart b/mobile/lib/models/server_info/server_config.model.dart index 88c27443c..37b98afad 100644 --- a/mobile/lib/models/server_info/server_config.model.dart +++ b/mobile/lib/models/server_info/server_config.model.dart @@ -15,11 +15,7 @@ class ServerConfig { required this.mapLightStyleUrl, }); - ServerConfig copyWith({ - int? trashDays, - String? oauthButtonText, - String? externalDomain, - }) { + ServerConfig copyWith({int? trashDays, String? oauthButtonText, String? externalDomain}) { return ServerConfig( trashDays: trashDays ?? this.trashDays, oauthButtonText: oauthButtonText ?? this.oauthButtonText, @@ -34,11 +30,11 @@ class ServerConfig { 'ServerConfig(trashDays: $trashDays, oauthButtonText: $oauthButtonText, externalDomain: $externalDomain)'; ServerConfig.fromDto(ServerConfigDto dto) - : trashDays = dto.trashDays, - oauthButtonText = dto.oauthButtonText, - externalDomain = dto.externalDomain, - mapDarkStyleUrl = dto.mapDarkStyleUrl, - mapLightStyleUrl = dto.mapLightStyleUrl; + : trashDays = dto.trashDays, + oauthButtonText = dto.oauthButtonText, + externalDomain = dto.externalDomain, + mapDarkStyleUrl = dto.mapDarkStyleUrl, + mapLightStyleUrl = dto.mapLightStyleUrl; @override bool operator ==(covariant ServerConfig other) { diff --git a/mobile/lib/models/server_info/server_disk_info.model.dart b/mobile/lib/models/server_info/server_disk_info.model.dart index 8248097ca..01042b9f6 100644 --- a/mobile/lib/models/server_info/server_disk_info.model.dart +++ b/mobile/lib/models/server_info/server_disk_info.model.dart @@ -13,12 +13,7 @@ class ServerDiskInfo { required this.diskUsagePercentage, }); - ServerDiskInfo copyWith({ - String? diskAvailable, - String? diskSize, - String? diskUse, - double? diskUsagePercentage, - }) { + ServerDiskInfo copyWith({String? diskAvailable, String? diskSize, String? diskUse, double? diskUsagePercentage}) { return ServerDiskInfo( diskAvailable: diskAvailable ?? this.diskAvailable, diskSize: diskSize ?? this.diskSize, @@ -33,10 +28,10 @@ class ServerDiskInfo { } ServerDiskInfo.fromDto(ServerStorageResponseDto dto) - : diskAvailable = dto.diskAvailable, - diskSize = dto.diskSize, - diskUse = dto.diskUse, - diskUsagePercentage = dto.diskUsagePercentage; + : diskAvailable = dto.diskAvailable, + diskSize = dto.diskSize, + diskUse = dto.diskUse, + diskUsagePercentage = dto.diskUsagePercentage; @override bool operator ==(Object other) { diff --git a/mobile/lib/models/server_info/server_features.model.dart b/mobile/lib/models/server_info/server_features.model.dart index 7e537ebf3..20b9f2961 100644 --- a/mobile/lib/models/server_info/server_features.model.dart +++ b/mobile/lib/models/server_info/server_features.model.dart @@ -13,12 +13,7 @@ class ServerFeatures { required this.passwordLogin, }); - ServerFeatures copyWith({ - bool? trash, - bool? map, - bool? oauthEnabled, - bool? passwordLogin, - }) { + ServerFeatures copyWith({bool? trash, bool? map, bool? oauthEnabled, bool? passwordLogin}) { return ServerFeatures( trash: trash ?? this.trash, map: map ?? this.map, @@ -33,10 +28,10 @@ class ServerFeatures { } ServerFeatures.fromDto(ServerFeaturesDto dto) - : trash = dto.trash, - map = dto.map, - oauthEnabled = dto.oauth, - passwordLogin = dto.passwordLogin; + : trash = dto.trash, + map = dto.map, + oauthEnabled = dto.oauth, + passwordLogin = dto.passwordLogin; @override bool operator ==(covariant ServerFeatures other) { diff --git a/mobile/lib/models/server_info/server_version.model.dart b/mobile/lib/models/server_info/server_version.model.dart index bd7153662..2cb41b041 100644 --- a/mobile/lib/models/server_info/server_version.model.dart +++ b/mobile/lib/models/server_info/server_version.model.dart @@ -5,22 +5,10 @@ class ServerVersion { final int minor; final int patch; - const ServerVersion({ - required this.major, - required this.minor, - required this.patch, - }); + const ServerVersion({required this.major, required this.minor, required this.patch}); - ServerVersion copyWith({ - int? major, - int? minor, - int? patch, - }) { - return ServerVersion( - major: major ?? this.major, - minor: minor ?? this.minor, - patch: patch ?? this.patch, - ); + ServerVersion copyWith({int? major, int? minor, int? patch}) { + return ServerVersion(major: major ?? this.major, minor: minor ?? this.minor, patch: patch ?? this.patch); } @override @@ -28,10 +16,7 @@ class ServerVersion { return 'ServerVersion(major: $major, minor: $minor, patch: $patch)'; } - ServerVersion.fromDto(ServerVersionResponseDto dto) - : major = dto.major, - minor = dto.minor, - patch = dto.patch_; + ServerVersion.fromDto(ServerVersionResponseDto dto) : major = dto.major, minor = dto.minor, patch = dto.patch_; @override bool operator ==(Object other) { diff --git a/mobile/lib/models/shared_link/shared_link.model.dart b/mobile/lib/models/shared_link/shared_link.model.dart index 135d191b2..57a1f441e 100644 --- a/mobile/lib/models/shared_link/shared_link.model.dart +++ b/mobile/lib/models/shared_link/shared_link.model.dart @@ -58,23 +58,23 @@ class SharedLink { } SharedLink.fromDto(SharedLinkResponseDto dto) - : id = dto.id, - allowDownload = dto.allowDownload, - allowUpload = dto.allowUpload, - description = dto.description, - password = dto.password, - expiresAt = dto.expiresAt, - key = dto.key, - showMetadata = dto.showMetadata, - type = dto.type == SharedLinkType.ALBUM ? SharedLinkSource.album : SharedLinkSource.individual, - title = dto.type == SharedLinkType.ALBUM - ? dto.album?.albumName.toUpperCase() ?? "UNKNOWN SHARE" - : "INDIVIDUAL SHARE", - thumbAssetId = dto.type == SharedLinkType.ALBUM - ? dto.album?.albumThumbnailAssetId - : dto.assets.isNotEmpty - ? dto.assets[0].id - : null; + : id = dto.id, + allowDownload = dto.allowDownload, + allowUpload = dto.allowUpload, + description = dto.description, + password = dto.password, + expiresAt = dto.expiresAt, + key = dto.key, + showMetadata = dto.showMetadata, + type = dto.type == SharedLinkType.ALBUM ? SharedLinkSource.album : SharedLinkSource.individual, + title = dto.type == SharedLinkType.ALBUM + ? dto.album?.albumName.toUpperCase() ?? "UNKNOWN SHARE" + : "INDIVIDUAL SHARE", + thumbAssetId = dto.type == SharedLinkType.ALBUM + ? dto.album?.albumThumbnailAssetId + : dto.assets.isNotEmpty + ? dto.assets[0].id + : null; @override String toString() => diff --git a/mobile/lib/models/upload/share_intent_attachment.model.dart b/mobile/lib/models/upload/share_intent_attachment.model.dart index 61157f367..ae05e4c49 100644 --- a/mobile/lib/models/upload/share_intent_attachment.model.dart +++ b/mobile/lib/models/upload/share_intent_attachment.model.dart @@ -5,21 +5,9 @@ import 'dart:io'; import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:path/path.dart'; -enum ShareIntentAttachmentType { - image, - video, -} +enum ShareIntentAttachmentType { image, video } -enum UploadStatus { - enqueued, - running, - complete, - notFound, - failed, - canceled, - waitingToRetry, - paused, -} +enum UploadStatus { enqueued, running, complete, notFound, failed, canceled, waitingToRetry, paused } class ShareIntentAttachment { final String path; @@ -90,9 +78,8 @@ class ShareIntentAttachment { String toJson() => json.encode(toMap()); - factory ShareIntentAttachment.fromJson(String source) => ShareIntentAttachment.fromMap( - json.decode(source) as Map, - ); + factory ShareIntentAttachment.fromJson(String source) => + ShareIntentAttachment.fromMap(json.decode(source) as Map); @override String toString() { diff --git a/mobile/lib/pages/album/album_additional_shared_user_selection.page.dart b/mobile/lib/pages/album/album_additional_shared_user_selection.page.dart index c0fc8c936..f40ac9cca 100644 --- a/mobile/lib/pages/album/album_additional_shared_user_selection.page.dart +++ b/mobile/lib/pages/album/album_additional_shared_user_selection.page.dart @@ -14,10 +14,7 @@ import 'package:immich_mobile/widgets/common/user_circle_avatar.dart'; class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget { final Album album; - const AlbumAdditionalSharedUserSelectionPage({ - super.key, - required this.album, - }); + const AlbumAdditionalSharedUserSelectionPage({super.key, required this.album}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -30,17 +27,9 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget { buildTileIcon(UserDto user) { if (sharedUsersList.value.contains(user)) { - return CircleAvatar( - backgroundColor: context.primaryColor, - child: const Icon( - Icons.check_rounded, - size: 25, - ), - ); + return CircleAvatar(backgroundColor: context.primaryColor, child: const Icon(Icons.check_rounded, size: 25)); } else { - return UserCircleAvatar( - user: user, - ); + return UserCircleAvatar(user: user); } } @@ -53,31 +42,19 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Chip( backgroundColor: context.primaryColor.withValues(alpha: 0.15), - label: Text( - user.name, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), + label: Text(user.name, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold)), ), ), ); } return ListView( children: [ - Wrap( - children: [...usersChip], - ), + Wrap(children: [...usersChip]), Padding( padding: const EdgeInsets.all(16.0), child: Text( 'suggestions'.tr(), - style: const TextStyle( - fontSize: 14, - color: Colors.grey, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), ), ), ListView.builder( @@ -87,31 +64,15 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget { return ListTile( leading: buildTileIcon(users[index]), dense: true, - title: Text( - users[index].name, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - subtitle: Text( - users[index].email, - style: const TextStyle( - fontSize: 12, - ), - ), + title: Text(users[index].name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), + subtitle: Text(users[index].email, style: const TextStyle(fontSize: 12)), onTap: () { if (sharedUsersList.value.contains(users[index])) { sharedUsersList.value = sharedUsersList.value - .where( - (selectedUser) => selectedUser.id != users[index].id, - ) + .where((selectedUser) => selectedUser.id != users[index].id) .toSet(); } else { - sharedUsersList.value = { - ...sharedUsersList.value, - users[index], - }; + sharedUsersList.value = {...sharedUsersList.value, users[index]}; } }, ); @@ -124,9 +85,7 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: const Text( - 'invite_to_album', - ).tr(), + title: const Text('invite_to_album').tr(), elevation: 0, centerTitle: false, leading: IconButton( @@ -138,19 +97,14 @@ class AlbumAdditionalSharedUserSelectionPage extends HookConsumerWidget { actions: [ TextButton( onPressed: sharedUsersList.value.isEmpty ? null : addNewUsersHandler, - child: const Text( - "add", - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ).tr(), + child: const Text("add", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(), ), ], ), body: suggestedShareUsers.widgetWhen( onData: (users) { for (var sharedUsers in album.sharedUsers) { - users.removeWhere( - (u) => u.id == sharedUsers.id || u.id == album.ownerId, - ); + users.removeWhere((u) => u.id == sharedUsers.id || u.id == album.ownerId); } return buildUserList(users); diff --git a/mobile/lib/pages/album/album_asset_selection.page.dart b/mobile/lib/pages/album/album_asset_selection.page.dart index e72ecb071..ccc4c44d4 100644 --- a/mobile/lib/pages/album/album_asset_selection.page.dart +++ b/mobile/lib/pages/album/album_asset_selection.page.dart @@ -13,11 +13,7 @@ import 'package:immich_mobile/widgets/asset_grid/immich_asset_grid.dart'; @RoutePage() class AlbumAssetSelectionPage extends HookConsumerWidget { - const AlbumAssetSelectionPage({ - super.key, - required this.existingAssets, - this.canDeselect = false, - }); + const AlbumAssetSelectionPage({super.key, required this.existingAssets, this.canDeselect = false}); final Set existingAssets; final bool canDeselect; @@ -52,10 +48,7 @@ class AlbumAssetSelectionPage extends HookConsumerWidget { }, ), title: selected.value.isEmpty - ? const Text( - 'add_photos', - style: TextStyle(fontSize: 18), - ).tr() + ? const Text('add_photos', style: TextStyle(fontSize: 18)).tr() : const Text( 'share_assets_selected', style: TextStyle(fontSize: 18), @@ -70,17 +63,12 @@ class AlbumAssetSelectionPage extends HookConsumerWidget { }, child: Text( canDeselect ? "done" : "add", - style: TextStyle( - fontWeight: FontWeight.bold, - color: context.primaryColor, - ), + style: TextStyle(fontWeight: FontWeight.bold, color: context.primaryColor), ).tr(), ), ], ), - body: assetSelectionRenderList.widgetWhen( - onData: (data) => buildBody(data), - ), + body: assetSelectionRenderList.widgetWhen(onData: (data) => buildBody(data)), ); } } diff --git a/mobile/lib/pages/album/album_control_button.dart b/mobile/lib/pages/album/album_control_button.dart index c453ace61..578eb839a 100644 --- a/mobile/lib/pages/album/album_control_button.dart +++ b/mobile/lib/pages/album/album_control_button.dart @@ -7,11 +7,7 @@ class AlbumControlButton extends ConsumerWidget { final void Function()? onAddPhotosPressed; final void Function()? onAddUsersPressed; - const AlbumControlButton({ - super.key, - this.onAddPhotosPressed, - this.onAddUsersPressed, - }); + const AlbumControlButton({super.key, this.onAddPhotosPressed, this.onAddUsersPressed}); @override Widget build(BuildContext context, WidgetRef ref) { diff --git a/mobile/lib/pages/album/album_date_range.dart b/mobile/lib/pages/album/album_date_range.dart index 57d808f22..dbfd9214f 100644 --- a/mobile/lib/pages/album/album_date_range.dart +++ b/mobile/lib/pages/album/album_date_range.dart @@ -33,9 +33,7 @@ class AlbumDateRange extends ConsumerWidget { padding: const EdgeInsets.only(left: 16.0), child: Text( _getDateRangeText(startDate, endDate), - style: context.textTheme.labelLarge?.copyWith( - color: context.colorScheme.onSurfaceVariant, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceVariant), ), ); } @@ -46,8 +44,9 @@ class AlbumDateRange extends ConsumerWidget { return DateFormat.yMMMd().format(startDate); } - final String startDateText = - (startDate.year == endDate.year ? DateFormat.MMMd() : DateFormat.yMMMd()).format(startDate); + final String startDateText = (startDate.year == endDate.year ? DateFormat.MMMd() : DateFormat.yMMMd()).format( + startDate, + ); final String endDateText = DateFormat.yMMMd().format(endDate); return "$startDateText - $endDateText"; } diff --git a/mobile/lib/pages/album/album_description.dart b/mobile/lib/pages/album/album_description.dart index 37c5beb2c..383367e8b 100644 --- a/mobile/lib/pages/album/album_description.dart +++ b/mobile/lib/pages/album/album_description.dart @@ -36,10 +36,7 @@ class AlbumDescription extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(left: 16, right: 8), - child: Text( - albumDescription ?? 'add_a_description'.tr(), - style: context.textTheme.bodyLarge, - ), + child: Text(albumDescription ?? 'add_a_description'.tr(), style: context.textTheme.bodyLarge), ); } } diff --git a/mobile/lib/pages/album/album_options.page.dart b/mobile/lib/pages/album/album_options.page.dart index 4c5109334..e659340f2 100644 --- a/mobile/lib/pages/album/album_options.page.dart +++ b/mobile/lib/pages/album/album_options.page.dart @@ -51,9 +51,7 @@ class AlbumOptionsPage extends HookConsumerWidget { final isSuccess = await ref.read(albumProvider.notifier).leaveAlbum(album); if (isSuccess) { - context.navigateTo( - const TabControllerRoute(children: [AlbumsRoute()]), - ); + context.navigateTo(const TabControllerRoute(children: [AlbumsRoute()])); } else { showErrorMessage(); } @@ -110,10 +108,7 @@ class AlbumOptionsPage extends HookConsumerWidget { return SafeArea( child: Padding( padding: const EdgeInsets.only(top: 24.0), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [...actions], - ), + child: Column(mainAxisSize: MainAxisSize.min, children: [...actions]), ), ); }, @@ -123,20 +118,9 @@ class AlbumOptionsPage extends HookConsumerWidget { buildOwnerInfo() { return ListTile( leading: owner != null ? UserCircleAvatar(user: owner.toDto()) : const SizedBox(), - title: Text( - album.owner.value?.name ?? "", - style: const TextStyle( - fontWeight: FontWeight.w500, - ), - ), - subtitle: Text( - album.owner.value?.email ?? "", - style: TextStyle(color: context.colorScheme.onSurfaceSecondary), - ), - trailing: Text( - "owner", - style: context.textTheme.labelLarge, - ).tr(), + title: Text(album.owner.value?.name ?? "", style: const TextStyle(fontWeight: FontWeight.w500)), + subtitle: Text(album.owner.value?.email ?? "", style: TextStyle(color: context.colorScheme.onSurfaceSecondary)), + trailing: Text("owner", style: context.textTheme.labelLarge).tr(), ); } @@ -148,22 +132,9 @@ class AlbumOptionsPage extends HookConsumerWidget { itemBuilder: (context, index) { final user = sharedUsers.value[index]; return ListTile( - leading: UserCircleAvatar( - user: user, - radius: 22, - ), - title: Text( - user.name, - style: const TextStyle( - fontWeight: FontWeight.w500, - ), - ), - subtitle: Text( - user.email, - style: TextStyle( - color: context.colorScheme.onSurfaceSecondary, - ), - ), + leading: UserCircleAvatar(user: user, radius: 22), + title: Text(user.name, style: const TextStyle(fontWeight: FontWeight.w500)), + subtitle: Text(user.email, style: TextStyle(color: context.colorScheme.onSurfaceSecondary)), trailing: userId == user.id || isOwner ? const Icon(Icons.more_horiz_rounded) : const SizedBox(), onTap: userId == user.id || isOwner ? () => handleUserClick(user) : null, ); @@ -206,9 +177,7 @@ class AlbumOptionsPage extends HookConsumerWidget { ).tr(), subtitle: Text( "let_others_respond", - style: context.textTheme.labelLarge?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.onSurfaceSecondary), ).tr(), ), buildSectionTitle("shared_album_section_people_title".tr()), diff --git a/mobile/lib/pages/album/album_shared_user_icons.dart b/mobile/lib/pages/album/album_shared_user_icons.dart index 723bb1e25..fe1823ec6 100644 --- a/mobile/lib/pages/album/album_shared_user_icons.dart +++ b/mobile/lib/pages/album/album_shared_user_icons.dart @@ -41,11 +41,7 @@ class AlbumSharedUserIcons extends HookConsumerWidget { itemBuilder: ((context, index) { return Padding( padding: const EdgeInsets.only(right: 8.0), - child: UserCircleAvatar( - user: sharedUsers.value[index], - radius: 18, - size: 36, - ), + child: UserCircleAvatar(user: sharedUsers.value[index], radius: 18, size: 36), ); }), itemCount: sharedUsers.value.length, diff --git a/mobile/lib/pages/album/album_shared_user_selection.page.dart b/mobile/lib/pages/album/album_shared_user_selection.page.dart index d5d963b20..562f02a2a 100644 --- a/mobile/lib/pages/album/album_shared_user_selection.page.dart +++ b/mobile/lib/pages/album/album_shared_user_selection.page.dart @@ -25,10 +25,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { final suggestedShareUsers = ref.watch(otherUsersProvider); createSharedAlbum() async { - var newAlbum = await ref.watch(albumProvider.notifier).createAlbum( - ref.watch(albumTitleProvider), - assets, - ); + var newAlbum = await ref.watch(albumProvider.notifier).createAlbum(ref.watch(albumTitleProvider), assets); if (newAlbum != null) { ref.watch(albumTitleProvider.notifier).clearAlbumTitle(); @@ -40,9 +37,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { child: SnackBar( content: Text( 'select_user_for_sharing_page_err_album', - style: context.textTheme.bodyLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ).tr(), ), ); @@ -50,17 +45,9 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { buildTileIcon(UserDto user) { if (sharedUsersList.value.contains(user)) { - return CircleAvatar( - backgroundColor: context.primaryColor, - child: const Icon( - Icons.check_rounded, - size: 25, - ), - ); + return CircleAvatar(backgroundColor: context.primaryColor, child: const Icon(Icons.check_rounded, size: 25)); } else { - return UserCircleAvatar( - user: user, - ); + return UserCircleAvatar(user: user); } } @@ -75,11 +62,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { backgroundColor: context.primaryColor.withValues(alpha: 0.15), label: Text( user.email, - style: const TextStyle( - fontSize: 12, - color: Colors.black87, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(fontSize: 12, color: Colors.black87, fontWeight: FontWeight.bold), ), ), ), @@ -87,18 +70,12 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { } return ListView( children: [ - Wrap( - children: [...usersChip], - ), + Wrap(children: [...usersChip]), Padding( padding: const EdgeInsets.all(16.0), child: const Text( 'suggestions', - style: TextStyle( - fontSize: 14, - color: Colors.grey, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), ).tr(), ), ListView.builder( @@ -107,25 +84,14 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { itemBuilder: ((context, index) { return ListTile( leading: buildTileIcon(users[index]), - title: Text( - users[index].email, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), + title: Text(users[index].email, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), onTap: () { if (sharedUsersList.value.contains(users[index])) { sharedUsersList.value = sharedUsersList.value - .where( - (selectedUser) => selectedUser.id != users[index].id, - ) + .where((selectedUser) => selectedUser.id != users[index].id) .toSet(); } else { - sharedUsersList.value = { - ...sharedUsersList.value, - users[index], - }; + sharedUsersList.value = {...sharedUsersList.value, users[index]}; } }, ); @@ -138,10 +104,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: Text( - 'invite_to_album', - style: TextStyle(color: context.primaryColor), - ).tr(), + title: Text('invite_to_album', style: TextStyle(color: context.primaryColor)).tr(), elevation: 0, centerTitle: false, leading: IconButton( @@ -152,9 +115,7 @@ class AlbumSharedUserSelectionPage extends HookConsumerWidget { ), actions: [ TextButton( - style: TextButton.styleFrom( - foregroundColor: context.primaryColor, - ), + style: TextButton.styleFrom(foregroundColor: context.primaryColor), onPressed: sharedUsersList.value.isEmpty ? null : createSharedAlbum, child: const Text( "create_album", diff --git a/mobile/lib/pages/album/album_title.dart b/mobile/lib/pages/album/album_title.dart index ccea200f3..6c7fc3faa 100644 --- a/mobile/lib/pages/album/album_title.dart +++ b/mobile/lib/pages/album/album_title.dart @@ -19,32 +19,20 @@ class AlbumTitle extends ConsumerWidget { return const (false, false, ''); } - return ( - album.ownerId == userId, - album.isRemote, - album.name, - ); + return (album.ownerId == userId, album.isRemote, album.name); }), ); if (isOwner && isRemote) { return Padding( padding: const EdgeInsets.only(left: 8, right: 8), - child: AlbumViewerEditableTitle( - albumName: albumName, - titleFocusNode: titleFocusNode, - ), + child: AlbumViewerEditableTitle(albumName: albumName, titleFocusNode: titleFocusNode), ); } return Padding( padding: const EdgeInsets.only(left: 16, right: 8), - child: Text( - albumName, - style: context.textTheme.headlineLarge?.copyWith( - fontWeight: FontWeight.w700, - ), - ), + child: Text(albumName, style: context.textTheme.headlineLarge?.copyWith(fontWeight: FontWeight.w700)), ); } } diff --git a/mobile/lib/pages/album/album_viewer.dart b/mobile/lib/pages/album/album_viewer.dart index 6d9519f4e..97853fb96 100644 --- a/mobile/lib/pages/album/album_viewer.dart +++ b/mobile/lib/pages/album/album_viewer.dart @@ -65,10 +65,7 @@ class AlbumViewer extends HookConsumerWidget { /// If they exist, add to selected asset state to show they are already selected. void onAddPhotosPressed() async { AssetSelectionPageResult? returnPayload = await context.pushRoute( - AlbumAssetSelectionRoute( - existingAssets: album.assets, - canDeselect: false, - ), + AlbumAssetSelectionRoute(existingAssets: album.assets, canDeselect: false), ); if (returnPayload != null && returnPayload.selectedAssets.isNotEmpty) { @@ -98,9 +95,7 @@ class AlbumViewer extends HookConsumerWidget { onActivitiesPressed() { if (album.remoteId != null) { ref.read(currentAssetProvider.notifier).set(null); - context.pushRoute( - const ActivitiesRoute(), - ); + context.pushRoute(const ActivitiesRoute()); } } @@ -129,14 +124,8 @@ class AlbumViewer extends HookConsumerWidget { children: [ const SizedBox(height: 32), const AlbumDateRange(), - AlbumTitle( - key: const ValueKey("albumTitle"), - titleFocusNode: titleFocusNode, - ), - AlbumDescription( - key: const ValueKey("albumDescription"), - descriptionFocusNode: descriptionFocusNode, - ), + AlbumTitle(key: const ValueKey("albumTitle"), titleFocusNode: titleFocusNode), + AlbumDescription(key: const ValueKey("albumDescription"), descriptionFocusNode: descriptionFocusNode), const AlbumSharedUserIcons(), if (album.isRemote) Padding( diff --git a/mobile/lib/pages/album/album_viewer.page.dart b/mobile/lib/pages/album/album_viewer.page.dart index 146a93a0a..c99dacd9b 100644 --- a/mobile/lib/pages/album/album_viewer.page.dart +++ b/mobile/lib/pages/album/album_viewer.page.dart @@ -21,9 +21,7 @@ class AlbumViewerPage extends HookConsumerWidget { ref.listen(assetSelectionTimelineProvider, (_, __) {}); ref.listen(albumWatcher(albumId), (_, albumFuture) { - albumFuture.whenData( - (value) => ref.read(currentAlbumProvider.notifier).set(value), - ); + albumFuture.whenData((value) => ref.read(currentAlbumProvider.notifier).set(value)); }); return const Scaffold(body: AlbumViewer()); diff --git a/mobile/lib/pages/albums/albums.page.dart b/mobile/lib/pages/albums/albums.page.dart index aea4cfa2b..5f155c2f0 100644 --- a/mobile/lib/pages/albums/albums.page.dart +++ b/mobile/lib/pages/albums/albums.page.dart @@ -52,21 +52,18 @@ class AlbumsPage extends HookConsumerWidget { filterMode.value = mode; } - useEffect( - () { - searchController.addListener(() { + useEffect(() { + searchController.addListener(() { + onSearch(searchController.text, filterMode.value); + }); + + return () { + searchController.removeListener(() { onSearch(searchController.text, filterMode.value); }); - - return () { - searchController.removeListener(() { - onSearch(searchController.text, filterMode.value); - }); - debounceTimer.value?.cancel(); - }; - }, - [], - ); + debounceTimer.value?.cancel(); + }; + }, []); clearSearch() { filterMode.value = QuickFilterMode.all; @@ -79,13 +76,8 @@ class AlbumsPage extends HookConsumerWidget { showUploadButton: false, actions: [ IconButton( - icon: const Icon( - Icons.add_rounded, - size: 28, - ), - onPressed: () => context.pushRoute( - CreateAlbumRoute(), - ), + icon: const Icon(Icons.add_rounded, size: 28), + onPressed: () => context.pushRoute(CreateAlbumRoute()), ), ], ), @@ -100,13 +92,8 @@ class AlbumsPage extends HookConsumerWidget { children: [ Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(0), - width: 0, - ), - borderRadius: const BorderRadius.all( - Radius.circular(24), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(0), width: 0), + borderRadius: const BorderRadius.all(Radius.circular(24)), gradient: LinearGradient( colors: [ context.colorScheme.primary.withValues(alpha: 0.075), @@ -124,10 +111,7 @@ class AlbumsPage extends HookConsumerWidget { hintText: 'search_albums'.tr(), prefixIcon: const Icon(Icons.search_rounded), suffixIcon: searchController.text.isNotEmpty - ? IconButton( - icon: const Icon(Icons.clear_rounded), - onPressed: clearSearch, - ) + ? IconButton(icon: const Icon(Icons.clear_rounded), onPressed: clearSearch) : null, controller: searchController, onChanged: (_) => onSearch(searchController.text, filterMode.value), @@ -153,10 +137,7 @@ class AlbumsPage extends HookConsumerWidget { isSelected: filterMode.value == QuickFilterMode.sharedWithMe, onTap: () { changeFilter(QuickFilterMode.sharedWithMe); - onSearch( - searchController.text, - QuickFilterMode.sharedWithMe, - ); + onSearch(searchController.text, QuickFilterMode.sharedWithMe); }, ), QuickFilterButton( @@ -164,10 +145,7 @@ class AlbumsPage extends HookConsumerWidget { isSelected: filterMode.value == QuickFilterMode.myAlbums, onTap: () { changeFilter(QuickFilterMode.myAlbums); - onSearch( - searchController.text, - QuickFilterMode.myAlbums, - ); + onSearch(searchController.text, QuickFilterMode.myAlbums); }, ), ], @@ -177,10 +155,7 @@ class AlbumsPage extends HookConsumerWidget { children: [ const SortButton(), IconButton( - icon: Icon( - isGrid.value ? Icons.view_list_outlined : Icons.grid_view_outlined, - size: 24, - ), + icon: Icon(isGrid.value ? Icons.view_list_outlined : Icons.grid_view_outlined, size: 24), onPressed: toggleViewMode, ), ], @@ -201,9 +176,7 @@ class AlbumsPage extends HookConsumerWidget { itemBuilder: (context, index) { return AlbumThumbnailCard( album: sorted[index], - onTap: () => context.pushRoute( - AlbumViewerRoute(albumId: sorted[index].id), - ), + onTap: () => context.pushRoute(AlbumViewerRoute(albumId: sorted[index].id)), showOwner: true, ); }, @@ -221,44 +194,22 @@ class AlbumsPage extends HookConsumerWidget { sorted[index].name, maxLines: 2, overflow: TextOverflow.ellipsis, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), ), subtitle: sorted[index].ownerId != null ? Text( - '${'items_count'.t( - context: context, - args: { - 'count': sorted[index].assetCount, - }, - )} • ${sorted[index].ownerId != userId ? 'shared_by_user'.t( - context: context, - args: { - 'user': sorted[index].ownerName!, - }, - ) : 'owned'.t(context: context)}', + '${'items_count'.t(context: context, args: {'count': sorted[index].assetCount})} • ${sorted[index].ownerId != userId ? 'shared_by_user'.t(context: context, args: {'user': sorted[index].ownerName!}) : 'owned'.t(context: context)}', overflow: TextOverflow.ellipsis, style: context.textTheme.bodyMedium?.copyWith( color: context.colorScheme.onSurfaceSecondary, ), ) : null, - onTap: () => context.pushRoute( - AlbumViewerRoute(albumId: sorted[index].id), - ), - leadingPadding: const EdgeInsets.only( - right: 16, - ), + onTap: () => context.pushRoute(AlbumViewerRoute(albumId: sorted[index].id)), + leadingPadding: const EdgeInsets.only(right: 16), leading: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(15), - ), - child: ImmichThumbnail( - asset: sorted[index].thumbnail.value, - width: 80, - height: 80, - ), + borderRadius: const BorderRadius.all(Radius.circular(15)), + child: ImmichThumbnail(asset: sorted[index].thumbnail.value, width: 80, height: 80), ), // minVerticalPadding: 1, ), @@ -275,12 +226,7 @@ class AlbumsPage extends HookConsumerWidget { } class QuickFilterButton extends StatelessWidget { - const QuickFilterButton({ - super.key, - required this.isSelected, - required this.onTap, - required this.label, - }); + const QuickFilterButton({super.key, required this.isSelected, required this.onTap, required this.label}); final bool isSelected; final VoidCallback onTap; @@ -291,18 +237,11 @@ class QuickFilterButton extends StatelessWidget { return TextButton( onPressed: onTap, style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - isSelected ? context.colorScheme.primary : Colors.transparent, - ), + backgroundColor: WidgetStateProperty.all(isSelected ? context.colorScheme.primary : Colors.transparent), shape: WidgetStateProperty.all( RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - side: BorderSide( - color: context.colorScheme.onSurface.withAlpha(25), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), + side: BorderSide(color: context.colorScheme.onSurface.withAlpha(25), width: 1), ), ), ), @@ -329,15 +268,9 @@ class SortButton extends ConsumerWidget { style: MenuStyle( elevation: const WidgetStatePropertyAll(1), shape: WidgetStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ), - ), - padding: const WidgetStatePropertyAll( - EdgeInsets.all(4), + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), ), + padding: const WidgetStatePropertyAll(EdgeInsets.all(4)), ), consumeOutsideTap: true, menuChildren: AlbumSortMode.values @@ -345,16 +278,18 @@ class SortButton extends ConsumerWidget { (mode) => MenuItemButton( leadingIcon: albumSortOption == mode ? albumSortIsReverse - ? Icon( - Icons.keyboard_arrow_down, - color: - albumSortOption == mode ? context.colorScheme.onPrimary : context.colorScheme.onSurface, - ) - : Icon( - Icons.keyboard_arrow_up_rounded, - color: - albumSortOption == mode ? context.colorScheme.onPrimary : context.colorScheme.onSurface, - ) + ? Icon( + Icons.keyboard_arrow_down, + color: albumSortOption == mode + ? context.colorScheme.onPrimary + : context.colorScheme.onSurface, + ) + : Icon( + Icons.keyboard_arrow_up_rounded, + color: albumSortOption == mode + ? context.colorScheme.onPrimary + : context.colorScheme.onSurface, + ) : const Icon(Icons.abc, color: Colors.transparent), onPressed: () { final selected = albumSortOption == mode; @@ -366,18 +301,12 @@ class SortButton extends ConsumerWidget { } }, style: ButtonStyle( - padding: WidgetStateProperty.all( - const EdgeInsets.fromLTRB(16, 16, 32, 16), - ), + padding: WidgetStateProperty.all(const EdgeInsets.fromLTRB(16, 16, 32, 16)), backgroundColor: WidgetStateProperty.all( albumSortOption == mode ? context.colorScheme.primary : Colors.transparent, ), shape: WidgetStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ), + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), ), ), child: Text( diff --git a/mobile/lib/pages/backup/album_preview.page.dart b/mobile/lib/pages/backup/album_preview.page.dart index 4cdc18097..def31afcd 100644 --- a/mobile/lib/pages/backup/album_preview.page.dart +++ b/mobile/lib/pages/backup/album_preview.page.dart @@ -22,23 +22,17 @@ class AlbumPreviewPage extends HookConsumerWidget { assets.value = await ref.read(albumMediaRepositoryProvider).getAssets(album.localId!); } - useEffect( - () { - getAssetsInAlbum(); - return null; - }, - [], - ); + useEffect(() { + getAssetsInAlbum(); + return null; + }, []); return Scaffold( appBar: AppBar( elevation: 0, title: Column( children: [ - Text( - album.name, - style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ), + Text(album.name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), Padding( padding: const EdgeInsets.only(top: 4.0), child: Text( @@ -52,10 +46,7 @@ class AlbumPreviewPage extends HookConsumerWidget { ), ], ), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_new_rounded), - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_new_rounded)), ), body: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( @@ -65,11 +56,7 @@ class AlbumPreviewPage extends HookConsumerWidget { ), itemCount: assets.value.length, itemBuilder: (context, index) { - return ImmichThumbnail( - asset: assets.value[index], - width: 100, - height: 100, - ); + return ImmichThumbnail(asset: assets.value[index], width: 100, height: 100); }, ), ); diff --git a/mobile/lib/pages/backup/backup_album_selection.page.dart b/mobile/lib/pages/backup/backup_album_selection.page.dart index 69e118cb7..d22221157 100644 --- a/mobile/lib/pages/backup/backup_album_selection.page.dart +++ b/mobile/lib/pages/backup/backup_album_selection.page.dart @@ -23,45 +23,29 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { final isDarkTheme = context.isDarkTheme; final albums = ref.watch(backupProvider).availableAlbums; - useEffect( - () { - ref.watch(backupProvider.notifier).getBackupInfo(); - return null; - }, - [], - ); + useEffect(() { + ref.watch(backupProvider.notifier).getBackupInfo(); + return null; + }, []); buildAlbumSelectionList() { if (albums.isEmpty) { - return const SliverToBoxAdapter( - child: Center( - child: CircularProgressIndicator(), - ), - ); + return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator())); } return SliverPadding( padding: const EdgeInsets.symmetric(vertical: 12.0), sliver: SliverList( - delegate: SliverChildBuilderDelegate( - ((context, index) { - return AlbumInfoListTile( - album: albums[index], - ); - }), - childCount: albums.length, - ), + delegate: SliverChildBuilderDelegate(((context, index) { + return AlbumInfoListTile(album: albums[index]); + }), childCount: albums.length), ), ); } buildAlbumSelectionGrid() { if (albums.isEmpty) { - return const SliverToBoxAdapter( - child: Center( - child: CircularProgressIndicator(), - ), - ); + return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator())); } return SliverPadding( @@ -74,9 +58,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ), itemCount: albums.length, itemBuilder: ((context, index) { - return AlbumInfoCard( - album: albums[index], - ); + return AlbumInfoCard(album: albums[index]); }), ), ); @@ -101,10 +83,7 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { ), backgroundColor: context.primaryColor, deleteIconColor: isDarkTheme ? Colors.black : Colors.white, - deleteIcon: const Icon( - Icons.cancel_rounded, - size: 15, - ), + deleteIcon: const Icon(Icons.cancel_rounded, size: 15), onDeleted: removeSelection, ), ), @@ -125,18 +104,11 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { child: Chip( label: Text( album.name, - style: TextStyle( - fontSize: 12, - color: context.scaffoldBackgroundColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 12, color: context.scaffoldBackgroundColor, fontWeight: FontWeight.bold), ), backgroundColor: Colors.red[300], deleteIconColor: context.scaffoldBackgroundColor, - deleteIcon: const Icon( - Icons.cancel_rounded, - size: 15, - ), + deleteIcon: const Icon(Icons.cancel_rounded, size: 15), onDeleted: removeSelection, ), ), @@ -155,13 +127,8 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), - title: const Text( - "backup_album_selection_page_select_albums", - ).tr(), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), + title: const Text("backup_album_selection_page_select_albums").tr(), elevation: 0, ), body: CustomScrollView( @@ -172,25 +139,14 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.symmetric( - vertical: 8.0, - horizontal: 16.0, - ), - child: Text( - "backup_album_selection_page_selection_info", - style: context.textTheme.titleSmall, - ).tr(), + padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), + child: Text("backup_album_selection_page_selection_info", style: context.textTheme.titleSmall).tr(), ), - // Selected Album Chips + // Selected Album Chips Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Wrap( - children: [ - ...buildSelectedAlbumNameChip(), - ...buildExcludedAlbumNameChip(), - ], - ), + child: Wrap(children: [...buildSelectedAlbumNameChip(), ...buildExcludedAlbumNameChip()]), ), SettingsSwitchListTile( @@ -198,21 +154,15 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { title: "sync_albums".tr(), subtitle: "sync_upload_album_setting_subtitle".tr(), contentPadding: const EdgeInsets.symmetric(horizontal: 16), - titleStyle: context.textTheme.bodyLarge?.copyWith( - fontWeight: FontWeight.bold, - ), - subtitleStyle: context.textTheme.labelLarge?.copyWith( - color: context.colorScheme.primary, - ), + titleStyle: context.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold), + subtitleStyle: context.textTheme.labelLarge?.copyWith(color: context.colorScheme.primary), onChanged: handleSyncAlbumToggle, ), ListTile( title: Text( "backup_album_selection_page_albums_device".tr( - namedArgs: { - 'count': ref.watch(backupProvider).availableAlbums.length.toString(), - }, + namedArgs: {'count': ref.watch(backupProvider).availableAlbums.length.toString()}, ), style: context.textTheme.titleSmall, ), @@ -220,46 +170,30 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(vertical: 8.0), child: Text( "backup_album_selection_page_albums_tap", - style: context.textTheme.labelLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), ).tr(), ), trailing: IconButton( splashRadius: 16, - icon: Icon( - Icons.info, - size: 20, - color: context.primaryColor, - ), + icon: Icon(Icons.info, size: 20, color: context.primaryColor), onPressed: () { // show the dialog showDialog( context: context, builder: (BuildContext context) { return AlertDialog( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), elevation: 5, title: Text( 'backup_album_selection_page_selection_info', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: context.primaryColor, - ), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: context.primaryColor), ).tr(), content: SingleChildScrollView( child: ListBody( children: [ const Text( 'backup_album_selection_page_assets_scatter', - style: TextStyle( - fontSize: 14, - ), + style: TextStyle(fontSize: 14), ).tr(), ], ), diff --git a/mobile/lib/pages/backup/backup_controller.page.dart b/mobile/lib/pages/backup/backup_controller.page.dart index 76a772884..093ff952a 100644 --- a/mobile/lib/pages/backup/backup_controller.page.dart +++ b/mobile/lib/pages/backup/backup_controller.page.dart @@ -31,52 +31,44 @@ class BackupControllerPage extends HookConsumerWidget { final didGetBackupInfo = useState(false); bool hasExclusiveAccess = backupState.backupProgress != BackUpProgressEnum.inBackground; - bool shouldBackup = backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length == 0 || + bool shouldBackup = + backupState.allUniqueAssets.length - backupState.selectedAlbumsBackupAssetsIds.length == 0 || !hasExclusiveAccess ? false : true; - useEffect( - () { - // Update the background settings information just to make sure we - // have the latest, since the platform channel will not update - // automatically - if (Platform.isIOS) { - ref.watch(iOSBackgroundSettingsProvider.notifier).refresh(); - } + useEffect(() { + // Update the background settings information just to make sure we + // have the latest, since the platform channel will not update + // automatically + if (Platform.isIOS) { + ref.watch(iOSBackgroundSettingsProvider.notifier).refresh(); + } - ref.watch(websocketProvider.notifier).stopListenToEvent('on_upload_success'); + ref.watch(websocketProvider.notifier).stopListenToEvent('on_upload_success'); - return () { - WakelockPlus.disable(); - }; - }, - [], - ); + return () { + WakelockPlus.disable(); + }; + }, []); - useEffect( - () { - if (backupState.backupProgress == BackUpProgressEnum.idle && !didGetBackupInfo.value) { - ref.watch(backupProvider.notifier).getBackupInfo(); - didGetBackupInfo.value = true; - } - return null; - }, - [backupState.backupProgress], - ); + useEffect(() { + if (backupState.backupProgress == BackUpProgressEnum.idle && !didGetBackupInfo.value) { + ref.watch(backupProvider.notifier).getBackupInfo(); + didGetBackupInfo.value = true; + } + return null; + }, [backupState.backupProgress]); - useEffect( - () { - if (backupState.backupProgress == BackUpProgressEnum.inProgress) { - WakelockPlus.enable(); - } else { - WakelockPlus.disable(); - } + useEffect(() { + if (backupState.backupProgress == BackUpProgressEnum.inProgress) { + WakelockPlus.enable(); + } else { + WakelockPlus.disable(); + } - return null; - }, - [backupState.backupProgress], - ); + return null; + }, [backupState.backupProgress]); Widget buildSelectedAlbumName() { var text = "backup_controller_page_backup_selected".tr(); @@ -95,9 +87,7 @@ class BackupControllerPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( text.trim().substring(0, text.length - 2), - style: context.textTheme.labelLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), ), ); } else { @@ -105,9 +95,7 @@ class BackupControllerPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( "backup_controller_page_none_selected".tr(), - style: context.textTheme.labelLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), ), ); } @@ -126,9 +114,7 @@ class BackupControllerPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( text.trim().substring(0, text.length - 2), - style: context.textTheme.labelLarge?.copyWith( - color: Colors.red[300], - ), + style: context.textTheme.labelLarge?.copyWith(color: Colors.red[300]), ), ); } else { @@ -141,22 +127,14 @@ class BackupControllerPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Card( shape: RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - side: BorderSide( - color: context.colorScheme.outlineVariant, - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), + side: BorderSide(color: context.colorScheme.outlineVariant, width: 1), ), elevation: 0, borderOnForeground: false, child: ListTile( minVerticalPadding: 18, - title: Text( - "backup_controller_page_albums", - style: context.textTheme.titleMedium, - ).tr(), + title: Text("backup_controller_page_albums", style: context.textTheme.titleMedium).tr(), subtitle: Padding( padding: const EdgeInsets.only(top: 8.0), child: Column( @@ -164,9 +142,7 @@ class BackupControllerPage extends HookConsumerWidget { children: [ Text( "backup_controller_page_to_backup", - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ).tr(), buildSelectedAlbumName(), buildExcludedAlbumName(), @@ -181,12 +157,7 @@ class BackupControllerPage extends HookConsumerWidget { // waited until backup albums are stored in DB ref.read(albumProvider.notifier).refreshDeviceAlbums(); }, - child: const Text( - "select", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ).tr(), + child: const Text("select", style: TextStyle(fontWeight: FontWeight.bold)).tr(), ), ), ), @@ -202,11 +173,10 @@ class BackupControllerPage extends HookConsumerWidget { Widget buildBackupButton() { return Padding( - padding: const EdgeInsets.only( - top: 24, - ), + padding: const EdgeInsets.only(top: 24), child: Container( - child: backupState.backupProgress == BackUpProgressEnum.inProgress || + child: + backupState.backupProgress == BackUpProgressEnum.inProgress || backupState.backupProgress == BackUpProgressEnum.manualInProgress ? ElevatedButton( style: ElevatedButton.styleFrom( @@ -221,22 +191,13 @@ class BackupControllerPage extends HookConsumerWidget { ref.read(backupProvider.notifier).cancelBackup(); } }, - child: const Text( - "cancel", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ).tr(), + child: const Text("cancel", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(), ) : ElevatedButton( onPressed: shouldBackup ? startBackup : null, child: const Text( "backup_controller_page_start_backup", - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold), ).tr(), ), ), @@ -246,36 +207,28 @@ class BackupControllerPage extends HookConsumerWidget { buildBackgroundBackupInfo() { return const ListTile( leading: Icon(Icons.info_outline_rounded), - title: Text( - "Background backup is currently running, cannot start manual backup", - ), + title: Text("Background backup is currently running, cannot start manual backup"), ); } buildLoadingIndicator() { return const Padding( padding: EdgeInsets.only(top: 42.0), - child: Center( - child: CircularProgressIndicator(), - ), + child: Center(child: CircularProgressIndicator()), ); } return Scaffold( appBar: AppBar( elevation: 0, - title: const Text( - "backup_controller_page_backup", - ).tr(), + title: const Text("backup_controller_page_backup").tr(), leading: IconButton( onPressed: () { ref.watch(websocketProvider.notifier).listenUploadEvent(); context.maybePop(true); }, splashRadius: 24, - icon: const Icon( - Icons.arrow_back_ios_rounded, - ), + icon: const Icon(Icons.arrow_back_ios_rounded), ), actions: [ Padding( @@ -283,9 +236,7 @@ class BackupControllerPage extends HookConsumerWidget { child: IconButton( onPressed: () => context.pushRoute(const BackupOptionsRoute()), splashRadius: 24, - icon: const Icon( - Icons.settings_outlined, - ), + icon: const Icon(Icons.settings_outlined), ), ), ], @@ -325,10 +276,7 @@ class BackupControllerPage extends HookConsumerWidget { if (!hasExclusiveAccess) buildBackgroundBackupInfo(), buildBackupButton(), ] - : [ - buildFolderSelectionTile(), - if (!didGetBackupInfo.value) buildLoadingIndicator(), - ], + : [buildFolderSelectionTile(), if (!didGetBackupInfo.value) buildLoadingIndicator()], ), ), ], diff --git a/mobile/lib/pages/backup/backup_options.page.dart b/mobile/lib/pages/backup/backup_options.page.dart index 29822cab1..846a32a74 100644 --- a/mobile/lib/pages/backup/backup_options.page.dart +++ b/mobile/lib/pages/backup/backup_options.page.dart @@ -15,9 +15,7 @@ class BackupOptionsPage extends StatelessWidget { leading: IconButton( onPressed: () => context.maybePop(true), splashRadius: 24, - icon: const Icon( - Icons.arrow_back_ios_rounded, - ), + icon: const Icon(Icons.arrow_back_ios_rounded), ), ), body: const BackupSettings(), diff --git a/mobile/lib/pages/backup/drift_backup.page.dart b/mobile/lib/pages/backup/drift_backup.page.dart index f691eb576..6d31c7594 100644 --- a/mobile/lib/pages/backup/drift_backup.page.dart +++ b/mobile/lib/pages/backup/drift_backup.page.dart @@ -51,35 +51,25 @@ class _DriftBackupPageState extends ConsumerState { Widget build(BuildContext context) { final selectedAlbum = ref .watch(backupAlbumProvider) - .where( - (album) => album.backupSelection == BackupSelection.selected, - ) + .where((album) => album.backupSelection == BackupSelection.selected) .toList(); return Scaffold( appBar: AppBar( elevation: 0, - title: Text( - "backup_controller_page_backup".t(), - ), + title: Text("backup_controller_page_backup".t()), leading: IconButton( onPressed: () { context.maybePop(true); }, splashRadius: 24, - icon: const Icon( - Icons.arrow_back_ios_rounded, - ), + icon: const Icon(Icons.arrow_back_ios_rounded), ), ), body: Stack( children: [ Padding( - padding: const EdgeInsets.only( - left: 16.0, - right: 16, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 16.0, right: 16, bottom: 32), child: ListView( children: [ const SizedBox(height: 8), @@ -89,15 +79,10 @@ class _DriftBackupPageState extends ConsumerState { const _BackupCard(), const _RemainderCard(), const Divider(), - BackupToggleButton( - onStart: () async => await startBackup(), - onStop: () async => await stopBackup(), - ), + BackupToggleButton(onStart: () async => await startBackup(), onStop: () async => await stopBackup()), TextButton.icon( icon: const Icon(Icons.info_outline_rounded), - onPressed: () => context.pushRoute( - const DriftUploadDetailRoute(), - ), + onPressed: () => context.pushRoute(const DriftUploadDetailRoute()), label: Text("view_details".t(context: context)), ), ], @@ -119,9 +104,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { String text = "backup_controller_page_backup_selected".tr(); final albums = ref .watch(backupAlbumProvider) - .where( - (album) => album.backupSelection == BackupSelection.selected, - ) + .where((album) => album.backupSelection == BackupSelection.selected) .toList(); if (albums.isNotEmpty) { @@ -137,9 +120,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( text.trim().substring(0, text.length - 2), - style: context.textTheme.labelLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), ), ); } else { @@ -147,9 +128,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( "backup_controller_page_none_selected".tr(), - style: context.textTheme.labelLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor), ), ); } @@ -159,9 +138,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { String text = "backup_controller_page_excluded".tr(); final albums = ref .watch(backupAlbumProvider) - .where( - (album) => album.backupSelection == BackupSelection.excluded, - ) + .where((album) => album.backupSelection == BackupSelection.excluded) .toList(); if (albums.isNotEmpty) { @@ -173,9 +150,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { padding: const EdgeInsets.only(top: 8.0), child: Text( text.trim().substring(0, text.length - 2), - style: context.textTheme.labelLarge?.copyWith( - color: Colors.red[300], - ), + style: context.textTheme.labelLarge?.copyWith(color: Colors.red[300]), ), ); } else { @@ -186,19 +161,13 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { return Card( shape: RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(20)), - side: BorderSide( - color: context.colorScheme.outlineVariant, - width: 1, - ), + side: BorderSide(color: context.colorScheme.outlineVariant, width: 1), ), elevation: 0, borderOnForeground: false, child: ListTile( minVerticalPadding: 18, - title: Text( - "backup_controller_page_albums", - style: context.textTheme.titleMedium, - ).tr(), + title: Text("backup_controller_page_albums", style: context.textTheme.titleMedium).tr(), subtitle: Padding( padding: const EdgeInsets.only(top: 8.0), child: Column( @@ -206,9 +175,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { children: [ Text( "backup_controller_page_to_backup", - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ).tr(), buildSelectedAlbumName(), buildExcludedAlbumName(), @@ -224,12 +191,7 @@ class _BackupAlbumSelectionCard extends ConsumerWidget { } ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id); }, - child: const Text( - "select", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ).tr(), + child: const Text("select", style: TextStyle(fontWeight: FontWeight.bold)).tr(), ), ), ); diff --git a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart index 3f12328a0..396b711d0 100644 --- a/mobile/lib/pages/backup/drift_backup_album_selection.page.dart +++ b/mobile/lib/pages/backup/drift_backup_album_selection.page.dart @@ -119,9 +119,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState setState(() => _searchQuery = value.trim()), ) - : const Text( - "backup_album_selection_page_select_albums", - ).t(context: context), + : const Text("backup_album_selection_page_select_albums").t(context: context), actions: [ if (!_isSearchMode) IconButton( @@ -151,27 +149,20 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState 600) { - return _AlbumSelectionGrid( - filteredAlbums: filteredAlbums, - searchQuery: _searchQuery, - ); + return _AlbumSelectionGrid(filteredAlbums: filteredAlbums, searchQuery: _searchQuery); } else { - return _AlbumSelectionList( - filteredAlbums: filteredAlbums, - searchQuery: _searchQuery, - ); + return _AlbumSelectionList(filteredAlbums: filteredAlbums, searchQuery: _searchQuery); } }, ), @@ -285,10 +250,7 @@ class _AlbumSelectionList extends StatelessWidget { final List filteredAlbums; final String searchQuery; - const _AlbumSelectionList({ - required this.filteredAlbums, - required this.searchQuery, - }); + const _AlbumSelectionList({required this.filteredAlbums, required this.searchQuery}); @override Widget build(BuildContext context) { @@ -304,24 +266,15 @@ class _AlbumSelectionList extends StatelessWidget { } if (filteredAlbums.isEmpty) { - return const SliverToBoxAdapter( - child: Center( - child: CircularProgressIndicator(), - ), - ); + return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator())); } return SliverPadding( padding: const EdgeInsets.symmetric(vertical: 12.0), sliver: SliverList( - delegate: SliverChildBuilderDelegate( - ((context, index) { - return DriftAlbumInfoListTile( - album: filteredAlbums[index], - ); - }), - childCount: filteredAlbums.length, - ), + delegate: SliverChildBuilderDelegate(((context, index) { + return DriftAlbumInfoListTile(album: filteredAlbums[index]); + }), childCount: filteredAlbums.length), ), ); } @@ -331,10 +284,7 @@ class _AlbumSelectionGrid extends StatelessWidget { final List filteredAlbums; final String searchQuery; - const _AlbumSelectionGrid({ - required this.filteredAlbums, - required this.searchQuery, - }); + const _AlbumSelectionGrid({required this.filteredAlbums, required this.searchQuery}); @override Widget build(BuildContext context) { @@ -350,11 +300,7 @@ class _AlbumSelectionGrid extends StatelessWidget { } if (filteredAlbums.isEmpty) { - return const SliverToBoxAdapter( - child: Center( - child: CircularProgressIndicator(), - ), - ); + return const SliverToBoxAdapter(child: Center(child: CircularProgressIndicator())); } return SliverPadding( @@ -367,9 +313,7 @@ class _AlbumSelectionGrid extends StatelessWidget { ), itemCount: filteredAlbums.length, itemBuilder: ((context, index) { - return DriftAlbumInfoListTile( - album: filteredAlbums[index], - ); + return DriftAlbumInfoListTile(album: filteredAlbums[index]); }), ), ); @@ -379,9 +323,7 @@ class _AlbumSelectionGrid extends StatelessWidget { class _SelectedAlbumNameChips extends ConsumerWidget { final List selectedBackupAlbums; - const _SelectedAlbumNameChips({ - required this.selectedBackupAlbums, - }); + const _SelectedAlbumNameChips({required this.selectedBackupAlbums}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -411,10 +353,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget { ), backgroundColor: context.primaryColor, deleteIconColor: context.isDarkTheme ? Colors.black : Colors.white, - deleteIcon: const Icon( - Icons.cancel_rounded, - size: 15, - ), + deleteIcon: const Icon(Icons.cancel_rounded, size: 15), onDeleted: removeSelection, ), ), @@ -428,9 +367,7 @@ class _SelectedAlbumNameChips extends ConsumerWidget { class _ExcludedAlbumNameChips extends ConsumerWidget { final List excludedBackupAlbums; - const _ExcludedAlbumNameChips({ - required this.excludedBackupAlbums, - }); + const _ExcludedAlbumNameChips({required this.excludedBackupAlbums}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -452,18 +389,11 @@ class _ExcludedAlbumNameChips extends ConsumerWidget { child: Chip( label: Text( album.name, - style: TextStyle( - fontSize: 12, - color: context.scaffoldBackgroundColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 12, color: context.scaffoldBackgroundColor, fontWeight: FontWeight.bold), ), backgroundColor: Colors.red[300], deleteIconColor: context.scaffoldBackgroundColor, - deleteIcon: const Icon( - Icons.cancel_rounded, - size: 15, - ), + deleteIcon: const Icon(Icons.cancel_rounded, size: 15), onDeleted: removeSelection, ), ), @@ -478,10 +408,7 @@ class _SelectAllButton extends ConsumerWidget { final List filteredAlbums; final List selectedBackupAlbums; - const _SelectAllButton({ - required this.filteredAlbums, - required this.selectedBackupAlbums, - }); + const _SelectAllButton({required this.filteredAlbums, required this.selectedBackupAlbums}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -505,13 +432,9 @@ class _SelectAllButton extends ConsumerWidget { icon: const Icon(Icons.select_all), label: AnimatedSwitcher( duration: const Duration(milliseconds: 200), - child: Text( - "select_all".t(context: context), - ), - ), - style: ElevatedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 12.0), + child: Text("select_all".t(context: context)), ), + style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)), ), ), const SizedBox(width: 8.0), @@ -528,9 +451,7 @@ class _SelectAllButton extends ConsumerWidget { : null, icon: const Icon(Icons.deselect), label: Text('deselect_all'.t(context: context)), - style: OutlinedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 12.0), - ), + style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12.0)), ), ), ], diff --git a/mobile/lib/pages/backup/drift_upload_detail.page.dart b/mobile/lib/pages/backup/drift_upload_detail.page.dart index 62d6341fd..36dbe4e12 100644 --- a/mobile/lib/pages/backup/drift_upload_detail.page.dart +++ b/mobile/lib/pages/backup/drift_upload_detail.page.dart @@ -16,9 +16,7 @@ class DriftUploadDetailPage extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final uploadItems = ref.watch( - driftBackupProvider.select((state) => state.uploadItems), - ); + final uploadItems = ref.watch(driftBackupProvider.select((state) => state.uploadItems)); return Scaffold( appBar: AppBar( @@ -36,26 +34,18 @@ class DriftUploadDetailPage extends ConsumerWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.cloud_off_rounded, - size: 80, - color: context.colorScheme.onSurface.withValues(alpha: 0.3), - ), + Icon(Icons.cloud_off_rounded, size: 80, color: context.colorScheme.onSurface.withValues(alpha: 0.3)), const SizedBox(height: 16), Text( "no_uploads_in_progress".t(context: context), - style: context.textTheme.titleMedium?.copyWith( - color: context.colorScheme.onSurface.withValues(alpha: 0.6), - ), + style: context.textTheme.titleMedium?.copyWith(color: context.colorScheme.onSurface.withValues(alpha: 0.6)), ), ], ), ); } - Widget _buildUploadList( - Map uploadItems, - ) { + Widget _buildUploadList(Map uploadItems) { return ListView.separated( addAutomaticKeepAlives: true, padding: const EdgeInsets.all(16), @@ -68,10 +58,7 @@ class DriftUploadDetailPage extends ConsumerWidget { ); } - Widget _buildUploadCard( - BuildContext context, - DriftUploadStatus item, - ) { + Widget _buildUploadCard(BuildContext context, DriftUploadStatus item) { final isCompleted = item.progress >= 1.0; final double progressPercentage = (item.progress * 100).clamp(0, 100); @@ -79,19 +66,12 @@ class DriftUploadDetailPage extends ConsumerWidget { elevation: 0, color: item.isFailed != null ? context.colorScheme.errorContainer : context.colorScheme.surfaceContainer, shape: RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.circular(16), - ), - side: BorderSide( - color: context.colorScheme.outline.withValues(alpha: 0.1), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(16)), + side: BorderSide(color: context.colorScheme.outline.withValues(alpha: 0.1), width: 1), ), child: InkWell( onTap: () => _showFileDetailDialog(context, item), - borderRadius: const BorderRadius.all( - Radius.circular(16), - ), + borderRadius: const BorderRadius.all(Radius.circular(16)), child: Padding( padding: const EdgeInsets.all(16), child: Column( @@ -105,9 +85,7 @@ class DriftUploadDetailPage extends ConsumerWidget { children: [ Text( path.basename(item.filename), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -166,18 +144,11 @@ class DriftUploadDetailPage extends ConsumerWidget { ), ), if (isCompleted) - Icon( - Icons.check_circle_rounded, - size: 28, - color: context.colorScheme.primary, - ) + Icon(Icons.check_circle_rounded, size: 28, color: context.colorScheme.primary) else Text( percentage.toStringAsFixed(0), - style: context.textTheme.labelSmall?.copyWith( - fontWeight: FontWeight.bold, - fontSize: 10, - ), + style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.bold, fontSize: 10), ), ], ), @@ -192,10 +163,7 @@ class DriftUploadDetailPage extends ConsumerWidget { ); } - Future _showFileDetailDialog( - BuildContext context, - DriftUploadStatus item, - ) async { + Future _showFileDetailDialog(BuildContext context, DriftUploadStatus item) async { showDialog( context: context, builder: (context) => FileDetailDialog(uploadStatus: item), @@ -206,10 +174,7 @@ class DriftUploadDetailPage extends ConsumerWidget { class FileDetailDialog extends ConsumerWidget { final DriftUploadStatus uploadStatus; - const FileDetailDialog({ - super.key, - required this.uploadStatus, - }); + const FileDetailDialog({super.key, required this.uploadStatus}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -217,29 +182,17 @@ class FileDetailDialog extends ConsumerWidget { insetPadding: const EdgeInsets.all(20), backgroundColor: context.colorScheme.surfaceContainerLow, shape: RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.circular(16), - ), - side: BorderSide( - color: context.colorScheme.outline.withValues(alpha: 0.2), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(16)), + side: BorderSide(color: context.colorScheme.outline.withValues(alpha: 0.2), width: 1), ), title: Row( children: [ - Icon( - Icons.info_outline, - color: context.primaryColor, - size: 24, - ), + Icon(Icons.info_outline, color: context.primaryColor, size: 24), const SizedBox(width: 8), Expanded( child: Text( "details".t(context: context), - style: context.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w600, - color: context.primaryColor, - ), + style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor), ), ), ], @@ -250,10 +203,7 @@ class FileDetailDialog extends ConsumerWidget { future: _getAssetDetails(ref, uploadStatus.taskId), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { - return const SizedBox( - height: 200, - child: Center(child: CircularProgressIndicator()), - ); + return const SizedBox(height: 200, child: Center(child: CircularProgressIndicator())); } final asset = snapshot.data; @@ -270,18 +220,11 @@ class FileDetailDialog extends ConsumerWidget { width: 128, height: 128, decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.outline.withValues(alpha: 0.2), - width: 1, - ), + border: Border.all(color: context.colorScheme.outline.withValues(alpha: 0.2), width: 1), borderRadius: const BorderRadius.all(Radius.circular(12)), ), child: asset != null - ? Thumbnail( - asset: asset, - size: const Size(512, 512), - fit: BoxFit.cover, - ) + ? Thumbnail(asset: asset, size: const Size(512, 512), fit: BoxFit.cover) : null, ), ), @@ -289,44 +232,14 @@ class FileDetailDialog extends ConsumerWidget { const SizedBox(height: 24), if (asset != null) ...[ _buildInfoSection(context, [ - _buildInfoRow( - context, - "Filename", - path.basename(uploadStatus.filename), - ), - _buildInfoRow( - context, - "Local ID", - asset.id, - ), - _buildInfoRow( - context, - "File Size", - formatHumanReadableBytes(uploadStatus.fileSize, 2), - ), + _buildInfoRow(context, "Filename", path.basename(uploadStatus.filename)), + _buildInfoRow(context, "Local ID", asset.id), + _buildInfoRow(context, "File Size", formatHumanReadableBytes(uploadStatus.fileSize, 2)), if (asset.width != null) _buildInfoRow(context, "Width", "${asset.width}px"), - if (asset.height != null) - _buildInfoRow( - context, - "Height", - "${asset.height}px", - ), - _buildInfoRow( - context, - "Created At", - asset.createdAt.toString(), - ), - _buildInfoRow( - context, - "Updated At", - asset.updatedAt.toString(), - ), - if (asset.checksum != null) - _buildInfoRow( - context, - "Checksum", - asset.checksum!, - ), + if (asset.height != null) _buildInfoRow(context, "Height", "${asset.height}px"), + _buildInfoRow(context, "Created At", asset.createdAt.toString()), + _buildInfoRow(context, "Updated At", asset.updatedAt.toString()), + if (asset.checksum != null) _buildInfoRow(context, "Checksum", asset.checksum!), ]), ], ], @@ -340,39 +253,23 @@ class FileDetailDialog extends ConsumerWidget { onPressed: () => Navigator.of(context).pop(), child: Text( "close".t(), - style: TextStyle( - fontWeight: FontWeight.w600, - color: context.primaryColor, - ), + style: TextStyle(fontWeight: FontWeight.w600, color: context.primaryColor), ), ), ], ); } - Widget _buildInfoSection( - BuildContext context, - List children, - ) { + Widget _buildInfoSection(BuildContext context, List children) { return Container( width: double.infinity, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: context.colorScheme.surfaceContainer, - borderRadius: const BorderRadius.all( - Radius.circular(12), - ), - border: Border.all( - color: context.colorScheme.outline.withValues(alpha: 0.1), - width: 1, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ...children, - ], + borderRadius: const BorderRadius.all(Radius.circular(12)), + border: Border.all(color: context.colorScheme.outline.withValues(alpha: 0.1), width: 1), ), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [...children]), ); } @@ -405,10 +302,7 @@ class FileDetailDialog extends ConsumerWidget { ); } - Future _getAssetDetails( - WidgetRef ref, - String localAssetId, - ) async { + Future _getAssetDetails(WidgetRef ref, String localAssetId) async { try { final repository = ref.read(localAssetRepository); return await repository.getById(localAssetId); diff --git a/mobile/lib/pages/backup/failed_backup_status.page.dart b/mobile/lib/pages/backup/failed_backup_status.page.dart index 8d0faf2d2..b533895cd 100644 --- a/mobile/lib/pages/backup/failed_backup_status.page.dart +++ b/mobile/lib/pages/backup/failed_backup_status.page.dart @@ -25,9 +25,7 @@ class FailedBackupStatusPage extends HookConsumerWidget { context.maybePop(true); }, splashRadius: 24, - icon: const Icon( - Icons.arrow_back_ios_rounded, - ), + icon: const Icon(Icons.arrow_back_ios_rounded), ), ), body: ListView.builder( @@ -37,19 +35,13 @@ class FailedBackupStatusPage extends HookConsumerWidget { var errorAsset = errorBackupList.elementAt(index); return Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 4, - ), + padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 4), child: Card( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(15), // if you need this ), - side: BorderSide( - color: Colors.black12, - width: 1, - ), + side: BorderSide(color: Colors.black12, width: 1), ), elevation: 0, child: Row( @@ -57,12 +49,7 @@ class FailedBackupStatusPage extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ConstrainedBox( - constraints: const BoxConstraints( - minWidth: 100, - minHeight: 100, - maxWidth: 100, - maxHeight: 150, - ), + constraints: const BoxConstraints(minWidth: 100, minHeight: 100, maxWidth: 100, maxHeight: 150), child: ClipRRect( borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(15), @@ -71,11 +58,7 @@ class FailedBackupStatusPage extends HookConsumerWidget { clipBehavior: Clip.hardEdge, child: Image( fit: BoxFit.cover, - image: ImmichLocalThumbnailProvider( - asset: errorAsset.asset, - height: 512, - width: 512, - ), + image: ImmichLocalThumbnailProvider(asset: errorAsset.asset, height: 512, width: 512), ), ), ), @@ -91,20 +74,14 @@ class FailedBackupStatusPage extends HookConsumerWidget { children: [ Text( DateFormat.yMMMMd().format( - DateTime.parse( - errorAsset.fileCreatedAt.toString(), - ).toLocal(), + DateTime.parse(errorAsset.fileCreatedAt.toString()).toLocal(), ), style: TextStyle( fontWeight: FontWeight.w600, color: context.isDarkTheme ? Colors.white70 : Colors.grey[800], ), ), - Icon( - Icons.error, - color: Colors.red.withAlpha(200), - size: 18, - ), + Icon(Icons.error, color: Colors.red.withAlpha(200), size: 18), ], ), Padding( @@ -113,10 +90,7 @@ class FailedBackupStatusPage extends HookConsumerWidget { errorAsset.fileName, maxLines: 1, overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: FontWeight.bold, - color: context.primaryColor, - ), + style: TextStyle(fontWeight: FontWeight.bold, color: context.primaryColor), ), ), Text( diff --git a/mobile/lib/pages/common/activities.page.dart b/mobile/lib/pages/common/activities.page.dart index 203df2d50..1a1955af4 100644 --- a/mobile/lib/pages/common/activities.page.dart +++ b/mobile/lib/pages/common/activities.page.dart @@ -16,9 +16,7 @@ import 'package:immich_mobile/widgets/activities/dismissible_activity.dart'; @RoutePage() class ActivitiesPage extends HookConsumerWidget { - const ActivitiesPage({ - super.key, - }); + const ActivitiesPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -60,9 +58,7 @@ class ActivitiesPage extends HookConsumerWidget { itemBuilder: (context, index) { // Additional vertical gap after the last element if (index == data.length) { - return const SizedBox( - height: 80, - ); + return const SizedBox(height: 80); } final activity = data[index]; @@ -73,8 +69,9 @@ class ActivitiesPage extends HookConsumerWidget { child: DismissibleActivity( activity.id, ActivityTile(activity), - onDismiss: - canDelete ? (activityId) async => await activityNotifier.removeActivity(activity.id) : null, + onDismiss: canDelete + ? (activityId) async => await activityNotifier.removeActivity(activity.id) + : null, ), ); }, diff --git a/mobile/lib/pages/common/app_log.page.dart b/mobile/lib/pages/common/app_log.page.dart index 359a541de..fe0c0ea44 100644 --- a/mobile/lib/pages/common/app_log.page.dart +++ b/mobile/lib/pages/common/app_log.page.dart @@ -12,17 +12,13 @@ import 'package:intl/intl.dart'; @RoutePage() class AppLogPage extends HookConsumerWidget { - const AppLogPage({ - super.key, - }); + const AppLogPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final immichLogger = LogService.I; final shouldReload = useState(false); - final logMessages = useFuture( - useMemoized(() => immichLogger.getMessages(), [shouldReload.value]), - ); + final logMessages = useFuture(useMemoized(() => immichLogger.getMessages(), [shouldReload.value])); Widget colorStatusIndicator(Color color) { return Column( @@ -31,38 +27,29 @@ class AppLogPage extends HookConsumerWidget { Container( width: 10, height: 10, - decoration: BoxDecoration( - color: color, - shape: BoxShape.circle, - ), + decoration: BoxDecoration(color: color, shape: BoxShape.circle), ), ], ); } Widget buildLeadingIcon(LogLevel level) => switch (level) { - LogLevel.info => colorStatusIndicator(context.primaryColor), - LogLevel.severe => colorStatusIndicator(Colors.redAccent), - LogLevel.warning => colorStatusIndicator(Colors.orangeAccent), - _ => colorStatusIndicator(Colors.grey), - }; + LogLevel.info => colorStatusIndicator(context.primaryColor), + LogLevel.severe => colorStatusIndicator(Colors.redAccent), + LogLevel.warning => colorStatusIndicator(Colors.orangeAccent), + _ => colorStatusIndicator(Colors.grey), + }; Color getTileColor(LogLevel level) => switch (level) { - LogLevel.info => Colors.transparent, - LogLevel.severe => Colors.redAccent.withValues(alpha: 0.25), - LogLevel.warning => Colors.orangeAccent.withValues(alpha: 0.25), - _ => context.primaryColor.withValues(alpha: 0.1), - }; + LogLevel.info => Colors.transparent, + LogLevel.severe => Colors.redAccent.withValues(alpha: 0.25), + LogLevel.warning => Colors.orangeAccent.withValues(alpha: 0.25), + _ => context.primaryColor.withValues(alpha: 0.1), + }; return Scaffold( appBar: AppBar( - title: const Text( - "Logs", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 16.0, - ), - ), + title: const Text("Logs", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0)), scrolledUnderElevation: 1, elevation: 2, actions: [ @@ -81,12 +68,7 @@ class AppLogPage extends HookConsumerWidget { Builder( builder: (BuildContext iconContext) { return IconButton( - icon: Icon( - Icons.share_rounded, - color: context.primaryColor, - semanticLabel: "Share logs", - size: 20.0, - ), + icon: Icon(Icons.share_rounded, color: context.primaryColor, semanticLabel: "Share logs", size: 20.0), onPressed: () { ImmichLogger.shareLogs(iconContext); }, @@ -98,10 +80,7 @@ class AppLogPage extends HookConsumerWidget { onPressed: () { context.maybePop(); }, - icon: const Icon( - Icons.arrow_back_ios_new_rounded, - size: 20.0, - ), + icon: const Icon(Icons.arrow_back_ios_new_rounded, size: 20.0), ), centerTitle: true, ), @@ -113,11 +92,7 @@ class AppLogPage extends HookConsumerWidget { itemBuilder: (context, index) { var logMessage = logMessages.data![index]; return ListTile( - onTap: () => context.pushRoute( - AppLogDetailRoute( - logMessage: logMessage, - ), - ), + onTap: () => context.pushRoute(AppLogDetailRoute(logMessage: logMessage)), trailing: const Icon(Icons.arrow_forward_ios_rounded), visualDensity: VisualDensity.compact, dense: true, @@ -125,18 +100,11 @@ class AppLogPage extends HookConsumerWidget { minLeadingWidth: 10, title: Text( truncateLogMessage(logMessage.message, 4), - style: TextStyle( - fontSize: 14.0, - color: context.colorScheme.onSurface, - fontFamily: "Inconsolata", - ), + style: TextStyle(fontSize: 14.0, color: context.colorScheme.onSurface, fontFamily: "Inconsolata"), ), subtitle: Text( "at ${DateFormat("HH:mm:ss.SSS").format(logMessage.createdAt)} in ${logMessage.logger}", - style: TextStyle( - fontSize: 12.0, - color: context.colorScheme.onSurfaceSecondary, - ), + style: TextStyle(fontSize: 12.0, color: context.colorScheme.onSurfaceSecondary), ), leading: buildLeadingIcon(logMessage.level), ); diff --git a/mobile/lib/pages/common/app_log_detail.page.dart b/mobile/lib/pages/common/app_log_detail.page.dart index d8647ca8e..a9cf634fa 100644 --- a/mobile/lib/pages/common/app_log_detail.page.dart +++ b/mobile/lib/pages/common/app_log_detail.page.dart @@ -27,11 +27,7 @@ class AppLogDetailPage extends HookConsumerWidget { padding: const EdgeInsets.only(bottom: 8.0), child: Text( header, - style: TextStyle( - fontSize: 12.0, - color: context.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 12.0, color: context.primaryColor, fontWeight: FontWeight.bold), ), ), IconButton( @@ -41,38 +37,26 @@ class AppLogDetailPage extends HookConsumerWidget { SnackBar( content: Text( "Copied to clipboard", - style: context.textTheme.bodyLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ), ), ); }); }, - icon: Icon( - Icons.copy, - size: 16.0, - color: context.primaryColor, - ), + icon: Icon(Icons.copy, size: 16.0, color: context.primaryColor), ), ], ), Container( decoration: BoxDecoration( color: context.colorScheme.surfaceContainerHigh, - borderRadius: const BorderRadius.all( - Radius.circular(15.0), - ), + borderRadius: const BorderRadius.all(Radius.circular(15.0)), ), child: Padding( padding: const EdgeInsets.all(8.0), child: SelectableText( text, - style: const TextStyle( - fontSize: 12.0, - fontWeight: FontWeight.bold, - fontFamily: "Inconsolata", - ), + style: const TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold, fontFamily: "Inconsolata"), ), ), ), @@ -91,29 +75,19 @@ class AppLogDetailPage extends HookConsumerWidget { padding: const EdgeInsets.only(bottom: 8.0), child: Text( "FROM", - style: TextStyle( - fontSize: 12.0, - color: context.primaryColor, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 12.0, color: context.primaryColor, fontWeight: FontWeight.bold), ), ), Container( decoration: BoxDecoration( color: context.colorScheme.surfaceContainerHigh, - borderRadius: const BorderRadius.all( - Radius.circular(15.0), - ), + borderRadius: const BorderRadius.all(Radius.circular(15.0)), ), child: Padding( padding: const EdgeInsets.all(8.0), child: SelectableText( context1.toString(), - style: const TextStyle( - fontSize: 12.0, - fontWeight: FontWeight.bold, - fontFamily: "Inconsolata", - ), + style: const TextStyle(fontSize: 12.0, fontWeight: FontWeight.bold, fontFamily: "Inconsolata"), ), ), ), @@ -123,20 +97,14 @@ class AppLogDetailPage extends HookConsumerWidget { } return Scaffold( - appBar: AppBar( - title: const Text("Log Detail"), - ), + appBar: AppBar(title: const Text("Log Detail")), body: SafeArea( child: ListView( children: [ buildTextWithCopyButton("MESSAGE", logMessage.message), if (logMessage.error != null) buildTextWithCopyButton("DETAILS", logMessage.error.toString()), if (logMessage.logger != null) buildLogContext1(logMessage.logger.toString()), - if (logMessage.stack != null) - buildTextWithCopyButton( - "STACK TRACE", - logMessage.stack.toString(), - ), + if (logMessage.stack != null) buildTextWithCopyButton("STACK TRACE", logMessage.stack.toString()), ], ), ), diff --git a/mobile/lib/pages/common/change_experience.page.dart b/mobile/lib/pages/common/change_experience.page.dart index 21464e39f..45392a38f 100644 --- a/mobile/lib/pages/common/change_experience.page.dart +++ b/mobile/lib/pages/common/change_experience.page.dart @@ -49,11 +49,9 @@ class _ChangeExperiencePageState extends ConsumerState { // Cancel uploads await Store.put(StoreKey.backgroundBackup, false); - ref.read(backupProvider.notifier).configureBackgroundBackup( - enabled: false, - onBatteryInfo: () {}, - onError: (_) {}, - ); + ref + .read(backupProvider.notifier) + .configureBackgroundBackup(enabled: false, onBatteryInfo: () {}, onError: (_) {}); ref.read(backupProvider.notifier).setAutoBackup(false); ref.read(backupProvider.notifier).cancelBackup(); ref.read(manualUploadProvider.notifier).cancelBackup(); @@ -65,14 +63,8 @@ class _ChangeExperiencePageState extends ConsumerState { if (permission.isGranted) { await ref.read(backgroundSyncProvider).syncLocal(full: true); - await migrateDeviceAssetToSqlite( - ref.read(isarProvider), - ref.read(driftProvider), - ); - await migrateBackupAlbumsToSqlite( - ref.read(isarProvider), - ref.read(driftProvider), - ); + await migrateDeviceAssetToSqlite(ref.read(isarProvider), ref.read(driftProvider)); + await migrateBackupAlbumsToSqlite(ref.read(isarProvider), ref.read(driftProvider)); } } else { await ref.read(backgroundSyncProvider).cancel(); @@ -98,16 +90,8 @@ class _ChangeExperiencePageState extends ConsumerState { AnimatedSwitcher( duration: Durations.long4, child: hasMigrated - ? const Icon( - Icons.check_circle_rounded, - color: Colors.green, - size: 48.0, - ) - : const SizedBox( - width: 50.0, - height: 50.0, - child: CircularProgressIndicator(), - ), + ? const Icon(Icons.check_circle_rounded, color: Colors.green, size: 48.0) + : const SizedBox(width: 50.0, height: 50.0, child: CircularProgressIndicator()), ), const SizedBox(height: 16.0), Center( diff --git a/mobile/lib/pages/common/create_album.page.dart b/mobile/lib/pages/common/create_album.page.dart index 02e1ea18d..5a0d4154f 100644 --- a/mobile/lib/pages/common/create_album.page.dart +++ b/mobile/lib/pages/common/create_album.page.dart @@ -20,10 +20,7 @@ import 'package:immich_mobile/widgets/album/shared_album_thumbnail_image.dart'; class CreateAlbumPage extends HookConsumerWidget { final List? assets; - const CreateAlbumPage({ - super.key, - this.assets, - }); + const CreateAlbumPage({super.key, this.assets}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -32,9 +29,7 @@ class CreateAlbumPage extends HookConsumerWidget { final albumDescriptionTextFieldFocusNode = useFocusNode(); final isAlbumTitleTextFieldFocus = useState(false); final isAlbumTitleEmpty = useState(true); - final selectedAssets = useState>( - assets != null ? Set.from(assets!) : const {}, - ); + final selectedAssets = useState>(assets != null ? Set.from(assets!) : const {}); void onBackgroundTapped() { albumTitleTextFieldFocusNode.unfocus(); @@ -50,10 +45,7 @@ class CreateAlbumPage extends HookConsumerWidget { onSelectPhotosButtonPressed() async { AssetSelectionPageResult? selectedAsset = await context.pushRoute( - AlbumAssetSelectionRoute( - existingAssets: selectedAssets.value, - canDeselect: true, - ), + AlbumAssetSelectionRoute(existingAssets: selectedAssets.value, canDeselect: true), ); if (selectedAsset == null) { selectedAssets.value = const {}; @@ -64,10 +56,7 @@ class CreateAlbumPage extends HookConsumerWidget { buildTitleInputField() { return Padding( - padding: const EdgeInsets.only( - right: 10, - left: 10, - ), + padding: const EdgeInsets.only(right: 10, left: 10), child: AlbumTitleTextField( isAlbumTitleEmpty: isAlbumTitleEmpty, albumTitleTextFieldFocusNode: albumTitleTextFieldFocusNode, @@ -79,10 +68,7 @@ class CreateAlbumPage extends HookConsumerWidget { buildDescriptionInputField() { return Padding( - padding: const EdgeInsets.only( - right: 10, - left: 10, - ), + padding: const EdgeInsets.only(right: 10, left: 10), child: AlbumViewerEditableDescription( albumDescription: '', descriptionFocusNode: albumDescriptionTextFieldFocusNode, @@ -95,10 +81,7 @@ class CreateAlbumPage extends HookConsumerWidget { return SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: 200, left: 18), - child: Text( - 'create_shared_album_page_share_add_assets', - style: context.textTheme.labelLarge, - ).tr(), + child: Text('create_shared_album_page_share_add_assets', style: context.textTheme.labelLarge).tr(), ), ); } @@ -115,18 +98,11 @@ class CreateAlbumPage extends HookConsumerWidget { style: FilledButton.styleFrom( alignment: Alignment.centerLeft, padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 16), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(10), - ), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10))), backgroundColor: context.colorScheme.surfaceContainerHigh, ), onPressed: onSelectPhotosButtonPressed, - icon: Icon( - Icons.add_rounded, - color: context.primaryColor, - ), + icon: Icon(Icons.add_rounded, color: context.primaryColor), label: Padding( padding: const EdgeInsets.only(left: 8.0), child: Text( @@ -174,17 +150,12 @@ class CreateAlbumPage extends HookConsumerWidget { crossAxisSpacing: 5.0, mainAxisSpacing: 5, ), - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - return GestureDetector( - onTap: onBackgroundTapped, - child: SharedAlbumThumbnailImage( - asset: selectedAssets.value.elementAt(index), - ), - ); - }, - childCount: selectedAssets.value.length, - ), + delegate: SliverChildBuilderDelegate((BuildContext context, int index) { + return GestureDetector( + onTap: onBackgroundTapped, + child: SharedAlbumThumbnailImage(asset: selectedAssets.value.elementAt(index)), + ); + }, childCount: selectedAssets.value.length), ), ); } @@ -194,10 +165,9 @@ class CreateAlbumPage extends HookConsumerWidget { Future createAlbum() async { onBackgroundTapped(); - var newAlbum = await ref.watch(albumProvider.notifier).createAlbum( - ref.read(albumTitleProvider), - selectedAssets.value, - ); + var newAlbum = await ref + .watch(albumProvider.notifier) + .createAlbum(ref.read(albumTitleProvider), selectedAssets.value); if (newAlbum != null) { ref.read(albumProvider.notifier).refreshRemoteAlbums(); @@ -220,9 +190,7 @@ class CreateAlbumPage extends HookConsumerWidget { }, icon: const Icon(Icons.close_rounded), ), - title: const Text( - 'create_album', - ).tr(), + title: const Text('create_album').tr(), actions: [ TextButton( onPressed: albumTitleController.text.isNotEmpty ? createAlbum : null, diff --git a/mobile/lib/pages/common/download_panel.dart b/mobile/lib/pages/common/download_panel.dart index 38212d548..0775f5b4e 100644 --- a/mobile/lib/pages/common/download_panel.dart +++ b/mobile/lib/pages/common/download_panel.dart @@ -6,22 +6,13 @@ import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/asset_viewer/download.provider.dart'; class DownloadPanel extends ConsumerWidget { - const DownloadPanel({ - super.key, - }); + const DownloadPanel({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final showProgress = ref.watch( - downloadStateProvider.select((state) => state.showProgress), - ); + final showProgress = ref.watch(downloadStateProvider.select((state) => state.showProgress)); - final tasks = ref - .watch( - downloadStateProvider.select((state) => state.taskProgress), - ) - .entries - .toList(); + final tasks = ref.watch(downloadStateProvider.select((state) => state.taskProgress)).entries.toList(); onCancelDownload(String id) { ref.watch(downloadStateProvider.notifier).cancelDownload(id); @@ -74,47 +65,35 @@ class DownloadTaskTile extends StatelessWidget { final progressPercent = (progress * 100).round(); String getStatusText() => switch (status) { - TaskStatus.running => 'downloading'.tr(), - TaskStatus.complete => 'download_complete'.tr(), - TaskStatus.failed => 'download_failed'.tr(), - TaskStatus.canceled => 'download_canceled'.tr(), - TaskStatus.paused => 'download_paused'.tr(), - TaskStatus.enqueued => 'download_enqueue'.tr(), - TaskStatus.notFound => 'download_notfound'.tr(), - TaskStatus.waitingToRetry => 'download_waiting_to_retry'.tr(), - }; + TaskStatus.running => 'downloading'.tr(), + TaskStatus.complete => 'download_complete'.tr(), + TaskStatus.failed => 'download_failed'.tr(), + TaskStatus.canceled => 'download_canceled'.tr(), + TaskStatus.paused => 'download_paused'.tr(), + TaskStatus.enqueued => 'download_enqueue'.tr(), + TaskStatus.notFound => 'download_notfound'.tr(), + TaskStatus.waitingToRetry => 'download_waiting_to_retry'.tr(), + }; return SizedBox( key: const ValueKey('download_progress'), width: context.width - 32, child: Card( clipBehavior: Clip.antiAlias, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(16), - ), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), child: ListTile( minVerticalPadding: 18, leading: const Icon(Icons.video_file_outlined), - title: Text( - getStatusText(), - style: context.textTheme.labelLarge, - ), + title: Text(getStatusText(), style: context.textTheme.labelLarge), trailing: IconButton( icon: Icon(Icons.close, color: context.colorScheme.onError), onPressed: onCancelDownload, - style: ElevatedButton.styleFrom( - backgroundColor: context.colorScheme.error.withAlpha(200), - ), + style: ElevatedButton.styleFrom(backgroundColor: context.colorScheme.error.withAlpha(200)), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - fileName, - style: context.textTheme.labelMedium, - ), + Text(fileName, style: context.textTheme.labelMedium), Row( children: [ Expanded( @@ -125,10 +104,7 @@ class DownloadTaskTile extends StatelessWidget { ), ), const SizedBox(width: 8), - Text( - '$progressPercent%', - style: context.textTheme.labelSmall, - ), + Text('$progressPercent%', style: context.textTheme.labelSmall), ], ), ], diff --git a/mobile/lib/pages/common/gallery_stacked_children.dart b/mobile/lib/pages/common/gallery_stacked_children.dart index eafc32504..7145bc255 100644 --- a/mobile/lib/pages/common/gallery_stacked_children.dart +++ b/mobile/lib/pages/common/gallery_stacked_children.dart @@ -36,11 +36,7 @@ class GalleryStackedChildren extends HookConsumerWidget { shrinkWrap: true, scrollDirection: Axis.horizontal, itemCount: stackElements.length, - padding: const EdgeInsets.only( - left: 5, - right: 5, - bottom: 30, - ), + padding: const EdgeInsets.only(left: 5, right: 5, bottom: 30), itemBuilder: (context, index) { final currentAsset = stackElements.elementAt(index); final assetId = currentAsset.remoteId; @@ -63,9 +59,7 @@ class GalleryStackedChildren extends HookConsumerWidget { ? const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(6)), - border: Border.fromBorderSide( - BorderSide(color: Colors.white, width: 2), - ), + border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 2)), ) : const BoxDecoration( color: Colors.white, diff --git a/mobile/lib/pages/common/gallery_viewer.page.dart b/mobile/lib/pages/common/gallery_viewer.page.dart index 05389018d..3c279dfcd 100644 --- a/mobile/lib/pages/common/gallery_viewer.page.dart +++ b/mobile/lib/pages/common/gallery_viewer.page.dart @@ -87,11 +87,7 @@ class GalleryViewerPage extends HookConsumerWidget { if (index < totalAssets.value && index >= 0) { final asset = loadAsset(index); await precacheImage( - ImmichImage.imageProvider( - asset: asset, - width: context.width, - height: context.height, - ), + ImmichImage.imageProvider(asset: asset, width: context.width, height: context.height), context, onError: onError, ); @@ -103,23 +99,20 @@ class GalleryViewerPage extends HookConsumerWidget { } } - useEffect( - () { - if (ref.read(showControlsProvider)) { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); - } else { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); - } + useEffect(() { + if (ref.read(showControlsProvider)) { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); + } else { + SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + } - // Delay this a bit so we can finish loading the page - Timer(const Duration(milliseconds: 400), () { - precacheNextImage(currentIndex.value + 1); - }); + // Delay this a bit so we can finish loading the page + Timer(const Duration(milliseconds: 400), () { + precacheNextImage(currentIndex.value + 1); + }); - return null; - }, - const [], - ); + return null; + }, const []); useEffect(() { final asset = loadAsset(currentIndex.value); @@ -136,9 +129,7 @@ class GalleryViewerPage extends HookConsumerWidget { duration: const Duration(seconds: 1), content: Text( "local_asset_cast_failed".tr(), - style: context.textTheme.bodyLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ), ), ); @@ -147,9 +138,7 @@ class GalleryViewerPage extends HookConsumerWidget { } } return null; - }, [ - ref.watch(castProvider).isCasting, - ]); + }, [ref.watch(castProvider).isCasting]); void showInfo() { final asset = ref.read(currentAssetProvider); @@ -157,9 +146,7 @@ class GalleryViewerPage extends HookConsumerWidget { return; } showModalBottomSheet( - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(15.0)), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15.0))), barrierColor: Colors.transparent, isScrollControlled: true, showDragHandle: true, @@ -174,20 +161,10 @@ class GalleryViewerPage extends HookConsumerWidget { expand: false, builder: (context, scrollController) { return Padding( - padding: EdgeInsets.only( - bottom: context.viewInsets.bottom, - ), - child: ref.watch(appSettingsServiceProvider).getSetting( - AppSettingsEnum.advancedTroubleshooting, - ) - ? AdvancedBottomSheet( - assetDetail: asset, - scrollController: scrollController, - ) - : DetailPanel( - asset: asset, - scrollController: scrollController, - ), + padding: EdgeInsets.only(bottom: context.viewInsets.bottom), + child: ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.advancedTroubleshooting) + ? AdvancedBottomSheet(assetDetail: asset, scrollController: scrollController) + : DetailPanel(asset: asset, scrollController: scrollController), ); }, ); @@ -258,10 +235,7 @@ class GalleryViewerPage extends HookConsumerWidget { tightMode: true, initialScale: PhotoViewComputedScale.contained * 0.99, minScale: PhotoViewComputedScale.contained * 0.99, - errorBuilder: (context, error, stackTrace) => ImmichImage( - asset, - fit: BoxFit.contain, - ), + errorBuilder: (context, error, stackTrace) => ImmichImage(asset, fit: BoxFit.contain), ); } @@ -283,11 +257,7 @@ class GalleryViewerPage extends HookConsumerWidget { asset: asset, image: Image( key: ValueKey(asset), - image: ImmichImage.imageProvider( - asset: asset, - width: context.width, - height: context.height, - ), + image: ImmichImage.imageProvider(asset: asset, width: context.width, height: context.height), fit: BoxFit.contain, height: context.height, width: context.width, @@ -342,17 +312,8 @@ class GalleryViewerPage extends HookConsumerWidget { child: Stack( fit: StackFit.expand, children: [ - BackdropFilter( - filter: ui.ImageFilter.blur( - sigmaX: 10, - sigmaY: 10, - ), - ), - ImmichThumbnail( - key: ValueKey(asset), - asset: asset, - fit: BoxFit.contain, - ), + BackdropFilter(filter: ui.ImageFilter.blur(sigmaX: 10, sigmaY: 10)), + ImmichThumbnail(key: ValueKey(asset), asset: asset, fit: BoxFit.contain), ], ), ); @@ -361,9 +322,9 @@ class GalleryViewerPage extends HookConsumerWidget { scrollPhysics: isZoomed.value ? const NeverScrollableScrollPhysics() // Don't allow paging while scrolled in : (Platform.isIOS - ? const FastScrollPhysics() // Use bouncing physics for iOS - : const FastClampingScrollPhysics() // Use heavy physics for Android - ), + ? const FastScrollPhysics() // Use bouncing physics for iOS + : const FastClampingScrollPhysics() // Use heavy physics for Android + ), itemCount: totalAssets.value, scrollDirection: Axis.horizontal, onPageChanged: (value, _) { @@ -401,9 +362,7 @@ class GalleryViewerPage extends HookConsumerWidget { duration: const Duration(seconds: 2), content: Text( "local_asset_cast_failed".tr(), - style: context.textTheme.bodyLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ), ), ); @@ -416,10 +375,7 @@ class GalleryViewerPage extends HookConsumerWidget { top: 0, left: 0, right: 0, - child: GalleryAppBar( - key: const ValueKey('app-bar'), - showInfo: showInfo, - ), + child: GalleryAppBar(key: const ValueKey('app-bar'), showInfo: showInfo), ), Positioned( bottom: 0, diff --git a/mobile/lib/pages/common/headers_settings.page.dart b/mobile/lib/pages/common/headers_settings.page.dart index 0f4ab882c..4cf683b4d 100644 --- a/mobile/lib/pages/common/headers_settings.page.dart +++ b/mobile/lib/pages/common/headers_settings.page.dart @@ -79,10 +79,8 @@ class HeaderSettingsPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0), itemCount: list.length, itemBuilder: (ctx, index) => list[index], - separatorBuilder: (context, index) => const Padding( - padding: EdgeInsets.only(bottom: 16.0, left: 8, right: 8), - child: Divider(), - ), + separatorBuilder: (context, index) => + const Padding(padding: EdgeInsets.only(bottom: 16.0, left: 8, right: 8), child: Divider()), ), ), ); @@ -109,12 +107,9 @@ class HeaderKeyValueSettings extends StatelessWidget { final SettingsHeader header; final Function() onRemove; - HeaderKeyValueSettings({ - super.key, - required this.header, - required this.onRemove, - }) : keyController = TextEditingController(text: header.key), - valueController = TextEditingController(text: header.value); + HeaderKeyValueSettings({super.key, required this.header, required this.onRemove}) + : keyController = TextEditingController(text: header.key), + valueController = TextEditingController(text: header.value); String? emptyFieldValidator(String? value) { if (value == null || value.isEmpty) { @@ -150,9 +145,7 @@ class HeaderKeyValueSettings extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 8), child: IconButton( - style: ElevatedButton.styleFrom( - padding: const EdgeInsets.symmetric(vertical: 12), - ), + style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12)), color: Colors.red[400], onPressed: onRemove, icon: const Icon(Icons.delete_outline), diff --git a/mobile/lib/pages/common/large_leading_tile.dart b/mobile/lib/pages/common/large_leading_tile.dart index d36e29642..456383447 100644 --- a/mobile/lib/pages/common/large_leading_tile.dart +++ b/mobile/lib/pages/common/large_leading_tile.dart @@ -8,10 +8,7 @@ class LargeLeadingTile extends StatelessWidget { required this.onTap, required this.title, this.subtitle, - this.leadingPadding = const EdgeInsets.symmetric( - vertical: 8, - horizontal: 16.0, - ), + this.leadingPadding = const EdgeInsets.symmetric(vertical: 8, horizontal: 16.0), this.borderRadius = 20.0, this.trailing, this.selected = false, @@ -47,18 +44,12 @@ class LargeLeadingTile extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ - Padding( - padding: leadingPadding, - child: leading, - ), + Padding(padding: leadingPadding, child: leading), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - width: context.width * 0.6, - child: title, - ), + SizedBox(width: context.width * 0.6, child: title), subtitle ?? const SizedBox.shrink(), ], ), diff --git a/mobile/lib/pages/common/native_video_viewer.page.dart b/mobile/lib/pages/common/native_video_viewer.page.dart index 0dbaf6125..d8b6db227 100644 --- a/mobile/lib/pages/common/native_video_viewer.page.dart +++ b/mobile/lib/pages/common/native_video_viewer.page.dart @@ -78,17 +78,15 @@ class NativeVideoViewerPage extends HookConsumerWidget { throw Exception('No file found for the video'); } - final source = await VideoSource.init( - path: file.path, - type: VideoSourceType.file, - ); + final source = await VideoSource.init(path: file.path, type: VideoSourceType.file); return source; } // Use a network URL for the video player controller final serverEndpoint = Store.get(StoreKey.serverEndpoint); - final isOriginalVideo = - ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.loadOriginalVideo); + final isOriginalVideo = ref + .read(appSettingsServiceProvider) + .getSetting(AppSettingsEnum.loadOriginalVideo); final String postfixUrl = isOriginalVideo ? 'original' : 'video/playback'; final String videoUrl = asset.livePhotoVideoId != null ? '$serverEndpoint/assets/${asset.livePhotoVideoId}/$postfixUrl' @@ -101,30 +99,24 @@ class NativeVideoViewerPage extends HookConsumerWidget { ); return source; } catch (error) { - log.severe( - 'Error creating video source for asset ${asset.fileName}: $error', - ); + log.severe('Error creating video source for asset ${asset.fileName}: $error'); return null; } } final videoSource = useMemoized>(() => createSource()); final aspectRatio = useState(asset.aspectRatio); - useMemoized( - () async { - if (!context.mounted || aspectRatio.value != null) { - return null; - } + useMemoized(() async { + if (!context.mounted || aspectRatio.value != null) { + return null; + } - try { - aspectRatio.value = await ref.read(assetServiceProvider).getAspectRatio(asset); - } catch (error) { - log.severe( - 'Error getting aspect ratio for asset ${asset.fileName}: $error', - ); - } - }, - ); + try { + aspectRatio.value = await ref.read(assetServiceProvider).getAspectRatio(asset); + } catch (error) { + log.severe('Error getting aspect ratio for asset ${asset.fileName}: $error'); + } + }); void checkIfBuffering() { if (!context.mounted) { @@ -134,8 +126,9 @@ class NativeVideoViewerPage extends HookConsumerWidget { final videoPlayback = ref.read(videoPlaybackValueProvider); if ((isBuffering.value || videoPlayback.state == VideoPlaybackState.initializing) && videoPlayback.state != VideoPlaybackState.buffering) { - ref.read(videoPlaybackValueProvider.notifier).value = - videoPlayback.copyWith(state: VideoPlaybackState.buffering); + ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback.copyWith( + state: VideoPlaybackState.buffering, + ); } } @@ -322,48 +315,42 @@ class NativeVideoViewerPage extends HookConsumerWidget { // This delay seems like a hacky way to resolve underlying bugs in video // playback, but other resolutions failed thus far Timer( - Platform.isIOS - ? Duration(milliseconds: 300 * playbackDelayFactor) - : imageToVideo - ? Duration(milliseconds: 200 * playbackDelayFactor) - : Duration(milliseconds: 400 * playbackDelayFactor), () { - if (!context.mounted) { - return; - } - - currentAsset.value = value; - if (currentAsset.value == asset) { - onPlaybackReady(); - } - }); - }); - - useEffect( - () { - // If opening a remote video from a hero animation, delay visibility to avoid a stutter - final timer = isVisible.value - ? null - : Timer( - const Duration(milliseconds: 300), - () => isVisible.value = true, - ); - - return () { - timer?.cancel(); - final playerController = controller.value; - if (playerController == null) { + Platform.isIOS + ? Duration(milliseconds: 300 * playbackDelayFactor) + : imageToVideo + ? Duration(milliseconds: 200 * playbackDelayFactor) + : Duration(milliseconds: 400 * playbackDelayFactor), + () { + if (!context.mounted) { return; } - removeListeners(playerController); - playerController.stop().catchError((error) { - log.fine('Error stopping video: $error'); - }); - WakelockPlus.disable(); - }; - }, - const [], - ); + currentAsset.value = value; + if (currentAsset.value == asset) { + onPlaybackReady(); + } + }, + ); + }); + + useEffect(() { + // If opening a remote video from a hero animation, delay visibility to avoid a stutter + final timer = isVisible.value ? null : Timer(const Duration(milliseconds: 300), () => isVisible.value = true); + + return () { + timer?.cancel(); + final playerController = controller.value; + if (playerController == null) { + return; + } + removeListeners(playerController); + playerController.stop().catchError((error) { + log.fine('Error stopping video: $error'); + }); + + WakelockPlus.disable(); + }; + }, const []); useOnAppLifecycleStateChange((_, state) async { if (state == AppLifecycleState.resumed && shouldPlayOnForeground.value) { @@ -393,12 +380,7 @@ class NativeVideoViewerPage extends HookConsumerWidget { child: AspectRatio( key: ValueKey(asset), aspectRatio: aspectRatio.value!, - child: isCurrent - ? NativeVideoPlayerView( - key: ValueKey(asset), - onViewReady: initController, - ) - : null, + child: isCurrent ? NativeVideoPlayerView(key: ValueKey(asset), onViewReady: initController) : null, ), ), ), diff --git a/mobile/lib/pages/common/settings.page.dart b/mobile/lib/pages/common/settings.page.dart index d18a7a113..d7ecb7e58 100644 --- a/mobile/lib/pages/common/settings.page.dart +++ b/mobile/lib/pages/common/settings.page.dart @@ -18,67 +18,31 @@ import 'package:immich_mobile/widgets/settings/preference_settings/preference_se import 'package:immich_mobile/widgets/settings/settings_card.dart'; enum SettingSection { - beta( - 'beta_sync', - Icons.sync_outlined, - "beta_sync_subtitle", - ), - advanced( - 'advanced', - Icons.build_outlined, - "advanced_settings_tile_subtitle", - ), - assetViewer( - 'asset_viewer_settings_title', - Icons.image_outlined, - "asset_viewer_settings_subtitle", - ), - backup( - 'backup', - Icons.cloud_upload_outlined, - "backup_setting_subtitle", - ), - languages( - 'language', - Icons.language, - "setting_languages_subtitle", - ), - networking( - 'networking_settings', - Icons.wifi, - "networking_subtitle", - ), - notifications( - 'notifications', - Icons.notifications_none_rounded, - "setting_notifications_subtitle", - ), - preferences( - 'preferences_settings_title', - Icons.interests_outlined, - "preferences_settings_subtitle", - ), - timeline( - 'asset_list_settings_title', - Icons.auto_awesome_mosaic_outlined, - "asset_list_settings_subtitle", - ); + beta('beta_sync', Icons.sync_outlined, "beta_sync_subtitle"), + advanced('advanced', Icons.build_outlined, "advanced_settings_tile_subtitle"), + assetViewer('asset_viewer_settings_title', Icons.image_outlined, "asset_viewer_settings_subtitle"), + backup('backup', Icons.cloud_upload_outlined, "backup_setting_subtitle"), + languages('language', Icons.language, "setting_languages_subtitle"), + networking('networking_settings', Icons.wifi, "networking_subtitle"), + notifications('notifications', Icons.notifications_none_rounded, "setting_notifications_subtitle"), + preferences('preferences_settings_title', Icons.interests_outlined, "preferences_settings_subtitle"), + timeline('asset_list_settings_title', Icons.auto_awesome_mosaic_outlined, "asset_list_settings_subtitle"); final String title; final String subtitle; final IconData icon; Widget get widget => switch (this) { - SettingSection.beta => const _BetaLandscapeToggle(), - SettingSection.advanced => const AdvancedSettings(), - SettingSection.assetViewer => const AssetViewerSettings(), - SettingSection.backup => const BackupSettings(), - SettingSection.languages => const LanguageSettings(), - SettingSection.networking => const NetworkingSettings(), - SettingSection.notifications => const NotificationSetting(), - SettingSection.preferences => const PreferenceSetting(), - SettingSection.timeline => const AssetListSettings(), - }; + SettingSection.beta => const _BetaLandscapeToggle(), + SettingSection.advanced => const AdvancedSettings(), + SettingSection.assetViewer => const AssetViewerSettings(), + SettingSection.backup => const BackupSettings(), + SettingSection.languages => const LanguageSettings(), + SettingSection.networking => const NetworkingSettings(), + SettingSection.notifications => const NotificationSetting(), + SettingSection.preferences => const PreferenceSetting(), + SettingSection.timeline => const AssetListSettings(), + }; const SettingSection(this.title, this.icon, this.subtitle); } @@ -91,10 +55,7 @@ class SettingsPage extends StatelessWidget { Widget build(BuildContext context) { context.locale; return Scaffold( - appBar: AppBar( - centerTitle: false, - title: const Text('settings').tr(), - ), + appBar: AppBar(centerTitle: false, title: const Text('settings').tr()), body: context.isMobile ? const _MobileLayout() : const _TabletLayout(), ); } @@ -164,10 +125,7 @@ class _TabletLayout extends HookWidget { ), ), const VerticalDivider(width: 1), - Expanded( - flex: 4, - child: selectedSection.value.widget, - ), + Expanded(flex: 4, child: selectedSection.value.widget), ], ); } @@ -198,10 +156,7 @@ class SettingsSubPage extends StatelessWidget { Widget build(BuildContext context) { context.locale; return Scaffold( - appBar: AppBar( - centerTitle: false, - title: Text(section.title).tr(), - ), + appBar: AppBar(centerTitle: false, title: Text(section.title).tr()), body: section.widget, ); } diff --git a/mobile/lib/pages/common/splash_screen.page.dart b/mobile/lib/pages/common/splash_screen.page.dart index 47cd64f7f..2bda4f90f 100644 --- a/mobile/lib/pages/common/splash_screen.page.dart +++ b/mobile/lib/pages/common/splash_screen.page.dart @@ -43,31 +43,26 @@ class SplashScreenPageState extends ConsumerState { final accessToken = Store.tryGet(StoreKey.accessToken); if (accessToken != null && serverUrl != null && endpoint != null) { - ref.read(authProvider.notifier).saveAuthInfo(accessToken: accessToken).then( - (a) => { - log.info('Successfully updated auth info with access token: $accessToken'), - }, + ref + .read(authProvider.notifier) + .saveAuthInfo(accessToken: accessToken) + .then( + (a) => {log.info('Successfully updated auth info with access token: $accessToken')}, onError: (exception) => { - log.severe( - 'Failed to update auth info with access token: $accessToken', - ), + log.severe('Failed to update auth info with access token: $accessToken'), ref.read(authProvider.notifier).logout(), context.replaceRoute(const LoginRoute()), }, ); } else { - log.severe( - 'Missing crucial offline login info - Logging out completely', - ); + log.severe('Missing crucial offline login info - Logging out completely'); ref.read(authProvider.notifier).logout(); context.replaceRoute(const LoginRoute()); return; } if (context.router.current.name == SplashScreenRoute.name) { - context.replaceRoute( - Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute(), - ); + context.replaceRoute(Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute()); } if (Store.isBetaTimelineEnabled) { @@ -85,11 +80,7 @@ class SplashScreenPageState extends ConsumerState { Widget build(BuildContext context) { return const Scaffold( body: Center( - child: Image( - image: AssetImage('assets/immich-logo.png'), - width: 80, - filterQuality: FilterQuality.high, - ), + child: Image(image: AssetImage('assets/immich-logo.png'), width: 80, filterQuality: FilterQuality.high), ), ); } diff --git a/mobile/lib/pages/common/tab_controller.page.dart b/mobile/lib/pages/common/tab_controller.page.dart index 676b1db11..ef637ba1c 100644 --- a/mobile/lib/pages/common/tab_controller.page.dart +++ b/mobile/lib/pages/common/tab_controller.page.dart @@ -36,9 +36,7 @@ class TabControllerPage extends HookConsumerWidget { width: 20, child: CircularProgressIndicator( strokeWidth: 2, - valueColor: AlwaysStoppedAnimation( - context.primaryColor, - ), + valueColor: AlwaysStoppedAnimation(context.primaryColor), ), ), ), @@ -65,51 +63,31 @@ class TabControllerPage extends HookConsumerWidget { final navigationDestinations = [ NavigationDestination( label: 'photos'.tr(), - icon: const Icon( - Icons.photo_library_outlined, - ), + icon: const Icon(Icons.photo_library_outlined), selectedIcon: buildIcon( isProcessing: isRefreshingAssets, - icon: Icon( - Icons.photo_library, - color: context.primaryColor, - ), + icon: Icon(Icons.photo_library, color: context.primaryColor), ), ), NavigationDestination( label: 'search'.tr(), - icon: const Icon( - Icons.search_rounded, - ), - selectedIcon: Icon( - Icons.search, - color: context.primaryColor, - ), + icon: const Icon(Icons.search_rounded), + selectedIcon: Icon(Icons.search, color: context.primaryColor), ), NavigationDestination( label: 'albums'.tr(), - icon: const Icon( - Icons.photo_album_outlined, - ), + icon: const Icon(Icons.photo_album_outlined), selectedIcon: buildIcon( isProcessing: isRefreshingRemoteAlbums, - icon: Icon( - Icons.photo_album_rounded, - color: context.primaryColor, - ), + icon: Icon(Icons.photo_album_rounded, color: context.primaryColor), ), ), NavigationDestination( label: 'library'.tr(), - icon: const Icon( - Icons.space_dashboard_outlined, - ), + icon: const Icon(Icons.space_dashboard_outlined), selectedIcon: buildIcon( isProcessing: isRefreshingAssets, - icon: Icon( - Icons.space_dashboard_rounded, - color: context.primaryColor, - ), + icon: Icon(Icons.space_dashboard_rounded, color: context.primaryColor), ), ), ]; @@ -125,13 +103,7 @@ class TabControllerPage extends HookConsumerWidget { Widget navigationRail(TabsRouter tabsRouter) { return NavigationRail( destinations: navigationDestinations - .map( - (e) => NavigationRailDestination( - icon: e.icon, - label: Text(e.label), - selectedIcon: e.selectedIcon, - ), - ) + .map((e) => NavigationRailDestination(icon: e.icon, label: Text(e.label), selectedIcon: e.selectedIcon)) .toList(), onDestinationSelected: (index) => onNavigationSelected(tabsRouter, index), selectedIndex: tabsRouter.activeIndex, @@ -142,17 +114,9 @@ class TabControllerPage extends HookConsumerWidget { final multiselectEnabled = ref.watch(multiselectProvider); return AutoTabsRouter( - routes: [ - const PhotosRoute(), - SearchRoute(), - const AlbumsRoute(), - const LibraryRoute(), - ], + routes: [const PhotosRoute(), SearchRoute(), const AlbumsRoute(), const LibraryRoute()], duration: const Duration(milliseconds: 600), - transitionBuilder: (context, child, animation) => FadeTransition( - opacity: animation, - child: child, - ), + transitionBuilder: (context, child, animation) => FadeTransition(opacity: animation, child: child), builder: (context, child) { final tabsRouter = AutoTabsRouter.of(context); return PopScope( diff --git a/mobile/lib/pages/common/tab_shell.page.dart b/mobile/lib/pages/common/tab_shell.page.dart index 3961a8b14..e06f7ca44 100644 --- a/mobile/lib/pages/common/tab_shell.page.dart +++ b/mobile/lib/pages/common/tab_shell.page.dart @@ -56,56 +56,30 @@ class _TabShellPageState extends ConsumerState { final navigationDestinations = [ NavigationDestination( label: 'photos'.tr(), - icon: const Icon( - Icons.photo_library_outlined, - ), - selectedIcon: Icon( - Icons.photo_library, - color: context.primaryColor, - ), + icon: const Icon(Icons.photo_library_outlined), + selectedIcon: Icon(Icons.photo_library, color: context.primaryColor), ), NavigationDestination( label: 'search'.tr(), - icon: const Icon( - Icons.search_rounded, - ), - selectedIcon: Icon( - Icons.search, - color: context.primaryColor, - ), + icon: const Icon(Icons.search_rounded), + selectedIcon: Icon(Icons.search, color: context.primaryColor), ), NavigationDestination( label: 'albums'.tr(), - icon: const Icon( - Icons.photo_album_outlined, - ), - selectedIcon: Icon( - Icons.photo_album_rounded, - color: context.primaryColor, - ), + icon: const Icon(Icons.photo_album_outlined), + selectedIcon: Icon(Icons.photo_album_rounded, color: context.primaryColor), ), NavigationDestination( label: 'library'.tr(), - icon: const Icon( - Icons.space_dashboard_outlined, - ), - selectedIcon: Icon( - Icons.space_dashboard_rounded, - color: context.primaryColor, - ), + icon: const Icon(Icons.space_dashboard_outlined), + selectedIcon: Icon(Icons.space_dashboard_rounded, color: context.primaryColor), ), ]; Widget navigationRail(TabsRouter tabsRouter) { return NavigationRail( destinations: navigationDestinations - .map( - (e) => NavigationRailDestination( - icon: e.icon, - label: Text(e.label), - selectedIcon: e.selectedIcon, - ), - ) + .map((e) => NavigationRailDestination(icon: e.icon, label: Text(e.label), selectedIcon: e.selectedIcon)) .toList(), onDestinationSelected: (index) => _onNavigationSelected(tabsRouter, index, ref), selectedIndex: tabsRouter.activeIndex, @@ -115,17 +89,9 @@ class _TabShellPageState extends ConsumerState { } return AutoTabsRouter( - routes: [ - const MainTimelineRoute(), - DriftSearchRoute(), - const DriftAlbumsRoute(), - const DriftLibraryRoute(), - ], + routes: [const MainTimelineRoute(), DriftSearchRoute(), const DriftAlbumsRoute(), const DriftLibraryRoute()], duration: const Duration(milliseconds: 600), - transitionBuilder: (context, child, animation) => FadeTransition( - opacity: animation, - child: child, - ), + transitionBuilder: (context, child, animation) => FadeTransition(opacity: animation, child: child), builder: (context, child) { final tabsRouter = AutoTabsRouter.of(context); return PopScope( @@ -142,10 +108,7 @@ class _TabShellPageState extends ConsumerState { ], ) : child, - bottomNavigationBar: _BottomNavigationBar( - tabsRouter: tabsRouter, - destinations: navigationDestinations, - ), + bottomNavigationBar: _BottomNavigationBar(tabsRouter: tabsRouter, destinations: navigationDestinations), ), ); }, @@ -175,10 +138,7 @@ void _onNavigationSelected(TabsRouter router, int index, WidgetRef ref) { } class _BottomNavigationBar extends ConsumerWidget { - const _BottomNavigationBar({ - required this.tabsRouter, - required this.destinations, - }); + const _BottomNavigationBar({required this.tabsRouter, required this.destinations}); final List destinations; final TabsRouter tabsRouter; diff --git a/mobile/lib/pages/editing/crop.page.dart b/mobile/lib/pages/editing/crop.page.dart index 97ef069e7..35fd61580 100644 --- a/mobile/lib/pages/editing/crop.page.dart +++ b/mobile/lib/pages/editing/crop.page.dart @@ -32,20 +32,10 @@ class CropImagePage extends HookWidget { leading: CloseButton(color: context.primaryColor), actions: [ IconButton( - icon: Icon( - Icons.done_rounded, - color: context.primaryColor, - size: 24, - ), + icon: Icon(Icons.done_rounded, color: context.primaryColor, size: 24), onPressed: () async { final croppedImage = await cropController.croppedImage(); - context.pushRoute( - EditImageRoute( - asset: asset, - image: croppedImage, - isEdited: true, - ), - ); + context.pushRoute(EditImageRoute(asset: asset, image: croppedImage, isEdited: true)); }, ), ], @@ -60,11 +50,7 @@ class CropImagePage extends HookWidget { padding: const EdgeInsets.only(top: 20), width: constraints.maxWidth * 0.9, height: constraints.maxHeight * 0.6, - child: CropImage( - controller: cropController, - image: image, - gridColor: Colors.white, - ), + child: CropImage(controller: cropController, image: image, gridColor: Colors.white), ), Expanded( child: Container( @@ -81,28 +67,18 @@ class CropImagePage extends HookWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.only( - left: 20, - right: 20, - bottom: 10, - ), + padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( - icon: Icon( - Icons.rotate_left, - color: context.themeData.iconTheme.color, - ), + icon: Icon(Icons.rotate_left, color: context.themeData.iconTheme.color), onPressed: () { cropController.rotateLeft(); }, ), IconButton( - icon: Icon( - Icons.rotate_right, - color: context.themeData.iconTheme.color, - ), + icon: Icon(Icons.rotate_right, color: context.themeData.iconTheme.color), onPressed: () { cropController.rotateRight(); }, @@ -178,17 +154,14 @@ class _AspectRatioButton extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ IconButton( - icon: Icon( - switch (label) { - 'Free' => Icons.crop_free_rounded, - '1:1' => Icons.crop_square_rounded, - '16:9' => Icons.crop_16_9_rounded, - '3:2' => Icons.crop_3_2_rounded, - '7:5' => Icons.crop_7_5_rounded, - _ => Icons.crop_free_rounded, - }, - color: aspectRatio.value == ratio ? context.primaryColor : context.themeData.iconTheme.color, - ), + icon: Icon(switch (label) { + 'Free' => Icons.crop_free_rounded, + '1:1' => Icons.crop_square_rounded, + '16:9' => Icons.crop_16_9_rounded, + '3:2' => Icons.crop_3_2_rounded, + '7:5' => Icons.crop_7_5_rounded, + _ => Icons.crop_free_rounded, + }, color: aspectRatio.value == ratio ? context.primaryColor : context.themeData.iconTheme.color), onPressed: () { cropController.crop = const Rect.fromLTRB(0.1, 0.1, 0.9, 0.9); aspectRatio.value = ratio; diff --git a/mobile/lib/pages/editing/edit.page.dart b/mobile/lib/pages/editing/edit.page.dart index 70940e955..c9ab01445 100644 --- a/mobile/lib/pages/editing/edit.page.dart +++ b/mobile/lib/pages/editing/edit.page.dart @@ -29,51 +29,34 @@ class EditImagePage extends ConsumerWidget { final Image image; final bool isEdited; - const EditImagePage({ - super.key, - required this.asset, - required this.image, - required this.isEdited, - }); + const EditImagePage({super.key, required this.asset, required this.image, required this.isEdited}); Future _imageToUint8List(Image image) async { final Completer completer = Completer(); - image.image.resolve(const ImageConfiguration()).addListener( - ImageStreamListener( - (ImageInfo info, bool _) { - info.image.toByteData(format: ImageByteFormat.png).then((byteData) { - if (byteData != null) { - completer.complete(byteData.buffer.asUint8List()); - } else { - completer.completeError('Failed to convert image to bytes'); - } - }); - }, - onError: (exception, stackTrace) => completer.completeError(exception), - ), + image.image + .resolve(const ImageConfiguration()) + .addListener( + ImageStreamListener((ImageInfo info, bool _) { + info.image.toByteData(format: ImageByteFormat.png).then((byteData) { + if (byteData != null) { + completer.complete(byteData.buffer.asUint8List()); + } else { + completer.completeError('Failed to convert image to bytes'); + } + }); + }, onError: (exception, stackTrace) => completer.completeError(exception)), ); return completer.future; } - Future _saveEditedImage( - BuildContext context, - Asset asset, - Image image, - WidgetRef ref, - ) async { + Future _saveEditedImage(BuildContext context, Asset asset, Image image, WidgetRef ref) async { try { final Uint8List imageData = await _imageToUint8List(image); - await ref.read(fileMediaRepositoryProvider).saveImage( - imageData, - title: "${p.withoutExtension(asset.fileName)}_edited.jpg", - ); + await ref + .read(fileMediaRepositoryProvider) + .saveImage(imageData, title: "${p.withoutExtension(asset.fileName)}_edited.jpg"); await ref.read(albumProvider.notifier).refreshDeviceAlbums(); context.navigator.popUntil((route) => route.isFirst); - ImmichToast.show( - durationInSecond: 3, - context: context, - msg: 'Image Saved!', - gravity: ToastGravity.CENTER, - ); + ImmichToast.show(durationInSecond: 3, context: context, msg: 'Image Saved!', gravity: ToastGravity.CENTER); } catch (e) { ImmichToast.show( durationInSecond: 6, @@ -91,37 +74,23 @@ class EditImagePage extends ConsumerWidget { title: Text("edit".tr()), backgroundColor: context.scaffoldBackgroundColor, leading: IconButton( - icon: Icon( - Icons.close_rounded, - color: context.primaryColor, - size: 24, - ), + icon: Icon(Icons.close_rounded, color: context.primaryColor, size: 24), onPressed: () => context.navigator.popUntil((route) => route.isFirst), ), actions: [ TextButton( onPressed: isEdited ? () => _saveEditedImage(context, asset, image, ref) : null, - child: Text( - "save_to_gallery".tr(), - style: TextStyle( - color: isEdited ? context.primaryColor : Colors.grey, - ), - ), + child: Text("save_to_gallery".tr(), style: TextStyle(color: isEdited ? context.primaryColor : Colors.grey)), ), ], ), backgroundColor: context.scaffoldBackgroundColor, body: Center( child: ConstrainedBox( - constraints: BoxConstraints( - maxHeight: context.height * 0.7, - maxWidth: context.width * 0.9, - ), + constraints: BoxConstraints(maxHeight: context.height * 0.7, maxWidth: context.width * 0.9), child: Container( decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(7), - ), + borderRadius: const BorderRadius.all(Radius.circular(7)), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.2), @@ -132,13 +101,8 @@ class EditImagePage extends ConsumerWidget { ], ), child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(7), - ), - child: Image( - image: image.image, - fit: BoxFit.contain, - ), + borderRadius: const BorderRadius.all(Radius.circular(7)), + child: Image(image: image.image, fit: BoxFit.contain), ), ), ), @@ -148,9 +112,7 @@ class EditImagePage extends ConsumerWidget { margin: const EdgeInsets.only(bottom: 60, right: 10, left: 10, top: 10), decoration: BoxDecoration( color: context.scaffoldBackgroundColor, - borderRadius: const BorderRadius.all( - Radius.circular(30), - ), + borderRadius: const BorderRadius.all(Radius.circular(30)), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, @@ -159,15 +121,9 @@ class EditImagePage extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( - icon: Icon( - Icons.crop_rotate_rounded, - color: context.themeData.iconTheme.color, - size: 25, - ), + icon: Icon(Icons.crop_rotate_rounded, color: context.themeData.iconTheme.color, size: 25), onPressed: () { - context.pushRoute( - CropImageRoute(asset: asset, image: image), - ); + context.pushRoute(CropImageRoute(asset: asset, image: image)); }, ), Text("crop".tr(), style: context.textTheme.displayMedium), @@ -177,18 +133,9 @@ class EditImagePage extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( - icon: Icon( - Icons.filter, - color: context.themeData.iconTheme.color, - size: 25, - ), + icon: Icon(Icons.filter, color: context.themeData.iconTheme.color, size: 25), onPressed: () { - context.pushRoute( - FilterImageRoute( - asset: asset, - image: image, - ), - ); + context.pushRoute(FilterImageRoute(asset: asset, image: image)); }, ), Text("filter".tr(), style: context.textTheme.displayMedium), diff --git a/mobile/lib/pages/editing/filter.page.dart b/mobile/lib/pages/editing/filter.page.dart index 3dc8d28a9..6d41b4c5b 100644 --- a/mobile/lib/pages/editing/filter.page.dart +++ b/mobile/lib/pages/editing/filter.page.dart @@ -18,21 +18,14 @@ class FilterImagePage extends HookWidget { final Image image; final Asset asset; - const FilterImagePage({ - super.key, - required this.image, - required this.asset, - }); + const FilterImagePage({super.key, required this.image, required this.asset}); @override Widget build(BuildContext context) { final colorFilter = useState(filters[0]); final selectedFilterIndex = useState(0); - Future createFilteredImage( - ui.Image inputImage, - ColorFilter filter, - ) { + Future createFilteredImage(ui.Image inputImage, ColorFilter filter) { final completer = Completer(); final size = Size(inputImage.width.toDouble(), inputImage.height.toDouble()); final recorder = ui.PictureRecorder(); @@ -55,11 +48,13 @@ class FilterImagePage extends HookWidget { Future applyFilterAndConvert(ColorFilter filter) async { final completer = Completer(); - image.image.resolve(ImageConfiguration.empty).addListener( - ImageStreamListener((ImageInfo info, bool _) { - completer.complete(info.image); - }), - ); + image.image + .resolve(ImageConfiguration.empty) + .addListener( + ImageStreamListener((ImageInfo info, bool _) { + completer.complete(info.image); + }), + ); final uiImage = await completer.future; final filteredUiImage = await createFilteredImage(uiImage, filter); @@ -76,20 +71,10 @@ class FilterImagePage extends HookWidget { leading: CloseButton(color: context.primaryColor), actions: [ IconButton( - icon: Icon( - Icons.done_rounded, - color: context.primaryColor, - size: 24, - ), + icon: Icon(Icons.done_rounded, color: context.primaryColor, size: 24), onPressed: () async { final filteredImage = await applyFilterAndConvert(colorFilter.value); - context.pushRoute( - EditImageRoute( - asset: asset, - image: filteredImage, - isEdited: true, - ), - ); + context.pushRoute(EditImageRoute(asset: asset, image: filteredImage, isEdited: true)); }, ), ], @@ -100,10 +85,7 @@ class FilterImagePage extends HookWidget { SizedBox( height: context.height * 0.7, child: Center( - child: ColorFiltered( - colorFilter: colorFilter.value, - child: image, - ), + child: ColorFiltered(colorFilter: colorFilter.value, child: image), ), ), SizedBox( @@ -156,21 +138,14 @@ class _FilterButton extends StatelessWidget { width: 80, height: 80, decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(10), - ), + borderRadius: const BorderRadius.all(Radius.circular(10)), border: isSelected ? Border.all(color: context.primaryColor, width: 3) : null, ), child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(10), - ), + borderRadius: const BorderRadius.all(Radius.circular(10)), child: ColorFiltered( colorFilter: filter, - child: FittedBox( - fit: BoxFit.cover, - child: image, - ), + child: FittedBox(fit: BoxFit.cover, child: image), ), ), ), diff --git a/mobile/lib/pages/library/archive.page.dart b/mobile/lib/pages/library/archive.page.dart index 2b4aa64f3..8ca1bb975 100644 --- a/mobile/lib/pages/library/archive.page.dart +++ b/mobile/lib/pages/library/archive.page.dart @@ -16,15 +16,10 @@ class ArchivePage extends HookConsumerWidget { final archiveRenderList = ref.watch(archiveTimelineProvider); final count = archiveRenderList.value?.totalAssets.toString() ?? "?"; return AppBar( - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), centerTitle: true, automaticallyImplyLeading: false, - title: const Text( - 'archive_page_title', - ).tr(namedArgs: {'count': count}), + title: const Text('archive_page_title').tr(namedArgs: {'count': count}), ); } diff --git a/mobile/lib/pages/library/favorite.page.dart b/mobile/lib/pages/library/favorite.page.dart index 070693fe4..649d7727d 100644 --- a/mobile/lib/pages/library/favorite.page.dart +++ b/mobile/lib/pages/library/favorite.page.dart @@ -14,15 +14,10 @@ class FavoritesPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { AppBar buildAppBar() { return AppBar( - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), centerTitle: true, automaticallyImplyLeading: false, - title: const Text( - 'favorites', - ).tr(), + title: const Text('favorites').tr(), ); } diff --git a/mobile/lib/pages/library/folder/folder.page.dart b/mobile/lib/pages/library/folder/folder.page.dart index d089aace6..2968bca18 100644 --- a/mobile/lib/pages/library/folder/folder.page.dart +++ b/mobile/lib/pages/library/folder/folder.page.dart @@ -16,10 +16,7 @@ import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/widgets/asset_grid/thumbnail_image.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; -RecursiveFolder? _findFolderInStructure( - RootFolder rootFolder, - RecursiveFolder targetFolder, -) { +RecursiveFolder? _findFolderInStructure(RootFolder rootFolder, RecursiveFolder targetFolder) { for (final folder in rootFolder.subfolders) { if (targetFolder.path == '/' && folder.path.isEmpty && folder.name == targetFolder.name) { return folder; @@ -49,29 +46,23 @@ class FolderPage extends HookConsumerWidget { final currentFolder = useState(folder); final sortOrder = useState(SortOrder.asc); - useEffect( - () { - if (folder == null) { - ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value); - } - return null; - }, - [], - ); + useEffect(() { + if (folder == null) { + ref.read(folderStructureProvider.notifier).fetchFolders(sortOrder.value); + } + return null; + }, []); // Update current folder when root structure changes - useEffect( - () { - if (folder != null && folderState.hasValue) { - final updatedFolder = _findFolderInStructure(folderState.value!, folder!); - if (updatedFolder != null) { - currentFolder.value = updatedFolder; - } + useEffect(() { + if (folder != null && folderState.hasValue) { + final updatedFolder = _findFolderInStructure(folderState.value!, folder!); + if (updatedFolder != null) { + currentFolder.value = updatedFolder; } - return null; - }, - [folderState], - ); + } + return null; + }, [folderState]); void onToggleSortOrder() { final newOrder = sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc; @@ -86,38 +77,19 @@ class FolderPage extends HookConsumerWidget { title: Text(currentFolder.value?.name ?? tr("folders")), elevation: 0, centerTitle: false, - actions: [ - IconButton( - icon: const Icon(Icons.swap_vert), - onPressed: onToggleSortOrder, - ), - ], + actions: [IconButton(icon: const Icon(Icons.swap_vert), onPressed: onToggleSortOrder)], ), body: folderState.when( data: (rootFolder) { if (folder == null) { - return FolderContent( - folder: rootFolder, - root: rootFolder, - sortOrder: sortOrder.value, - ); + return FolderContent(folder: rootFolder, root: rootFolder, sortOrder: sortOrder.value); } else { - return FolderContent( - folder: currentFolder.value!, - root: rootFolder, - sortOrder: sortOrder.value, - ); + return FolderContent(folder: currentFolder.value!, root: rootFolder, sortOrder: sortOrder.value); } }, - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) { - ImmichToast.show( - context: context, - msg: "failed_to_load_folder".tr(), - toastType: ToastType.error, - ); + ImmichToast.show(context: context, msg: "failed_to_load_folder".tr(), toastType: ToastType.error); return Center(child: const Text("failed_to_load_folder").tr()); }, ), @@ -130,26 +102,18 @@ class FolderContent extends HookConsumerWidget { final RootFolder root; final SortOrder sortOrder; - const FolderContent({ - super.key, - this.folder, - required this.root, - this.sortOrder = SortOrder.asc, - }); + const FolderContent({super.key, this.folder, required this.root, this.sortOrder = SortOrder.asc}); @override Widget build(BuildContext context, WidgetRef ref) { final folderRenderlist = ref.watch(folderRenderListProvider(folder!)); // Initial asset fetch - useEffect( - () { - if (folder == null) return; - ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder); - return null; - }, - [folder], - ); + useEffect(() { + if (folder == null) return; + ref.read(folderRenderListProvider(folder!).notifier).fetchAssets(sortOrder); + return null; + }, [folder]); if (folder == null) { return Center(child: const Text("folder_not_found").tr()); @@ -182,18 +146,12 @@ class FolderContent extends HookConsumerWidget { if (folder!.subfolders.isNotEmpty) ...folder!.subfolders.map( (subfolder) => LargeLeadingTile( - leading: Icon( - Icons.folder, - color: context.primaryColor, - size: 48, - ), + leading: Icon(Icons.folder, color: context.primaryColor, size: 48), title: Text( subfolder.name, softWrap: false, overflow: TextOverflow.ellipsis, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), ), subtitle: subfolder.subfolders.isNotEmpty ? Text( @@ -212,23 +170,15 @@ class FolderContent extends HookConsumerWidget { onTap: () { ref.read(currentAssetProvider.notifier).set(asset); context.pushRoute( - GalleryViewerRoute( - renderList: list, - initialIndex: list.allAssets!.indexOf(asset), - ), + GalleryViewerRoute(renderList: list, initialIndex: list.allAssets!.indexOf(asset)), ); }, leading: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(15), - ), + borderRadius: const BorderRadius.all(Radius.circular(15)), child: SizedBox( width: 80, height: 80, - child: ThumbnailImage( - asset: asset, - showStorageIndicator: false, - ), + child: ThumbnailImage(asset: asset, showStorageIndicator: false), ), ), title: Text( @@ -236,30 +186,20 @@ class FolderContent extends HookConsumerWidget { maxLines: 2, softWrap: false, overflow: TextOverflow.ellipsis, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), ), subtitle: Text( "${asset.exifInfo?.fileSize != null ? formatBytes(asset.exifInfo?.fileSize ?? 0) : ""} • ${DateFormat.yMMMd().format(asset.fileCreatedAt)}", - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), ), ), ], ); }, - loading: () => const Center( - child: CircularProgressIndicator(), - ), + loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) { - ImmichToast.show( - context: context, - msg: "failed_to_load_assets".tr(), - toastType: ToastType.error, - ); + ImmichToast.show(context: context, msg: "failed_to_load_assets".tr(), toastType: ToastType.error); return Center(child: const Text("failed_to_load_assets").tr()); }, ), @@ -273,11 +213,7 @@ class FolderPath extends StatelessWidget { final RootFolder currentFolder; final RootFolder root; - const FolderPath({ - super.key, - required this.currentFolder, - required this.root, - }); + const FolderPath({super.key, required this.currentFolder, required this.root}); @override Widget build(BuildContext context) { diff --git a/mobile/lib/pages/library/library.page.dart b/mobile/lib/pages/library/library.page.dart index f51817d06..483427d2d 100644 --- a/mobile/lib/pages/library/library.page.dart +++ b/mobile/lib/pages/library/library.page.dart @@ -74,17 +74,11 @@ class LibraryPage extends ConsumerWidget { const Wrap( spacing: 8, runSpacing: 8, - children: [ - PeopleCollectionCard(), - PlacesCollectionCard(), - LocalAlbumsCollectionCard(), - ], + children: [PeopleCollectionCard(), PlacesCollectionCard(), LocalAlbumsCollectionCard()], ), const SizedBox(height: 12), const QuickAccessButtons(), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), ], ), ), @@ -100,13 +94,8 @@ class QuickAccessButtons extends ConsumerWidget { return Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(10), - width: 1, - ), - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(10), width: 1), + borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( colors: [ context.colorScheme.primary.withAlpha(10), @@ -130,41 +119,26 @@ class QuickAccessButtons extends ConsumerWidget { bottomRight: Radius.circular(partners.isEmpty ? 20 : 0), ), ), - leading: const Icon( - Icons.folder_outlined, - size: 26, - ), + leading: const Icon(Icons.folder_outlined, size: 26), title: Text( IntlKeys.folders.tr(), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), onTap: () => context.pushRoute(FolderRoute()), ), ListTile( - leading: const Icon( - Icons.lock_outline_rounded, - size: 26, - ), + leading: const Icon(Icons.lock_outline_rounded, size: 26), title: Text( IntlKeys.locked_folder.tr(), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), onTap: () => context.pushRoute(const LockedRoute()), ), ListTile( - leading: const Icon( - Icons.group_outlined, - size: 26, - ), + leading: const Icon(Icons.group_outlined, size: 26), title: Text( IntlKeys.partners.tr(), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), onTap: () => context.pushRoute(const PartnerRoute()), ), @@ -196,24 +170,13 @@ class PartnerList extends ConsumerWidget { bottomRight: Radius.circular(isLastItem ? 20 : 0), ), ), - contentPadding: const EdgeInsets.only( - left: 12.0, - right: 18.0, - ), + contentPadding: const EdgeInsets.only(left: 12.0, right: 18.0), leading: userAvatar(context, partner, radius: 16), title: const Text( "partner_list_user_photos", - style: TextStyle( - fontWeight: FontWeight.w500, - ), - ).tr( - namedArgs: { - 'user': partner.name, - }, - ), - onTap: () => context.pushRoute( - (PartnerDetailRoute(partner: partner)), - ), + style: TextStyle(fontWeight: FontWeight.w500), + ).tr(namedArgs: {'user': partner.name}), + onTap: () => context.pushRoute((PartnerDetailRoute(partner: partner))), ); }, ); @@ -241,22 +204,15 @@ class PeopleCollectionCard extends ConsumerWidget { height: size, width: size, decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(30), - context.colorScheme.primary.withAlpha(25), - ], + colors: [context.colorScheme.primary.withAlpha(30), context.colorScheme.primary.withAlpha(25)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: people.widgetWhen( - onLoading: () => const Center( - child: CircularProgressIndicator(), - ), + onLoading: () => const Center(child: CircularProgressIndicator()), onData: (people) { return GridView.count( crossAxisCount: 2, @@ -308,9 +264,7 @@ class LocalAlbumsCollectionCard extends HookConsumerWidget { final size = context.width * widthFactor - 20.0; return GestureDetector( - onTap: () => context.pushRoute( - const LocalAlbumsRoute(), - ), + onTap: () => context.pushRoute(const LocalAlbumsRoute()), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -321,10 +275,7 @@ class LocalAlbumsCollectionCard extends HookConsumerWidget { decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(30), - context.colorScheme.primary.withAlpha(25), - ], + colors: [context.colorScheme.primary.withAlpha(30), context.colorScheme.primary.withAlpha(25)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), @@ -336,10 +287,7 @@ class LocalAlbumsCollectionCard extends HookConsumerWidget { mainAxisSpacing: 8, physics: const NeverScrollableScrollPhysics(), children: albums.take(4).map((album) { - return AlbumThumbnailCard( - album: album, - showTitle: false, - ); + return AlbumThumbnailCard(album: album, showTitle: false); }).toList(), ), ), @@ -373,11 +321,7 @@ class PlacesCollectionCard extends StatelessWidget { final size = context.width * widthFactor - 20.0; return GestureDetector( - onTap: () => context.pushRoute( - PlacesCollectionRoute( - currentLocation: null, - ), - ), + onTap: () => context.pushRoute(PlacesCollectionRoute(currentLocation: null)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -392,10 +336,7 @@ class PlacesCollectionCard extends StatelessWidget { child: IgnorePointer( child: MapThumbnail( zoom: 8, - centre: const LatLng( - 21.44950, - -157.91959, - ), + centre: const LatLng(21.44950, -157.91959), showAttribution: false, themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light, ), @@ -425,12 +366,7 @@ class ActionButton extends StatelessWidget { final IconData icon; final String label; - const ActionButton({ - super.key, - required this.onPressed, - required this.icon, - required this.label, - }); + const ActionButton({super.key, required this.onPressed, required this.icon, required this.label}); @override Widget build(BuildContext context) { @@ -439,13 +375,7 @@ class ActionButton extends StatelessWidget { onPressed: onPressed, label: Padding( padding: const EdgeInsets.only(left: 4.0), - child: Text( - label, - style: TextStyle( - color: context.colorScheme.onSurface, - fontSize: 15, - ), - ), + child: Text(label, style: TextStyle(color: context.colorScheme.onSurface, fontSize: 15)), ), style: FilledButton.styleFrom( elevation: 0, @@ -454,16 +384,10 @@ class ActionButton extends StatelessWidget { alignment: Alignment.centerLeft, shape: RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(25)), - side: BorderSide( - color: context.colorScheme.onSurface.withAlpha(10), - width: 1, - ), + side: BorderSide(color: context.colorScheme.onSurface.withAlpha(10), width: 1), ), ), - icon: Icon( - icon, - color: context.primaryColor, - ), + icon: Icon(icon, color: context.primaryColor), ), ); } diff --git a/mobile/lib/pages/library/local_albums.page.dart b/mobile/lib/pages/library/local_albums.page.dart index 5c6091c76..e52a8326d 100644 --- a/mobile/lib/pages/library/local_albums.page.dart +++ b/mobile/lib/pages/library/local_albums.page.dart @@ -18,9 +18,7 @@ class LocalAlbumsPage extends HookConsumerWidget { final albums = ref.watch(localAlbumsProvider); return Scaffold( - appBar: AppBar( - title: Text('on_this_device'.tr()), - ), + appBar: AppBar(title: Text('on_this_device'.tr())), body: ListView.builder( padding: const EdgeInsets.all(18.0), itemCount: albums.length, @@ -28,31 +26,18 @@ class LocalAlbumsPage extends HookConsumerWidget { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: LargeLeadingTile( - leadingPadding: const EdgeInsets.only( - right: 16, - ), + leadingPadding: const EdgeInsets.only(right: 16), leading: ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(15)), - child: ImmichThumbnail( - asset: albums[index].thumbnail.value, - width: 80, - height: 80, - ), + child: ImmichThumbnail(asset: albums[index].thumbnail.value, width: 80, height: 80), ), title: Text( albums[index].name, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), ), subtitle: Text( - 'items_count'.t( - context: context, - args: {'count': albums[index].assetCount}, - ), - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + 'items_count'.t(context: context, args: {'count': albums[index].assetCount}), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), onTap: () => context.pushRoute(AlbumViewerRoute(albumId: albums[index].id)), ), diff --git a/mobile/lib/pages/library/locked/locked.page.dart b/mobile/lib/pages/library/locked/locked.page.dart index eef12a710..aea62e005 100644 --- a/mobile/lib/pages/library/locked/locked.page.dart +++ b/mobile/lib/pages/library/locked/locked.page.dart @@ -19,29 +19,23 @@ class LockedPage extends HookConsumerWidget { final showOverlay = useState(false); final authProviderNotifier = ref.read(authProvider.notifier); // lock the page when it is destroyed - useEffect( - () { - return () { - authProviderNotifier.lockPinCode(); - }; - }, - [], - ); + useEffect(() { + return () { + authProviderNotifier.lockPinCode(); + }; + }, []); - useEffect( - () { - if (context.mounted) { - if (appLifeCycle == AppLifecycleState.resumed) { - showOverlay.value = false; - } else { - showOverlay.value = true; - } + useEffect(() { + if (context.mounted) { + if (appLifeCycle == AppLifecycleState.resumed) { + showOverlay.value = false; + } else { + showOverlay.value = true; } + } - return null; - }, - [appLifeCycle], - ); + return null; + }, [appLifeCycle]); return Scaffold( appBar: ref.watch(multiselectProvider) ? null : const LockPageAppBar(), @@ -51,12 +45,7 @@ class LockedPage extends HookConsumerWidget { renderListProvider: lockedTimelineProvider, topWidget: Padding( padding: const EdgeInsets.all(16.0), - child: Center( - child: Text( - 'no_locked_photos_message'.tr(), - style: context.textTheme.labelLarge, - ), - ), + child: Center(child: Text('no_locked_photos_message'.tr(), style: context.textTheme.labelLarge)), ), editEnabled: false, favoriteEnabled: false, @@ -84,9 +73,7 @@ class LockPageAppBar extends ConsumerWidget implements PreferredSizeWidget { ), centerTitle: true, automaticallyImplyLeading: false, - title: const Text( - 'locked_folder', - ).tr(), + title: const Text('locked_folder').tr(), ); } diff --git a/mobile/lib/pages/library/locked/pin_auth.page.dart b/mobile/lib/pages/library/locked/pin_auth.page.dart index abe224792..36befa001 100644 --- a/mobile/lib/pages/library/locked/pin_auth.page.dart +++ b/mobile/lib/pages/library/locked/pin_auth.page.dart @@ -23,18 +23,12 @@ class PinAuthPage extends HookConsumerWidget { final isBetaTimeline = Store.isBetaTimelineEnabled; Future registerBiometric(String pinCode) async { - final isRegistered = await ref.read(localAuthProvider.notifier).registerBiometric( - context, - pinCode, - ); + final isRegistered = await ref.read(localAuthProvider.notifier).registerBiometric(context, pinCode); if (isRegistered) { context.showSnackBar( SnackBar( - content: Text( - 'biometric_auth_enabled'.tr(), - style: context.textTheme.labelLarge, - ), + content: Text('biometric_auth_enabled'.tr(), style: context.textTheme.labelLarge), duration: const Duration(seconds: 3), backgroundColor: context.colorScheme.primaryContainer, ), @@ -79,20 +73,14 @@ class PinAuthPage extends HookConsumerWidget { } return Scaffold( - appBar: AppBar( - title: Text('locked_folder'.tr()), - ), + appBar: AppBar(title: Text('locked_folder'.tr())), body: ListView( shrinkWrap: true, children: [ Padding( padding: const EdgeInsets.only(top: 36.0), child: showPinRegistrationForm.value - ? Center( - child: PinRegistrationForm( - onDone: () => showPinRegistrationForm.value = false, - ), - ) + ? Center(child: PinRegistrationForm(onDone: () => showPinRegistrationForm.value = false)) : Column( children: [ Center( @@ -112,17 +100,11 @@ class PinAuthPage extends HookConsumerWidget { Padding( padding: const EdgeInsets.only(right: 16.0), child: TextButton.icon( - icon: const Icon( - Icons.fingerprint, - size: 28, - ), + icon: const Icon(Icons.fingerprint, size: 28), onPressed: enableBiometricAuth, label: Text( 'use_biometric'.tr(), - style: context.textTheme.labelLarge?.copyWith( - color: context.primaryColor, - fontSize: 18, - ), + style: context.textTheme.labelLarge?.copyWith(color: context.primaryColor, fontSize: 18), ), ), ), diff --git a/mobile/lib/pages/library/partner/drift_partner.page.dart b/mobile/lib/pages/library/partner/drift_partner.page.dart index d65f2bc09..171fe0ea0 100644 --- a/mobile/lib/pages/library/partner/drift_partner.page.dart +++ b/mobile/lib/pages/library/partner/drift_partner.page.dart @@ -22,10 +22,7 @@ class DriftPartnerPage extends HookConsumerWidget { addNewUsersHandler() async { final potentialPartners = potentialPartnersAsync.value; if (potentialPartners == null || potentialPartners.isEmpty) { - ImmichToast.show( - context: context, - msg: "partner_page_no_more_users".tr(), - ); + ImmichToast.show(context: context, msg: "partner_page_no_more_users".tr()); return; } @@ -77,18 +74,13 @@ class DriftPartnerPage extends HookConsumerWidget { centerTitle: false, actions: [ IconButton( - onPressed: potentialPartnersAsync.whenOrNull( - data: (data) => addNewUsersHandler, - ), + onPressed: potentialPartnersAsync.whenOrNull(data: (data) => addNewUsersHandler), icon: const Icon(Icons.person_add), tooltip: "add_partner".tr(), ), ], ), - body: _SharedToPartnerList( - onAddPartner: addNewUsersHandler, - onDeletePartner: onDeleteUser, - ), + body: _SharedToPartnerList(onAddPartner: addNewUsersHandler, onDeletePartner: onDeleteUser), ); } } @@ -97,10 +89,7 @@ class _SharedToPartnerList extends ConsumerWidget { final VoidCallback onAddPartner; final Function(PartnerUserDto partner) onDeletePartner; - const _SharedToPartnerList({ - required this.onAddPartner, - required this.onDeletePartner, - }); + const _SharedToPartnerList({required this.onAddPartner, required this.onDeletePartner}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -116,10 +105,7 @@ class _SharedToPartnerList extends ConsumerWidget { children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 8), - child: const Text( - "partner_page_empty_message", - style: TextStyle(fontSize: 14), - ).tr(), + child: const Text("partner_page_empty_message", style: TextStyle(fontSize: 14)).tr(), ), Align( alignment: Alignment.center, @@ -142,18 +128,13 @@ class _SharedToPartnerList extends ConsumerWidget { leading: PartnerUserAvatar(partner: partner), title: Text(partner.name), subtitle: Text(partner.email), - trailing: IconButton( - icon: const Icon(Icons.person_remove), - onPressed: () => onDeletePartner(partner), - ), + trailing: IconButton(icon: const Icon(Icons.person_remove), onPressed: () => onDeletePartner(partner)), ); }, ); }, loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stack) => Center( - child: Text("Error loading partners: $error"), - ), + error: (error, stack) => Center(child: Text("Error loading partners: $error")), ); } } diff --git a/mobile/lib/pages/library/partner/partner.page.dart b/mobile/lib/pages/library/partner/partner.page.dart index fb0dfe2ec..eae4228a2 100644 --- a/mobile/lib/pages/library/partner/partner.page.dart +++ b/mobile/lib/pages/library/partner/partner.page.dart @@ -22,10 +22,7 @@ class PartnerPage extends HookConsumerWidget { addNewUsersHandler() async { final users = availableUsers.value; if (users == null || users.isEmpty) { - ImmichToast.show( - context: context, - msg: "partner_page_no_more_users".tr(), - ); + ImmichToast.show(context: context, msg: "partner_page_no_more_users".tr()); return; } @@ -40,10 +37,7 @@ class PartnerPage extends HookConsumerWidget { onPressed: () => context.pop(u), child: Row( children: [ - Padding( - padding: const EdgeInsets.only(right: 8), - child: userAvatar(context, u), - ), + Padding(padding: const EdgeInsets.only(right: 8), child: userAvatar(context, u)), Text(u.name), ], ), @@ -57,11 +51,7 @@ class PartnerPage extends HookConsumerWidget { if (ok) { ref.invalidate(partnerSharedByProvider); } else { - ImmichToast.show( - context: context, - msg: "partner_page_partner_add_failed".tr(), - toastType: ToastType.error, - ); + ImmichToast.show(context: context, msg: "partner_page_partner_add_failed".tr(), toastType: ToastType.error); } } } @@ -87,9 +77,7 @@ class PartnerPage extends HookConsumerWidget { padding: const EdgeInsets.only(left: 16.0, top: 16.0), child: Text( "partner_page_shared_to_title", - style: context.textTheme.titleSmall?.copyWith( - color: context.colorScheme.onSurface.withAlpha(200), - ), + style: context.textTheme.titleSmall?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), ).tr(), ), if (users.isNotEmpty) @@ -99,10 +87,7 @@ class PartnerPage extends HookConsumerWidget { itemBuilder: ((context, index) { return ListTile( leading: userAvatar(context, users[index]), - title: Text( - users[index].email, - style: context.textTheme.bodyLarge, - ), + title: Text(users[index].email, style: context.textTheme.bodyLarge), trailing: IconButton( icon: const Icon(Icons.person_remove), onPressed: () => onDeleteUser(users[index]), @@ -118,17 +103,12 @@ class PartnerPage extends HookConsumerWidget { children: [ Padding( padding: const EdgeInsets.symmetric(vertical: 8), - child: const Text( - "partner_page_empty_message", - style: TextStyle(fontSize: 14), - ).tr(), + child: const Text("partner_page_empty_message", style: TextStyle(fontSize: 14)).tr(), ), Align( alignment: Alignment.center, child: ElevatedButton.icon( - onPressed: availableUsers.whenOrNull( - data: (data) => addNewUsersHandler, - ), + onPressed: availableUsers.whenOrNull(data: (data) => addNewUsersHandler), icon: const Icon(Icons.person_add), label: const Text("add_partner").tr(), ), diff --git a/mobile/lib/pages/library/partner/partner_detail.page.dart b/mobile/lib/pages/library/partner/partner_detail.page.dart index 78af3f093..1f15dab6a 100644 --- a/mobile/lib/pages/library/partner/partner_detail.page.dart +++ b/mobile/lib/pages/library/partner/partner_detail.page.dart @@ -22,24 +22,18 @@ class PartnerDetailPage extends HookConsumerWidget { final inTimeline = useState(partner.inTimeline); bool toggleInProcess = false; - useEffect( - () { - Future.microtask( - () async => { - await ref.read(assetProvider.notifier).getAllAsset(), - }, - ); - return null; - }, - [], - ); + useEffect(() { + Future.microtask(() async => {await ref.read(assetProvider.notifier).getAllAsset()}); + return null; + }, []); void toggleInTimeline() async { if (toggleInProcess) return; toggleInProcess = true; try { - final ok = - await ref.read(partnerSharedWithProvider.notifier).updatePartner(partner, inTimeline: !inTimeline.value); + final ok = await ref + .read(partnerSharedWithProvider.notifier) + .updatePartner(partner, inTimeline: !inTimeline.value); if (ok) { inTimeline.value = !inTimeline.value; final action = inTimeline.value ? "shown on" : "hidden from"; @@ -65,28 +59,16 @@ class PartnerDetailPage extends HookConsumerWidget { return Scaffold( appBar: ref.watch(multiselectProvider) ? null - : AppBar( - title: Text(partner.name), - elevation: 0, - centerTitle: false, - ), + : AppBar(title: Text(partner.name), elevation: 0, centerTitle: false), body: MultiselectGrid( topWidget: Padding( padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 16.0), child: Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(10), - width: 1, - ), - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(10), width: 1), + borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(10), - context.colorScheme.primary.withAlpha(15), - ], + colors: [context.colorScheme.primary.withAlpha(10), context.colorScheme.primary.withAlpha(15)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), @@ -96,18 +78,13 @@ class PartnerDetailPage extends HookConsumerWidget { child: ListTile( title: Text( "Show in timeline", - style: context.textTheme.titleSmall?.copyWith( - color: context.colorScheme.primary, - ), + style: context.textTheme.titleSmall?.copyWith(color: context.colorScheme.primary), ), subtitle: Text( "Show photos and videos from this user in your timeline", style: context.textTheme.bodyMedium, ), - trailing: Switch( - value: inTimeline.value, - onChanged: (_) => toggleInTimeline(), - ), + trailing: Switch(value: inTimeline.value, onChanged: (_) => toggleInTimeline()), ), ), ), diff --git a/mobile/lib/pages/library/people/people_collection.page.dart b/mobile/lib/pages/library/people/people_collection.page.dart index 837553ac4..375d4d2a9 100644 --- a/mobile/lib/pages/library/people/people_collection.page.dart +++ b/mobile/lib/pages/library/people/people_collection.page.dart @@ -21,10 +21,7 @@ class PeopleCollectionPage extends HookConsumerWidget { final formFocus = useFocusNode(); final ValueNotifier search = useState(null); - showNameEditModel( - String personId, - String personName, - ) { + showNameEditModel(String personId, String personName) { return showDialog( context: context, useRootNavigator: false, @@ -84,22 +81,14 @@ class PeopleCollectionPage extends HookConsumerWidget { children: [ GestureDetector( onTap: () { - context.pushRoute( - PersonResultRoute( - personId: person.id, - personName: person.name, - ), - ); + context.pushRoute(PersonResultRoute(personId: person.id, personName: person.name)); }, child: Material( shape: const CircleBorder(side: BorderSide.none), elevation: 3, child: CircleAvatar( maxRadius: isTablet ? 120 / 2 : 96 / 2, - backgroundImage: NetworkImage( - getFaceThumbnailUrl(person.id), - headers: headers, - ), + backgroundImage: NetworkImage(getFaceThumbnailUrl(person.id), headers: headers), ), ), ), @@ -115,15 +104,11 @@ class PeopleCollectionPage extends HookConsumerWidget { ), ) : Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, - ), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( person.name, overflow: TextOverflow.ellipsis, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), ), ), diff --git a/mobile/lib/pages/library/places/places_collection.page.dart b/mobile/lib/pages/library/places/places_collection.page.dart index 98bf372a9..73c38a109 100644 --- a/mobile/lib/pages/library/places/places_collection.page.dart +++ b/mobile/lib/pages/library/places/places_collection.page.dart @@ -61,11 +61,7 @@ class PlacesCollectionPage extends HookConsumerWidget { child: MapThumbnail( onTap: (_, __) => context.pushRoute(MapRoute(initialLocation: currentLocation)), zoom: 8, - centre: currentLocation ?? - const LatLng( - 21.44950, - -157.91959, - ), + centre: currentLocation ?? const LatLng(21.44950, -157.91959), showAttribution: false, themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light, ), @@ -113,16 +109,10 @@ class PlaceTile extends StatelessWidget { SearchRoute( prefilter: SearchFilter( people: {}, - location: SearchLocationFilter( - city: name, - ), + location: SearchLocationFilter(city: name), camera: SearchCameraFilter(), date: SearchDateFilter(), - display: SearchDisplayFilters( - isNotInAlbum: false, - isArchive: false, - isFavorite: false, - ), + display: SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), mediaType: AssetType.other, ), ), @@ -131,16 +121,9 @@ class PlaceTile extends StatelessWidget { return LargeLeadingTile( onTap: () => navigateToPlace(), - title: Text( - name, - style: context.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w500, - ), - ), + title: Text(name, style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500)), leading: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), child: CachedNetworkImage( width: 80, height: 80, diff --git a/mobile/lib/pages/library/shared_link/shared_link.page.dart b/mobile/lib/pages/library/shared_link/shared_link.page.dart index 94af8f913..66a77fb76 100644 --- a/mobile/lib/pages/library/shared_link/shared_link.page.dart +++ b/mobile/lib/pages/library/shared_link/shared_link.page.dart @@ -17,16 +17,13 @@ class SharedLinkPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final sharedLinks = ref.watch(sharedLinksStateProvider); - useEffect( - () { - ref.read(sharedLinksStateProvider.notifier).fetchLinks(); - return () { - if (!context.mounted) return; - ref.invalidate(sharedLinksStateProvider); - }; - }, - [], - ); + useEffect(() { + ref.read(sharedLinksStateProvider.notifier).fetchLinks(); + return () { + if (!context.mounted) return; + ref.invalidate(sharedLinksStateProvider); + }; + }, []); Widget buildNoShares() { return Column( @@ -36,30 +33,19 @@ class SharedLinkPage extends HookConsumerWidget { padding: const EdgeInsets.only(left: 16.0, top: 16.0), child: const Text( "shared_link_manage_links", - style: TextStyle( - fontSize: 14, - color: Colors.grey, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), ).tr(), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Padding( padding: const EdgeInsets.symmetric(vertical: 10), - child: const Text( - "you_dont_have_any_shared_links", - style: TextStyle(fontSize: 14), - ).tr(), + child: const Text("you_dont_have_any_shared_links", style: TextStyle(fontSize: 14)).tr(), ), ), Expanded( child: Center( - child: Icon( - Icons.link_off, - size: 100, - color: context.themeData.iconTheme.color?.withValues(alpha: 0.5), - ), + child: Icon(Icons.link_off, size: 100, color: context.themeData.iconTheme.color?.withValues(alpha: 0.5)), ), ), ], @@ -74,9 +60,7 @@ class SharedLinkPage extends HookConsumerWidget { padding: const EdgeInsets.only(left: 16.0, top: 16.0, bottom: 30.0), child: Text( "shared_link_manage_links", - style: context.textTheme.labelLarge?.copyWith( - color: context.textTheme.labelLarge?.color?.withAlpha(200), - ), + style: context.textTheme.labelLarge?.copyWith(color: context.textTheme.labelLarge?.color?.withAlpha(200)), ).tr(), ), Expanded( @@ -111,11 +95,7 @@ class SharedLinkPage extends HookConsumerWidget { } return Scaffold( - appBar: AppBar( - title: const Text("shared_link_app_bar_title").tr(), - elevation: 0, - centerTitle: false, - ), + appBar: AppBar(title: const Text("shared_link_app_bar_title").tr(), elevation: 0, centerTitle: false), body: SafeArea( child: sharedLinks.widgetWhen( onError: (error, stackTrace) => buildNoShares(), diff --git a/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart b/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart index c6db85a0f..dcd503335 100644 --- a/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart +++ b/mobile/lib/pages/library/shared_link/shared_link_edit.page.dart @@ -19,12 +19,7 @@ class SharedLinkEditPage extends HookConsumerWidget { final List? assetsList; final String? albumId; - const SharedLinkEditPage({ - super.key, - this.existingLink, - this.assetsList, - this.albumId, - }); + const SharedLinkEditPage({super.key, this.existingLink, this.assetsList, this.albumId}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -46,20 +41,11 @@ class SharedLinkEditPage extends HookConsumerWidget { if (existingLink!.type == SharedLinkSource.album) { return Row( children: [ - const Text( - 'public_album', - style: TextStyle(fontWeight: FontWeight.bold), - ).tr(), - const Text( - " | ", - style: TextStyle(fontWeight: FontWeight.bold), - ), + const Text('public_album', style: TextStyle(fontWeight: FontWeight.bold)).tr(), + const Text(" | ", style: TextStyle(fontWeight: FontWeight.bold)), Text( existingLink!.title, - style: TextStyle( - color: colorScheme.primary, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold), ), ], ); @@ -68,21 +54,12 @@ class SharedLinkEditPage extends HookConsumerWidget { if (existingLink!.type == SharedLinkSource.individual) { return Row( children: [ - const Text( - 'shared_link_individual_shared', - style: TextStyle(fontWeight: FontWeight.bold), - ).tr(), - const Text( - " | ", - style: TextStyle(fontWeight: FontWeight.bold), - ), + const Text('shared_link_individual_shared', style: TextStyle(fontWeight: FontWeight.bold)).tr(), + const Text(" | ", style: TextStyle(fontWeight: FontWeight.bold)), Expanded( child: Text( existingLink!.description ?? "--", - style: TextStyle( - color: colorScheme.primary, - fontWeight: FontWeight.bold, - ), + style: TextStyle(color: colorScheme.primary, fontWeight: FontWeight.bold), overflow: TextOverflow.ellipsis, ), ), @@ -91,10 +68,7 @@ class SharedLinkEditPage extends HookConsumerWidget { } } - return const Text( - "create_link_to_share_description", - style: TextStyle(fontWeight: FontWeight.bold), - ).tr(); + return const Text("create_link_to_share_description", style: TextStyle(fontWeight: FontWeight.bold)).tr(); } Widget buildDescriptionField() { @@ -106,20 +80,12 @@ class SharedLinkEditPage extends HookConsumerWidget { autofocus: false, decoration: InputDecoration( labelText: 'description'.tr(), - labelStyle: TextStyle( - fontWeight: FontWeight.bold, - color: colorScheme.primary, - ), + labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary), floatingLabelBehavior: FloatingLabelBehavior.always, border: const OutlineInputBorder(), hintText: 'shared_link_edit_description_hint'.tr(), - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 14, - ), - disabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5)), - ), + hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14), + disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))), ), onTapOutside: (_) => descriptionFocusNode.unfocus(), ); @@ -132,20 +98,12 @@ class SharedLinkEditPage extends HookConsumerWidget { autofocus: false, decoration: InputDecoration( labelText: 'password'.tr(), - labelStyle: TextStyle( - fontWeight: FontWeight.bold, - color: colorScheme.primary, - ), + labelStyle: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary), floatingLabelBehavior: FloatingLabelBehavior.always, border: const OutlineInputBorder(), hintText: 'shared_link_edit_password_hint'.tr(), - hintStyle: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 14, - ), - disabledBorder: OutlineInputBorder( - borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5)), - ), + hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14), + disabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey.withValues(alpha: 0.5))), ), ); } @@ -156,10 +114,7 @@ class SharedLinkEditPage extends HookConsumerWidget { onChanged: newShareLink.value.isEmpty ? (value) => showMetadata.value = value : null, activeColor: colorScheme.primary, dense: true, - title: Text( - "show_metadata", - style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold), - ).tr(), + title: Text("show_metadata", style: themeData.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold)).tr(), ); } @@ -206,10 +161,7 @@ class SharedLinkEditPage extends HookConsumerWidget { return DropdownMenu( label: Text( "expire_after", - style: TextStyle( - fontWeight: FontWeight.bold, - color: colorScheme.primary, - ), + style: TextStyle(fontWeight: FontWeight.bold, color: colorScheme.primary), ).tr(), enableSearch: false, enableFilter: false, @@ -220,26 +172,17 @@ class SharedLinkEditPage extends HookConsumerWidget { expiryAfter.value = value!; }, dropdownMenuEntries: [ - DropdownMenuEntry( - value: 0, - label: "never".tr(), - ), + DropdownMenuEntry(value: 0, label: "never".tr()), DropdownMenuEntry( value: 30, label: "shared_link_edit_expire_after_option_minutes".tr(namedArgs: {'count': "30"}), ), - DropdownMenuEntry( - value: 60, - label: "shared_link_edit_expire_after_option_hour".tr(), - ), + DropdownMenuEntry(value: 60, label: "shared_link_edit_expire_after_option_hour".tr()), DropdownMenuEntry( value: 60 * 6, label: "shared_link_edit_expire_after_option_hours".tr(namedArgs: {'count': "6"}), ), - DropdownMenuEntry( - value: 60 * 24, - label: "shared_link_edit_expire_after_option_day".tr(), - ), + DropdownMenuEntry(value: 60 * 24, label: "shared_link_edit_expire_after_option_day".tr()), DropdownMenuEntry( value: 60 * 24 * 7, label: "shared_link_edit_expire_after_option_days".tr(namedArgs: {'count': "7"}), @@ -266,9 +209,7 @@ class SharedLinkEditPage extends HookConsumerWidget { SnackBar( content: Text( "shared_link_clipboard_copied_massage", - style: context.textTheme.bodyLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ).tr(), duration: const Duration(seconds: 2), ), @@ -279,23 +220,14 @@ class SharedLinkEditPage extends HookConsumerWidget { Widget buildNewLinkField() { return Column( children: [ - const Padding( - padding: EdgeInsets.only( - top: 20, - bottom: 20, - ), - child: Divider(), - ), + const Padding(padding: EdgeInsets.only(top: 20, bottom: 20), child: Divider()), TextFormField( readOnly: true, initialValue: newShareLink.value, decoration: InputDecoration( border: const OutlineInputBorder(), enabledBorder: themeData.inputDecorationTheme.focusedBorder, - suffixIcon: IconButton( - onPressed: copyLinkToClipboard, - icon: const Icon(Icons.copy), - ), + suffixIcon: IconButton(onPressed: copyLinkToClipboard, icon: const Icon(Icons.copy)), ), ), Padding( @@ -306,13 +238,7 @@ class SharedLinkEditPage extends HookConsumerWidget { onPressed: () { context.maybePop(); }, - child: const Text( - "done", - style: TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ).tr(), + child: const Text("done", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(), ), ), ), @@ -325,7 +251,9 @@ class SharedLinkEditPage extends HookConsumerWidget { } Future handleNewLink() async { - final newLink = await ref.read(sharedLinkServiceProvider).createSharedLink( + final newLink = await ref + .read(sharedLinkServiceProvider) + .createSharedLink( albumId: albumId, assetIds: assetsList, showMeta: showMetadata.value, @@ -336,9 +264,7 @@ class SharedLinkEditPage extends HookConsumerWidget { expiresAt: expiryAfter.value == 0 ? null : calculateExpiry(), ); ref.invalidate(sharedLinksStateProvider); - final externalDomain = ref.read( - serverInfoProvider.select((s) => s.serverConfig.externalDomain), - ); + final externalDomain = ref.read(serverInfoProvider.select((s) => s.serverConfig.externalDomain)); var serverUrl = externalDomain.isNotEmpty ? externalDomain : getServerUrl(); if (serverUrl != null && !serverUrl.endsWith('/')) { serverUrl += '/'; @@ -390,7 +316,9 @@ class SharedLinkEditPage extends HookConsumerWidget { changeExpiry = true; } - await ref.read(sharedLinkServiceProvider).updateSharedLink( + await ref + .read(sharedLinkServiceProvider) + .updateSharedLink( existingLink!.id, showMeta: meta, allowDownload: download, @@ -406,9 +334,7 @@ class SharedLinkEditPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: Text( - existingLink == null ? "create_link_to_share" : "edit_link", - ).tr(), + title: Text(existingLink == null ? "create_link_to_share" : "edit_link").tr(), elevation: 0, leading: const CloseButton(), centerTitle: false, @@ -416,32 +342,15 @@ class SharedLinkEditPage extends HookConsumerWidget { body: SafeArea( child: ListView( children: [ + Padding(padding: const EdgeInsets.all(padding), child: buildLinkTitle()), + Padding(padding: const EdgeInsets.all(padding), child: buildDescriptionField()), + Padding(padding: const EdgeInsets.all(padding), child: buildPasswordField()), Padding( - padding: const EdgeInsets.all(padding), - child: buildLinkTitle(), - ), - Padding( - padding: const EdgeInsets.all(padding), - child: buildDescriptionField(), - ), - Padding( - padding: const EdgeInsets.all(padding), - child: buildPasswordField(), - ), - Padding( - padding: const EdgeInsets.only( - left: padding, - right: padding, - bottom: padding, - ), + padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding), child: buildShowMetaButton(), ), Padding( - padding: const EdgeInsets.only( - left: padding, - right: padding, - bottom: padding, - ), + padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding), child: buildAllowDownloadButton(), ), Padding( @@ -450,48 +359,30 @@ class SharedLinkEditPage extends HookConsumerWidget { ), if (existingLink != null) Padding( - padding: const EdgeInsets.only( - left: padding, - right: padding, - bottom: padding, - ), + padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding), child: buildEditExpiryButton(), ), Padding( - padding: const EdgeInsets.only( - left: padding, - right: padding, - bottom: padding, - ), + padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding), child: buildExpiryAfterButton(), ), if (newShareLink.value.isEmpty) Align( alignment: Alignment.bottomRight, child: Padding( - padding: const EdgeInsets.only( - right: padding + 10, - bottom: padding, - ), + padding: const EdgeInsets.only(right: padding + 10, bottom: padding), child: ElevatedButton( onPressed: existingLink != null ? handleEditLink : handleNewLink, child: Text( existingLink != null ? "shared_link_edit_submit_button" : "create_link", - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), ).tr(), ), ), ), if (newShareLink.value.isNotEmpty) Padding( - padding: const EdgeInsets.only( - left: padding, - right: padding, - bottom: padding, - ), + padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding), child: buildNewLinkField(), ), ], diff --git a/mobile/lib/pages/library/trash.page.dart b/mobile/lib/pages/library/trash.page.dart index 9ffe7ae70..2279998c2 100644 --- a/mobile/lib/pages/library/trash.page.dart +++ b/mobile/lib/pages/library/trash.page.dart @@ -29,10 +29,7 @@ class TrashPage extends HookConsumerWidget { final selection = useState({}); final processing = useProcessingOverlay(); - void selectionListener( - bool multiselect, - Set selectedAssets, - ) { + void selectionListener(bool multiselect, Set selectedAssets) { selectionEnabledHook.value = multiselect; selection.value = selectedAssets; } @@ -43,11 +40,7 @@ class TrashPage extends HookConsumerWidget { processing.value = false; selectionEnabledHook.value = false; if (context.mounted) { - ImmichToast.show( - context: context, - msg: 'trash_emptied'.tr(), - gravity: ToastGravity.BOTTOM, - ); + ImmichToast.show(context: context, msg: 'trash_emptied'.tr(), gravity: ToastGravity.BOTTOM); } } @@ -88,10 +81,7 @@ class TrashPage extends HookConsumerWidget { handlePermanentDelete() async { await showDialog( context: context, - builder: (context) => DeleteDialog( - alert: "delete_dialog_alert_remote", - onDelete: () => onPermanentlyDelete(), - ), + builder: (context) => DeleteDialog(alert: "delete_dialog_alert_remote", onDelete: () => onPermanentlyDelete()), ); } @@ -138,8 +128,9 @@ class TrashPage extends HookConsumerWidget { selectionEnabledHook.value = false; selection.value = {}; }, - icon: - !selectionEnabledHook.value ? const Icon(Icons.arrow_back_ios_rounded) : const Icon(Icons.close_rounded), + icon: !selectionEnabledHook.value + ? const Icon(Icons.arrow_back_ios_rounded) + : const Icon(Icons.close_rounded), ), centerTitle: !selectionEnabledHook.value, automaticallyImplyLeading: false, @@ -149,14 +140,8 @@ class TrashPage extends HookConsumerWidget { PopupMenuButton( itemBuilder: (context) { return [ - PopupMenuItem( - value: () => selectionEnabledHook.value = true, - child: const Text('select').tr(), - ), - PopupMenuItem( - value: handleEmptyTrash, - child: const Text('empty_trash').tr(), - ), + PopupMenuItem(value: () => selectionEnabledHook.value = true, child: const Text('select').tr()), + PopupMenuItem(value: handleEmptyTrash, child: const Text('empty_trash').tr()), ]; }, onSelected: (fn) => fn(), @@ -177,40 +162,28 @@ class TrashPage extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ TextButton.icon( - icon: Icon( - Icons.delete_forever, - color: Colors.red[400], - ), + icon: Icon(Icons.delete_forever, color: Colors.red[400]), label: Text( selection.value.isEmpty ? 'trash_page_delete_all'.tr() : 'delete'.tr(), - style: TextStyle( - fontSize: 14, - color: Colors.red[400], - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 14, color: Colors.red[400], fontWeight: FontWeight.bold), ), onPressed: processing.value ? null : selection.value.isEmpty - ? handleEmptyTrash - : handlePermanentDelete, + ? handleEmptyTrash + : handlePermanentDelete, ), TextButton.icon( - icon: const Icon( - Icons.history_rounded, - ), + icon: const Icon(Icons.history_rounded), label: Text( selection.value.isEmpty ? 'trash_page_restore_all'.tr() : 'restore'.tr(), - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold), ), onPressed: processing.value ? null : selection.value.isEmpty - ? handleRestoreAll - : handleRestore, + ? handleRestoreAll + : handleRestore, ), ], ), @@ -227,9 +200,7 @@ class TrashPage extends HookConsumerWidget { ), body: trashRenderList.widgetWhen( onData: (data) => data.isEmpty - ? Center( - child: Text('trash_page_no_assets'.tr()), - ) + ? Center(child: Text('trash_page_no_assets'.tr())) : Stack( children: [ SafeArea( @@ -240,13 +211,8 @@ class TrashPage extends HookConsumerWidget { showMultiSelectIndicator: false, showStack: true, topWidget: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 24, - ), - child: const Text( - "trash_page_info", - ).tr(namedArgs: {"days": "$trashDays"}), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 24), + child: const Text("trash_page_info").tr(namedArgs: {"days": "$trashDays"}), ), ), ), diff --git a/mobile/lib/pages/login/change_password.page.dart b/mobile/lib/pages/login/change_password.page.dart index b05397ee3..248526df1 100644 --- a/mobile/lib/pages/login/change_password.page.dart +++ b/mobile/lib/pages/login/change_password.page.dart @@ -9,8 +9,6 @@ class ChangePasswordPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - return const Scaffold( - body: ChangePasswordForm(), - ); + return const Scaffold(body: ChangePasswordForm()); } } diff --git a/mobile/lib/pages/login/login.page.dart b/mobile/lib/pages/login/login.page.dart index 8045ae649..e1d551900 100644 --- a/mobile/lib/pages/login/login.page.dart +++ b/mobile/lib/pages/login/login.page.dart @@ -21,12 +21,10 @@ class LoginPage extends HookConsumerWidget { appVersion.value = packageInfo.version; } - useEffect( - () { - getAppInfo(); - return null; - }, - ); + useEffect(() { + getAppInfo(); + return null; + }); return Scaffold( body: LoginForm(), diff --git a/mobile/lib/pages/onboarding/permission_onboarding.page.dart b/mobile/lib/pages/onboarding/permission_onboarding.page.dart index 023320858..52d4ac012 100644 --- a/mobile/lib/pages/onboarding/permission_onboarding.page.dart +++ b/mobile/lib/pages/onboarding/permission_onboarding.page.dart @@ -26,24 +26,18 @@ class PermissionOnboardingPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - 'permission_onboarding_request', - style: context.textTheme.titleMedium, - textAlign: TextAlign.center, - ).tr(), + Text('permission_onboarding_request', style: context.textTheme.titleMedium, textAlign: TextAlign.center).tr(), const SizedBox(height: 18), ElevatedButton( onPressed: () => ref.read(galleryPermissionNotifier.notifier).requestGalleryPermission().then((permission) async { - if (permission.isGranted) { - // If permission is limited, we will show the limited - // permission page - goToBackup(); - } - }), - child: const Text( - 'continue', - ).tr(), + if (permission.isGranted) { + // If permission is limited, we will show the limited + // permission page + goToBackup(); + } + }), + child: const Text('continue').tr(), ), ], ); @@ -62,10 +56,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { textAlign: TextAlign.center, ).tr(), const SizedBox(height: 18), - ElevatedButton( - onPressed: () => goToBackup(), - child: const Text('permission_onboarding_get_started').tr(), - ), + ElevatedButton(onPressed: () => goToBackup(), child: const Text('permission_onboarding_get_started').tr()), ], ); } @@ -78,11 +69,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon( - Icons.warning_outlined, - color: Colors.yellow, - size: 48, - ), + const Icon(Icons.warning_outlined, color: Colors.yellow, size: 48), const SizedBox(height: 8), Text( 'permission_onboarding_permission_limited', @@ -92,17 +79,10 @@ class PermissionOnboardingPage extends HookConsumerWidget { const SizedBox(height: 18), ElevatedButton( onPressed: () => openAppSettings(), - child: const Text( - 'permission_onboarding_go_to_settings', - ).tr(), + child: const Text('permission_onboarding_go_to_settings').tr(), ), const SizedBox(height: 8.0), - TextButton( - onPressed: () => goToBackup(), - child: const Text( - 'permission_onboarding_continue_anyway', - ).tr(), - ), + TextButton(onPressed: () => goToBackup(), child: const Text('permission_onboarding_continue_anyway').tr()), ], ); } @@ -112,11 +92,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const Icon( - Icons.warning_outlined, - color: Colors.red, - size: 48, - ), + const Icon(Icons.warning_outlined, color: Colors.red, size: 48), const SizedBox(height: 8), Text( 'permission_onboarding_permission_denied', @@ -126,9 +102,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { const SizedBox(height: 18), ElevatedButton( onPressed: () => openAppSettings(), - child: const Text( - 'permission_onboarding_go_to_settings', - ).tr(), + child: const Text('permission_onboarding_go_to_settings').tr(), ), ], ); @@ -138,7 +112,7 @@ class PermissionOnboardingPage extends HookConsumerWidget { PermissionStatus.limited => buildPermissionLimited(), PermissionStatus.denied => buildRequestPermission(), PermissionStatus.granted || PermissionStatus.provisional => buildPermissionGranted(), - PermissionStatus.restricted || PermissionStatus.permanentlyDenied => buildPermissionDenied() + PermissionStatus.restricted || PermissionStatus.permanentlyDenied => buildPermissionDenied(), }; return Scaffold( @@ -150,21 +124,13 @@ class PermissionOnboardingPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ - const ImmichLogo( - heroTag: 'logo', - ), + const ImmichLogo(heroTag: 'logo'), const ImmichTitleText(), AnimatedSwitcher( duration: const Duration(milliseconds: 500), - child: Padding( - padding: const EdgeInsets.all(18.0), - child: child, - ), - ), - TextButton( - child: const Text('back').tr(), - onPressed: () => context.maybePop(), + child: Padding(padding: const EdgeInsets.all(18.0), child: child), ), + TextButton(child: const Text('back').tr(), onPressed: () => context.maybePop()), ], ), ), diff --git a/mobile/lib/pages/photos/memory.page.dart b/mobile/lib/pages/photos/memory.page.dart index 4826e19f8..20bd32a17 100644 --- a/mobile/lib/pages/photos/memory.page.dart +++ b/mobile/lib/pages/photos/memory.page.dart @@ -16,26 +16,19 @@ import 'package:immich_mobile/widgets/memories/memory_epilogue.dart'; import 'package:immich_mobile/widgets/memories/memory_progress_indicator.dart'; @RoutePage() - /// Expects [currentAssetProvider] to be set before navigating to this page class MemoryPage extends HookConsumerWidget { final List memories; final int memoryIndex; - const MemoryPage({ - required this.memories, - required this.memoryIndex, - super.key, - }); + const MemoryPage({required this.memories, required this.memoryIndex, super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final currentMemory = useState(memories[memoryIndex]); final currentAssetPage = useState(0); final currentMemoryIndex = useState(memoryIndex); - final assetProgress = useState( - "${currentAssetPage.value + 1}|${currentMemory.value.assets.length}", - ); + final assetProgress = useState("${currentAssetPage.value + 1}|${currentMemory.value.assets.length}"); const bgColor = Colors.black; final currentAsset = useState(null); @@ -55,19 +48,13 @@ class MemoryPage extends HookConsumerWidget { }); toNextMemory() { - memoryPageController.nextPage( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - ); + memoryPageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn); } void toPreviousMemory() { if (currentMemoryIndex.value > 0) { // Move to the previous memory page - memoryPageController.previousPage( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - ); + memoryPageController.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn); // Wait for the next frame to ensure the page is built SchedulerBinding.instance.addPostFrameCallback((_) { @@ -94,10 +81,7 @@ class MemoryPage extends HookConsumerWidget { // Go to the next asset PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; - controller.nextPage( - curve: Curves.easeInOut, - duration: const Duration(milliseconds: 500), - ); + controller.nextPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500)); } else { // Go to the next memory since we are at the end of our assets toNextMemory(); @@ -109,10 +93,7 @@ class MemoryPage extends HookConsumerWidget { // Go to the previous asset PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; - controller.previousPage( - curve: Curves.easeInOut, - duration: const Duration(milliseconds: 500), - ); + controller.previousPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500)); } else { // Go to the previous memory since we are at the end of our assets toPreviousMemory(); @@ -161,11 +142,7 @@ class MemoryPage extends HookConsumerWidget { // Precache the asset final size = MediaQuery.sizeOf(context); await precacheImage( - ImmichImage.imageProvider( - asset: asset, - width: size.width, - height: size.height, - ), + ImmichImage.imageProvider(asset: asset, width: size.width, height: size.height), context, size: size, ); @@ -219,9 +196,7 @@ class MemoryPage extends HookConsumerWidget { backgroundColor: bgColor, body: SafeArea( child: PageView.builder( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), + physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), scrollDirection: Axis.vertical, controller: memoryPageController, onPageChanged: (pageNumber) { @@ -252,12 +227,7 @@ class MemoryPage extends HookConsumerWidget { return Column( children: [ Padding( - padding: const EdgeInsets.only( - left: 24.0, - right: 24.0, - top: 8.0, - bottom: 2.0, - ), + padding: const EdgeInsets.only(left: 24.0, right: 24.0, top: 8.0, bottom: 2.0), child: AnimatedBuilder( animation: assetController, builder: (context, child) { @@ -277,9 +247,7 @@ class MemoryPage extends HookConsumerWidget { child: Stack( children: [ PageView.builder( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), + physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), controller: assetController, onPageChanged: onAssetChanged, scrollDirection: Axis.horizontal, @@ -290,11 +258,7 @@ class MemoryPage extends HookConsumerWidget { children: [ Container( color: Colors.black, - child: MemoryCard( - asset: asset, - title: memories[mIndex].title, - showTitle: index == 0, - ), + child: MemoryCard(asset: asset, title: memories[mIndex].title, showTitle: index == 0), ), Positioned.fill( child: Row( @@ -335,27 +299,19 @@ class MemoryPage extends HookConsumerWidget { // turn off full screen mode here // https://github.com/Milad-Akarie/auto_route_library/issues/1799 context.maybePop(); - SystemChrome.setEnabledSystemUIMode( - SystemUiMode.edgeToEdge, - ); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); }, shape: const CircleBorder(), color: Colors.white.withValues(alpha: 0.2), elevation: 0, - child: const Icon( - Icons.close_rounded, - color: Colors.white, - ), + child: const Icon(Icons.close_rounded, color: Colors.white), ), ), if (currentAsset.value != null && currentAsset.value!.isVideo) Positioned( bottom: 24, right: 32, - child: Icon( - Icons.videocam_outlined, - color: Colors.grey[200], - ), + child: Icon(Icons.videocam_outlined, color: Colors.grey[200]), ), ], ), diff --git a/mobile/lib/pages/photos/photos.page.dart b/mobile/lib/pages/photos/photos.page.dart index 2cc3c44e3..957c32b22 100644 --- a/mobile/lib/pages/photos/photos.page.dart +++ b/mobile/lib/pages/photos/photos.page.dart @@ -29,17 +29,14 @@ class PhotosPage extends HookConsumerWidget { final tipOneOpacity = useState(0.0); final refreshCount = useState(0); - useEffect( - () { - ref.read(websocketProvider.notifier).connect(); - Future(() => ref.read(assetProvider.notifier).getAllAsset()); - Future(() => ref.read(albumProvider.notifier).refreshRemoteAlbums()); - ref.read(serverInfoProvider.notifier).getServerInfo(); + useEffect(() { + ref.read(websocketProvider.notifier).connect(); + Future(() => ref.read(assetProvider.notifier).getAllAsset()); + Future(() => ref.read(albumProvider.notifier).refreshRemoteAlbums()); + ref.read(serverInfoProvider.notifier).getServerInfo(); - return; - }, - [], - ); + return; + }, []); Widget buildLoadingIndicator() { Timer(const Duration(seconds: 2), () => tipOneOpacity.value = 1); @@ -53,9 +50,7 @@ class PhotosPage extends HookConsumerWidget { padding: const EdgeInsets.only(top: 16.0), child: Text( 'home_page_building_timeline', - style: context.textTheme.titleMedium?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor), ).tr(), ), const SizedBox(height: 8), diff --git a/mobile/lib/pages/search/all_motion_videos.page.dart b/mobile/lib/pages/search/all_motion_videos.page.dart index 5d1081db3..60bb8a6cf 100644 --- a/mobile/lib/pages/search/all_motion_videos.page.dart +++ b/mobile/lib/pages/search/all_motion_videos.page.dart @@ -17,16 +17,9 @@ class AllMotionPhotosPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( title: const Text('search_page_motion_photos').tr(), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), - ), - body: motionPhotos.widgetWhen( - onData: (assets) => ImmichAssetGrid( - assets: assets, - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), ), + body: motionPhotos.widgetWhen(onData: (assets) => ImmichAssetGrid(assets: assets)), ); } } diff --git a/mobile/lib/pages/search/all_people.page.dart b/mobile/lib/pages/search/all_people.page.dart index 6fcf07fbf..b2814e6c1 100644 --- a/mobile/lib/pages/search/all_people.page.dart +++ b/mobile/lib/pages/search/all_people.page.dart @@ -17,13 +17,8 @@ class AllPeoplePage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: const Text( - 'people', - ).tr(), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), + title: const Text('people').tr(), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), ), body: curatedPeople.widgetWhen( onData: (people) => ExploreGrid( diff --git a/mobile/lib/pages/search/all_places.page.dart b/mobile/lib/pages/search/all_places.page.dart index 63908a5e2..c92f87d3a 100644 --- a/mobile/lib/pages/search/all_places.page.dart +++ b/mobile/lib/pages/search/all_places.page.dart @@ -17,19 +17,10 @@ class AllPlacesPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: const Text( - 'places', - ).tr(), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), - ), - body: places.widgetWhen( - onData: (data) => ExploreGrid( - curatedContent: data, - ), + title: const Text('places').tr(), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), ), + body: places.widgetWhen(onData: (data) => ExploreGrid(curatedContent: data)), ); } } diff --git a/mobile/lib/pages/search/all_videos.page.dart b/mobile/lib/pages/search/all_videos.page.dart index 6d123d9d7..acad043a5 100644 --- a/mobile/lib/pages/search/all_videos.page.dart +++ b/mobile/lib/pages/search/all_videos.page.dart @@ -14,10 +14,7 @@ class AllVideosPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( title: const Text('videos').tr(), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), ), body: MultiselectGrid(renderListProvider: allVideosTimelineProvider), ); diff --git a/mobile/lib/pages/search/map/map.page.dart b/mobile/lib/pages/search/map/map.page.dart index 62df4a50a..34522f0f0 100644 --- a/mobile/lib/pages/search/map/map.page.dart +++ b/mobile/lib/pages/search/map/map.page.dart @@ -62,17 +62,11 @@ class MapPage extends HookConsumerWidget { final bounds = await mapController.value!.getVisibleRegion(); final inBounds = markers.value - .where( - (m) => bounds.contains(LatLng(m.latLng.latitude, m.latLng.longitude)), - ) + .where((m) => bounds.contains(LatLng(m.latLng.latitude, m.latLng.longitude))) .toList(); // Notify bottom sheet to update asset grid only when there are new assets if (markersInBounds.value.length != inBounds.length) { - bottomSheetStreamController.add( - MapAssetsInBoundsUpdated( - inBounds.map((e) => e.assetRemoteId).toList(), - ), - ); + bottomSheetStreamController.add(MapAssetsInBoundsUpdated(inBounds.map((e) => e.assetRemoteId).toList())); } markersInBounds.value = inBounds; } @@ -80,9 +74,7 @@ class MapPage extends HookConsumerWidget { // removes all sources and layers and re-adds them with the updated markers Future reloadLayers() async { if (mapController.value != null) { - layerDebouncer.run( - () => mapController.value!.reloadAllLayersForMarkers(markers.value), - ); + layerDebouncer.run(() => mapController.value!.reloadAllLayersForMarkers(markers.value)); } } @@ -97,15 +89,12 @@ class MapPage extends HookConsumerWidget { } } - useEffect( - () { - final currentAssetLink = ref.read(currentAssetProvider.notifier).ref.keepAlive(); + useEffect(() { + final currentAssetLink = ref.read(currentAssetProvider.notifier).ref.keepAlive(); - loadMarkers(); - return currentAssetLink.close; - }, - [], - ); + loadMarkers(); + return currentAssetLink.close; + }, []); // Refetch markers when map state is changed ref.listen(mapStateNotifierProvider, (_, current) { @@ -121,16 +110,9 @@ class MapPage extends HookConsumerWidget { }); // updates the selected markers position based on the current map camera - Future updateAssetMarkerPosition( - MapMarker marker, { - bool shouldAnimate = true, - }) async { + Future updateAssetMarkerPosition(MapMarker marker, {bool shouldAnimate = true}) async { final assetPoint = await mapController.value!.toScreenLocation(marker.latLng); - selectedMarker.value = _AssetMarkerMeta( - point: assetPoint, - marker: marker, - shouldAnimate: shouldAnimate, - ); + selectedMarker.value = _AssetMarkerMeta(point: assetPoint, marker: marker, shouldAnimate: shouldAnimate); (assetPoint, marker, shouldAnimate); } @@ -160,10 +142,7 @@ class MapPage extends HookConsumerWidget { mapController.value = controller; controller.addListener(() { if (controller.isCameraMoving && selectedMarker.value != null) { - updateAssetMarkerPosition( - selectedMarker.value!.marker, - shouldAnimate: false, - ); + updateAssetMarkerPosition(selectedMarker.value!.marker, shouldAnimate: false); } }); } @@ -180,22 +159,13 @@ class MapPage extends HookConsumerWidget { } // Since we only have a single asset, we can just show GroupAssetBy.none - final renderList = await RenderList.fromAssets( - [asset], - GroupAssetsBy.none, - ); + final renderList = await RenderList.fromAssets([asset], GroupAssetsBy.none); ref.read(currentAssetProvider.notifier).set(asset); if (asset.isVideo) { ref.read(showControlsProvider.notifier).show = false; } - context.pushRoute( - GalleryViewerRoute( - initialIndex: 0, - heroOffset: 0, - renderList: renderList, - ), - ); + context.pushRoute(GalleryViewerRoute(initialIndex: 0, heroOffset: 0, renderList: renderList)); } /// BOTTOM SHEET CALLBACKS @@ -216,10 +186,7 @@ class MapPage extends HookConsumerWidget { if (mapController.value != null && assetMarker != null) { // Offset the latitude a little to show the marker just above the viewports center final offset = context.isMobile ? 0.02 : 0; - final latlng = LatLng( - assetMarker.latLng.latitude - offset, - assetMarker.latLng.longitude, - ); + final latlng = LatLng(assetMarker.latLng.latitude - offset, assetMarker.latLng.longitude); mapController.value!.animateCamera( CameraUpdate.newLatLngZoom(latlng, mapZoomToAssetLevel), duration: const Duration(milliseconds: 800), @@ -243,10 +210,7 @@ class MapPage extends HookConsumerWidget { if (mapController.value != null && location != null) { mapController.value!.animateCamera( - CameraUpdate.newLatLngZoom( - LatLng(location.latitude, location.longitude), - mapZoomToAssetLevel, - ), + CameraUpdate.newLatLngZoom(LatLng(location.latitude, location.longitude), mapZoomToAssetLevel), duration: const Duration(milliseconds: 800), ); } @@ -311,9 +275,7 @@ class MapPage extends HookConsumerWidget { bottom: context.padding.bottom + 16, child: ElevatedButton( onPressed: onZoomToLocation, - style: ElevatedButton.styleFrom( - shape: const CircleBorder(), - ), + style: ElevatedButton.styleFrom(shape: const CircleBorder()), child: const Icon(Icons.my_location), ), ), @@ -344,11 +306,7 @@ class _AssetMarkerMeta { final MapMarker marker; final bool shouldAnimate; - const _AssetMarkerMeta({ - required this.point, - required this.marker, - required this.shouldAnimate, - }); + const _AssetMarkerMeta({required this.point, required this.marker, required this.shouldAnimate}); @override String toString() => '_AssetMarkerMeta(point: $point, marker: $marker, shouldAnimate: $shouldAnimate)'; diff --git a/mobile/lib/pages/search/map/map_location_picker.page.dart b/mobile/lib/pages/search/map/map_location_picker.page.dart index 9b7bbd0cd..0fe8b769f 100644 --- a/mobile/lib/pages/search/map/map_location_picker.page.dart +++ b/mobile/lib/pages/search/map/map_location_picker.page.dart @@ -16,10 +16,7 @@ import 'package:immich_mobile/utils/map_utils.dart'; class MapLocationPickerPage extends HookConsumerWidget { final LatLng initialLatLng; - const MapLocationPickerPage({ - super.key, - this.initialLatLng = const LatLng(0, 0), - }); + const MapLocationPickerPage({super.key, this.initialLatLng = const LatLng(0, 0)}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -66,10 +63,7 @@ class MapLocationPickerPage extends HookConsumerWidget { onData: (style) => Container( clipBehavior: Clip.antiAliasWithSaveLayer, decoration: const BoxDecoration( - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(40), - bottomRight: Radius.circular(40), - ), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(40), bottomRight: Radius.circular(40)), ), child: MapLibreMap( initialCameraPosition: CameraPosition(target: initialLatLng, zoom: 12), @@ -108,9 +102,7 @@ class _AppBar extends StatelessWidget implements PreferredSizeWidget { alignment: Alignment.centerLeft, child: ElevatedButton( onPressed: onClose, - style: ElevatedButton.styleFrom( - shape: const CircleBorder(), - ), + style: ElevatedButton.styleFrom(shape: const CircleBorder()), child: const Icon(Icons.arrow_back_ios_new_rounded), ), ), @@ -126,11 +118,7 @@ class _BottomBar extends StatelessWidget { final Function() onUseLocation; final Function() onGetCurrentLocation; - const _BottomBar({ - required this.selectedLatLng, - required this.onUseLocation, - required this.onGetCurrentLocation, - }); + const _BottomBar({required this.selectedLatLng, required this.onUseLocation, required this.onGetCurrentLocation}); @override Widget build(BuildContext context) { @@ -149,9 +137,8 @@ class _BottomBar extends StatelessWidget { const SizedBox(width: 15), ValueListenableBuilder( valueListenable: selectedLatLng, - builder: (_, value, __) => Text( - "${value.latitude.toStringAsFixed(4)}, ${value.longitude.toStringAsFixed(4)}", - ), + builder: (_, value, __) => + Text("${value.latitude.toStringAsFixed(4)}, ${value.longitude.toStringAsFixed(4)}"), ), ], ), @@ -162,10 +149,7 @@ class _BottomBar extends StatelessWidget { onPressed: onUseLocation, child: const Text("map_location_picker_page_use_location").tr(), ), - ElevatedButton( - onPressed: onGetCurrentLocation, - child: const Icon(Icons.my_location), - ), + ElevatedButton(onPressed: onGetCurrentLocation, child: const Icon(Icons.my_location)), ], ), ], diff --git a/mobile/lib/pages/search/person_result.page.dart b/mobile/lib/pages/search/person_result.page.dart index 859c7e8a8..7d2e612d2 100644 --- a/mobile/lib/pages/search/person_result.page.dart +++ b/mobile/lib/pages/search/person_result.page.dart @@ -15,11 +15,7 @@ class PersonResultPage extends HookConsumerWidget { final String personId; final String personName; - const PersonResultPage({ - super.key, - required this.personId, - required this.personName, - }); + const PersonResultPage({super.key, required this.personId, required this.personName}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -30,10 +26,7 @@ class PersonResultPage extends HookConsumerWidget { context: context, useRootNavigator: false, builder: (BuildContext context) { - return PersonNameEditForm( - personId: personId, - personName: name.value, - ); + return PersonNameEditForm(personId: personId, personName: name.value); }, ).then((result) { if (result != null && result.success) { @@ -55,10 +48,7 @@ class PersonResultPage extends HookConsumerWidget { children: [ ListTile( leading: const Icon(Icons.edit_outlined), - title: const Text( - 'edit_name', - style: TextStyle(fontWeight: FontWeight.bold), - ).tr(), + title: const Text('edit_name', style: TextStyle(fontWeight: FontWeight.bold)).tr(), onTap: showEditNameDialog, ), ], @@ -75,27 +65,13 @@ class PersonResultPage extends HookConsumerWidget { ? Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - 'add_a_name', - style: context.textTheme.titleMedium?.copyWith( - color: context.primaryColor, - ), - ).tr(), - Text( - 'find_them_fast', - style: context.textTheme.labelLarge, - ).tr(), + Text('add_a_name', style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor)).tr(), + Text('find_them_fast', style: context.textTheme.labelLarge).tr(), ], ) : Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - name.value, - style: context.textTheme.titleLarge, - overflow: TextOverflow.ellipsis, - ), - ], + children: [Text(name.value, style: context.textTheme.titleLarge, overflow: TextOverflow.ellipsis)], ), ); } @@ -103,16 +79,8 @@ class PersonResultPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( title: Text(name.value), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), - actions: [ - IconButton( - onPressed: buildBottomSheet, - icon: const Icon(Icons.more_vert_rounded), - ), - ], + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), + actions: [IconButton(onPressed: buildBottomSheet, icon: const Icon(Icons.more_vert_rounded))], ), body: MultiselectGrid( renderListProvider: personAssetsProvider(personId), @@ -122,16 +90,10 @@ class PersonResultPage extends HookConsumerWidget { children: [ CircleAvatar( radius: 36, - backgroundImage: NetworkImage( - getFaceThumbnailUrl(personId), - headers: ApiService.getRequestHeaders(), - ), + backgroundImage: NetworkImage(getFaceThumbnailUrl(personId), headers: ApiService.getRequestHeaders()), ), Expanded( - child: Padding( - padding: const EdgeInsets.only(left: 16.0, right: 16.0), - child: buildTitleBlock(), - ), + child: Padding(padding: const EdgeInsets.only(left: 16.0, right: 16.0), child: buildTitleBlock()), ), ], ), diff --git a/mobile/lib/pages/search/recently_taken.page.dart b/mobile/lib/pages/search/recently_taken.page.dart index cc1eb7086..988af2faf 100644 --- a/mobile/lib/pages/search/recently_taken.page.dart +++ b/mobile/lib/pages/search/recently_taken.page.dart @@ -17,16 +17,9 @@ class RecentlyTakenPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( title: const Text('recently_taken_page_title').tr(), - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.arrow_back_ios_rounded), - ), - ), - body: recents.widgetWhen( - onData: (searchResponse) => ImmichAssetGrid( - assets: searchResponse, - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.arrow_back_ios_rounded)), ), + body: recents.widgetWhen(onData: (searchResponse) => ImmichAssetGrid(assets: searchResponse)), ); } } diff --git a/mobile/lib/pages/search/search.page.dart b/mobile/lib/pages/search/search.page.dart index d9a20e8b4..97205e000 100644 --- a/mobile/lib/pages/search/search.page.dart +++ b/mobile/lib/pages/search/search.page.dart @@ -41,12 +41,7 @@ class SearchPage extends HookConsumerWidget { location: prefilter?.location ?? SearchLocationFilter(), camera: prefilter?.camera ?? SearchCameraFilter(), date: prefilter?.date ?? SearchDateFilter(), - display: prefilter?.display ?? - SearchDisplayFilters( - isNotInAlbum: false, - isArchive: false, - isFavorite: false, - ), + display: prefilter?.display ?? SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), mediaType: prefilter?.mediaType ?? AssetType.other, language: "${context.locale.languageCode}-${context.locale.countryCode}", ), @@ -65,10 +60,7 @@ class SearchPage extends HookConsumerWidget { SnackBar searchInfoSnackBar(String message) { return SnackBar( - content: Text( - message, - style: context.textTheme.labelLarge, - ), + content: Text(message, style: context.textTheme.labelLarge), showCloseIcon: true, behavior: SnackBarBehavior.fixed, closeIconColor: context.colorScheme.onSurface, @@ -89,9 +81,7 @@ class SearchPage extends HookConsumerWidget { final hasResult = await ref.watch(paginatedSearchProvider.notifier).search(filter.value); if (!hasResult) { - context.showSnackBar( - searchInfoSnackBar('search_no_result'.tr()), - ); + context.showSnackBar(searchInfoSnackBar('search_no_result'.tr())); } previousFilter.value = filter.value; @@ -103,9 +93,7 @@ class SearchPage extends HookConsumerWidget { final hasResult = await ref.watch(paginatedSearchProvider.notifier).search(filter.value); if (!hasResult) { - context.showSnackBar( - searchInfoSnackBar('search_no_more_result'.tr()), - ); + context.showSnackBar(searchInfoSnackBar('search_no_more_result'.tr())); } isSearching.value = false; @@ -113,39 +101,26 @@ class SearchPage extends HookConsumerWidget { searchPrefilter() { if (prefilter != null) { - Future.delayed( - Duration.zero, - () { - search(); + Future.delayed(Duration.zero, () { + search(); - if (prefilter!.location.city != null) { - locationCurrentFilterWidget.value = Text( - prefilter!.location.city!, - style: context.textTheme.labelLarge, - ); - } - }, - ); + if (prefilter!.location.city != null) { + locationCurrentFilterWidget.value = Text(prefilter!.location.city!, style: context.textTheme.labelLarge); + } + }); } } - useEffect( - () { - Future.microtask( - () => ref.invalidate(paginatedSearchProvider), - ); - searchPrefilter(); + useEffect(() { + Future.microtask(() => ref.invalidate(paginatedSearchProvider)); + searchPrefilter(); - return null; - }, - [], - ); + return null; + }, []); showPeoplePicker() { handleOnSelect(Set value) { - filter.value = filter.value.copyWith( - people: value, - ); + filter.value = filter.value.copyWith(people: value); peopleCurrentFilterWidget.value = Text( value.map((e) => e.name != '' ? e.name : 'no_name'.tr()).join(', '), @@ -154,9 +129,7 @@ class SearchPage extends HookConsumerWidget { } handleClear() { - filter.value = filter.value.copyWith( - people: {}, - ); + filter.value = filter.value.copyWith(people: {}); peopleCurrentFilterWidget.value = null; search(); @@ -172,10 +145,7 @@ class SearchPage extends HookConsumerWidget { expanded: true, onSearch: search, onClear: handleClear, - child: PeoplePicker( - onSelect: handleOnSelect, - filter: filter.value.people, - ), + child: PeoplePicker(onSelect: handleOnSelect, filter: filter.value.people), ), ), ); @@ -184,11 +154,7 @@ class SearchPage extends HookConsumerWidget { showLocationPicker() { handleOnSelect(Map value) { filter.value = filter.value.copyWith( - location: SearchLocationFilter( - country: value['country'], - city: value['city'], - state: value['state'], - ), + location: SearchLocationFilter(country: value['country'], city: value['city'], state: value['state']), ); final locationText = []; @@ -204,16 +170,11 @@ class SearchPage extends HookConsumerWidget { locationText.add(value['city']!); } - locationCurrentFilterWidget.value = Text( - locationText.join(', '), - style: context.textTheme.labelLarge, - ); + locationCurrentFilterWidget.value = Text(locationText.join(', '), style: context.textTheme.labelLarge); } handleClear() { - filter.value = filter.value.copyWith( - location: SearchLocationFilter(), - ); + filter.value = filter.value.copyWith(location: SearchLocationFilter()); locationCurrentFilterWidget.value = null; search(); @@ -230,15 +191,10 @@ class SearchPage extends HookConsumerWidget { child: Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: Container( - padding: EdgeInsets.only( - bottom: context.viewInsets.bottom, - ), + padding: EdgeInsets.only(bottom: context.viewInsets.bottom), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: LocationPicker( - onSelected: handleOnSelect, - filter: filter.value.location, - ), + child: LocationPicker(onSelected: handleOnSelect, filter: filter.value.location), ), ), ), @@ -249,10 +205,7 @@ class SearchPage extends HookConsumerWidget { showCameraPicker() { handleOnSelect(Map value) { filter.value = filter.value.copyWith( - camera: SearchCameraFilter( - make: value['make'], - model: value['model'], - ), + camera: SearchCameraFilter(make: value['make'], model: value['model']), ); cameraCurrentFilterWidget.value = Text( @@ -262,9 +215,7 @@ class SearchPage extends HookConsumerWidget { } handleClear() { - filter.value = filter.value.copyWith( - camera: SearchCameraFilter(), - ); + filter.value = filter.value.copyWith(camera: SearchCameraFilter()); cameraCurrentFilterWidget.value = null; search(); @@ -280,10 +231,7 @@ class SearchPage extends HookConsumerWidget { onClear: handleClear, child: Padding( padding: const EdgeInsets.all(16.0), - child: CameraPicker( - onSelect: handleOnSelect, - filter: filter.value.camera, - ), + child: CameraPicker(onSelect: handleOnSelect, filter: filter.value.camera), ), ), ); @@ -315,9 +263,7 @@ class SearchPage extends HookConsumerWidget { ); if (date == null) { - filter.value = filter.value.copyWith( - date: SearchDateFilter(), - ); + filter.value = filter.value.copyWith(date: SearchDateFilter()); dateRangeCurrentFilterWidget.value = null; search(); @@ -327,13 +273,7 @@ class SearchPage extends HookConsumerWidget { filter.value = filter.value.copyWith( date: SearchDateFilter( takenAfter: date.start, - takenBefore: date.end.add( - const Duration( - hours: 23, - minutes: 59, - seconds: 59, - ), - ), + takenBefore: date.end.add(const Duration(hours: 23, minutes: 59, seconds: 59)), ), ); @@ -361,24 +301,20 @@ class SearchPage extends HookConsumerWidget { // MEDIA PICKER showMediaTypePicker() { handleOnSelected(AssetType assetType) { - filter.value = filter.value.copyWith( - mediaType: assetType, - ); + filter.value = filter.value.copyWith(mediaType: assetType); mediaTypeCurrentFilterWidget.value = Text( assetType == AssetType.image ? 'image'.tr() : assetType == AssetType.video - ? 'video'.tr() - : 'all'.tr(), + ? 'video'.tr() + : 'all'.tr(), style: context.textTheme.labelLarge, ); } handleClear() { - filter.value = filter.value.copyWith( - mediaType: AssetType.other, - ); + filter.value = filter.value.copyWith(mediaType: AssetType.other); mediaTypeCurrentFilterWidget.value = null; search(); @@ -390,10 +326,7 @@ class SearchPage extends HookConsumerWidget { title: 'search_filter_media_type_title'.tr(), onSearch: search, onClear: handleClear, - child: MediaTypePicker( - onSelect: handleOnSelected, - filter: filter.value.mediaType, - ), + child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType), ), ); } @@ -405,31 +338,19 @@ class SearchPage extends HookConsumerWidget { value.forEach((key, value) { switch (key) { case DisplayOption.notInAlbum: - filter.value = filter.value.copyWith( - display: filter.value.display.copyWith( - isNotInAlbum: value, - ), - ); + filter.value = filter.value.copyWith(display: filter.value.display.copyWith(isNotInAlbum: value)); if (value) { filterText.add('search_filter_display_option_not_in_album'.tr()); } break; case DisplayOption.archive: - filter.value = filter.value.copyWith( - display: filter.value.display.copyWith( - isArchive: value, - ), - ); + filter.value = filter.value.copyWith(display: filter.value.display.copyWith(isArchive: value)); if (value) { filterText.add('archive'.tr()); } break; case DisplayOption.favorite: - filter.value = filter.value.copyWith( - display: filter.value.display.copyWith( - isFavorite: value, - ), - ); + filter.value = filter.value.copyWith(display: filter.value.display.copyWith(isFavorite: value)); if (value) { filterText.add('favorite'.tr()); } @@ -442,19 +363,12 @@ class SearchPage extends HookConsumerWidget { return; } - displayOptionCurrentFilterWidget.value = Text( - filterText.join(', '), - style: context.textTheme.labelLarge, - ); + displayOptionCurrentFilterWidget.value = Text(filterText.join(', '), style: context.textTheme.labelLarge); } handleClear() { filter.value = filter.value.copyWith( - display: SearchDisplayFilters( - isNotInAlbum: false, - isArchive: false, - isFavorite: false, - ), + display: SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), ); displayOptionCurrentFilterWidget.value = null; @@ -467,10 +381,7 @@ class SearchPage extends HookConsumerWidget { title: 'display_options'.tr(), onSearch: search, onClear: handleClear, - child: DisplayOptionPicker( - onSelect: handleOnSelect, - filter: filter.value.display, - ), + child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display), ), ); } @@ -478,27 +389,15 @@ class SearchPage extends HookConsumerWidget { handleTextSubmitted(String value) { switch (textSearchType.value) { case TextSearchType.context: - filter.value = filter.value.copyWith( - filename: '', - context: value, - description: '', - ); + filter.value = filter.value.copyWith(filename: '', context: value, description: ''); break; case TextSearchType.filename: - filter.value = filter.value.copyWith( - filename: value, - context: '', - description: '', - ); + filter.value = filter.value.copyWith(filename: value, context: '', description: ''); break; case TextSearchType.description: - filter.value = filter.value.copyWith( - filename: '', - context: '', - description: value, - ); + filter.value = filter.value.copyWith(filename: '', context: '', description: value); break; } @@ -506,10 +405,10 @@ class SearchPage extends HookConsumerWidget { } IconData getSearchPrefixIcon() => switch (textSearchType.value) { - TextSearchType.context => Icons.image_search_rounded, - TextSearchType.filename => Icons.abc_rounded, - TextSearchType.description => Icons.text_snippet_outlined, - }; + TextSearchType.context => Icons.image_search_rounded, + TextSearchType.filename => Icons.abc_rounded, + TextSearchType.description => Icons.text_snippet_outlined, + }; return Scaffold( resizeToAvoidBottomInset: false, @@ -522,21 +421,11 @@ class SearchPage extends HookConsumerWidget { style: MenuStyle( elevation: const WidgetStatePropertyAll(1), shape: WidgetStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ), - ), - padding: const WidgetStatePropertyAll( - EdgeInsets.all(4), + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), ), + padding: const WidgetStatePropertyAll(EdgeInsets.all(4)), ), - builder: ( - BuildContext context, - MenuController controller, - Widget? child, - ) { + builder: (BuildContext context, MenuController controller, Widget? child) { return IconButton( onPressed: () { if (controller.isOpen) { @@ -610,13 +499,8 @@ class SearchPage extends HookConsumerWidget { ], title: Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(0), - width: 0, - ), - borderRadius: const BorderRadius.all( - Radius.circular(24), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(0), width: 0), + borderRadius: const BorderRadius.all(Radius.circular(24)), gradient: LinearGradient( colors: [ context.colorScheme.primary.withValues(alpha: 0.075), @@ -632,12 +516,7 @@ class SearchPage extends HookConsumerWidget { key: const Key('search_text_field'), controller: textSearchController, contentPadding: prefilter != null ? const EdgeInsets.only(left: 24) : const EdgeInsets.all(8), - prefixIcon: prefilter != null - ? null - : Icon( - getSearchPrefixIcon(), - color: context.colorScheme.primary, - ), + prefixIcon: prefilter != null ? null : Icon(getSearchPrefixIcon(), color: context.colorScheme.primary), onSubmitted: handleTextSubmitted, focusNode: ref.watch(searchInputFocusProvider), ), @@ -697,14 +576,9 @@ class SearchPage extends HookConsumerWidget { ), ), if (isSearching.value) - const Expanded( - child: Center(child: CircularProgressIndicator()), - ) + const Expanded(child: Center(child: CircularProgressIndicator())) else - SearchResultGrid( - onScrollEnd: loadMoreSearchResult, - isSearching: isSearching.value, - ), + SearchResultGrid(onScrollEnd: loadMoreSearchResult, isSearching: isSearching.value), ], ), ); @@ -715,11 +589,7 @@ class SearchResultGrid extends StatelessWidget { final VoidCallback onScrollEnd; final bool isSearching; - const SearchResultGrid({ - super.key, - required this.onScrollEnd, - this.isSearching = false, - }); + const SearchResultGrid({super.key, required this.onScrollEnd, this.isSearching = false}); @override Widget build(BuildContext context) { @@ -777,12 +647,7 @@ class SearchEmptyContent extends StatelessWidget { ), ), const SizedBox(height: 16), - Center( - child: Text( - 'search_page_search_photos_videos'.tr(), - style: context.textTheme.labelLarge, - ), - ), + Center(child: Text('search_page_search_photos_videos'.tr(), style: context.textTheme.labelLarge)), const SizedBox(height: 32), const QuickLinkList(), ], @@ -798,13 +663,8 @@ class QuickLinkList extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - border: Border.all( - color: context.colorScheme.outline.withAlpha(10), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), + border: Border.all(color: context.colorScheme.outline.withAlpha(10), width: 1), gradient: LinearGradient( colors: [ context.colorScheme.primary.withAlpha(10), @@ -868,19 +728,9 @@ class QuickLink extends StatelessWidget { ); return ListTile( - shape: RoundedRectangleBorder( - borderRadius: borderRadius, - ), - leading: Icon( - icon, - size: 26, - ), - title: Text( - title, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), - ), + shape: RoundedRectangleBorder(borderRadius: borderRadius), + leading: Icon(icon, size: 26), + title: Text(title, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500)), onTap: onTap, ); } diff --git a/mobile/lib/pages/settings/beta_sync_settings.page.dart b/mobile/lib/pages/settings/beta_sync_settings.page.dart index ba23ccf5e..992557b7c 100644 --- a/mobile/lib/pages/settings/beta_sync_settings.page.dart +++ b/mobile/lib/pages/settings/beta_sync_settings.page.dart @@ -5,9 +5,7 @@ import 'package:immich_mobile/widgets/settings/beta_sync_settings/beta_sync_sett @RoutePage() class BetaSyncSettingsPage extends StatelessWidget { - const BetaSyncSettingsPage({ - super.key, - }); + const BetaSyncSettingsPage({super.key}); @override Widget build(BuildContext context) { @@ -18,9 +16,7 @@ class BetaSyncSettingsPage extends StatelessWidget { leading: IconButton( onPressed: () => context.maybePop(true), splashRadius: 24, - icon: const Icon( - Icons.arrow_back_ios_rounded, - ), + icon: const Icon(Icons.arrow_back_ios_rounded), ), ), body: const BetaSyncSettings(), diff --git a/mobile/lib/pages/share_intent/share_intent.page.dart b/mobile/lib/pages/share_intent/share_intent.page.dart index 2b328b7ed..9d2dbe80c 100644 --- a/mobile/lib/pages/share_intent/share_intent.page.dart +++ b/mobile/lib/pages/share_intent/share_intent.page.dart @@ -60,22 +60,16 @@ class ShareIntentPage extends HookConsumerWidget { appBar: AppBar( title: Column( children: [ - const Text('upload_to_immich').tr( - namedArgs: {'count': candidates.length.toString()}, - ), + const Text('upload_to_immich').tr(namedArgs: {'count': candidates.length.toString()}), Text( currentEndpoint, - style: context.textTheme.labelMedium?.copyWith( - color: context.colorScheme.onSurface.withAlpha(200), - ), + style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)), ), ], ), leading: IconButton( onPressed: () { - context.navigateTo( - Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute(), - ); + context.navigateTo(Store.isBetaTimelineEnabled ? const TabShellRoute() : const TabControllerRoute()); }, icon: const Icon(Icons.arrow_back), ), @@ -84,16 +78,10 @@ class ShareIntentPage extends HookConsumerWidget { itemCount: attachments.length, itemBuilder: (context, index) { final attachment = attachments[index]; - final target = candidates.firstWhere( - (element) => element.id == attachment.id, - orElse: () => attachment, - ); + final target = candidates.firstWhere((element) => element.id == attachment.id, orElse: () => attachment); return Padding( - padding: const EdgeInsets.symmetric( - vertical: 4.0, - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(vertical: 4.0, horizontal: 16), child: LargeLeadingTile( onTap: () => toggleSelection(attachment), disabled: isUploaded.value, @@ -103,21 +91,11 @@ class ShareIntentPage extends HookConsumerWidget { ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(16)), child: attachment.isImage - ? Image.file( - attachment.file, - width: 64, - height: 64, - fit: BoxFit.cover, - ) + ? Image.file(attachment.file, width: 64, height: 64, fit: BoxFit.cover) : const SizedBox( width: 64, height: 64, - child: Center( - child: Icon( - Icons.videocam, - color: Colors.white, - ), - ), + child: Center(child: Icon(Icons.videocam, color: Colors.white)), ), ), if (attachment.isImage) @@ -128,25 +106,13 @@ class ShareIntentPage extends HookConsumerWidget { Icons.image, color: Colors.white, size: 20, - shadows: [ - Shadow( - offset: Offset(0, 0), - blurRadius: 8.0, - color: Colors.black45, - ), - ], + shadows: [Shadow(offset: Offset(0, 0), blurRadius: 8.0, color: Colors.black45)], ), ), ], ), - title: Text( - attachment.fileName, - style: context.textTheme.titleSmall, - ), - subtitle: Text( - attachment.fileSize, - style: context.textTheme.labelLarge, - ), + title: Text(attachment.fileName, style: context.textTheme.titleSmall), + subtitle: Text(attachment.fileSize, style: context.textTheme.labelLarge), trailing: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), child: UploadStatusIcon( @@ -185,22 +151,14 @@ class UploadingText extends StatelessWidget { return element.status == UploadStatus.complete; }).length; - return const Text("shared_intent_upload_button_progress_text").tr( - namedArgs: { - 'current': uploadedCount.toString(), - 'total': candidates.length.toString(), - }, - ); + return const Text( + "shared_intent_upload_button_progress_text", + ).tr(namedArgs: {'current': uploadedCount.toString(), 'total': candidates.length.toString()}); } } class UploadStatusIcon extends StatelessWidget { - const UploadStatusIcon({ - super.key, - required this.status, - required this.selected, - this.progress = 0, - }); + const UploadStatusIcon({super.key, required this.status, required this.selected, this.progress = 0}); final UploadStatus status; final double progress; @@ -218,55 +176,42 @@ class UploadStatusIcon extends StatelessWidget { final statusIcon = switch (status) { UploadStatus.enqueued => Icon( - Icons.check_circle_rounded, - color: context.primaryColor, - semanticLabel: 'enqueued'.tr(), - ), + Icons.check_circle_rounded, + color: context.primaryColor, + semanticLabel: 'enqueued'.tr(), + ), UploadStatus.running => Stack( - alignment: AlignmentDirectional.center, - children: [ - SizedBox( - width: 40, - height: 40, - child: TweenAnimationBuilder( - tween: Tween(begin: 0.0, end: progress), - duration: const Duration(milliseconds: 500), - builder: (context, value, _) => CircularProgressIndicator( - backgroundColor: context.colorScheme.surfaceContainerLow, - strokeWidth: 3, - value: value, - semanticsLabel: 'uploading'.tr(), - ), + alignment: AlignmentDirectional.center, + children: [ + SizedBox( + width: 40, + height: 40, + child: TweenAnimationBuilder( + tween: Tween(begin: 0.0, end: progress), + duration: const Duration(milliseconds: 500), + builder: (context, value, _) => CircularProgressIndicator( + backgroundColor: context.colorScheme.surfaceContainerLow, + strokeWidth: 3, + value: value, + semanticsLabel: 'uploading'.tr(), ), ), - Text( - (progress * 100).toStringAsFixed(0), - style: context.textTheme.labelSmall?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ], - ), - UploadStatus.complete => Icon( - Icons.check_circle_rounded, - color: Colors.green, - semanticLabel: 'completed'.tr(), - ), - UploadStatus.notFound || UploadStatus.failed => Icon( - Icons.error_rounded, - color: Colors.red, - semanticLabel: 'failed'.tr(), - ), - UploadStatus.canceled => Icon( - Icons.cancel_rounded, - color: Colors.red, - semanticLabel: 'canceled'.tr(), - ), + ), + Text( + (progress * 100).toStringAsFixed(0), + style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.bold), + ), + ], + ), + UploadStatus.complete => Icon(Icons.check_circle_rounded, color: Colors.green, semanticLabel: 'completed'.tr()), + UploadStatus.notFound || + UploadStatus.failed => Icon(Icons.error_rounded, color: Colors.red, semanticLabel: 'failed'.tr()), + UploadStatus.canceled => Icon(Icons.cancel_rounded, color: Colors.red, semanticLabel: 'canceled'.tr()), UploadStatus.waitingToRetry || UploadStatus.paused => Icon( - Icons.pause_circle_rounded, - color: context.primaryColor, - semanticLabel: 'paused'.tr(), - ), + Icons.pause_circle_rounded, + color: context.primaryColor, + semanticLabel: 'paused'.tr(), + ), }; return statusIcon; diff --git a/mobile/lib/platform/native_sync_api.g.dart b/mobile/lib/platform/native_sync_api.g.dart index b4d1d91b69a1bbf919318af9edae383dc80cdefe..67a320a96dfd608c9726fa3c36bfd9b32584d188 100644 GIT binary patch delta 307 zcmbQ##@OG=xIvYLn@a%>Caba-O%7#==hA@-Zr;N3hA}uZMMohoF*j95p`@|^NG2Dh zCYGe8IF{%rloq7GnB|!%B^f#j8L64+895vnpZN}fZcQRWS*x?lWX}U^%ROy3rjPL zQd1O4GBS(xAX&6=*8} delta 386 zcmeBgWt`N;xIvX=vH^?H>( - DriftAssetSelectionTimelineRoute( - lockedSelectionAssets: assets.toSet(), - ), + DriftAssetSelectionTimelineRoute(lockedSelectionAssets: assets.toSet()), ); - DLog.log( - "Selected ${selectedAssets?.length ?? 0} assets", - ); + DLog.log("Selected ${selectedAssets?.length ?? 0} assets"); return Future.value(); }, ), - _Feature( - name: '', - icon: Icons.vertical_align_center_sharp, - onTap: (_, __) => Future.value(), - ), + _Feature(name: '', icon: Icons.vertical_align_center_sharp, onTap: (_, __) => Future.value()), _Feature( name: 'Sync Local', icon: Icons.photo_album_rounded, @@ -76,11 +68,7 @@ final _features = [ icon: Icons.save_rounded, onTap: (_, ref) => ref.read(driftProvider).customStatement("pragma wal_checkpoint(truncate)"), ), - _Feature( - name: '', - icon: Icons.vertical_align_center_sharp, - onTap: (_, __) => Future.value(), - ), + _Feature(name: '', icon: Icons.vertical_align_center_sharp, onTap: (_, __) => Future.value()), _Feature( name: 'Clear Delta Checkpoint', icon: Icons.delete_rounded, @@ -88,10 +76,7 @@ final _features = [ ), _Feature( name: 'Clear Local Data', - style: const TextStyle( - color: Colors.orange, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: Colors.orange, fontWeight: FontWeight.bold), icon: Icons.delete_forever_rounded, onTap: (_, ref) async { final db = ref.read(driftProvider); @@ -102,10 +87,7 @@ final _features = [ ), _Feature( name: 'Clear Remote Data', - style: const TextStyle( - color: Colors.orange, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: Colors.orange, fontWeight: FontWeight.bold), icon: Icons.delete_sweep_rounded, onTap: (_, ref) async { final db = ref.read(driftProvider); @@ -123,29 +105,20 @@ final _features = [ ), _Feature( name: 'Local Media Summary', - style: const TextStyle( - color: Colors.indigo, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: Colors.indigo, fontWeight: FontWeight.bold), icon: Icons.table_chart_rounded, onTap: (ctx, _) => ctx.pushRoute(const LocalMediaSummaryRoute()), ), _Feature( name: 'Remote Media Summary', - style: const TextStyle( - color: Colors.indigo, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: Colors.indigo, fontWeight: FontWeight.bold), icon: Icons.summarize_rounded, onTap: (ctx, _) => ctx.pushRoute(const RemoteMediaSummaryRoute()), ), _Feature( name: 'Reset Sqlite', icon: Icons.table_view_rounded, - style: const TextStyle( - color: Colors.red, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(color: Colors.red, fontWeight: FontWeight.bold), onTap: (_, ref) async { final drift = ref.read(driftProvider); // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member @@ -165,10 +138,7 @@ class FeatInDevPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Features in Development'), - centerTitle: true, - ), + appBar: AppBar(title: const Text('Features in Development'), centerTitle: true), body: Column( children: [ Flexible( @@ -178,10 +148,7 @@ class FeatInDevPage extends StatelessWidget { final feat = _features[index]; return Consumer( builder: (ctx, ref, _) => ListTile( - title: Text( - feat.name, - style: feat.style, - ), + title: Text(feat.name, style: feat.style), trailing: Icon(feat.icon), visualDensity: VisualDensity.compact, onTap: () => unawaited(feat.onTap(ctx, ref)), @@ -200,12 +167,7 @@ class FeatInDevPage extends StatelessWidget { } class _Feature { - const _Feature({ - required this.name, - required this.icon, - required this.onTap, - this.style, - }); + const _Feature({required this.name, required this.icon, required this.onTap, this.style}); final String name; final IconData icon; @@ -244,18 +206,11 @@ class _DevLogs extends StatelessWidget { return ListTile( title: Text( logMessage.message, - style: TextStyle( - color: ctx.colorScheme.onSurface, - fontSize: 14.0, - overflow: TextOverflow.ellipsis, - ), + style: TextStyle(color: ctx.colorScheme.onSurface, fontSize: 14.0, overflow: TextOverflow.ellipsis), ), subtitle: Text( "at ${DateFormat("HH:mm:ss.SSS").format(logMessage.createdAt)}", - style: TextStyle( - color: ctx.colorScheme.onSurfaceSecondary, - fontSize: 12.0, - ), + style: TextStyle(color: ctx.colorScheme.onSurfaceSecondary, fontSize: 12.0), ), dense: true, visualDensity: VisualDensity.compact, diff --git a/mobile/lib/presentation/pages/dev/media_stat.page.dart b/mobile/lib/presentation/pages/dev/media_stat.page.dart index 70e93fd21..b48d8fc30 100644 --- a/mobile/lib/presentation/pages/dev/media_stat.page.dart +++ b/mobile/lib/presentation/pages/dev/media_stat.page.dart @@ -21,12 +21,7 @@ class _Summary extends StatelessWidget { final Future countFuture; final void Function()? onTap; - const _Summary({ - required this.name, - required this.countFuture, - this.leading, - this.onTap, - }); + const _Summary({required this.name, required this.countFuture, this.leading, this.onTap}); @override Widget build(BuildContext context) { @@ -40,31 +35,17 @@ class _Summary extends StatelessWidget { } else if (snapshot.hasError) { subtitle = const Icon(Icons.error_rounded); } else { - subtitle = Text( - '${snapshot.data ?? 0}', - style: ctx.textTheme.bodyLarge, - ); + subtitle = Text('${snapshot.data ?? 0}', style: ctx.textTheme.bodyLarge); } - return ListTile( - leading: leading, - title: Text(name), - trailing: subtitle, - onTap: onTap, - ); + return ListTile(leading: leading, title: Text(name), trailing: subtitle, onTap: onTap); }, ); } } final _localStats = [ - _Stat( - name: 'Local Assets', - load: (db) => db.managers.localAssetEntity.count(), - ), - _Stat( - name: 'Local Albums', - load: (db) => db.managers.localAlbumEntity.count(), - ), + _Stat(name: 'Local Assets', load: (db) => db.managers.localAssetEntity.count()), + _Stat(name: 'Local Albums', load: (db) => db.managers.localAlbumEntity.count()), ]; @RoutePage() @@ -97,10 +78,7 @@ class LocalMediaSummaryPage extends StatelessWidget { const Divider(), Padding( padding: const EdgeInsets.only(left: 15), - child: Text( - "Album summary", - style: ctx.textTheme.titleMedium, - ), + child: Text("Album summary", style: ctx.textTheme.titleMedium), ), ], ), @@ -117,15 +95,14 @@ class LocalMediaSummaryPage extends StatelessWidget { return SliverList.builder( itemBuilder: (_, index) { final album = albums[index]; - final countFuture = - db.managers.localAlbumAssetEntity.filter((f) => f.albumId.id.equals(album.id)).count(); + final countFuture = db.managers.localAlbumAssetEntity + .filter((f) => f.albumId.id.equals(album.id)) + .count(); return _Summary( leading: const Icon(Icons.photo_album_rounded), name: album.name, countFuture: countFuture, - onTap: () => context.router.push( - LocalTimelineRoute(album: album), - ), + onTap: () => context.router.push(LocalTimelineRoute(album: album)), ); }, itemCount: albums.length, @@ -141,38 +118,14 @@ class LocalMediaSummaryPage extends StatelessWidget { } final _remoteStats = [ - _Stat( - name: 'Remote Assets', - load: (db) => db.managers.remoteAssetEntity.count(), - ), - _Stat( - name: 'Exif Entities', - load: (db) => db.managers.remoteExifEntity.count(), - ), - _Stat( - name: 'Remote Albums', - load: (db) => db.managers.remoteAlbumEntity.count(), - ), - _Stat( - name: 'Memories', - load: (db) => db.managers.memoryEntity.count(), - ), - _Stat( - name: 'Memories Assets', - load: (db) => db.managers.memoryAssetEntity.count(), - ), - _Stat( - name: 'Stacks', - load: (db) => db.managers.stackEntity.count(), - ), - _Stat( - name: 'People', - load: (db) => db.managers.personEntity.count(), - ), - _Stat( - name: 'AssetFaces', - load: (db) => db.managers.assetFaceEntity.count(), - ), + _Stat(name: 'Remote Assets', load: (db) => db.managers.remoteAssetEntity.count()), + _Stat(name: 'Exif Entities', load: (db) => db.managers.remoteExifEntity.count()), + _Stat(name: 'Remote Albums', load: (db) => db.managers.remoteAlbumEntity.count()), + _Stat(name: 'Memories', load: (db) => db.managers.memoryEntity.count()), + _Stat(name: 'Memories Assets', load: (db) => db.managers.memoryAssetEntity.count()), + _Stat(name: 'Stacks', load: (db) => db.managers.stackEntity.count()), + _Stat(name: 'People', load: (db) => db.managers.personEntity.count()), + _Stat(name: 'AssetFaces', load: (db) => db.managers.assetFaceEntity.count()), ]; @RoutePage() @@ -205,10 +158,7 @@ class RemoteMediaSummaryPage extends StatelessWidget { const Divider(), Padding( padding: const EdgeInsets.only(left: 15), - child: Text( - "Album summary", - style: ctx.textTheme.titleMedium, - ), + child: Text("Album summary", style: ctx.textTheme.titleMedium), ), ], ), @@ -225,15 +175,14 @@ class RemoteMediaSummaryPage extends StatelessWidget { return SliverList.builder( itemBuilder: (_, index) { final album = albums[index]; - final countFuture = - db.managers.remoteAlbumAssetEntity.filter((f) => f.albumId.id.equals(album.id)).count(); + final countFuture = db.managers.remoteAlbumAssetEntity + .filter((f) => f.albumId.id.equals(album.id)) + .count(); return _Summary( leading: const Icon(Icons.photo_album_rounded), name: album.name, countFuture: countFuture, - onTap: () => context.router.push( - RemoteAlbumRoute(album: album), - ), + onTap: () => context.router.push(RemoteAlbumRoute(album: album)), ); }, itemCount: albums.length, diff --git a/mobile/lib/presentation/pages/drift_album.page.dart b/mobile/lib/presentation/pages/drift_album.page.dart index e22c63ac2..0835c741a 100644 --- a/mobile/lib/presentation/pages/drift_album.page.dart +++ b/mobile/lib/presentation/pages/drift_album.page.dart @@ -35,13 +35,8 @@ class _DriftAlbumsPageState extends ConsumerState { pinned: true, actions: [ IconButton( - icon: const Icon( - Icons.add_rounded, - size: 28, - ), - onPressed: () => context.pushRoute( - const DriftCreateAlbumRoute(), - ), + icon: const Icon(Icons.add_rounded, size: 28), + onPressed: () => context.pushRoute(const DriftCreateAlbumRoute()), ), ], showUploadButton: false, @@ -49,9 +44,7 @@ class _DriftAlbumsPageState extends ConsumerState { AlbumSelector( onAlbumSelected: (album) { ref.read(currentRemoteAlbumProvider.notifier).setAlbum(album); - context.router.push( - RemoteAlbumRoute(album: album), - ); + context.router.push(RemoteAlbumRoute(album: album)); }, ), ], diff --git a/mobile/lib/presentation/pages/drift_archive.page.dart b/mobile/lib/presentation/pages/drift_archive.page.dart index 8a6f1607d..ee8417bca 100644 --- a/mobile/lib/presentation/pages/drift_archive.page.dart +++ b/mobile/lib/presentation/pages/drift_archive.page.dart @@ -16,18 +16,16 @@ class DriftArchivePage extends StatelessWidget { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception('User must be logged in to access archive'); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access archive'); + } - final timelineService = ref.watch(timelineFactoryProvider).archive(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).archive(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( appBar: MesmerizingSliverAppBar( diff --git a/mobile/lib/presentation/pages/drift_asset_selection_timeline.page.dart b/mobile/lib/presentation/pages/drift_asset_selection_timeline.page.dart index 0e5631082..19f813cdb 100644 --- a/mobile/lib/presentation/pages/drift_asset_selection_timeline.page.dart +++ b/mobile/lib/presentation/pages/drift_asset_selection_timeline.page.dart @@ -10,10 +10,7 @@ import 'package:immich_mobile/providers/user.provider.dart'; @RoutePage() class DriftAssetSelectionTimelinePage extends ConsumerWidget { final Set lockedSelectionAssets; - const DriftAssetSelectionTimelinePage({ - super.key, - this.lockedSelectionAssets = const {}, - }); + const DriftAssetSelectionTimelinePage({super.key, this.lockedSelectionAssets = const {}}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -21,27 +18,19 @@ class DriftAssetSelectionTimelinePage extends ConsumerWidget { overrides: [ multiSelectProvider.overrideWith( () => MultiSelectNotifier( - MultiSelectState( - selectedAssets: {}, - lockedSelectionAssets: lockedSelectionAssets, - forceEnable: true, - ), + MultiSelectState(selectedAssets: {}, lockedSelectionAssets: lockedSelectionAssets, forceEnable: true), ), ), - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception( - 'User must be logged in to access asset selection timeline', - ); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access asset selection timeline'); + } - final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: const Timeline(), ); diff --git a/mobile/lib/presentation/pages/drift_create_album.page.dart b/mobile/lib/presentation/pages/drift_create_album.page.dart index ba7157b15..bac23b45c 100644 --- a/mobile/lib/presentation/pages/drift_create_album.page.dart +++ b/mobile/lib/presentation/pages/drift_create_album.page.dart @@ -70,12 +70,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { Widget _buildContent() { if (selectedAssets.isEmpty) { - return SliverList( - delegate: SliverChildListDelegate([ - _buildEmptyState(), - _buildSelectPhotosButton(), - ]), - ); + return SliverList(delegate: SliverChildListDelegate([_buildEmptyState(), _buildSelectPhotosButton()])); } else { return _buildSelectedImageGrid(); } @@ -84,10 +79,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { Widget _buildEmptyState() { return Padding( padding: const EdgeInsets.only(top: 0, left: 18), - child: Text( - 'create_shared_album_page_share_add_assets', - style: context.textTheme.labelLarge, - ).t(), + child: Text('create_shared_album_page_share_add_assets', style: context.textTheme.labelLarge).t(), ); } @@ -97,27 +89,17 @@ class _DriftCreateAlbumPageState extends ConsumerState { child: FilledButton.icon( style: FilledButton.styleFrom( alignment: Alignment.centerLeft, - padding: const EdgeInsets.symmetric( - vertical: 24.0, - horizontal: 16.0, - ), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(10.0)), - ), + padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10.0))), backgroundColor: context.colorScheme.surfaceContainerHigh, ), onPressed: onSelectPhotos, icon: Icon(Icons.add_rounded, color: context.primaryColor), label: Padding( - padding: const EdgeInsets.only( - left: 8.0, - ), + padding: const EdgeInsets.only(left: 8.0), child: Text( 'create_shared_album_page_share_select_photos', - style: context.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w600, - color: context.primaryColor, - ), + style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w600, color: context.primaryColor), ).t(), ), ), @@ -133,16 +115,13 @@ class _DriftCreateAlbumPageState extends ConsumerState { crossAxisSpacing: 1.0, mainAxisSpacing: 1.0, ), - delegate: SliverChildBuilderDelegate( - (context, index) { - final asset = selectedAssets.elementAt(index); - return GestureDetector( - onTap: onBackgroundTapped, - child: Thumbnail(asset: asset), - ); - }, - childCount: selectedAssets.length, - ), + delegate: SliverChildBuilderDelegate((context, index) { + final asset = selectedAssets.elementAt(index); + return GestureDetector( + onTap: onBackgroundTapped, + child: Thumbnail(asset: asset), + ); + }, childCount: selectedAssets.length), ), ); } @@ -162,9 +141,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { Future onSelectPhotos() async { final assets = await context.pushRoute>( - DriftAssetSelectionTimelineRoute( - lockedSelectionAssets: selectedAssets, - ), + DriftAssetSelectionTimelineRoute(lockedSelectionAssets: selectedAssets), ); if (assets == null || assets.isEmpty) { @@ -183,16 +160,15 @@ class _DriftCreateAlbumPageState extends ConsumerState { if (title.isEmpty) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('create_album_title_required'.t()), - backgroundColor: context.colorScheme.error, - ), + SnackBar(content: Text('create_album_title_required'.t()), backgroundColor: context.colorScheme.error), ); } return; } - final album = await ref.watch(remoteAlbumProvider.notifier).createAlbum( + final album = await ref + .watch(remoteAlbumProvider.notifier) + .createAlbum( title: title, description: albumDescriptionController.text.trim(), assetIds: selectedAssets.map((asset) { @@ -203,18 +179,13 @@ class _DriftCreateAlbumPageState extends ConsumerState { if (album != null) { ref.read(currentRemoteAlbumProvider.notifier).setAlbum(album); - context.replaceRoute( - RemoteAlbumRoute(album: album), - ); + context.replaceRoute(RemoteAlbumRoute(album: album)); } } Widget buildTitleInputField() { return Padding( - padding: const EdgeInsets.only( - right: 10.0, - left: 10.0, - ), + padding: const EdgeInsets.only(right: 10.0, left: 10.0), child: _AlbumTitleTextField( focusNode: albumTitleTextFieldFocusNode, textController: albumTitleController, @@ -230,11 +201,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { Widget buildDescriptionInputField() { return Padding( - padding: const EdgeInsets.only( - right: 10.0, - left: 10.0, - top: 8, - ), + padding: const EdgeInsets.only(right: 10.0, left: 10.0, top: 8), child: _AlbumViewerEditableDescription( textController: albumDescriptionController, focusNode: albumDescriptionTextFieldFocusNode, @@ -244,11 +211,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { Widget buildControlButton() { return Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 8.0, - bottom: 8.0, - ), + padding: const EdgeInsets.only(left: 12.0, top: 8.0, bottom: 8.0), child: SizedBox( height: 42.0, child: ListView( @@ -272,10 +235,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { elevation: 0, centerTitle: false, backgroundColor: context.scaffoldBackgroundColor, - leading: IconButton( - onPressed: () => context.maybePop(), - icon: const Icon(Icons.close_rounded), - ), + leading: IconButton(onPressed: () => context.maybePop(), icon: const Icon(Icons.close_rounded)), title: const Text('create_album').t(), actions: [ TextButton( @@ -292,12 +252,7 @@ class _DriftCreateAlbumPageState extends ConsumerState { ), body: GestureDetector( onTap: onBackgroundTapped, - child: CustomScrollView( - slivers: [ - _buildSliverAppBar(), - _buildContent(), - ], - ), + child: CustomScrollView(slivers: [_buildSliverAppBar(), _buildContent()]), ), ); } @@ -341,11 +296,7 @@ class _AlbumTitleTextFieldState extends State<_AlbumTitleTextField> { Widget build(BuildContext context) { return TextField( focusNode: widget.focusNode, - style: TextStyle( - fontSize: 28.0, - color: context.colorScheme.onSurface, - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 28.0, color: context.colorScheme.onSurface, fontWeight: FontWeight.bold), controller: widget.textController, onTap: () { if (widget.textController.text == 'create_album_page_untitled'.t(context: context)) { @@ -353,35 +304,23 @@ class _AlbumTitleTextFieldState extends State<_AlbumTitleTextField> { } }, decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric( - horizontal: 8.0, - vertical: 16.0, - ), + contentPadding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0), suffixIcon: widget.textController.text.isNotEmpty && widget.isFocus ? IconButton( onPressed: () { widget.textController.clear(); }, - icon: Icon( - Icons.cancel_rounded, - color: context.primaryColor, - ), + icon: Icon(Icons.cancel_rounded, color: context.primaryColor), splashRadius: 10.0, ) : null, enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Colors.transparent), - borderRadius: BorderRadius.all( - Radius.circular(16.0), - ), + borderRadius: BorderRadius.all(Radius.circular(16.0)), ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: context.primaryColor.withValues(alpha: 0.3), - ), - borderRadius: const BorderRadius.all( - Radius.circular(16.0), - ), + borderSide: BorderSide(color: context.primaryColor.withValues(alpha: 0.3)), + borderRadius: const BorderRadius.all(Radius.circular(16.0)), ), hintText: 'add_a_title'.t(), hintStyle: context.themeData.inputDecorationTheme.hintStyle?.copyWith( @@ -398,10 +337,7 @@ class _AlbumTitleTextFieldState extends State<_AlbumTitleTextField> { } class _AlbumViewerEditableDescription extends StatefulWidget { - const _AlbumViewerEditableDescription({ - required this.textController, - required this.focusNode, - }); + const _AlbumViewerEditableDescription({required this.textController, required this.focusNode}); final TextEditingController textController; final FocusNode focusNode; @@ -448,37 +384,23 @@ class _AlbumViewerEditableDescriptionState extends State<_AlbumViewerEditableDes minLines: 1, controller: widget.textController, decoration: InputDecoration( - contentPadding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 16.0, - ), + contentPadding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 16.0), suffixIcon: widget.focusNode.hasFocus && widget.textController.text.isNotEmpty ? IconButton( onPressed: () { widget.textController.clear(); }, - icon: Icon( - Icons.cancel_rounded, - color: context.primaryColor, - ), + icon: Icon(Icons.cancel_rounded, color: context.primaryColor), splashRadius: 10.0, ) : null, enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: context.colorScheme.outline.withValues(alpha: 0.3), - ), - borderRadius: const BorderRadius.all( - Radius.circular(16.0), - ), + borderSide: BorderSide(color: context.colorScheme.outline.withValues(alpha: 0.3)), + borderRadius: const BorderRadius.all(Radius.circular(16.0)), ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: context.primaryColor.withValues(alpha: 0.3), - ), - borderRadius: const BorderRadius.all( - Radius.circular(16.0), - ), + borderSide: BorderSide(color: context.primaryColor.withValues(alpha: 0.3)), + borderRadius: const BorderRadius.all(Radius.circular(16.0)), ), hintStyle: context.themeData.inputDecorationTheme.hintStyle?.copyWith( fontSize: 16.0, diff --git a/mobile/lib/presentation/pages/drift_favorite.page.dart b/mobile/lib/presentation/pages/drift_favorite.page.dart index 5648fd7fa..2bc3f2636 100644 --- a/mobile/lib/presentation/pages/drift_favorite.page.dart +++ b/mobile/lib/presentation/pages/drift_favorite.page.dart @@ -16,18 +16,16 @@ class DriftFavoritePage extends StatelessWidget { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception('User must be logged in to access favorite'); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access favorite'); + } - final timelineService = ref.watch(timelineFactoryProvider).favorite(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).favorite(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( appBar: MesmerizingSliverAppBar( diff --git a/mobile/lib/presentation/pages/drift_library.page.dart b/mobile/lib/presentation/pages/drift_library.page.dart index 5cf47bc99..28fa6c6a1 100644 --- a/mobile/lib/presentation/pages/drift_library.page.dart +++ b/mobile/lib/presentation/pages/drift_library.page.dart @@ -27,12 +27,7 @@ class DriftLibraryPage extends ConsumerWidget { return const Scaffold( body: CustomScrollView( slivers: [ - ImmichSliverAppBar( - snap: false, - floating: false, - pinned: true, - showUploadButton: false, - ), + ImmichSliverAppBar(snap: false, floating: false, pinned: true, showUploadButton: false), _ActionButtonGrid(), _CollectionCards(), _QuickAccessButtonList(), @@ -47,9 +42,7 @@ class _ActionButtonGrid extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final isTrashEnable = ref.watch( - serverInfoProvider.select((state) => state.serverFeatures.trash), - ); + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); return SliverPadding( padding: const EdgeInsets.only(left: 16, top: 16, right: 16, bottom: 12), @@ -97,11 +90,7 @@ class _ActionButtonGrid extends ConsumerWidget { } class _ActionButton extends StatelessWidget { - const _ActionButton({ - required this.icon, - required this.onTap, - required this.label, - }); + const _ActionButton({required this.icon, required this.onTap, required this.label}); final IconData icon; final VoidCallback onTap; @@ -114,13 +103,7 @@ class _ActionButton extends StatelessWidget { onPressed: onTap, label: Padding( padding: const EdgeInsets.only(left: 4.0), - child: Text( - label, - style: TextStyle( - color: context.colorScheme.onSurface, - fontSize: 15, - ), - ), + child: Text(label, style: TextStyle(color: context.colorScheme.onSurface, fontSize: 15)), ), style: FilledButton.styleFrom( elevation: 0, @@ -129,16 +112,10 @@ class _ActionButton extends StatelessWidget { alignment: Alignment.centerLeft, shape: RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(25)), - side: BorderSide( - color: context.colorScheme.onSurface.withAlpha(10), - width: 1, - ), + side: BorderSide(color: context.colorScheme.onSurface.withAlpha(10), width: 1), ), ), - icon: Icon( - icon, - color: context.primaryColor, - ), + icon: Icon(icon, color: context.primaryColor), ), ); } @@ -155,11 +132,7 @@ class _CollectionCards extends StatelessWidget { child: Wrap( spacing: 8, runSpacing: 8, - children: [ - _PeopleCollectionCard(), - _PlacesCollectionCard(), - _LocalAlbumsCollectionCard(), - ], + children: [_PeopleCollectionCard(), _PlacesCollectionCard(), _LocalAlbumsCollectionCard()], ), ), ); @@ -188,22 +161,15 @@ class _PeopleCollectionCard extends ConsumerWidget { height: size, width: size, decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(30), - context.colorScheme.primary.withAlpha(25), - ], + colors: [context.colorScheme.primary.withAlpha(30), context.colorScheme.primary.withAlpha(25)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: people.widgetWhen( - onLoading: () => const Center( - child: CircularProgressIndicator(), - ), + onLoading: () => const Center(child: CircularProgressIndicator()), onData: (people) { return GridView.count( crossAxisCount: 2, @@ -253,9 +219,7 @@ class _PlacesCollectionCard extends StatelessWidget { final size = context.width * widthFactor - 20.0; return GestureDetector( - onTap: () => context.pushRoute( - DriftPlaceRoute(currentLocation: null), - ), + onTap: () => context.pushRoute(DriftPlaceRoute(currentLocation: null)), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -270,10 +234,7 @@ class _PlacesCollectionCard extends StatelessWidget { child: IgnorePointer( child: MapThumbnail( zoom: 8, - centre: const LatLng( - 21.44950, - -157.91959, - ), + centre: const LatLng(21.44950, -157.91959), showAttribution: false, themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light, ), @@ -323,10 +284,7 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget { decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(30), - context.colorScheme.primary.withAlpha(25), - ], + colors: [context.colorScheme.primary.withAlpha(30), context.colorScheme.primary.withAlpha(25)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), @@ -340,24 +298,14 @@ class _LocalAlbumsCollectionCard extends ConsumerWidget { children: albums.when( data: (data) { return data.take(4).map((album) { - return LocalAlbumThumbnail( - albumId: album.id, - ); + return LocalAlbumThumbnail(albumId: album.id); }).toList(); }, error: (error, _) { - return [ - Center( - child: Text('Error: $error'), - ), - ]; + return [Center(child: Text('Error: $error'))]; }, loading: () { - return [ - const Center( - child: CircularProgressIndicator(), - ), - ]; + return [const Center(child: CircularProgressIndicator())]; }, ), ), @@ -394,13 +342,8 @@ class _QuickAccessButtonList extends ConsumerWidget { sliver: SliverToBoxAdapter( child: Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(10), - width: 1, - ), - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(10), width: 1), + borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( colors: [ context.colorScheme.primary.withAlpha(10), @@ -425,41 +368,26 @@ class _QuickAccessButtonList extends ConsumerWidget { bottomRight: Radius.circular(partners.isEmpty ? 20 : 0), ), ), - leading: const Icon( - Icons.folder_outlined, - size: 26, - ), + leading: const Icon(Icons.folder_outlined, size: 26), title: Text( 'folders'.t(context: context), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), onTap: () => context.pushRoute(FolderRoute()), ), ListTile( - leading: const Icon( - Icons.lock_outline_rounded, - size: 26, - ), + leading: const Icon(Icons.lock_outline_rounded, size: 26), title: Text( 'locked_folder'.t(context: context), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), onTap: () => context.pushRoute(const DriftLockedFolderRoute()), ), ListTile( - leading: const Icon( - Icons.group_outlined, - size: 26, - ), + leading: const Icon(Icons.group_outlined, size: 26), title: Text( 'partners'.t(context: context), - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500), ), onTap: () => context.pushRoute(const DriftPartnerRoute()), ), @@ -494,22 +422,13 @@ class _PartnerList extends StatelessWidget { bottomRight: Radius.circular(isLastItem ? 20 : 0), ), ), - contentPadding: const EdgeInsets.only( - left: 12.0, - right: 18.0, - ), - leading: PartnerUserAvatar( - partner: partner, - ), + contentPadding: const EdgeInsets.only(left: 12.0, right: 18.0), + leading: PartnerUserAvatar(partner: partner), title: const Text( "partner_list_user_photos", - style: TextStyle( - fontWeight: FontWeight.w500, - ), + style: TextStyle(fontWeight: FontWeight.w500), ).t(context: context, args: {'user': partner.name}), - onTap: () => context.pushRoute( - DriftPartnerDetailRoute(partner: partner), - ), + onTap: () => context.pushRoute(DriftPartnerDetailRoute(partner: partner)), ); }, ); diff --git a/mobile/lib/presentation/pages/drift_local_album.page.dart b/mobile/lib/presentation/pages/drift_local_album.page.dart index 7add23259..536d9d82e 100644 --- a/mobile/lib/presentation/pages/drift_local_album.page.dart +++ b/mobile/lib/presentation/pages/drift_local_album.page.dart @@ -16,14 +16,7 @@ class DriftLocalAlbumsPage extends StatelessWidget { @override Widget build(BuildContext context) { - return const Scaffold( - body: CustomScrollView( - slivers: [ - LocalAlbumsSliverAppBar(), - _AlbumList(), - ], - ), - ); + return const Scaffold(body: CustomScrollView(slivers: [LocalAlbumsSliverAppBar(), _AlbumList()])); } } @@ -37,10 +30,7 @@ class _AlbumList extends ConsumerWidget { return albums.when( loading: () => const SliverToBoxAdapter( child: Center( - child: Padding( - padding: EdgeInsets.all(20.0), - child: CircularProgressIndicator(), - ), + child: Padding(padding: EdgeInsets.all(20.0), child: CircularProgressIndicator()), ), ), error: (error, stack) => SliverToBoxAdapter( @@ -49,9 +39,7 @@ class _AlbumList extends ConsumerWidget { padding: const EdgeInsets.all(20.0), child: Text( 'Error loading albums: $error, stack: $stack', - style: TextStyle( - color: context.colorScheme.error, - ), + style: TextStyle(color: context.colorScheme.error), ), ), ), @@ -60,10 +48,7 @@ class _AlbumList extends ConsumerWidget { if (albums.isEmpty) { return const SliverToBoxAdapter( child: Center( - child: Padding( - padding: EdgeInsets.all(20.0), - child: Text('No albums found'), - ), + child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')), ), ); } @@ -77,30 +62,12 @@ class _AlbumList extends ConsumerWidget { return Padding( padding: const EdgeInsets.only(bottom: 8.0), child: LargeLeadingTile( - leadingPadding: const EdgeInsets.only( - right: 16, - ), - leading: SizedBox( - width: 80, - height: 80, - child: LocalAlbumThumbnail( - albumId: album.id, - ), - ), - title: Text( - album.name, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), - ), + leadingPadding: const EdgeInsets.only(right: 16), + leading: SizedBox(width: 80, height: 80, child: LocalAlbumThumbnail(albumId: album.id)), + title: Text(album.name, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600)), subtitle: Text( - 'items_count'.t( - context: context, - args: {'count': album.assetCount}, - ), - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + 'items_count'.t(context: context, args: {'count': album.assetCount}), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), onTap: () => context.pushRoute(LocalTimelineRoute(album: album)), ), diff --git a/mobile/lib/presentation/pages/drift_locked_folder.page.dart b/mobile/lib/presentation/pages/drift_locked_folder.page.dart index 417e902de..b19e8468c 100644 --- a/mobile/lib/presentation/pages/drift_locked_folder.page.dart +++ b/mobile/lib/presentation/pages/drift_locked_folder.page.dart @@ -45,27 +45,23 @@ class _DriftLockedFolderPageState extends ConsumerState w Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception('User must be logged in to access locked folder'); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access locked folder'); + } - final timelineService = ref.watch(timelineFactoryProvider).lockedFolder(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).lockedFolder(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: _showOverlay ? const SizedBox() : PopScope( onPopInvokedWithResult: (didPop, _) => didPop ? ref.read(authProvider.notifier).lockPinCode() : null, child: Timeline( - appBar: MesmerizingSliverAppBar( - title: 'locked_folder'.t(context: context), - ), + appBar: MesmerizingSliverAppBar(title: 'locked_folder'.t(context: context)), bottomSheet: const LockedFolderBottomSheet(), ), ), diff --git a/mobile/lib/presentation/pages/drift_memory.page.dart b/mobile/lib/presentation/pages/drift_memory.page.dart index c42feff0e..55e5d24ec 100644 --- a/mobile/lib/presentation/pages/drift_memory.page.dart +++ b/mobile/lib/presentation/pages/drift_memory.page.dart @@ -22,20 +22,14 @@ class DriftMemoryPage extends HookConsumerWidget { final List memories; final int memoryIndex; - const DriftMemoryPage({ - required this.memories, - required this.memoryIndex, - super.key, - }); + const DriftMemoryPage({required this.memories, required this.memoryIndex, super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final currentMemory = useState(memories[memoryIndex]); final currentAssetPage = useState(0); final currentMemoryIndex = useState(memoryIndex); - final assetProgress = useState( - "${currentAssetPage.value + 1}|${currentMemory.value.assets.length}", - ); + final assetProgress = useState("${currentAssetPage.value + 1}|${currentMemory.value.assets.length}"); const bgColor = Colors.black; final currentAsset = useState(null); @@ -55,19 +49,13 @@ class DriftMemoryPage extends HookConsumerWidget { }); toNextMemory() { - memoryPageController.nextPage( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - ); + memoryPageController.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn); } void toPreviousMemory() { if (currentMemoryIndex.value > 0) { // Move to the previous memory page - memoryPageController.previousPage( - duration: const Duration(milliseconds: 500), - curve: Curves.easeIn, - ); + memoryPageController.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.easeIn); // Wait for the next frame to ensure the page is built SchedulerBinding.instance.addPostFrameCallback((_) { @@ -94,10 +82,7 @@ class DriftMemoryPage extends HookConsumerWidget { // Go to the next asset PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; - controller.nextPage( - curve: Curves.easeInOut, - duration: const Duration(milliseconds: 500), - ); + controller.nextPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500)); } else { // Go to the next memory since we are at the end of our assets toNextMemory(); @@ -109,10 +94,7 @@ class DriftMemoryPage extends HookConsumerWidget { // Go to the previous asset PageController controller = memoryAssetPageControllers[currentMemoryIndex.value]; - controller.previousPage( - curve: Curves.easeInOut, - duration: const Duration(milliseconds: 500), - ); + controller.previousPage(curve: Curves.easeInOut, duration: const Duration(milliseconds: 500)); } else { // Go to the previous memory since we are at the end of our assets toPreviousMemory(); @@ -160,14 +142,7 @@ class DriftMemoryPage extends HookConsumerWidget { // Precache the asset final size = MediaQuery.sizeOf(context); - await precacheImage( - getFullImageProvider( - asset, - size: Size(size.width, size.height), - ), - context, - size: size, - ); + await precacheImage(getFullImageProvider(asset, size: Size(size.width, size.height)), context, size: size); } // Precache the next page right away if we are on the first page @@ -219,9 +194,7 @@ class DriftMemoryPage extends HookConsumerWidget { backgroundColor: bgColor, body: SafeArea( child: PageView.builder( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), + physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), scrollDirection: Axis.vertical, controller: memoryPageController, onPageChanged: (pageNumber) { @@ -249,23 +222,13 @@ class DriftMemoryPage extends HookConsumerWidget { } final yearsAgo = DateTime.now().year - memories[mIndex].data.year; - final title = 'years_ago'.t( - context: context, - args: { - 'years': yearsAgo.toString(), - }, - ); + final title = 'years_ago'.t(context: context, args: {'years': yearsAgo.toString()}); // Build horizontal page final assetController = memoryAssetPageControllers[mIndex]; return Column( children: [ Padding( - padding: const EdgeInsets.only( - left: 24.0, - right: 24.0, - top: 8.0, - bottom: 2.0, - ), + padding: const EdgeInsets.only(left: 24.0, right: 24.0, top: 8.0, bottom: 2.0), child: AnimatedBuilder( animation: assetController, builder: (context, child) { @@ -285,9 +248,7 @@ class DriftMemoryPage extends HookConsumerWidget { child: Stack( children: [ PageView.builder( - physics: const BouncingScrollPhysics( - parent: AlwaysScrollableScrollPhysics(), - ), + physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()), controller: assetController, onPageChanged: onAssetChanged, scrollDirection: Axis.horizontal, @@ -298,11 +259,7 @@ class DriftMemoryPage extends HookConsumerWidget { children: [ Container( color: Colors.black, - child: DriftMemoryCard( - asset: asset, - title: title, - showTitle: index == 0, - ), + child: DriftMemoryCard(asset: asset, title: title, showTitle: index == 0), ), Positioned.fill( child: Row( @@ -343,35 +300,24 @@ class DriftMemoryPage extends HookConsumerWidget { // turn off full screen mode here // https://github.com/Milad-Akarie/auto_route_library/issues/1799 context.maybePop(); - SystemChrome.setEnabledSystemUIMode( - SystemUiMode.edgeToEdge, - ); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); }, shape: const CircleBorder(), color: Colors.white.withValues(alpha: 0.2), elevation: 0, - child: const Icon( - Icons.close_rounded, - color: Colors.white, - ), + child: const Icon(Icons.close_rounded, color: Colors.white), ), ), if (currentAsset.value != null && currentAsset.value!.isVideo) Positioned( bottom: 24, right: 32, - child: Icon( - Icons.videocam_outlined, - color: Colors.grey[200], - ), + child: Icon(Icons.videocam_outlined, color: Colors.grey[200]), ), ], ), ), - DriftMemoryBottomInfo( - memory: memories[mIndex], - title: title, - ), + DriftMemoryBottomInfo(memory: memories[mIndex], title: title), ], ); }, diff --git a/mobile/lib/presentation/pages/drift_partner_detail.page.dart b/mobile/lib/presentation/pages/drift_partner_detail.page.dart index 3d9d28aea..95c5b008b 100644 --- a/mobile/lib/presentation/pages/drift_partner_detail.page.dart +++ b/mobile/lib/presentation/pages/drift_partner_detail.page.dart @@ -15,28 +15,20 @@ import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart'; class DriftPartnerDetailPage extends StatelessWidget { final PartnerUserDto partner; - const DriftPartnerDetailPage({ - super.key, - required this.partner, - }); + const DriftPartnerDetailPage({super.key, required this.partner}); @override Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(partner.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + timelineServiceProvider.overrideWith((ref) { + final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(partner.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( - appBar: MesmerizingSliverAppBar( - title: partner.name, - icon: Icons.person_outline, - ), + appBar: MesmerizingSliverAppBar(title: partner.name, icon: Icons.person_outline), topSliverWidget: _InfoBox(partner: partner), topSliverWidgetHeight: 110, bottomSheet: const PartnerDetailBottomSheet(), @@ -48,9 +40,7 @@ class DriftPartnerDetailPage extends StatelessWidget { class _InfoBox extends ConsumerStatefulWidget { final PartnerUserDto partner; - const _InfoBox({ - required this.partner, - }); + const _InfoBox({required this.partner}); @override ConsumerState<_InfoBox> createState() => _InfoBoxState(); @@ -72,10 +62,7 @@ class _InfoBoxState extends ConsumerState<_InfoBox> { } try { - await ref.read(partnerUsersProvider.notifier).toggleShowInTimeline( - widget.partner.id, - user.id, - ); + await ref.read(partnerUsersProvider.notifier).toggleShowInTimeline(widget.partner.id, user.id); setState(() { _inTimeline = !_inTimeline; @@ -101,18 +88,10 @@ class _InfoBoxState extends ConsumerState<_InfoBox> { padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 16.0), child: Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(10), - width: 1, - ), - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(10), width: 1), + borderRadius: const BorderRadius.all(Radius.circular(20)), gradient: LinearGradient( - colors: [ - context.colorScheme.primary.withAlpha(10), - context.colorScheme.primary.withAlpha(15), - ], + colors: [context.colorScheme.primary.withAlpha(10), context.colorScheme.primary.withAlpha(15)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), @@ -122,18 +101,13 @@ class _InfoBoxState extends ConsumerState<_InfoBox> { child: ListTile( title: Text( "Show in timeline", - style: context.textTheme.titleSmall?.copyWith( - color: context.colorScheme.primary, - ), + style: context.textTheme.titleSmall?.copyWith(color: context.colorScheme.primary), ), subtitle: Text( "Show photos and videos from this user in your timeline", style: context.textTheme.bodyMedium, ), - trailing: Switch( - value: _inTimeline, - onChanged: (_) => _toggleInTimeline(), - ), + trailing: Switch(value: _inTimeline, onChanged: (_) => _toggleInTimeline()), ), ), ), diff --git a/mobile/lib/presentation/pages/drift_place.page.dart b/mobile/lib/presentation/pages/drift_place.page.dart index 969bfc70f..e85bb90d5 100644 --- a/mobile/lib/presentation/pages/drift_place.page.dart +++ b/mobile/lib/presentation/pages/drift_place.page.dart @@ -52,9 +52,7 @@ class _PlaceSliverAppBar extends StatelessWidget { pinned: true, snap: false, backgroundColor: context.colorScheme.surfaceContainer, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(5)), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5))), automaticallyImplyLeading: search.value == null, centerTitle: true, title: search.value != null @@ -98,20 +96,14 @@ class _Map extends StatelessWidget { child: MapThumbnail( onTap: (_, __) => context.pushRoute(MapRoute(initialLocation: currentLocation)), zoom: 8, - centre: currentLocation ?? - const LatLng( - 21.44950, - -157.91959, - ), + centre: currentLocation ?? const LatLng(21.44950, -157.91959), showAttribution: false, themeMode: context.isDarkTheme ? ThemeMode.dark : ThemeMode.light, ), ), ), ) - : const SliverToBoxAdapter( - child: SizedBox.shrink(), - ); + : const SliverToBoxAdapter(child: SizedBox.shrink()); } } @@ -127,10 +119,7 @@ class _PlaceList extends ConsumerWidget { return places.when( loading: () => const SliverToBoxAdapter( child: Center( - child: Padding( - padding: EdgeInsets.all(20.0), - child: CircularProgressIndicator(), - ), + child: Padding(padding: EdgeInsets.all(20.0), child: CircularProgressIndicator()), ), ), error: (error, stack) => SliverToBoxAdapter( @@ -139,9 +128,7 @@ class _PlaceList extends ConsumerWidget { padding: const EdgeInsets.all(20.0), child: Text( 'Error loading places: $error, stack: $stack', - style: TextStyle( - color: context.colorScheme.error, - ), + style: TextStyle(color: context.colorScheme.error), ), ), ), @@ -174,21 +161,10 @@ class _PlaceTile extends StatelessWidget { Widget build(BuildContext context) { return LargeLeadingTile( onTap: () => context.pushRoute(DriftPlaceDetailRoute(place: place.$1)), - title: Text( - place.$1, - style: context.textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w500, - ), - ), + title: Text(place.$1, style: context.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w500)), leading: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - child: Thumbnail( - size: const Size(80, 80), - fit: BoxFit.cover, - remoteId: place.$2, - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), + child: Thumbnail(size: const Size(80, 80), fit: BoxFit.cover, remoteId: place.$2), ), ); } diff --git a/mobile/lib/presentation/pages/drift_place_detail.page.dart b/mobile/lib/presentation/pages/drift_place_detail.page.dart index d55725231..0f5022794 100644 --- a/mobile/lib/presentation/pages/drift_place_detail.page.dart +++ b/mobile/lib/presentation/pages/drift_place_detail.page.dart @@ -9,28 +9,20 @@ import 'package:immich_mobile/widgets/common/mesmerizing_sliver_app_bar.dart'; class DriftPlaceDetailPage extends StatelessWidget { final String place; - const DriftPlaceDetailPage({ - super.key, - required this.place, - }); + const DriftPlaceDetailPage({super.key, required this.place}); @override Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final timelineService = ref.watch(timelineFactoryProvider).place(place); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + timelineServiceProvider.overrideWith((ref) { + final timelineService = ref.watch(timelineFactoryProvider).place(place); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( - appBar: MesmerizingSliverAppBar( - title: place, - icon: Icons.location_on, - ), + appBar: MesmerizingSliverAppBar(title: place, icon: Icons.location_on), ), ); } diff --git a/mobile/lib/presentation/pages/drift_recently_taken.page.dart b/mobile/lib/presentation/pages/drift_recently_taken.page.dart index c99c36bd2..ceb121b12 100644 --- a/mobile/lib/presentation/pages/drift_recently_taken.page.dart +++ b/mobile/lib/presentation/pages/drift_recently_taken.page.dart @@ -15,24 +15,18 @@ class DriftRecentlyTakenPage extends StatelessWidget { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception( - 'User must be logged in to access recently taken', - ); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access recently taken'); + } - final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).remoteAssets(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], - child: Timeline( - appBar: MesmerizingSliverAppBar(title: 'recently_taken'.t()), - ), + child: Timeline(appBar: MesmerizingSliverAppBar(title: 'recently_taken'.t())), ); } } diff --git a/mobile/lib/presentation/pages/drift_remote_album.page.dart b/mobile/lib/presentation/pages/drift_remote_album.page.dart index 4173e262b..336050d5a 100644 --- a/mobile/lib/presentation/pages/drift_remote_album.page.dart +++ b/mobile/lib/presentation/pages/drift_remote_album.page.dart @@ -21,10 +21,7 @@ import 'package:immich_mobile/widgets/common/remote_album_sliver_app_bar.dart'; class RemoteAlbumPage extends ConsumerStatefulWidget { final RemoteAlbum album; - const RemoteAlbumPage({ - super.key, - required this.album, - }); + const RemoteAlbumPage({super.key, required this.album}); @override ConsumerState createState() => _RemoteAlbumPageState(); @@ -40,16 +37,16 @@ class _RemoteAlbumPageState extends ConsumerState { final albumAssets = await ref.read(remoteAlbumProvider.notifier).getAssets(widget.album.id); final newAssets = await context.pushRoute>( - DriftAssetSelectionTimelineRoute( - lockedSelectionAssets: albumAssets.toSet(), - ), + DriftAssetSelectionTimelineRoute(lockedSelectionAssets: albumAssets.toSet()), ); if (newAssets == null || newAssets.isEmpty) { return; } - final added = await ref.read(remoteAlbumProvider.notifier).addAssets( + final added = await ref + .read(remoteAlbumProvider.notifier) + .addAssets( widget.album.id, newAssets.map((asset) { final remoteAsset = asset as RemoteAsset; @@ -60,21 +57,14 @@ class _RemoteAlbumPageState extends ConsumerState { if (added > 0) { ImmichToast.show( context: context, - msg: "assets_added_to_album_count".t( - context: context, - args: { - 'count': added.toString(), - }, - ), + msg: "assets_added_to_album_count".t(context: context, args: {'count': added.toString()}), toastType: ToastType.success, ); } } Future addUsers(BuildContext context) async { - final newUsers = await context.pushRoute>( - DriftUserSelectionRoute(album: widget.album), - ); + final newUsers = await context.pushRoute>(DriftUserSelectionRoute(album: widget.album)); if (newUsers == null || newUsers.isEmpty) { return; @@ -86,12 +76,7 @@ class _RemoteAlbumPageState extends ConsumerState { if (newUsers.isNotEmpty) { ImmichToast.show( context: context, - msg: "users_added_to_album_count".t( - context: context, - args: { - 'count': newUsers.length, - }, - ), + msg: "users_added_to_album_count".t(context: context, args: {'count': newUsers.length}), toastType: ToastType.success, ); } @@ -107,9 +92,7 @@ class _RemoteAlbumPageState extends ConsumerState { } Future toggleAlbumOrder() async { - await ref.read(remoteAlbumProvider.notifier).toggleAlbumOrder( - widget.album.id, - ); + await ref.read(remoteAlbumProvider.notifier).toggleAlbumOrder(widget.album.id); ref.invalidate(timelineServiceProvider); } @@ -123,16 +106,9 @@ class _RemoteAlbumPageState extends ConsumerState { content: Column( mainAxisSize: MainAxisSize.min, children: [ - Text( - 'album_delete_confirmation'.t( - context: context, - args: {'album': widget.album.name}, - ), - ), + Text('album_delete_confirmation'.t(context: context, args: {'album': widget.album.name})), const SizedBox(height: 8), - Text( - 'album_delete_confirmation_description'.t(context: context), - ), + Text('album_delete_confirmation_description'.t(context: context)), ], ), actions: [ @@ -142,9 +118,7 @@ class _RemoteAlbumPageState extends ConsumerState { ), TextButton( onPressed: () => Navigator.of(context).pop(true), - style: TextButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.error, - ), + style: TextButton.styleFrom(foregroundColor: Theme.of(context).colorScheme.error), child: Text('delete_album'.t(context: context)), ), ], @@ -230,13 +204,11 @@ class _RemoteAlbumPageState extends ConsumerState { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final timelineService = ref.watch(timelineFactoryProvider).remoteAlbum(albumId: widget.album.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + timelineServiceProvider.overrideWith((ref) { + final timelineService = ref.watch(timelineFactoryProvider).remoteAlbum(albumId: widget.album.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( appBar: RemoteAlbumSliverAppBar( @@ -245,9 +217,7 @@ class _RemoteAlbumPageState extends ConsumerState { onToggleAlbumOrder: () => toggleAlbumOrder(), onEditTitle: () => showEditTitleAndDescription(context), ), - bottomSheet: RemoteAlbumBottomSheet( - album: widget.album, - ), + bottomSheet: RemoteAlbumBottomSheet(album: widget.album), ), ); } @@ -257,18 +227,13 @@ class _EditAlbumData { final String name; final String? description; - const _EditAlbumData({ - required this.name, - this.description, - }); + const _EditAlbumData({required this.name, this.description}); } class _EditAlbumDialog extends ConsumerStatefulWidget { final RemoteAlbum album; - const _EditAlbumDialog({ - required this.album, - }); + const _EditAlbumDialog({required this.album}); @override ConsumerState<_EditAlbumDialog> createState() => _EditAlbumDialogState(); @@ -302,19 +267,14 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { final newTitle = titleController.text.trim(); final newDescription = descriptionController.text.trim(); - await ref.read(remoteAlbumProvider.notifier).updateAlbum( - widget.album.id, - name: newTitle, - description: newDescription.isEmpty ? null : newDescription, - ); + await ref + .read(remoteAlbumProvider.notifier) + .updateAlbum(widget.album.id, name: newTitle, description: newDescription.isEmpty ? null : newDescription); if (mounted) { - Navigator.of(context).pop( - _EditAlbumData( - name: newTitle, - description: newDescription.isEmpty ? null : newDescription, - ), - ); + Navigator.of( + context, + ).pop(_EditAlbumData(name: newTitle, description: newDescription.isEmpty ? null : newDescription)); } } catch (e) { if (mounted) { @@ -331,11 +291,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { Widget build(BuildContext context) { return Dialog( insetPadding: const EdgeInsets.all(24), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(16), - ), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16))), child: SingleChildScrollView( child: Container( padding: const EdgeInsets.all(16), @@ -348,16 +304,9 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { children: [ Row( children: [ - Icon( - Icons.edit_outlined, - color: context.colorScheme.primary, - size: 24, - ), + Icon(Icons.edit_outlined, color: context.colorScheme.primary, size: 24), const SizedBox(width: 12), - Text( - 'edit_album'.t(context: context), - style: context.textTheme.titleMedium, - ), + Text('edit_album'.t(context: context), style: context.textTheme.titleMedium), ], ), const SizedBox(height: 24), @@ -365,9 +314,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { // Album Name Text( 'album_name'.t(context: context).toUpperCase(), - style: context.textTheme.labelSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600), ), const SizedBox(height: 4), TextFormField( @@ -375,9 +322,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { maxLines: 1, textCapitalization: TextCapitalization.sentences, decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(12)), - ), + border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(12))), filled: true, fillColor: context.colorScheme.surface, ), @@ -394,9 +339,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { // Description Text( 'description'.t(context: context).toUpperCase(), - style: context.textTheme.labelSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.labelSmall?.copyWith(fontWeight: FontWeight.w600), ), const SizedBox(height: 4), TextFormField( @@ -404,11 +347,7 @@ class _EditAlbumDialogState extends ConsumerState<_EditAlbumDialog> { maxLines: 4, textCapitalization: TextCapitalization.sentences, decoration: InputDecoration( - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(12), - ), - ), + border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(12))), filled: true, fillColor: context.colorScheme.surface, ), diff --git a/mobile/lib/presentation/pages/drift_trash.page.dart b/mobile/lib/presentation/pages/drift_trash.page.dart index 61fc5e35f..4d18d12d0 100644 --- a/mobile/lib/presentation/pages/drift_trash.page.dart +++ b/mobile/lib/presentation/pages/drift_trash.page.dart @@ -16,18 +16,16 @@ class DriftTrashPage extends StatelessWidget { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception('User must be logged in to access trash'); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to access trash'); + } - final timelineService = ref.watch(timelineFactoryProvider).trash(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).trash(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( showStorageIndicator: true, @@ -42,18 +40,14 @@ class DriftTrashPage extends StatelessWidget { topSliverWidgetHeight: 24, topSliverWidget: Consumer( builder: (context, ref, child) { - final trashDays = ref.watch( - serverInfoProvider.select((v) => v.serverConfig.trashDays), - ); + final trashDays = ref.watch(serverInfoProvider.select((v) => v.serverConfig.trashDays)); return SliverPadding( padding: const EdgeInsets.all(16.0), sliver: SliverToBoxAdapter( child: SizedBox( height: 24.0, - child: const Text( - "trash_page_info", - ).t(context: context, args: {"days": "$trashDays"}), + child: const Text("trash_page_info").t(context: context, args: {"days": "$trashDays"}), ), ), ); diff --git a/mobile/lib/presentation/pages/drift_user_selection.page.dart b/mobile/lib/presentation/pages/drift_user_selection.page.dart index 5aaa438a1..e8835e714 100644 --- a/mobile/lib/presentation/pages/drift_user_selection.page.dart +++ b/mobile/lib/presentation/pages/drift_user_selection.page.dart @@ -49,10 +49,7 @@ final driftUsersProvider = FutureProvider.autoDispose>((ref) async class DriftUserSelectionPage extends HookConsumerWidget { final RemoteAlbum album; - const DriftUserSelectionPage({ - super.key, - required this.album, - }); + const DriftUserSelectionPage({super.key, required this.album}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -65,17 +62,9 @@ class DriftUserSelectionPage extends HookConsumerWidget { buildTileIcon(UserDto user) { if (sharedUsersList.value.contains(user)) { - return CircleAvatar( - backgroundColor: context.primaryColor, - child: const Icon( - Icons.check_rounded, - size: 25, - ), - ); + return CircleAvatar(backgroundColor: context.primaryColor, child: const Icon(Icons.check_rounded, size: 25)); } else { - return UserCircleAvatar( - user: user, - ); + return UserCircleAvatar(user: user); } } @@ -88,31 +77,19 @@ class DriftUserSelectionPage extends HookConsumerWidget { padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Chip( backgroundColor: context.primaryColor.withValues(alpha: 0.15), - label: Text( - user.name, - style: const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ), + label: Text(user.name, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold)), ), ), ); } return ListView( children: [ - Wrap( - children: [...usersChip], - ), + Wrap(children: [...usersChip]), Padding( padding: const EdgeInsets.all(16.0), child: Text( 'suggestions'.tr(), - style: const TextStyle( - fontSize: 14, - color: Colors.grey, - fontWeight: FontWeight.bold, - ), + style: const TextStyle(fontSize: 14, color: Colors.grey, fontWeight: FontWeight.bold), ), ), ListView.builder( @@ -122,31 +99,15 @@ class DriftUserSelectionPage extends HookConsumerWidget { return ListTile( leading: buildTileIcon(users[index]), dense: true, - title: Text( - users[index].name, - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - subtitle: Text( - users[index].email, - style: const TextStyle( - fontSize: 12, - ), - ), + title: Text(users[index].name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), + subtitle: Text(users[index].email, style: const TextStyle(fontSize: 12)), onTap: () { if (sharedUsersList.value.contains(users[index])) { sharedUsersList.value = sharedUsersList.value - .where( - (selectedUser) => selectedUser.id != users[index].id, - ) + .where((selectedUser) => selectedUser.id != users[index].id) .toSet(); } else { - sharedUsersList.value = { - ...sharedUsersList.value, - users[index], - }; + sharedUsersList.value = {...sharedUsersList.value, users[index]}; } }, ); @@ -159,9 +120,7 @@ class DriftUserSelectionPage extends HookConsumerWidget { return Scaffold( appBar: AppBar( - title: const Text( - 'invite_to_album', - ).tr(), + title: const Text('invite_to_album').tr(), elevation: 0, centerTitle: false, leading: IconButton( @@ -173,10 +132,7 @@ class DriftUserSelectionPage extends HookConsumerWidget { actions: [ TextButton( onPressed: sharedUsersList.value.isEmpty ? null : addNewUsersHandler, - child: const Text( - "add", - style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold), - ).tr(), + child: const Text("add", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(), ), ], ), diff --git a/mobile/lib/presentation/pages/drift_video.page.dart b/mobile/lib/presentation/pages/drift_video.page.dart index 94c5620f9..eef05acdc 100644 --- a/mobile/lib/presentation/pages/drift_video.page.dart +++ b/mobile/lib/presentation/pages/drift_video.page.dart @@ -15,22 +15,18 @@ class DriftVideoPage extends StatelessWidget { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final user = ref.watch(currentUserProvider); - if (user == null) { - throw Exception('User must be logged in to video'); - } + timelineServiceProvider.overrideWith((ref) { + final user = ref.watch(currentUserProvider); + if (user == null) { + throw Exception('User must be logged in to video'); + } - final timelineService = ref.watch(timelineFactoryProvider).video(user.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + final timelineService = ref.watch(timelineFactoryProvider).video(user.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], - child: Timeline( - appBar: MesmerizingSliverAppBar(title: 'videos'.t()), - ), + child: Timeline(appBar: MesmerizingSliverAppBar(title: 'videos'.t())), ); } } diff --git a/mobile/lib/presentation/pages/local_timeline.page.dart b/mobile/lib/presentation/pages/local_timeline.page.dart index d322b5d9d..67bc17cb3 100644 --- a/mobile/lib/presentation/pages/local_timeline.page.dart +++ b/mobile/lib/presentation/pages/local_timeline.page.dart @@ -17,13 +17,11 @@ class LocalTimelinePage extends StatelessWidget { Widget build(BuildContext context) { return ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final timelineService = ref.watch(timelineFactoryProvider).localAlbum(albumId: album.id); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + timelineServiceProvider.overrideWith((ref) { + final timelineService = ref.watch(timelineFactoryProvider).localAlbum(albumId: album.id); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], child: Timeline( appBar: MesmerizingSliverAppBar(title: album.name), diff --git a/mobile/lib/presentation/pages/search/drift_search.page.dart b/mobile/lib/presentation/pages/search/drift_search.page.dart index 868f1ff29..f61fad548 100644 --- a/mobile/lib/presentation/pages/search/drift_search.page.dart +++ b/mobile/lib/presentation/pages/search/drift_search.page.dart @@ -44,12 +44,7 @@ class DriftSearchPage extends HookConsumerWidget { location: preFilter?.location ?? SearchLocationFilter(), camera: preFilter?.camera ?? SearchCameraFilter(), date: preFilter?.date ?? SearchDateFilter(), - display: preFilter?.display ?? - SearchDisplayFilters( - isNotInAlbum: false, - isArchive: false, - isFavorite: false, - ), + display: preFilter?.display ?? SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), mediaType: preFilter?.mediaType ?? AssetType.other, language: "${context.locale.languageCode}-${context.locale.countryCode}", ), @@ -68,10 +63,7 @@ class DriftSearchPage extends HookConsumerWidget { SnackBar searchInfoSnackBar(String message) { return SnackBar( - content: Text( - message, - style: context.textTheme.labelLarge, - ), + content: Text(message, style: context.textTheme.labelLarge), showCloseIcon: true, behavior: SnackBarBehavior.fixed, closeIconColor: context.colorScheme.onSurface, @@ -92,9 +84,7 @@ class DriftSearchPage extends HookConsumerWidget { final hasResult = await ref.watch(paginatedSearchProvider.notifier).search(filter.value); if (!hasResult) { - context.showSnackBar( - searchInfoSnackBar('search_no_result'.t(context: context)), - ); + context.showSnackBar(searchInfoSnackBar('search_no_result'.t(context: context))); } previousFilter.value = filter.value; @@ -106,9 +96,7 @@ class DriftSearchPage extends HookConsumerWidget { final hasResult = await ref.watch(paginatedSearchProvider.notifier).search(filter.value); if (!hasResult) { - context.showSnackBar( - searchInfoSnackBar('search_no_more_result'.t(context: context)), - ); + context.showSnackBar(searchInfoSnackBar('search_no_more_result'.t(context: context))); } isSearching.value = false; @@ -116,39 +104,26 @@ class DriftSearchPage extends HookConsumerWidget { searchPreFilter() { if (preFilter != null) { - Future.delayed( - Duration.zero, - () { - search(); + Future.delayed(Duration.zero, () { + search(); - if (preFilter!.location.city != null) { - locationCurrentFilterWidget.value = Text( - preFilter!.location.city!, - style: context.textTheme.labelLarge, - ); - } - }, - ); + if (preFilter!.location.city != null) { + locationCurrentFilterWidget.value = Text(preFilter!.location.city!, style: context.textTheme.labelLarge); + } + }); } } - useEffect( - () { - Future.microtask( - () => ref.invalidate(paginatedSearchProvider), - ); - searchPreFilter(); + useEffect(() { + Future.microtask(() => ref.invalidate(paginatedSearchProvider)); + searchPreFilter(); - return null; - }, - [], - ); + return null; + }, []); showPeoplePicker() { handleOnSelect(Set value) { - filter.value = filter.value.copyWith( - people: value, - ); + filter.value = filter.value.copyWith(people: value); peopleCurrentFilterWidget.value = Text( value.map((e) => e.name != '' ? e.name : 'no_name'.t(context: context)).join(', '), @@ -157,9 +132,7 @@ class DriftSearchPage extends HookConsumerWidget { } handleClear() { - filter.value = filter.value.copyWith( - people: {}, - ); + filter.value = filter.value.copyWith(people: {}); peopleCurrentFilterWidget.value = null; search(); @@ -175,10 +148,7 @@ class DriftSearchPage extends HookConsumerWidget { expanded: true, onSearch: search, onClear: handleClear, - child: PeoplePicker( - onSelect: handleOnSelect, - filter: filter.value.people, - ), + child: PeoplePicker(onSelect: handleOnSelect, filter: filter.value.people), ), ), ); @@ -187,11 +157,7 @@ class DriftSearchPage extends HookConsumerWidget { showLocationPicker() { handleOnSelect(Map value) { filter.value = filter.value.copyWith( - location: SearchLocationFilter( - country: value['country'], - city: value['city'], - state: value['state'], - ), + location: SearchLocationFilter(country: value['country'], city: value['city'], state: value['state']), ); final locationText = []; @@ -207,16 +173,11 @@ class DriftSearchPage extends HookConsumerWidget { locationText.add(value['city']!); } - locationCurrentFilterWidget.value = Text( - locationText.join(', '), - style: context.textTheme.labelLarge, - ); + locationCurrentFilterWidget.value = Text(locationText.join(', '), style: context.textTheme.labelLarge); } handleClear() { - filter.value = filter.value.copyWith( - location: SearchLocationFilter(), - ); + filter.value = filter.value.copyWith(location: SearchLocationFilter()); locationCurrentFilterWidget.value = null; search(); @@ -233,15 +194,10 @@ class DriftSearchPage extends HookConsumerWidget { child: Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: Container( - padding: EdgeInsets.only( - bottom: context.viewInsets.bottom, - ), + padding: EdgeInsets.only(bottom: context.viewInsets.bottom), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: LocationPicker( - onSelected: handleOnSelect, - filter: filter.value.location, - ), + child: LocationPicker(onSelected: handleOnSelect, filter: filter.value.location), ), ), ), @@ -252,10 +208,7 @@ class DriftSearchPage extends HookConsumerWidget { showCameraPicker() { handleOnSelect(Map value) { filter.value = filter.value.copyWith( - camera: SearchCameraFilter( - make: value['make'], - model: value['model'], - ), + camera: SearchCameraFilter(make: value['make'], model: value['model']), ); cameraCurrentFilterWidget.value = Text( @@ -265,9 +218,7 @@ class DriftSearchPage extends HookConsumerWidget { } handleClear() { - filter.value = filter.value.copyWith( - camera: SearchCameraFilter(), - ); + filter.value = filter.value.copyWith(camera: SearchCameraFilter()); cameraCurrentFilterWidget.value = null; search(); @@ -283,10 +234,7 @@ class DriftSearchPage extends HookConsumerWidget { onClear: handleClear, child: Padding( padding: const EdgeInsets.all(16.0), - child: CameraPicker( - onSelect: handleOnSelect, - filter: filter.value.camera, - ), + child: CameraPicker(onSelect: handleOnSelect, filter: filter.value.camera), ), ), ); @@ -318,9 +266,7 @@ class DriftSearchPage extends HookConsumerWidget { ); if (date == null) { - filter.value = filter.value.copyWith( - date: SearchDateFilter(), - ); + filter.value = filter.value.copyWith(date: SearchDateFilter()); dateRangeCurrentFilterWidget.value = null; search(); @@ -330,13 +276,7 @@ class DriftSearchPage extends HookConsumerWidget { filter.value = filter.value.copyWith( date: SearchDateFilter( takenAfter: date.start, - takenBefore: date.end.add( - const Duration( - hours: 23, - minutes: 59, - seconds: 59, - ), - ), + takenBefore: date.end.add(const Duration(hours: 23, minutes: 59, seconds: 59)), ), ); @@ -365,24 +305,20 @@ class DriftSearchPage extends HookConsumerWidget { // MEDIA PICKER showMediaTypePicker() { handleOnSelected(AssetType assetType) { - filter.value = filter.value.copyWith( - mediaType: assetType, - ); + filter.value = filter.value.copyWith(mediaType: assetType); mediaTypeCurrentFilterWidget.value = Text( assetType == AssetType.image ? 'image'.t(context: context) : assetType == AssetType.video - ? 'video'.t(context: context) - : 'all'.t(context: context), + ? 'video'.t(context: context) + : 'all'.t(context: context), style: context.textTheme.labelLarge, ); } handleClear() { - filter.value = filter.value.copyWith( - mediaType: AssetType.other, - ); + filter.value = filter.value.copyWith(mediaType: AssetType.other); mediaTypeCurrentFilterWidget.value = null; search(); @@ -394,10 +330,7 @@ class DriftSearchPage extends HookConsumerWidget { title: 'search_filter_media_type_title'.t(context: context), onSearch: search, onClear: handleClear, - child: MediaTypePicker( - onSelect: handleOnSelected, - filter: filter.value.mediaType, - ), + child: MediaTypePicker(onSelect: handleOnSelected, filter: filter.value.mediaType), ), ); } @@ -409,33 +342,19 @@ class DriftSearchPage extends HookConsumerWidget { value.forEach((key, value) { switch (key) { case DisplayOption.notInAlbum: - filter.value = filter.value.copyWith( - display: filter.value.display.copyWith( - isNotInAlbum: value, - ), - ); + filter.value = filter.value.copyWith(display: filter.value.display.copyWith(isNotInAlbum: value)); if (value) { - filterText.add( - 'search_filter_display_option_not_in_album'.t(context: context), - ); + filterText.add('search_filter_display_option_not_in_album'.t(context: context)); } break; case DisplayOption.archive: - filter.value = filter.value.copyWith( - display: filter.value.display.copyWith( - isArchive: value, - ), - ); + filter.value = filter.value.copyWith(display: filter.value.display.copyWith(isArchive: value)); if (value) { filterText.add('archive'.t(context: context)); } break; case DisplayOption.favorite: - filter.value = filter.value.copyWith( - display: filter.value.display.copyWith( - isFavorite: value, - ), - ); + filter.value = filter.value.copyWith(display: filter.value.display.copyWith(isFavorite: value)); if (value) { filterText.add('favorite'.t(context: context)); } @@ -448,19 +367,12 @@ class DriftSearchPage extends HookConsumerWidget { return; } - displayOptionCurrentFilterWidget.value = Text( - filterText.join(', '), - style: context.textTheme.labelLarge, - ); + displayOptionCurrentFilterWidget.value = Text(filterText.join(', '), style: context.textTheme.labelLarge); } handleClear() { filter.value = filter.value.copyWith( - display: SearchDisplayFilters( - isNotInAlbum: false, - isArchive: false, - isFavorite: false, - ), + display: SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), ); displayOptionCurrentFilterWidget.value = null; @@ -473,10 +385,7 @@ class DriftSearchPage extends HookConsumerWidget { title: 'display_options'.t(context: context), onSearch: search, onClear: handleClear, - child: DisplayOptionPicker( - onSelect: handleOnSelect, - filter: filter.value.display, - ), + child: DisplayOptionPicker(onSelect: handleOnSelect, filter: filter.value.display), ), ); } @@ -484,27 +393,15 @@ class DriftSearchPage extends HookConsumerWidget { handleTextSubmitted(String value) { switch (textSearchType.value) { case TextSearchType.context: - filter.value = filter.value.copyWith( - filename: '', - context: value, - description: '', - ); + filter.value = filter.value.copyWith(filename: '', context: value, description: ''); break; case TextSearchType.filename: - filter.value = filter.value.copyWith( - filename: value, - context: '', - description: '', - ); + filter.value = filter.value.copyWith(filename: value, context: '', description: ''); break; case TextSearchType.description: - filter.value = filter.value.copyWith( - filename: '', - context: '', - description: value, - ); + filter.value = filter.value.copyWith(filename: '', context: '', description: value); break; } @@ -512,10 +409,10 @@ class DriftSearchPage extends HookConsumerWidget { } IconData getSearchPrefixIcon() => switch (textSearchType.value) { - TextSearchType.context => Icons.image_search_rounded, - TextSearchType.filename => Icons.abc_rounded, - TextSearchType.description => Icons.text_snippet_outlined, - }; + TextSearchType.context => Icons.image_search_rounded, + TextSearchType.filename => Icons.abc_rounded, + TextSearchType.description => Icons.text_snippet_outlined, + }; return Scaffold( resizeToAvoidBottomInset: false, @@ -528,21 +425,11 @@ class DriftSearchPage extends HookConsumerWidget { style: MenuStyle( elevation: const WidgetStatePropertyAll(1), shape: WidgetStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ), - ), - padding: const WidgetStatePropertyAll( - EdgeInsets.all(4), + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), ), + padding: const WidgetStatePropertyAll(EdgeInsets.all(4)), ), - builder: ( - BuildContext context, - MenuController controller, - Widget? child, - ) { + builder: (BuildContext context, MenuController controller, Widget? child) { return IconButton( onPressed: () { if (controller.isOpen) { @@ -616,13 +503,8 @@ class DriftSearchPage extends HookConsumerWidget { ], title: Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(0), - width: 0, - ), - borderRadius: const BorderRadius.all( - Radius.circular(24), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(0), width: 0), + borderRadius: const BorderRadius.all(Radius.circular(24)), gradient: LinearGradient( colors: [ context.colorScheme.primary.withValues(alpha: 0.075), @@ -638,12 +520,7 @@ class DriftSearchPage extends HookConsumerWidget { key: const Key('search_text_field'), controller: textSearchController, contentPadding: preFilter != null ? const EdgeInsets.only(left: 24) : const EdgeInsets.all(8), - prefixIcon: preFilter != null - ? null - : Icon( - getSearchPrefixIcon(), - color: context.colorScheme.primary, - ), + prefixIcon: preFilter != null ? null : Icon(getSearchPrefixIcon(), color: context.colorScheme.primary), onSubmitted: handleTextSubmitted, focusNode: ref.watch(searchInputFocusProvider), ), @@ -705,10 +582,7 @@ class DriftSearchPage extends HookConsumerWidget { ), ), if (isSearching.value) - const SliverFillRemaining( - hasScrollBody: false, - child: Center(child: CircularProgressIndicator()), - ) + const SliverFillRemaining(hasScrollBody: false, child: Center(child: CircularProgressIndicator())) else _SearchResultGrid(onScrollEnd: loadMoreSearchResult), ], @@ -747,19 +621,13 @@ class _SearchResultGrid extends ConsumerWidget { child: SliverFillRemaining( child: ProviderScope( overrides: [ - timelineServiceProvider.overrideWith( - (ref) { - final timelineService = ref.watch(timelineFactoryProvider).fromAssets(searchResult.assets); - ref.onDispose(timelineService.dispose); - return timelineService; - }, - ), + timelineServiceProvider.overrideWith((ref) { + final timelineService = ref.watch(timelineFactoryProvider).fromAssets(searchResult.assets); + ref.onDispose(timelineService.dispose); + return timelineService; + }), ], - child: Timeline( - key: ValueKey(searchResult.totalAssets), - appBar: null, - groupBy: GroupAssetsBy.none, - ), + child: Timeline(key: ValueKey(searchResult.totalAssets), appBar: null, groupBy: GroupAssetsBy.none), ), ), ); @@ -784,16 +652,10 @@ class _SearchEmptyContent extends StatelessWidget { ), const SizedBox(height: 16), Center( - child: Text( - 'search_page_search_photos_videos'.t(context: context), - style: context.textTheme.labelLarge, - ), + child: Text('search_page_search_photos_videos'.t(context: context), style: context.textTheme.labelLarge), ), const SizedBox(height: 32), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: _QuickLinkList(), - ), + const Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: _QuickLinkList()), ], ), ); @@ -807,13 +669,8 @@ class _QuickLinkList extends StatelessWidget { Widget build(BuildContext context) { return Container( decoration: BoxDecoration( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - border: Border.all( - color: context.colorScheme.outline.withAlpha(10), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), + border: Border.all(color: context.colorScheme.outline.withAlpha(10), width: 1), gradient: LinearGradient( colors: [ context.colorScheme.primary.withAlpha(10), @@ -876,19 +733,9 @@ class _QuickLink extends StatelessWidget { ); return ListTile( - shape: RoundedRectangleBorder( - borderRadius: borderRadius, - ), - leading: Icon( - icon, - size: 26, - ), - title: Text( - title, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w500, - ), - ), + shape: RoundedRectangleBorder(borderRadius: borderRadius), + leading: Icon(icon, size: 26), + title: Text(title, style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w500)), onTap: onTap, ); } diff --git a/mobile/lib/presentation/pages/search/paginated_search.provider.dart b/mobile/lib/presentation/pages/search/paginated_search.provider.dart index c93d002b9..718a241ba 100644 --- a/mobile/lib/presentation/pages/search/paginated_search.provider.dart +++ b/mobile/lib/presentation/pages/search/paginated_search.provider.dart @@ -24,10 +24,7 @@ class PaginatedSearchNotifier extends StateNotifier { return false; } - state = SearchResult( - assets: [...state.assets, ...result.assets], - nextPage: result.nextPage, - ); + state = SearchResult(assets: [...state.assets, ...result.assets], nextPage: result.nextPage); return true; } diff --git a/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart index e461a9028..d30ba07d0 100644 --- a/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart @@ -27,10 +27,7 @@ class ArchiveActionButton extends ConsumerWidget { EventStream.shared.emit(const ViewerReloadAssetEvent()); } - final successMessage = 'archive_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'archive_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart index 9704c4b13..5ec6c8bc5 100644 --- a/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart @@ -39,14 +39,10 @@ class BaseActionButton extends StatelessWidget { } return ConstrainedBox( - constraints: BoxConstraints( - maxWidth: maxWidth, - ), + constraints: BoxConstraints(maxWidth: maxWidth), child: MaterialButton( padding: const EdgeInsets.all(10), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(20)), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20))), textColor: textColor, onPressed: onPressed, onLongPress: onLongPressed, @@ -59,10 +55,7 @@ class BaseActionButton extends StatelessWidget { const SizedBox(height: 8), Text( label, - style: const TextStyle( - fontSize: 14.0, - fontWeight: FontWeight.w400, - ), + style: const TextStyle(fontSize: 14.0, fontWeight: FontWeight.w400), maxLines: 3, textAlign: TextAlign.center, softWrap: true, diff --git a/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart index c80dbaaf2..26b8ba6f4 100644 --- a/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart @@ -20,10 +20,7 @@ class CastActionButton extends ConsumerWidget { iconColor: isCasting ? context.primaryColor : null, // null = default color label: "cast".t(context: context), onPressed: () { - showDialog( - context: context, - builder: (context) => const CastDialog(), - ); + showDialog(context: context, builder: (context) => const CastDialog()); }, menuItem: menuItem, ); diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart index f910a2a9e..723700af5 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart @@ -40,9 +40,7 @@ class DeleteActionButton extends ConsumerWidget { onPressed: () => Navigator.of(context).pop(true), child: Text( 'confirm'.t(context: context), - style: TextStyle( - color: context.colorScheme.error, - ), + style: TextStyle(color: context.colorScheme.error), ), ), ], @@ -58,10 +56,7 @@ class DeleteActionButton extends ConsumerWidget { EventStream.shared.emit(const ViewerReloadAssetEvent()); } - final successMessage = 'delete_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'delete_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart index 7a9465dfb..cccdee9b3 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart @@ -33,10 +33,7 @@ class DeleteLocalActionButton extends ConsumerWidget { return; } - final successMessage = 'delete_local_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'delete_local_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_trash_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_trash_action_button.widget.dart index dafbdbc78..cb0e7091c 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_trash_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_trash_action_button.widget.dart @@ -43,17 +43,10 @@ class DeleteTrashActionButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return TextButton.icon( - icon: Icon( - Icons.delete_forever, - color: Colors.red[400], - ), + icon: Icon(Icons.delete_forever, color: Colors.red[400]), label: Text( "delete".t(context: context), - style: TextStyle( - fontSize: 14, - color: Colors.red[400], - fontWeight: FontWeight.bold, - ), + style: TextStyle(fontSize: 14, color: Colors.red[400], fontWeight: FontWeight.bold), ), onPressed: () => _onTap(context, ref), ); diff --git a/mobile/lib/presentation/widgets/action_buttons/edit_location_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/edit_location_action_button.widget.dart index fc642483b..1a8a1a5c3 100644 --- a/mobile/lib/presentation/widgets/action_buttons/edit_location_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/edit_location_action_button.widget.dart @@ -25,10 +25,7 @@ class EditLocationActionButton extends ConsumerWidget { ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'edit_location_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'edit_location_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart index c330a7bbb..0aca5158e 100644 --- a/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart @@ -12,11 +12,7 @@ class FavoriteActionButton extends ConsumerWidget { final ActionSource source; final bool menuItem; - const FavoriteActionButton({ - super.key, - required this.source, - this.menuItem = false, - }); + const FavoriteActionButton({super.key, required this.source, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -31,10 +27,7 @@ class FavoriteActionButton extends ConsumerWidget { ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'favorite_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'favorite_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart index 8857a1b2d..a1f6f7e7d 100644 --- a/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart @@ -12,11 +12,7 @@ class RemoveFromAlbumActionButton extends ConsumerWidget { final String albumId; final ActionSource source; - const RemoveFromAlbumActionButton({ - super.key, - required this.albumId, - required this.source, - }); + const RemoveFromAlbumActionButton({super.key, required this.albumId, required this.source}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { diff --git a/mobile/lib/presentation/widgets/action_buttons/restore_trash_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/restore_trash_action_button.widget.dart index 7cdc28e1e..e7928bd32 100644 --- a/mobile/lib/presentation/widgets/action_buttons/restore_trash_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/restore_trash_action_button.widget.dart @@ -20,10 +20,7 @@ class RestoreTrashActionButton extends ConsumerWidget { final result = await ref.read(actionProvider.notifier).restoreTrash(source); ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'assets_restored_count'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'assets_restored_count'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( @@ -38,16 +35,8 @@ class RestoreTrashActionButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return TextButton.icon( - icon: const Icon( - Icons.history_rounded, - ), - label: Text( - 'restore'.t(), - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), + icon: const Icon(Icons.history_rounded), + label: Text('restore'.t(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)), onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/stack_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/stack_action_button.widget.dart index d448c5ce8..22fccf547 100644 --- a/mobile/lib/presentation/widgets/action_buttons/stack_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/stack_action_button.widget.dart @@ -27,10 +27,7 @@ class StackActionButton extends ConsumerWidget { final result = await ref.read(actionProvider.notifier).stack(user.id, source); ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'stack_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'stack_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart index d26bdfad0..df8f54460 100644 --- a/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart @@ -30,10 +30,7 @@ class TrashActionButton extends ConsumerWidget { EventStream.shared.emit(const ViewerReloadAssetEvent()); } - final successMessage = 'trash_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'trash_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart index d01a5cc47..b457a1b4c 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart @@ -21,10 +21,7 @@ class UnArchiveActionButton extends ConsumerWidget { final result = await ref.read(actionProvider.notifier).unArchive(source); ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'unarchive_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'unarchive_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart index a45bdfb06..7fdc5e81e 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart @@ -12,11 +12,7 @@ class UnFavoriteActionButton extends ConsumerWidget { final ActionSource source; final bool menuItem; - const UnFavoriteActionButton({ - super.key, - required this.source, - this.menuItem = false, - }); + const UnFavoriteActionButton({super.key, required this.source, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -31,10 +27,7 @@ class UnFavoriteActionButton extends ConsumerWidget { ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'unfavorite_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'unfavorite_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart index bf96e6ea4..ecc8a39c7 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart @@ -21,10 +21,7 @@ class UnStackActionButton extends ConsumerWidget { final result = await ref.read(actionProvider.notifier).unStack(source); ref.read(multiSelectProvider.notifier).reset(); - final successMessage = 'unstack_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'unstack_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart index 9e2fc9b30..f037d365d 100644 --- a/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart @@ -20,10 +20,7 @@ class UploadActionButton extends ConsumerWidget { final result = await ref.read(actionProvider.notifier).upload(source); - final successMessage = 'upload_action_prompt'.t( - context: context, - args: {'count': result.count.toString()}, - ); + final successMessage = 'upload_action_prompt'.t(context: context, args: {'count': result.count.toString()}); if (context.mounted) { ImmichToast.show( diff --git a/mobile/lib/presentation/widgets/album/album_selector.widget.dart b/mobile/lib/presentation/widgets/album/album_selector.widget.dart index 5d9378eca..cb6a38041 100644 --- a/mobile/lib/presentation/widgets/album/album_selector.widget.dart +++ b/mobile/lib/presentation/widgets/album/album_selector.widget.dart @@ -27,10 +27,7 @@ typedef AlbumSelectorCallback = void Function(RemoteAlbum album); class AlbumSelector extends ConsumerStatefulWidget { final AlbumSelectorCallback onAlbumSelected; - const AlbumSelector({ - super.key, - required this.onAlbumSelected, - }); + const AlbumSelector({super.key, required this.onAlbumSelected}); @override ConsumerState createState() => _AlbumSelectorState(); @@ -113,21 +110,10 @@ class _AlbumSelectorState extends ConsumerState { onSearch: onSearch, searchController: searchController, ), - _QuickSortAndViewMode( - isGrid: isGrid, - onToggleViewMode: toggleViewMode, - ), + _QuickSortAndViewMode(isGrid: isGrid, onToggleViewMode: toggleViewMode), isGrid - ? _AlbumGrid( - albums: albums, - userId: userId, - onAlbumSelected: widget.onAlbumSelected, - ) - : _AlbumList( - albums: albums, - userId: userId, - onAlbumSelected: widget.onAlbumSelected, - ), + ? _AlbumGrid(albums: albums, userId: userId, onAlbumSelected: widget.onAlbumSelected) + : _AlbumList(albums: albums, userId: userId, onAlbumSelected: widget.onAlbumSelected), ], ); } @@ -151,18 +137,12 @@ class _SortButtonState extends ConsumerState<_SortButton> { setState(() { albumSortIsReverse = !albumSortIsReverse; }); - ref.read(remoteAlbumProvider.notifier).sortFilteredAlbums( - sortMode, - isReverse: albumSortIsReverse, - ); + ref.read(remoteAlbumProvider.notifier).sortFilteredAlbums(sortMode, isReverse: albumSortIsReverse); } else { setState(() { albumSortOption = sortMode; }); - ref.read(remoteAlbumProvider.notifier).sortFilteredAlbums( - sortMode, - isReverse: albumSortIsReverse, - ); + ref.read(remoteAlbumProvider.notifier).sortFilteredAlbums(sortMode, isReverse: albumSortIsReverse); } } @@ -172,15 +152,9 @@ class _SortButtonState extends ConsumerState<_SortButton> { style: MenuStyle( elevation: const WidgetStatePropertyAll(1), shape: WidgetStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ), - ), - padding: const WidgetStatePropertyAll( - EdgeInsets.all(4), + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), ), + padding: const WidgetStatePropertyAll(EdgeInsets.all(4)), ), consumeOutsideTap: true, menuChildren: RemoteAlbumSortMode.values @@ -188,33 +162,27 @@ class _SortButtonState extends ConsumerState<_SortButton> { (sortMode) => MenuItemButton( leadingIcon: albumSortOption == sortMode ? albumSortIsReverse - ? Icon( - Icons.keyboard_arrow_down, - color: albumSortOption == sortMode - ? context.colorScheme.onPrimary - : context.colorScheme.onSurface, - ) - : Icon( - Icons.keyboard_arrow_up_rounded, - color: albumSortOption == sortMode - ? context.colorScheme.onPrimary - : context.colorScheme.onSurface, - ) + ? Icon( + Icons.keyboard_arrow_down, + color: albumSortOption == sortMode + ? context.colorScheme.onPrimary + : context.colorScheme.onSurface, + ) + : Icon( + Icons.keyboard_arrow_up_rounded, + color: albumSortOption == sortMode + ? context.colorScheme.onPrimary + : context.colorScheme.onSurface, + ) : const Icon(Icons.abc, color: Colors.transparent), onPressed: () => onMenuTapped(sortMode), style: ButtonStyle( - padding: WidgetStateProperty.all( - const EdgeInsets.fromLTRB(16, 16, 32, 16), - ), + padding: WidgetStateProperty.all(const EdgeInsets.fromLTRB(16, 16, 32, 16)), backgroundColor: WidgetStateProperty.all( albumSortOption == sortMode ? context.colorScheme.primary : Colors.transparent, ), shape: WidgetStateProperty.all( - const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(24), - ), - ), + const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(24))), ), ), child: Text( @@ -243,12 +211,8 @@ class _SortButtonState extends ConsumerState<_SortButton> { Padding( padding: const EdgeInsets.only(right: 5), child: albumSortIsReverse - ? const Icon( - Icons.keyboard_arrow_down, - ) - : const Icon( - Icons.keyboard_arrow_up_rounded, - ), + ? const Icon(Icons.keyboard_arrow_down) + : const Icon(Icons.keyboard_arrow_up_rounded), ), Text( albumSortOption.key.t(context: context), @@ -287,13 +251,8 @@ class _SearchBar extends StatelessWidget { sliver: SliverToBoxAdapter( child: Container( decoration: BoxDecoration( - border: Border.all( - color: context.colorScheme.onSurface.withAlpha(0), - width: 0, - ), - borderRadius: const BorderRadius.all( - Radius.circular(24), - ), + border: Border.all(color: context.colorScheme.onSurface.withAlpha(0), width: 0), + borderRadius: const BorderRadius.all(Radius.circular(24)), gradient: LinearGradient( colors: [ context.colorScheme.primary.withValues(alpha: 0.075), @@ -311,10 +270,7 @@ class _SearchBar extends StatelessWidget { hintText: 'search_albums'.tr(), prefixIcon: const Icon(Icons.search_rounded), suffixIcon: searchController.text.isNotEmpty - ? IconButton( - icon: const Icon(Icons.clear_rounded), - onPressed: onClearSearch, - ) + ? IconButton(icon: const Icon(Icons.clear_rounded), onPressed: onClearSearch) : null, controller: searchController, onChanged: (_) => onSearch(searchController.text, filterMode), @@ -362,10 +318,7 @@ class _QuickFilterButtonRow extends StatelessWidget { isSelected: filterMode == QuickFilterMode.sharedWithMe, onTap: () { onChangeFilter(QuickFilterMode.sharedWithMe); - onSearch( - searchController.text, - QuickFilterMode.sharedWithMe, - ); + onSearch(searchController.text, QuickFilterMode.sharedWithMe); }, ), _QuickFilterButton( @@ -373,10 +326,7 @@ class _QuickFilterButtonRow extends StatelessWidget { isSelected: filterMode == QuickFilterMode.myAlbums, onTap: () { onChangeFilter(QuickFilterMode.myAlbums); - onSearch( - searchController.text, - QuickFilterMode.myAlbums, - ); + onSearch(searchController.text, QuickFilterMode.myAlbums); }, ), ], @@ -387,11 +337,7 @@ class _QuickFilterButtonRow extends StatelessWidget { } class _QuickFilterButton extends StatelessWidget { - const _QuickFilterButton({ - required this.isSelected, - required this.onTap, - required this.label, - }); + const _QuickFilterButton({required this.isSelected, required this.onTap, required this.label}); final bool isSelected; final VoidCallback onTap; @@ -402,18 +348,11 @@ class _QuickFilterButton extends StatelessWidget { return TextButton( onPressed: onTap, style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - isSelected ? context.colorScheme.primary : Colors.transparent, - ), + backgroundColor: WidgetStateProperty.all(isSelected ? context.colorScheme.primary : Colors.transparent), shape: WidgetStateProperty.all( RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.circular(20), - ), - side: BorderSide( - color: context.colorScheme.onSurface.withAlpha(25), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(20)), + side: BorderSide(color: context.colorScheme.onSurface.withAlpha(25), width: 1), ), ), ), @@ -429,10 +368,7 @@ class _QuickFilterButton extends StatelessWidget { } class _QuickSortAndViewMode extends StatelessWidget { - const _QuickSortAndViewMode({ - required this.isGrid, - required this.onToggleViewMode, - }); + const _QuickSortAndViewMode({required this.isGrid, required this.onToggleViewMode}); final bool isGrid; final VoidCallback onToggleViewMode; @@ -447,10 +383,7 @@ class _QuickSortAndViewMode extends StatelessWidget { children: [ const _SortButton(), IconButton( - icon: Icon( - isGrid ? Icons.view_list_outlined : Icons.grid_view_outlined, - size: 24, - ), + icon: Icon(isGrid ? Icons.view_list_outlined : Icons.grid_view_outlined, size: 24), onPressed: onToggleViewMode, ), ], @@ -461,11 +394,7 @@ class _QuickSortAndViewMode extends StatelessWidget { } class _AlbumList extends ConsumerWidget { - const _AlbumList({ - required this.albums, - required this.userId, - required this.onAlbumSelected, - }); + const _AlbumList({required this.albums, required this.userId, required this.onAlbumSelected}); final List albums; final String? userId; @@ -476,10 +405,7 @@ class _AlbumList extends ConsumerWidget { if (albums.isEmpty) { return const SliverToBoxAdapter( child: Center( - child: Padding( - padding: EdgeInsets.all(20.0), - child: Text('No albums found'), - ), + child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')), ), ); } @@ -491,51 +417,25 @@ class _AlbumList extends ConsumerWidget { final album = albums[index]; return Padding( - padding: const EdgeInsets.only( - bottom: 8.0, - ), + padding: const EdgeInsets.only(bottom: 8.0), child: LargeLeadingTile( title: Text( album.name, maxLines: 2, overflow: TextOverflow.ellipsis, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), ), subtitle: Text( - '${'items_count'.t( - context: context, - args: { - 'count': album.assetCount, - }, - )} • ${album.ownerId != userId ? 'shared_by_user'.t( - context: context, - args: { - 'user': album.ownerName, - }, - ) : 'owned'.t(context: context)}', + '${'items_count'.t(context: context, args: {'count': album.assetCount})} • ${album.ownerId != userId ? 'shared_by_user'.t(context: context, args: {'user': album.ownerName}) : 'owned'.t(context: context)}', overflow: TextOverflow.ellipsis, - style: context.textTheme.bodyMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + style: context.textTheme.bodyMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), onTap: () => onAlbumSelected(album), - leadingPadding: const EdgeInsets.only( - right: 16, - ), + leadingPadding: const EdgeInsets.only(right: 16), leading: album.thumbnailAssetId != null ? ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(15), - ), - child: SizedBox( - width: 80, - height: 80, - child: Thumbnail( - remoteId: album.thumbnailAssetId, - ), - ), + borderRadius: const BorderRadius.all(Radius.circular(15)), + child: SizedBox(width: 80, height: 80, child: Thumbnail(remoteId: album.thumbnailAssetId)), ) : SizedBox( width: 80, @@ -544,16 +444,9 @@ class _AlbumList extends ConsumerWidget { decoration: BoxDecoration( color: context.colorScheme.surfaceContainer, borderRadius: const BorderRadius.all(Radius.circular(16)), - border: Border.all( - color: context.colorScheme.outline.withAlpha(50), - width: 1, - ), - ), - child: const Icon( - Icons.photo_album_rounded, - size: 24, - color: Colors.grey, + border: Border.all(color: context.colorScheme.outline.withAlpha(50), width: 1), ), + child: const Icon(Icons.photo_album_rounded, size: 24, color: Colors.grey), ), ), ), @@ -566,11 +459,7 @@ class _AlbumList extends ConsumerWidget { } class _AlbumGrid extends StatelessWidget { - const _AlbumGrid({ - required this.albums, - required this.userId, - required this.onAlbumSelected, - }); + const _AlbumGrid({required this.albums, required this.userId, required this.onAlbumSelected}); final List albums; final String? userId; @@ -581,10 +470,7 @@ class _AlbumGrid extends StatelessWidget { if (albums.isEmpty) { return const SliverToBoxAdapter( child: Center( - child: Padding( - padding: EdgeInsets.all(20.0), - child: Text('No albums found'), - ), + child: Padding(padding: EdgeInsets.all(20.0), child: Text('No albums found')), ), ); } @@ -598,28 +484,17 @@ class _AlbumGrid extends StatelessWidget { crossAxisSpacing: 4, childAspectRatio: .7, ), - delegate: SliverChildBuilderDelegate( - (context, index) { - final album = albums[index]; - return _GridAlbumCard( - album: album, - userId: userId, - onAlbumSelected: onAlbumSelected, - ); - }, - childCount: albums.length, - ), + delegate: SliverChildBuilderDelegate((context, index) { + final album = albums[index]; + return _GridAlbumCard(album: album, userId: userId, onAlbumSelected: onAlbumSelected); + }, childCount: albums.length), ), ); } } class _GridAlbumCard extends ConsumerWidget { - const _GridAlbumCard({ - required this.album, - required this.userId, - required this.onAlbumSelected, - }); + const _GridAlbumCard({required this.album, required this.userId, required this.onAlbumSelected}); final RemoteAlbum album; final String? userId; @@ -633,13 +508,8 @@ class _GridAlbumCard extends ConsumerWidget { elevation: 0, color: context.colorScheme.surfaceBright, shape: RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.circular(16), - ), - side: BorderSide( - color: context.colorScheme.onSurface.withAlpha(25), - width: 1, - ), + borderRadius: const BorderRadius.all(Radius.circular(16)), + side: BorderSide(color: context.colorScheme.onSurface.withAlpha(25), width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -647,22 +517,14 @@ class _GridAlbumCard extends ConsumerWidget { Expanded( flex: 2, child: ClipRRect( - borderRadius: const BorderRadius.vertical( - top: Radius.circular(15), - ), + borderRadius: const BorderRadius.vertical(top: Radius.circular(15)), child: SizedBox( width: double.infinity, child: album.thumbnailAssetId != null - ? Thumbnail( - remoteId: album.thumbnailAssetId, - ) + ? Thumbnail(remoteId: album.thumbnailAssetId) : Container( color: context.colorScheme.surfaceContainerHighest, - child: const Icon( - Icons.photo_album_rounded, - size: 40, - color: Colors.grey, - ), + child: const Icon(Icons.photo_album_rounded, size: 40, color: Colors.grey), ), ), ), @@ -679,27 +541,13 @@ class _GridAlbumCard extends ConsumerWidget { album.name, maxLines: 2, overflow: TextOverflow.ellipsis, - style: context.textTheme.titleSmall?.copyWith( - fontWeight: FontWeight.w600, - ), + style: context.textTheme.titleSmall?.copyWith(fontWeight: FontWeight.w600), ), Text( - '${'items_count'.t( - context: context, - args: { - 'count': album.assetCount, - }, - )} • ${album.ownerId != userId ? 'shared_by_user'.t( - context: context, - args: { - 'user': album.ownerName, - }, - ) : 'owned'.t(context: context)}', + '${'items_count'.t(context: context, args: {'count': album.assetCount})} • ${album.ownerId != userId ? 'shared_by_user'.t(context: context, args: {'user': album.ownerName}) : 'owned'.t(context: context)}', maxLines: 1, overflow: TextOverflow.ellipsis, - style: context.textTheme.labelMedium?.copyWith( - color: context.colorScheme.onSurfaceSecondary, - ), + style: context.textTheme.labelMedium?.copyWith(color: context.colorScheme.onSurfaceSecondary), ), ], ), @@ -718,17 +566,15 @@ class AddToAlbumHeader extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { Future onCreateAlbum() async { - final newAlbum = await ref.read(remoteAlbumProvider.notifier).createAlbum( + final newAlbum = await ref + .read(remoteAlbumProvider.notifier) + .createAlbum( title: "Untitled Album", assetIds: ref.read(multiSelectProvider).selectedAssets.map((e) => (e as RemoteAsset).id).toList(), ); if (newAlbum == null) { - ImmichToast.show( - context: context, - toastType: ToastType.error, - msg: 'errors.failed_to_create_album'.tr(), - ); + ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr()); return; } @@ -736,38 +582,23 @@ class AddToAlbumHeader extends ConsumerWidget { } return SliverPadding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), + padding: const EdgeInsets.symmetric(horizontal: 16), sliver: SliverToBoxAdapter( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "add_to_album", - style: context.textTheme.titleSmall, - ).tr(), + Text("add_to_album", style: context.textTheme.titleSmall).tr(), TextButton.icon( style: TextButton.styleFrom( - padding: const EdgeInsets.symmetric( - horizontal: 8, - vertical: 4, - ), // remove internal padding + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), // remove internal padding minimumSize: const Size(0, 0), // allow shrinking tapTargetSize: MaterialTapTargetSize.shrinkWrap, // remove extra height ), onPressed: onCreateAlbum, - icon: Icon( - Icons.add, - color: context.primaryColor, - ), + icon: Icon(Icons.add, color: context.primaryColor), label: Text( "common_create_new_album", - style: TextStyle( - color: context.primaryColor, - fontWeight: FontWeight.bold, - fontSize: 14, - ), + style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14), ).tr(), ), ], diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart index e78c8ea8a..1eb3366e3 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.provider.dart @@ -13,7 +13,5 @@ class StackChildrenNotifier extends AutoDisposeFamilyAsyncNotifier, BaseAsset?>( - StackChildrenNotifier.new, -); +final stackChildrenNotifier = AsyncNotifierProvider.autoDispose + .family, BaseAsset?>(StackChildrenNotifier.new); diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart index 92f516157..e5d1487d5 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_stack.widget.dart @@ -11,9 +11,7 @@ class AssetStackRow extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - int opacity = ref.watch( - assetViewerProvider.select((state) => state.backgroundOpacity), - ); + int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)); final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); if (!showControls) { @@ -27,11 +25,10 @@ class AssetStackRow extends ConsumerWidget { child: AnimatedOpacity( opacity: opacity / 255, duration: Durations.short2, - child: ref.watch(stackChildrenNotifier(asset)).when( - data: (state) => SizedBox.square( - dimension: 80, - child: _StackList(stack: state), - ), + child: ref + .watch(stackChildrenNotifier(asset)) + .when( + data: (state) => SizedBox.square(dimension: 80, child: _StackList(stack: state)), error: (_, __) => const SizedBox.shrink(), loading: () => const SizedBox.shrink(), ), @@ -49,11 +46,7 @@ class _StackList extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return ListView.builder( scrollDirection: Axis.horizontal, - padding: const EdgeInsets.only( - left: 5, - right: 5, - bottom: 30, - ), + padding: const EdgeInsets.only(left: 5, right: 5, bottom: 30), itemCount: stack.length, itemBuilder: (ctx, index) { final asset = stack[index]; @@ -71,9 +64,7 @@ class _StackList extends ConsumerWidget { ? const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(6)), - border: Border.fromBorderSide( - BorderSide(color: Colors.white, width: 2), - ), + border: Border.fromBorderSide(BorderSide(color: Colors.white, width: 2)), ) : const BoxDecoration( color: Colors.white, @@ -87,10 +78,7 @@ class _StackList extends ConsumerWidget { children: [ Image( fit: BoxFit.cover, - image: getThumbnailImageProvider( - remoteId: asset.id, - size: const Size.square(60), - ), + image: getThumbnailImageProvider(remoteId: asset.id, size: const Size.square(60)), ), if (asset.isVideo) const Icon( @@ -98,11 +86,7 @@ class _StackList extends ConsumerWidget { color: Colors.white, size: 16, shadows: [ - Shadow( - blurRadius: 5.0, - color: Color.fromRGBO(0, 0, 0, 0.6), - offset: Offset(0.0, 0.0), - ), + Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0)), ], ), ], diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart index 8fbc28f07..c6b2360c9 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart @@ -36,12 +36,7 @@ class AssetViewerPage extends StatelessWidget { final TimelineService timelineService; final int? heroOffset; - const AssetViewerPage({ - super.key, - required this.initialIndex, - required this.timelineService, - this.heroOffset, - }); + const AssetViewerPage({super.key, required this.initialIndex, required this.timelineService, this.heroOffset}); @override Widget build(BuildContext context) { @@ -59,12 +54,7 @@ class AssetViewer extends ConsumerStatefulWidget { final Platform? platform; final int? heroOffset; - const AssetViewer({ - super.key, - required this.initialIndex, - this.platform, - this.heroOffset, - }); + const AssetViewer({super.key, required this.initialIndex, this.platform, this.heroOffset}); @override ConsumerState createState() => _AssetViewerState(); @@ -162,11 +152,7 @@ class _AssetViewerState extends ConsumerState { context, onError: (_, __) {}, ), - precacheImage( - getFullImageProvider(asset, size: screenSize), - context, - onError: (_, __) {}, - ), + precacheImage(getFullImageProvider(asset, size: screenSize), context, onError: (_, __) {}), ]), ); } @@ -222,9 +208,7 @@ class _AssetViewerState extends ConsumerState { duration: const Duration(seconds: 2), content: Text( "local_asset_cast_failed".tr(), - style: context.textTheme.bodyLarge?.copyWith( - color: context.primaryColor, - ), + style: context.textTheme.bodyLarge?.copyWith(color: context.primaryColor), ), ), ); @@ -262,7 +246,8 @@ class _AssetViewerState extends ConsumerState { viewController = controller; dragDownPosition = details.localPosition; initialPhotoViewState = controller.value; - final isZoomed = scaleStateController.scaleState == PhotoViewScaleState.zoomedIn || + final isZoomed = + scaleStateController.scaleState == PhotoViewScaleState.zoomedIn || scaleStateController.scaleState == PhotoViewScaleState.covering; if (!showingBottomSheet && isZoomed) { blockGestures = true; @@ -350,10 +335,7 @@ class _AssetViewerState extends ConsumerState { final backgroundOpacity = (255 * (1.0 - (scaleReduction / dragRatio))).round(); - viewController?.updateMultiple( - position: initialPhotoViewState.position + delta, - scale: updatedScale, - ); + viewController?.updateMultiple(position: initialPhotoViewState.position + delta, scale: updatedScale); ref.read(assetViewerProvider.notifier).setOpacity(backgroundOpacity); } @@ -450,32 +432,21 @@ class _AssetViewerState extends ConsumerState { }); } - void _openBottomSheet( - BuildContext ctx, { - double extent = _kBottomSheetMinimumExtent, - }) { + void _openBottomSheet(BuildContext ctx, {double extent = _kBottomSheetMinimumExtent}) { ref.read(assetViewerProvider.notifier).setBottomSheet(true); initialScale = viewController?.scale; viewController?.updateMultiple(scale: _getScaleForBottomSheet); previousExtent = _kBottomSheetMinimumExtent; sheetCloseController = showBottomSheet( context: ctx, - sheetAnimationStyle: const AnimationStyle( - duration: Durations.short4, - reverseDuration: Durations.short2, - ), + sheetAnimationStyle: const AnimationStyle(duration: Durations.short4, reverseDuration: Durations.short2), constraints: const BoxConstraints(maxWidth: double.infinity), - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20.0))), backgroundColor: ctx.colorScheme.surfaceContainerLowest, builder: (_) { return NotificationListener( onNotification: _onNotification, - child: AssetDetailBottomSheet( - controller: bottomSheetController, - initialChildSize: extent, - ), + child: AssetDetailBottomSheet(controller: bottomSheetController, initialChildSize: extent), ); }, ); @@ -496,18 +467,10 @@ class _AssetViewerState extends ConsumerState { return; } isSnapping = true; - bottomSheetController.animateTo( - _kBottomSheetSnapExtent, - duration: Durations.short3, - curve: Curves.easeOut, - ); + bottomSheetController.animateTo(_kBottomSheetSnapExtent, duration: Durations.short3, curve: Curves.easeOut); } - Widget _placeholderBuilder( - BuildContext ctx, - ImageChunkEvent? progress, - int index, - ) { + Widget _placeholderBuilder(BuildContext ctx, ImageChunkEvent? progress, int index) { BaseAsset asset = ref.read(timelineServiceProvider).getAsset(index); final stackChildren = ref.read(stackChildrenNotifier(asset)).valueOrNull; if (stackChildren != null && stackChildren.isNotEmpty) { @@ -517,14 +480,7 @@ class _AssetViewerState extends ConsumerState { width: double.infinity, height: double.infinity, color: backgroundColor, - child: Thumbnail( - asset: asset, - fit: BoxFit.contain, - size: Size( - ctx.width, - ctx.height, - ), - ), + child: Thumbnail(asset: asset, fit: BoxFit.contain, size: Size(ctx.width, ctx.height)), ); } @@ -574,11 +530,7 @@ class _AssetViewerState extends ConsumerState { width: ctx.width, height: ctx.height, color: backgroundColor, - child: Thumbnail( - asset: asset, - fit: BoxFit.contain, - size: size, - ), + child: Thumbnail(asset: asset, fit: BoxFit.contain, size: size), ), ); } @@ -662,8 +614,7 @@ class _AssetViewerState extends ConsumerState { pageController: pageController, scrollPhysics: platform.isIOS ? const FastScrollPhysics() // Use bouncing physics for iOS - : const FastClampingScrollPhysics() // Use heavy physics for Android - , + : const FastClampingScrollPhysics(), // Use heavy physics for Android itemCount: totalAssets, onPageChanged: _onPageChanged, onPageBuild: _onPageBuild, @@ -678,10 +629,7 @@ class _AssetViewerState extends ConsumerState { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const AssetStackRow(), - if (!isInLockedView) const ViewerBottomBar(), - ], + children: [const AssetStackRow(), if (!isInLockedView) const ViewerBottomBar()], ), ), ); diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart index 32d5249bd..88513516e 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.state.dart @@ -79,17 +79,11 @@ class AssetViewerStateNotifier extends AutoDisposeNotifier { } void setOpacity(int opacity) { - state = state.copyWith( - backgroundOpacity: opacity, - showingControls: opacity == 255 ? true : state.showingControls, - ); + state = state.copyWith(backgroundOpacity: opacity, showingControls: opacity == 255 ? true : state.showingControls); } void setBottomSheet(bool showing) { - state = state.copyWith( - showingBottomSheet: showing, - showingControls: showing ? true : state.showingControls, - ); + state = state.copyWith(showingBottomSheet: showing, showingControls: showing ? true : state.showingControls); if (showing) { ref.read(videoPlayerControlsProvider.notifier).pause(); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart index 8c04fd5a8..881ed4d15 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart @@ -25,12 +25,8 @@ class ViewerBottomBar extends ConsumerWidget { final user = ref.watch(currentUserProvider); final isOwner = asset is RemoteAsset && asset.ownerId == user?.id; - final isSheetOpen = ref.watch( - assetViewerProvider.select((s) => s.showingBottomSheet), - ); - int opacity = ref.watch( - assetViewerProvider.select((state) => state.backgroundOpacity), - ); + final isSheetOpen = ref.watch(assetViewerProvider.select((s) => s.showingBottomSheet)); + int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)); final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); if (!showControls) { @@ -42,13 +38,8 @@ class ViewerBottomBar extends ConsumerWidget { if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer), if (asset.hasRemote && isOwner) const ArchiveActionButton(source: ActionSource.viewer), asset.isLocalOnly - ? const DeleteLocalActionButton( - source: ActionSource.viewer, - ) - : const DeleteActionButton( - source: ActionSource.viewer, - showConfirmation: true, - ), + ? const DeleteLocalActionButton(source: ActionSource.viewer) + : const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true), ]; return IgnorePointer( @@ -64,9 +55,7 @@ class ViewerBottomBar extends ConsumerWidget { data: context.themeData.copyWith( iconTheme: const IconThemeData(size: 22, color: Colors.white), textTheme: context.themeData.textTheme.copyWith( - labelLarge: context.themeData.textTheme.labelLarge?.copyWith( - color: Colors.white, - ), + labelLarge: context.themeData.textTheme.labelLarge?.copyWith(color: Colors.white), ), ), child: Container( @@ -77,10 +66,7 @@ class ViewerBottomBar extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ if (asset.isVideo) const VideoControls(), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: actions, - ), + Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: actions), ], ), ), diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart index e24bb3d7c..73ec6b456 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart @@ -29,11 +29,7 @@ class AssetDetailBottomSheet extends ConsumerWidget { final DraggableScrollableController? controller; final double initialChildSize; - const AssetDetailBottomSheet({ - this.controller, - this.initialChildSize = 0.35, - super.key, - }); + const AssetDetailBottomSheet({this.controller, this.initialChildSize = 0.35, super.key}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -42,9 +38,7 @@ class AssetDetailBottomSheet extends ConsumerWidget { return const SizedBox.shrink(); } - final isTrashEnable = ref.watch( - serverInfoProvider.select((state) => state.serverFeatures.trash), - ); + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); final isInLockedView = ref.watch(inLockedViewProvider); @@ -58,9 +52,7 @@ class AssetDetailBottomSheet extends ConsumerWidget { ? const TrashActionButton(source: ActionSource.viewer) : const DeletePermanentActionButton(source: ActionSource.viewer), const DeleteActionButton(source: ActionSource.viewer), - const MoveToLockFolderActionButton( - source: ActionSource.viewer, - ), + const MoveToLockFolderActionButton(source: ActionSource.viewer), ], if (asset.storage == AssetState.local) ...[ const DeleteLocalActionButton(source: ActionSource.viewer), @@ -153,9 +145,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget { // Asset Date and Time _SheetTile( title: _getDateTime(context, asset), - titleStyle: context.textTheme.bodyMedium?.copyWith( - fontWeight: FontWeight.w600, - ), + titleStyle: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600), ), const SheetLocationDetails(), // Details header @@ -185,11 +175,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget { _SheetTile( title: cameraTitle, titleStyle: context.textTheme.labelLarge, - leading: Icon( - Icons.camera_outlined, - size: 24, - color: context.textTheme.labelLarge?.color, - ), + leading: Icon(Icons.camera_outlined, size: 24, color: context.textTheme.labelLarge?.color), subtitle: _getCameraInfoSubtitle(exifInfo), subtitleStyle: context.textTheme.bodyMedium?.copyWith( color: context.textTheme.bodyMedium?.color?.withAlpha(155), @@ -207,13 +193,7 @@ class _SheetTile extends StatelessWidget { final TextStyle? titleStyle; final TextStyle? subtitleStyle; - const _SheetTile({ - required this.title, - this.titleStyle, - this.leading, - this.subtitle, - this.subtitleStyle, - }); + const _SheetTile({required this.title, this.titleStyle, this.leading, this.subtitle, this.subtitleStyle}); @override Widget build(BuildContext context) { diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/location_details.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/location_details.widget.dart index f91dafb3e..ab57ea4d8 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/location_details.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/location_details.widget.dart @@ -38,20 +38,13 @@ class _SheetLocationDetailsState extends ConsumerState { _mapController = controller; } - void _onExifChanged( - AsyncValue? previous, - AsyncValue current, - ) { + void _onExifChanged(AsyncValue? previous, AsyncValue current) { asset = ref.read(currentAssetNotifier); setState(() { exifInfo = current.valueOrNull; final hasCoordinates = exifInfo?.hasCoordinates ?? false; if (exifInfo != null && hasCoordinates) { - _mapController?.moveCamera( - CameraUpdate.newLatLng( - LatLng(exifInfo!.latitude!, exifInfo!.longitude!), - ), - ); + _mapController?.moveCamera(CameraUpdate.newLatLng(LatLng(exifInfo!.latitude!, exifInfo!.longitude!))); } }); } @@ -59,11 +52,7 @@ class _SheetLocationDetailsState extends ConsumerState { @override void initState() { super.initState(); - ref.listenManual( - currentAssetExifProvider, - _onExifChanged, - fireImmediately: true, - ); + ref.listenManual(currentAssetExifProvider, _onExifChanged, fireImmediately: true); } @override @@ -80,10 +69,7 @@ class _SheetLocationDetailsState extends ConsumerState { final coordinates = "${exifInfo!.latitude!.toStringAsFixed(4)}, ${exifInfo!.longitude!.toStringAsFixed(4)}"; return Padding( - padding: EdgeInsets.symmetric( - vertical: 16.0, - horizontal: context.isMobile ? 16.0 : 56.0, - ), + padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: context.isMobile ? 16.0 : 56.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -97,25 +83,16 @@ class _SheetLocationDetailsState extends ConsumerState { ), ), ), - ExifMap( - exifInfo: exifInfo!, - markerId: remoteId, - onMapCreated: _onMapCreated, - ), + ExifMap(exifInfo: exifInfo!, markerId: remoteId, onMapCreated: _onMapCreated), const SizedBox(height: 15), if (locationName != null) Padding( padding: const EdgeInsets.only(bottom: 4.0), - child: Text( - locationName, - style: context.textTheme.labelLarge, - ), + child: Text(locationName, style: context.textTheme.labelLarge), ), Text( coordinates, - style: context.textTheme.labelMedium?.copyWith( - color: context.textTheme.labelMedium?.color?.withAlpha(150), - ), + style: context.textTheme.labelMedium?.copyWith(color: context.textTheme.labelMedium?.color?.withAlpha(150)), ), ], ), diff --git a/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart index f1163ad2f..450012f7f 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart @@ -36,25 +36,18 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { final showViewInTimelineButton = previousRouteName != TabShellRoute.name && previousRouteName != null; final isShowingSheet = ref.watch(assetViewerProvider.select((state) => state.showingBottomSheet)); - int opacity = ref.watch( - assetViewerProvider.select((state) => state.backgroundOpacity), - ); + int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)); final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); if (!showControls) { opacity = 0; } - final isCasting = ref.watch( - castProvider.select((c) => c.isCasting), - ); + final isCasting = ref.watch(castProvider.select((c) => c.isCasting)); final websocketConnected = ref.watch(websocketProvider.select((c) => c.isConnected)); final actions = [ - if (isCasting || (asset.hasRemote && websocketConnected)) - const CastActionButton( - menuItem: true, - ), + if (isCasting || (asset.hasRemote && websocketConnected)) const CastActionButton(menuItem: true), if (showViewInTimelineButton) IconButton( onPressed: () async { @@ -68,19 +61,13 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { if (asset.hasRemote && isOwner && !asset.isFavorite) const FavoriteActionButton(source: ActionSource.viewer, menuItem: true), if (asset.hasRemote && isOwner && asset.isFavorite) - const UnFavoriteActionButton( - source: ActionSource.viewer, - menuItem: true, - ), + const UnFavoriteActionButton(source: ActionSource.viewer, menuItem: true), if (asset.isMotionPhoto) const MotionPhotoActionButton(menuItem: true), const _KebabMenu(), ]; final lockedViewActions = [ - if (isCasting || (asset.hasRemote && websocketConnected)) - const CastActionButton( - menuItem: true, - ), + if (isCasting || (asset.hasRemote && websocketConnected)) const CastActionButton(menuItem: true), const _KebabMenu(), ]; @@ -98,8 +85,8 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { actions: isShowingSheet ? null : isInLockedView - ? lockedViewActions - : actions, + ? lockedViewActions + : actions, ), ), ); diff --git a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart index f0d665b8c..32510c2ca 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart @@ -27,10 +27,7 @@ import 'package:logging/logging.dart'; import 'package:native_video_player/native_video_player.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; -bool _isCurrentAsset( - BaseAsset asset, - BaseAsset? currentAsset, -) { +bool _isCurrentAsset(BaseAsset asset, BaseAsset? currentAsset) { if (asset is RemoteAsset) { return switch (currentAsset) { RemoteAsset remoteAsset => remoteAsset.id == asset.id, @@ -98,10 +95,7 @@ class NativeVideoViewer extends HookConsumerWidget { throw Exception('No file found for the video'); } - final source = await VideoSource.init( - path: file.path, - type: VideoSourceType.file, - ); + final source = await VideoSource.init(path: file.path, type: VideoSourceType.file); return source; } @@ -122,31 +116,24 @@ class NativeVideoViewer extends HookConsumerWidget { ); return source; } catch (error) { - log.severe( - 'Error creating video source for asset ${asset.name}: $error', - ); + log.severe('Error creating video source for asset ${asset.name}: $error'); return null; } } final videoSource = useMemoized>(() => createSource()); final aspectRatio = useState(null); - useMemoized( - () async { - if (!context.mounted || aspectRatio.value != null) { - return null; - } + useMemoized(() async { + if (!context.mounted || aspectRatio.value != null) { + return null; + } - try { - aspectRatio.value = await ref.read(assetServiceProvider).getAspectRatio(asset); - } catch (error) { - log.severe( - 'Error getting aspect ratio for asset ${asset.name}: $error', - ); - } - }, - [asset.heroTag], - ); + try { + aspectRatio.value = await ref.read(assetServiceProvider).getAspectRatio(asset); + } catch (error) { + log.severe('Error getting aspect ratio for asset ${asset.name}: $error'); + } + }, [asset.heroTag]); void checkIfBuffering() { if (!context.mounted) { @@ -156,8 +143,9 @@ class NativeVideoViewer extends HookConsumerWidget { final videoPlayback = ref.read(videoPlaybackValueProvider); if ((isBuffering.value || videoPlayback.state == VideoPlaybackState.initializing) && videoPlayback.state != VideoPlaybackState.buffering) { - ref.read(videoPlaybackValueProvider.notifier).value = - videoPlayback.copyWith(state: VideoPlaybackState.buffering); + ref.read(videoPlaybackValueProvider.notifier).value = videoPlayback.copyWith( + state: VideoPlaybackState.buffering, + ); } } @@ -345,48 +333,42 @@ class NativeVideoViewer extends HookConsumerWidget { // This delay seems like a hacky way to resolve underlying bugs in video // playback, but other resolutions failed thus far Timer( - Platform.isIOS - ? Duration(milliseconds: 300 * playbackDelayFactor) - : imageToVideo - ? Duration(milliseconds: 200 * playbackDelayFactor) - : Duration(milliseconds: 400 * playbackDelayFactor), () { - if (!context.mounted) { - return; - } - - currentAsset.value = value; - if (currentAsset.value == asset) { - onPlaybackReady(); - } - }); - }); - - useEffect( - () { - // If opening a remote video from a hero animation, delay visibility to avoid a stutter - final timer = isVisible.value - ? null - : Timer( - const Duration(milliseconds: 300), - () => isVisible.value = true, - ); - - return () { - timer?.cancel(); - final playerController = controller.value; - if (playerController == null) { + Platform.isIOS + ? Duration(milliseconds: 300 * playbackDelayFactor) + : imageToVideo + ? Duration(milliseconds: 200 * playbackDelayFactor) + : Duration(milliseconds: 400 * playbackDelayFactor), + () { + if (!context.mounted) { return; } - removeListeners(playerController); - playerController.stop().catchError((error) { - log.fine('Error stopping video: $error'); - }); - WakelockPlus.disable(); - }; - }, - const [], - ); + currentAsset.value = value; + if (currentAsset.value == asset) { + onPlaybackReady(); + } + }, + ); + }); + + useEffect(() { + // If opening a remote video from a hero animation, delay visibility to avoid a stutter + final timer = isVisible.value ? null : Timer(const Duration(milliseconds: 300), () => isVisible.value = true); + + return () { + timer?.cancel(); + final playerController = controller.value; + if (playerController == null) { + return; + } + removeListeners(playerController); + playerController.stop().catchError((error) { + log.fine('Error stopping video: $error'); + }); + + WakelockPlus.disable(); + }; + }, const []); useOnAppLifecycleStateChange((_, state) async { if (state == AppLifecycleState.resumed && shouldPlayOnForeground.value) { @@ -416,12 +398,7 @@ class NativeVideoViewer extends HookConsumerWidget { child: AspectRatio( key: ValueKey(asset), aspectRatio: aspectRatio.value!, - child: isCurrent - ? NativeVideoPlayerView( - key: ValueKey(asset), - onViewReady: initController, - ) - : null, + child: isCurrent ? NativeVideoPlayerView(key: ValueKey(asset), onViewReady: initController) : null, ), ), ), diff --git a/mobile/lib/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart index 1fc01bb8e..c1324b8ac 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart @@ -13,16 +13,11 @@ import 'package:immich_mobile/widgets/common/delayed_loading_indicator.dart'; class VideoViewerControls extends HookConsumerWidget { final Duration hideTimerDuration; - const VideoViewerControls({ - super.key, - this.hideTimerDuration = const Duration(seconds: 5), - }); + const VideoViewerControls({super.key, this.hideTimerDuration = const Duration(seconds: 5)}); @override Widget build(BuildContext context, WidgetRef ref) { - final assetIsVideo = ref.watch( - currentAssetNotifier.select((asset) => asset != null && asset.isVideo), - ); + final assetIsVideo = ref.watch(currentAssetNotifier.select((asset) => asset != null && asset.isVideo)); bool showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); final showBottomSheet = ref.watch(assetViewerProvider.select((s) => s.showingBottomSheet)); if (showBottomSheet) { @@ -33,20 +28,17 @@ class VideoViewerControls extends HookConsumerWidget { final cast = ref.watch(castProvider); // A timer to hide the controls - final hideTimer = useTimer( - hideTimerDuration, - () { - if (!context.mounted) { - return; - } - final state = ref.read(videoPlaybackValueProvider).state; + final hideTimer = useTimer(hideTimerDuration, () { + if (!context.mounted) { + return; + } + final state = ref.read(videoPlaybackValueProvider).state; - // Do not hide on paused - if (state != VideoPlaybackState.paused && state != VideoPlaybackState.completed && assetIsVideo) { - ref.read(assetViewerProvider.notifier).setControls(false); - } - }, - ); + // Do not hide on paused + if (state != VideoPlaybackState.paused && state != VideoPlaybackState.completed && assetIsVideo) { + ref.read(assetViewerProvider.notifier).setControls(false); + } + }); final showBuffering = state == VideoPlaybackState.buffering && !cast.isCasting; /// Shows the controls and starts the timer to hide them @@ -97,11 +89,7 @@ class VideoViewerControls extends HookConsumerWidget { child: Stack( children: [ if (showBuffering) - const Center( - child: DelayedLoadingIndicator( - fadeInDuration: Duration(milliseconds: 400), - ), - ) + const Center(child: DelayedLoadingIndicator(fadeInDuration: Duration(milliseconds: 400))) else GestureDetector( onTap: () => ref.read(assetViewerProvider.notifier).setControls(false), diff --git a/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart b/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart index 520111070..a74c16922 100644 --- a/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart +++ b/mobile/lib/presentation/widgets/backup/backup_toggle_button.widget.dart @@ -11,11 +11,7 @@ class BackupToggleButton extends ConsumerStatefulWidget { final VoidCallback onStart; final VoidCallback onStop; - const BackupToggleButton({ - super.key, - required this.onStart, - required this.onStop, - }); + const BackupToggleButton({super.key, required this.onStart, required this.onStop}); @override ConsumerState createState() => BackupToggleButtonState(); @@ -29,17 +25,12 @@ class BackupToggleButtonState extends ConsumerState with Sin @override void initState() { super.initState(); - _animationController = AnimationController( - duration: const Duration(seconds: 8), - vsync: this, - ); + _animationController = AnimationController(duration: const Duration(seconds: 8), vsync: this); - _gradientAnimation = Tween(begin: 0, end: 1).animate( - CurvedAnimation( - parent: _animationController, - curve: Curves.easeInOut, - ), - ); + _gradientAnimation = Tween( + begin: 0, + end: 1, + ).animate(CurvedAnimation(parent: _animationController, curve: Curves.easeInOut)); _isEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup); } @@ -66,21 +57,13 @@ class BackupToggleButtonState extends ConsumerState with Sin @override Widget build(BuildContext context) { - final enqueueCount = ref.watch( - driftBackupProvider.select((state) => state.enqueueCount), - ); + final enqueueCount = ref.watch(driftBackupProvider.select((state) => state.enqueueCount)); - final enqueueTotalCount = ref.watch( - driftBackupProvider.select((state) => state.enqueueTotalCount), - ); + final enqueueTotalCount = ref.watch(driftBackupProvider.select((state) => state.enqueueTotalCount)); - final isCanceling = ref.watch( - driftBackupProvider.select((state) => state.isCanceling), - ); + final isCanceling = ref.watch(driftBackupProvider.select((state) => state.isCanceling)); - final uploadTasks = ref.watch( - driftBackupProvider.select((state) => state.uploadItems), - ); + final uploadTasks = ref.watch(driftBackupProvider.select((state) => state.uploadItems)); final isUploading = uploadTasks.isNotEmpty; @@ -116,11 +99,7 @@ class BackupToggleButtonState extends ConsumerState with Sin end: Alignment.bottomRight, ), boxShadow: [ - BoxShadow( - color: context.primaryColor.withValues(alpha: 0.1), - blurRadius: 12, - offset: const Offset(0, 2), - ), + BoxShadow(color: context.primaryColor.withValues(alpha: 0.1), blurRadius: 12, offset: const Offset(0, 2)), ], ), child: Container( @@ -151,18 +130,8 @@ class BackupToggleButtonState extends ConsumerState with Sin ), ), child: isUploading - ? const SizedBox( - width: 24, - height: 24, - child: CircularProgressIndicator( - strokeWidth: 2, - ), - ) - : Icon( - Icons.cloud_upload_outlined, - color: context.primaryColor, - size: 24, - ), + ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2)) + : Icon(Icons.cloud_upload_outlined, color: context.primaryColor, size: 24), ), const SizedBox(width: 16), Expanded( @@ -185,10 +154,7 @@ class BackupToggleButtonState extends ConsumerState with Sin Text( "queue_status".t( context: context, - args: { - 'count': enqueueCount.toString(), - 'total': enqueueTotalCount.toString(), - }, + args: {'count': enqueueCount.toString(), 'total': enqueueTotalCount.toString()}, ), style: context.textTheme.labelLarge?.copyWith( color: context.colorScheme.onSurfaceSecondary, @@ -197,10 +163,7 @@ class BackupToggleButtonState extends ConsumerState with Sin if (isCanceling) Row( children: [ - Text( - "canceling".t(), - style: context.textTheme.labelLarge, - ), + Text("canceling".t(), style: context.textTheme.labelLarge), const SizedBox(width: 4), SizedBox( width: 18, @@ -215,10 +178,7 @@ class BackupToggleButtonState extends ConsumerState with Sin ], ), ), - Switch.adaptive( - value: _isEnabled, - onChanged: (value) => isCanceling ? null : _onToggle(value), - ), + Switch.adaptive(value: _isEnabled, onChanged: (value) => isCanceling ? null : _onToggle(value)), ], ), ), diff --git a/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart index 76243cf80..648592699 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart @@ -24,9 +24,7 @@ class ArchiveBottomSheet extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final multiselect = ref.watch(multiSelectProvider); - final isTrashEnable = ref.watch( - serverInfoProvider.select((state) => state.serverFeatures.trash), - ); + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); return BaseBottomSheet( initialChildSize: 0.25, @@ -41,14 +39,10 @@ class ArchiveBottomSheet extends ConsumerWidget { const DownloadActionButton(source: ActionSource.timeline), isTrashEnable ? const TrashActionButton(source: ActionSource.timeline) - : const DeletePermanentActionButton( - source: ActionSource.timeline, - ), + : const DeletePermanentActionButton(source: ActionSource.timeline), const EditDateTimeActionButton(), const EditLocationActionButton(source: ActionSource.timeline), - const MoveToLockFolderActionButton( - source: ActionSource.timeline, - ), + const MoveToLockFolderActionButton(source: ActionSource.timeline), const StackActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal) ...[ diff --git a/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart index b3e71567e..a2c88d9fd 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart @@ -73,9 +73,7 @@ class _BaseDraggableScrollableSheetState extends ConsumerState borderOnForeground: false, clipBehavior: Clip.antiAlias, elevation: 6.0, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(18)), - ), + shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(18))), margin: const EdgeInsets.symmetric(horizontal: 0), child: CustomScrollView( controller: scrollController, @@ -89,11 +87,7 @@ class _BaseDraggableScrollableSheetState extends ConsumerState if (widget.actions.isNotEmpty) SizedBox( height: 115, - child: ListView( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - children: widget.actions, - ), + child: ListView(shrinkWrap: true, scrollDirection: Axis.horizontal, children: widget.actions), ), if (widget.actions.isNotEmpty) ...[ const Divider(indent: 16, endIndent: 16), diff --git a/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart index 3f3f93374..ec0fded6c 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart @@ -24,9 +24,7 @@ class FavoriteBottomSheet extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final multiselect = ref.watch(multiSelectProvider); - final isTrashEnable = ref.watch( - serverInfoProvider.select((state) => state.serverFeatures.trash), - ); + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); return BaseBottomSheet( initialChildSize: 0.25, @@ -41,14 +39,10 @@ class FavoriteBottomSheet extends ConsumerWidget { const DownloadActionButton(source: ActionSource.timeline), isTrashEnable ? const TrashActionButton(source: ActionSource.timeline) - : const DeletePermanentActionButton( - source: ActionSource.timeline, - ), + : const DeletePermanentActionButton(source: ActionSource.timeline), const EditDateTimeActionButton(), const EditLocationActionButton(source: ActionSource.timeline), - const MoveToLockFolderActionButton( - source: ActionSource.timeline, - ), + const MoveToLockFolderActionButton(source: ActionSource.timeline), const StackActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal) ...[ diff --git a/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart index d338cfa83..3912aef15 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/general_bottom_sheet.widget.dart @@ -31,9 +31,7 @@ class GeneralBottomSheet extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final multiselect = ref.watch(multiSelectProvider); - final isTrashEnable = ref.watch( - serverInfoProvider.select((state) => state.serverFeatures.trash), - ); + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); Future addAssetsToAlbum(RemoteAlbum album) async { final selectedAssets = multiselect.selectedAssets; @@ -41,24 +39,19 @@ class GeneralBottomSheet extends ConsumerWidget { return; } - final addedCount = await ref.read(remoteAlbumProvider.notifier).addAssets( - album.id, - selectedAssets.map((e) => (e as RemoteAsset).id).toList(), - ); + final addedCount = await ref + .read(remoteAlbumProvider.notifier) + .addAssets(album.id, selectedAssets.map((e) => (e as RemoteAsset).id).toList()); if (addedCount != selectedAssets.length) { ImmichToast.show( context: context, - msg: 'add_to_album_bottom_sheet_already_exists'.tr( - namedArgs: {"album": album.name}, - ), + msg: 'add_to_album_bottom_sheet_already_exists'.tr(namedArgs: {"album": album.name}), ); } else { ImmichToast.show( context: context, - msg: 'add_to_album_bottom_sheet_added'.tr( - namedArgs: {"album": album.name}, - ), + msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {"album": album.name}), ); } @@ -78,18 +71,14 @@ class GeneralBottomSheet extends ConsumerWidget { const DownloadActionButton(source: ActionSource.timeline), isTrashEnable ? const TrashActionButton(source: ActionSource.timeline) - : const DeletePermanentActionButton( - source: ActionSource.timeline, - ), + : const DeletePermanentActionButton(source: ActionSource.timeline), const DeleteActionButton(source: ActionSource.timeline), if (multiselect.hasLocal || multiselect.hasMerged) ...[ const DeleteLocalActionButton(source: ActionSource.timeline), ], const EditDateTimeActionButton(), const EditLocationActionButton(source: ActionSource.timeline), - const MoveToLockFolderActionButton( - source: ActionSource.timeline, - ), + const MoveToLockFolderActionButton(source: ActionSource.timeline), const StackActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal) ...[ @@ -99,9 +88,7 @@ class GeneralBottomSheet extends ConsumerWidget { ], slivers: [ const AddToAlbumHeader(), - AlbumSelector( - onAlbumSelected: addAssetsToAlbum, - ), + AlbumSelector(onAlbumSelected: addAssetsToAlbum), ], ); } diff --git a/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart index ff77c7990..9765b6168 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart @@ -27,9 +27,7 @@ class RemoteAlbumBottomSheet extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final multiselect = ref.watch(multiSelectProvider); - final isTrashEnable = ref.watch( - serverInfoProvider.select((state) => state.serverFeatures.trash), - ); + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); return BaseBottomSheet( initialChildSize: 0.25, @@ -44,24 +42,17 @@ class RemoteAlbumBottomSheet extends ConsumerWidget { const DownloadActionButton(source: ActionSource.timeline), isTrashEnable ? const TrashActionButton(source: ActionSource.timeline) - : const DeletePermanentActionButton( - source: ActionSource.timeline, - ), + : const DeletePermanentActionButton(source: ActionSource.timeline), const EditDateTimeActionButton(), const EditLocationActionButton(source: ActionSource.timeline), - const MoveToLockFolderActionButton( - source: ActionSource.timeline, - ), + const MoveToLockFolderActionButton(source: ActionSource.timeline), const StackActionButton(source: ActionSource.timeline), ], if (multiselect.hasLocal) ...[ const DeleteLocalActionButton(source: ActionSource.timeline), const UploadActionButton(source: ActionSource.timeline), ], - RemoveFromAlbumActionButton( - source: ActionSource.timeline, - albumId: album.id, - ), + RemoveFromAlbumActionButton(source: ActionSource.timeline, albumId: album.id), ], ); } diff --git a/mobile/lib/presentation/widgets/images/image_provider.dart b/mobile/lib/presentation/widgets/images/image_provider.dart index e4effd080..d94480b43 100644 --- a/mobile/lib/presentation/widgets/images/image_provider.dart +++ b/mobile/lib/presentation/widgets/images/image_provider.dart @@ -5,20 +5,12 @@ import 'package:immich_mobile/domain/services/setting.service.dart'; import 'package:immich_mobile/presentation/widgets/images/local_image_provider.dart'; import 'package:immich_mobile/presentation/widgets/images/remote_image_provider.dart'; -ImageProvider getFullImageProvider( - BaseAsset asset, { - Size size = const Size(1080, 1920), -}) { +ImageProvider getFullImageProvider(BaseAsset asset, {Size size = const Size(1080, 1920)}) { // Create new provider and cache it final ImageProvider provider; if (_shouldUseLocalAsset(asset)) { final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).localId!; - provider = LocalFullImageProvider( - id: id, - name: asset.name, - size: size, - type: asset.type, - ); + provider = LocalFullImageProvider(id: id, name: asset.name, size: size, type: asset.type); } else { final String assetId; if (asset is LocalAsset && asset.hasRemote) { @@ -34,15 +26,8 @@ ImageProvider getFullImageProvider( return provider; } -ImageProvider getThumbnailImageProvider({ - BaseAsset? asset, - String? remoteId, - Size size = const Size.square(256), -}) { - assert( - asset != null || remoteId != null, - 'Either asset or remoteId must be provided', - ); +ImageProvider getThumbnailImageProvider({BaseAsset? asset, String? remoteId, Size size = const Size.square(256)}) { + assert(asset != null || remoteId != null, 'Either asset or remoteId must be provided'); if (remoteId != null) { return RemoteThumbProvider(assetId: remoteId); @@ -50,12 +35,7 @@ ImageProvider getThumbnailImageProvider({ if (_shouldUseLocalAsset(asset!)) { final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).localId!; - return LocalThumbProvider( - id: id, - updatedAt: asset.updatedAt, - name: asset.name, - size: size, - ); + return LocalThumbProvider(id: id, updatedAt: asset.updatedAt, name: asset.name, size: size); } final String assetId; diff --git a/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart b/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart index dcf0f2852..8b9ede4c6 100644 --- a/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart +++ b/mobile/lib/presentation/widgets/images/local_album_thumbnail.widget.dart @@ -5,10 +5,7 @@ import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart' import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; class LocalAlbumThumbnail extends ConsumerWidget { - const LocalAlbumThumbnail({ - super.key, - required this.albumId, - }); + const LocalAlbumThumbnail({super.key, required this.albumId}); final String albumId; @override @@ -21,34 +18,21 @@ class LocalAlbumThumbnail extends ConsumerWidget { decoration: BoxDecoration( color: context.colorScheme.surfaceContainer, borderRadius: const BorderRadius.all(Radius.circular(16)), - border: Border.all( - color: context.colorScheme.outline.withAlpha(50), - width: 1, - ), - ), - child: Icon( - Icons.collections, - size: 24, - color: context.primaryColor, + border: Border.all(color: context.colorScheme.outline.withAlpha(50), width: 1), ), + child: Icon(Icons.collections, size: 24, color: context.primaryColor), ); } return ClipRRect( borderRadius: const BorderRadius.all(Radius.circular(16)), - child: Thumbnail( - asset: data, - ), + child: Thumbnail(asset: data), ); }, error: (error, stack) { return const Icon(Icons.error, size: 24); }, - loading: () => const SizedBox( - width: 24, - height: 24, - child: Center(child: CircularProgressIndicator()), - ), + loading: () => const SizedBox(width: 24, height: 24, child: Center(child: CircularProgressIndicator())), ); } } diff --git a/mobile/lib/presentation/widgets/images/local_image_provider.dart b/mobile/lib/presentation/widgets/images/local_image_provider.dart index 41bc19ba5..350bcbb8f 100644 --- a/mobile/lib/presentation/widgets/images/local_image_provider.dart +++ b/mobile/lib/presentation/widgets/images/local_image_provider.dart @@ -39,10 +39,7 @@ class LocalThumbProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage( - LocalThumbProvider key, - ImageDecoderCallback decode, - ) { + ImageStreamCompleter loadImage(LocalThumbProvider key, ImageDecoderCallback decode) { final cache = cacheManager ?? ThumbnailImageCacheManager(); return MultiFrameImageStreamCompleter( codec: _codec(key, cache, decode), @@ -57,11 +54,7 @@ class LocalThumbProvider extends ImageProvider { ); } - Future _codec( - LocalThumbProvider key, - CacheManager cache, - ImageDecoderCallback decode, - ) async { + Future _codec(LocalThumbProvider key, CacheManager cache, ImageDecoderCallback decode) async { final cacheKey = '${key.id}-${key.updatedAt}-${key.size.width}x${key.size.height}'; final fileFromCache = await cache.getFileFromCache(cacheKey); @@ -75,9 +68,7 @@ class LocalThumbProvider extends ImageProvider { final thumbnailBytes = await _assetMediaRepository.getThumbnail(key.id, size: key.size); if (thumbnailBytes == null) { PaintingBinding.instance.imageCache.evict(key); - throw StateError( - "Loading thumb for local photo ${key.name} failed", - ); + throw StateError("Loading thumb for local photo ${key.name} failed"); } final buffer = await ImmutableBuffer.fromUint8List(thumbnailBytes); @@ -107,12 +98,7 @@ class LocalFullImageProvider extends ImageProvider { final Size size; final AssetType type; - const LocalFullImageProvider({ - required this.id, - required this.name, - required this.size, - required this.type, - }); + const LocalFullImageProvider({required this.id, required this.name, required this.size, required this.type}); @override Future obtainKey(ImageConfiguration configuration) { @@ -120,10 +106,7 @@ class LocalFullImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage( - LocalFullImageProvider key, - ImageDecoderCallback decode, - ) { + ImageStreamCompleter loadImage(LocalFullImageProvider key, ImageDecoderCallback decode) { return MultiImageStreamCompleter( codec: _codec(key, decode), scale: 1.0, @@ -134,10 +117,7 @@ class LocalFullImageProvider extends ImageProvider { } // Streams in each stage of the image as we ask for it - Stream _codec( - LocalFullImageProvider key, - ImageDecoderCallback decode, - ) async* { + Stream _codec(LocalFullImageProvider key, ImageDecoderCallback decode) async* { try { switch (key.type) { case AssetType.image: @@ -156,16 +136,11 @@ class LocalFullImageProvider extends ImageProvider { } } catch (error, stack) { Logger('ImmichLocalImageProvider').severe('Error loading local image ${key.name}', error, stack); - throw const ImageLoadingException( - 'Could not load image from local storage', - ); + throw const ImageLoadingException('Could not load image from local storage'); } } - Future _getThumbnailCodec( - LocalFullImageProvider key, - ImageDecoderCallback decode, - ) async { + Future _getThumbnailCodec(LocalFullImageProvider key, ImageDecoderCallback decode) async { final thumbBytes = await _assetMediaRepository.getThumbnail(key.id, size: key.size); if (thumbBytes == null) { return null; @@ -174,10 +149,7 @@ class LocalFullImageProvider extends ImageProvider { return decode(buffer); } - Stream _decodeProgressive( - LocalFullImageProvider key, - ImageDecoderCallback decode, - ) async* { + Stream _decodeProgressive(LocalFullImageProvider key, ImageDecoderCallback decode) async* { final file = await _storageRepository.getFileForAsset(key.id); if (file == null) { throw StateError("Opening file for asset ${key.name} failed"); diff --git a/mobile/lib/presentation/widgets/images/remote_image_provider.dart b/mobile/lib/presentation/widgets/images/remote_image_provider.dart index 14d13a08d..27f310f4f 100644 --- a/mobile/lib/presentation/widgets/images/remote_image_provider.dart +++ b/mobile/lib/presentation/widgets/images/remote_image_provider.dart @@ -15,10 +15,7 @@ class RemoteThumbProvider extends ImageProvider { final String assetId; final CacheManager? cacheManager; - const RemoteThumbProvider({ - required this.assetId, - this.cacheManager, - }); + const RemoteThumbProvider({required this.assetId, this.cacheManager}); @override Future obtainKey(ImageConfiguration configuration) { @@ -26,10 +23,7 @@ class RemoteThumbProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage( - RemoteThumbProvider key, - ImageDecoderCallback decode, - ) { + ImageStreamCompleter loadImage(RemoteThumbProvider key, ImageDecoderCallback decode) { final cache = cacheManager ?? RemoteImageCacheManager(); final chunkController = StreamController(); return MultiFrameImageStreamCompleter( @@ -49,9 +43,7 @@ class RemoteThumbProvider extends ImageProvider { ImageDecoderCallback decode, StreamController chunkController, ) async { - final preview = getThumbnailUrlForRemoteId( - key.assetId, - ); + final preview = getThumbnailUrlForRemoteId(key.assetId); return ImageLoader.loadImageFromCache( preview, @@ -79,10 +71,7 @@ class RemoteFullImageProvider extends ImageProvider { final String assetId; final CacheManager? cacheManager; - const RemoteFullImageProvider({ - required this.assetId, - this.cacheManager, - }); + const RemoteFullImageProvider({required this.assetId, this.cacheManager}); @override Future obtainKey(ImageConfiguration configuration) { @@ -90,10 +79,7 @@ class RemoteFullImageProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage( - RemoteFullImageProvider key, - ImageDecoderCallback decode, - ) { + ImageStreamCompleter loadImage(RemoteFullImageProvider key, ImageDecoderCallback decode) { final cache = cacheManager ?? RemoteImageCacheManager(); final chunkEvents = StreamController(); return MultiImageStreamCompleter( diff --git a/mobile/lib/presentation/widgets/images/thumb_hash_provider.dart b/mobile/lib/presentation/widgets/images/thumb_hash_provider.dart index cd286a4cd..8d292523d 100644 --- a/mobile/lib/presentation/widgets/images/thumb_hash_provider.dart +++ b/mobile/lib/presentation/widgets/images/thumb_hash_provider.dart @@ -8,9 +8,7 @@ import 'package:thumbhash/thumbhash.dart'; class ThumbHashProvider extends ImageProvider { final String thumbHash; - const ThumbHashProvider({ - required this.thumbHash, - }); + const ThumbHashProvider({required this.thumbHash}); @override Future obtainKey(ImageConfiguration configuration) { @@ -18,20 +16,11 @@ class ThumbHashProvider extends ImageProvider { } @override - ImageStreamCompleter loadImage( - ThumbHashProvider key, - ImageDecoderCallback decode, - ) { - return MultiFrameImageStreamCompleter( - codec: _loadCodec(key, decode), - scale: 1.0, - ); + ImageStreamCompleter loadImage(ThumbHashProvider key, ImageDecoderCallback decode) { + return MultiFrameImageStreamCompleter(codec: _loadCodec(key, decode), scale: 1.0); } - Future _loadCodec( - ThumbHashProvider key, - ImageDecoderCallback decode, - ) async { + Future _loadCodec(ThumbHashProvider key, ImageDecoderCallback decode) async { final image = thumbHashToRGBA(base64Decode(key.thumbHash)); return decode(await ImmutableBuffer.fromUint8List(rgbaToBmp(image))); } diff --git a/mobile/lib/presentation/widgets/images/thumbnail.widget.dart b/mobile/lib/presentation/widgets/images/thumbnail.widget.dart index 80f6af617..8335bd406 100644 --- a/mobile/lib/presentation/widgets/images/thumbnail.widget.dart +++ b/mobile/lib/presentation/widgets/images/thumbnail.widget.dart @@ -8,16 +8,8 @@ import 'package:logging/logging.dart'; import 'package:octo_image/octo_image.dart'; class Thumbnail extends StatelessWidget { - const Thumbnail({ - this.asset, - this.remoteId, - this.size = const Size.square(256), - this.fit = BoxFit.cover, - super.key, - }) : assert( - asset != null || remoteId != null, - 'Either asset or remoteId must be provided', - ); + const Thumbnail({this.asset, this.remoteId, this.size = const Size.square(256), this.fit = BoxFit.cover, super.key}) + : assert(asset != null || remoteId != null, 'Either asset or remoteId must be provided'); final BaseAsset? asset; final String? remoteId; @@ -33,12 +25,7 @@ class Thumbnail extends StatelessWidget { image: provider, octoSet: OctoSet( placeholderBuilder: _blurHashPlaceholderBuilder(thumbHash, fit: fit), - errorBuilder: _blurHashErrorBuilder( - thumbHash, - provider: provider, - fit: fit, - asset: asset, - ), + errorBuilder: _blurHashErrorBuilder(thumbHash, provider: provider, fit: fit, asset: asset), ), fadeOutDuration: const Duration(milliseconds: 100), fadeInDuration: Duration.zero, @@ -50,10 +37,7 @@ class Thumbnail extends StatelessWidget { } } -OctoPlaceholderBuilder _blurHashPlaceholderBuilder( - String? thumbHash, { - BoxFit? fit, -}) { +OctoPlaceholderBuilder _blurHashPlaceholderBuilder(String? thumbHash, {BoxFit? fit}) { return (context) => thumbHash == null ? const ThumbnailPlaceholder() : FadeInPlaceholderImage( @@ -63,12 +47,7 @@ OctoPlaceholderBuilder _blurHashPlaceholderBuilder( ); } -OctoErrorBuilder _blurHashErrorBuilder( - String? blurhash, { - BaseAsset? asset, - ImageProvider? provider, - BoxFit? fit, -}) => +OctoErrorBuilder _blurHashErrorBuilder(String? blurhash, {BaseAsset? asset, ImageProvider? provider, BoxFit? fit}) => (context, e, s) { Logger("ImThumbnail").warning("Error loading thumbnail for ${asset?.name}", e, s); provider?.evict(); @@ -76,10 +55,7 @@ OctoErrorBuilder _blurHashErrorBuilder( alignment: Alignment.center, children: [ _blurHashPlaceholderBuilder(blurhash, fit: fit)(context), - const Opacity( - opacity: 0.75, - child: Icon(Icons.error_outline_rounded), - ), + const Opacity(opacity: 0.75, child: Icon(Icons.error_outline_rounded)), ], ); }; diff --git a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart index ce4e50cbd..b9ef1ca45 100644 --- a/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart +++ b/mobile/lib/presentation/widgets/images/thumbnail_tile.widget.dart @@ -30,29 +30,25 @@ class ThumbnailTile extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final heroIndex = heroOffset ?? TabsRouterScope.of(context)?.controller.activeIndex ?? 0; - final assetContainerColor = - context.isDarkTheme ? context.primaryColor.darken(amount: 0.4) : context.primaryColor.lighten(amount: 0.75); + final assetContainerColor = context.isDarkTheme + ? context.primaryColor.darken(amount: 0.4) + : context.primaryColor.lighten(amount: 0.75); final isSelected = ref.watch( - multiSelectProvider.select( - (multiselect) => multiselect.selectedAssets.contains(asset), - ), + multiSelectProvider.select((multiselect) => multiselect.selectedAssets.contains(asset)), ); final borderStyle = lockSelection ? BoxDecoration( color: context.colorScheme.surfaceContainerHighest, - border: Border.all( - color: context.colorScheme.surfaceContainerHighest, - width: 6, - ), + border: Border.all(color: context.colorScheme.surfaceContainerHighest, width: 6), ) : isSelected - ? BoxDecoration( - color: assetContainerColor, - border: Border.all(color: assetContainerColor, width: 6), - ) - : const BoxDecoration(); + ? BoxDecoration( + color: assetContainerColor, + border: Border.all(color: assetContainerColor, width: 6), + ) + : const BoxDecoration(); final hasStack = asset is RemoteAsset && (asset as RemoteAsset).stackId != null; @@ -63,28 +59,22 @@ class ThumbnailTile extends ConsumerWidget { curve: Curves.decelerate, decoration: borderStyle, child: ClipRRect( - borderRadius: - isSelected || lockSelection ? const BorderRadius.all(Radius.circular(15.0)) : BorderRadius.zero, + borderRadius: isSelected || lockSelection + ? const BorderRadius.all(Radius.circular(15.0)) + : BorderRadius.zero, child: Stack( children: [ Positioned.fill( child: Hero( tag: '${asset.heroTag}_$heroIndex', - child: Thumbnail( - asset: asset, - fit: fit, - size: size, - ), + child: Thumbnail(asset: asset, fit: fit, size: size), ), ), if (hasStack) Align( alignment: Alignment.topRight, child: Padding( - padding: EdgeInsets.only( - right: 10.0, - top: asset.isVideo ? 24.0 : 6.0, - ), + padding: EdgeInsets.only(right: 10.0, top: asset.isVideo ? 24.0 : 6.0), child: const _TileOverlayIcon(Icons.burst_mode_rounded), ), ), @@ -99,26 +89,26 @@ class ThumbnailTile extends ConsumerWidget { if (showStorageIndicator) switch (asset.storage) { AssetState.local => const Align( - alignment: Alignment.bottomRight, - child: Padding( - padding: EdgeInsets.only(right: 10.0, bottom: 6.0), - child: _TileOverlayIcon(Icons.cloud_off_outlined), - ), + alignment: Alignment.bottomRight, + child: Padding( + padding: EdgeInsets.only(right: 10.0, bottom: 6.0), + child: _TileOverlayIcon(Icons.cloud_off_outlined), ), + ), AssetState.remote => const Align( - alignment: Alignment.bottomRight, - child: Padding( - padding: EdgeInsets.only(right: 10.0, bottom: 6.0), - child: _TileOverlayIcon(Icons.cloud_outlined), - ), + alignment: Alignment.bottomRight, + child: Padding( + padding: EdgeInsets.only(right: 10.0, bottom: 6.0), + child: _TileOverlayIcon(Icons.cloud_outlined), ), + ), AssetState.merged => const Align( - alignment: Alignment.bottomRight, - child: Padding( - padding: EdgeInsets.only(right: 10.0, bottom: 6.0), - child: _TileOverlayIcon(Icons.cloud_done_outlined), - ), + alignment: Alignment.bottomRight, + child: Padding( + padding: EdgeInsets.only(right: 10.0, bottom: 6.0), + child: _TileOverlayIcon(Icons.cloud_done_outlined), ), + ), }, if (asset.isFavorite) const Align( @@ -154,41 +144,22 @@ class _SelectionIndicator extends StatelessWidget { final bool isLocked; final Color? color; - const _SelectionIndicator({ - required this.isSelected, - required this.isLocked, - this.color, - }); + const _SelectionIndicator({required this.isSelected, required this.isLocked, this.color}); @override Widget build(BuildContext context) { if (isLocked) { return DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: color, - ), - child: const Icon( - Icons.check_circle_rounded, - color: Colors.grey, - ), + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + child: const Icon(Icons.check_circle_rounded, color: Colors.grey), ); } else if (isSelected) { return DecoratedBox( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: color, - ), - child: Icon( - Icons.check_circle_rounded, - color: context.primaryColor, - ), + decoration: BoxDecoration(shape: BoxShape.circle, color: color), + child: Icon(Icons.check_circle_rounded, color: context.primaryColor), ); } else { - return const Icon( - Icons.circle_outlined, - color: Colors.white, - ); + return const Icon(Icons.circle_outlined, color: Colors.white); } } } @@ -212,12 +183,7 @@ class _VideoIndicator extends StatelessWidget { color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold, - shadows: [ - Shadow( - blurRadius: 5.0, - color: Color.fromRGBO(0, 0, 0, 0.6), - ), - ], + shadows: [Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6))], ), ), const _TileOverlayIcon(Icons.play_circle_outline_rounded), @@ -237,13 +203,7 @@ class _TileOverlayIcon extends StatelessWidget { icon, color: Colors.white, size: 16, - shadows: [ - const Shadow( - blurRadius: 5.0, - color: Color.fromRGBO(0, 0, 0, 0.6), - offset: Offset(0.0, 0.0), - ), - ], + shadows: [const Shadow(blurRadius: 5.0, color: Color.fromRGBO(0, 0, 0, 0.6), offset: Offset(0.0, 0.0))], ); } } diff --git a/mobile/lib/presentation/widgets/memory/memory_bottom_info.widget.dart b/mobile/lib/presentation/widgets/memory/memory_bottom_info.widget.dart index 943b74288..f067bc6bf 100644 --- a/mobile/lib/presentation/widgets/memory/memory_bottom_info.widget.dart +++ b/mobile/lib/presentation/widgets/memory/memory_bottom_info.widget.dart @@ -11,11 +11,7 @@ import 'package:immich_mobile/routing/router.dart'; class DriftMemoryBottomInfo extends StatelessWidget { final DriftMemory memory; final String title; - const DriftMemoryBottomInfo({ - super.key, - required this.memory, - required this.title, - }); + const DriftMemoryBottomInfo({super.key, required this.memory, required this.title}); @override Widget build(BuildContext context) { @@ -23,47 +19,39 @@ class DriftMemoryBottomInfo extends StatelessWidget { final fileCreatedDate = memory.assets.first.createdAt; return Padding( padding: const EdgeInsets.all(16.0), - child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: TextStyle( - color: Colors.grey[400], - fontSize: 13.0, - fontWeight: FontWeight.w500, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle(color: Colors.grey[400], fontSize: 13.0, fontWeight: FontWeight.w500), ), - ), - Text( - df.format(fileCreatedDate), - style: const TextStyle( - color: Colors.white, - fontSize: 15.0, - fontWeight: FontWeight.w500, + Text( + df.format(fileCreatedDate), + style: const TextStyle(color: Colors.white, fontSize: 15.0, fontWeight: FontWeight.w500), ), - ), - ], - ), - Tooltip( - message: 'view_in_timeline'.tr(), - child: MaterialButton( - minWidth: 0, - onPressed: () async { - await context.maybePop(); - await context.navigateTo(const TabShellRoute(children: [MainTimelineRoute()])); - EventStream.shared.emit(ScrollToDateEvent(fileCreatedDate)); - }, - shape: const CircleBorder(), - color: Colors.white.withValues(alpha: 0.2), - elevation: 0, - child: const Icon( - Icons.open_in_new, - color: Colors.white, + ], + ), + Tooltip( + message: 'view_in_timeline'.tr(), + child: MaterialButton( + minWidth: 0, + onPressed: () async { + await context.maybePop(); + await context.navigateTo(const TabShellRoute(children: [MainTimelineRoute()])); + EventStream.shared.emit(ScrollToDateEvent(fileCreatedDate)); + }, + shape: const CircleBorder(), + color: Colors.white.withValues(alpha: 0.2), + elevation: 0, + child: const Icon(Icons.open_in_new, color: Colors.white), ), ), - ), - ]), + ], + ), ); } } diff --git a/mobile/lib/presentation/widgets/memory/memory_card.widget.dart b/mobile/lib/presentation/widgets/memory/memory_card.widget.dart index e69c848f4..eaed60b20 100644 --- a/mobile/lib/presentation/widgets/memory/memory_card.widget.dart +++ b/mobile/lib/presentation/widgets/memory/memory_card.widget.dart @@ -29,17 +29,12 @@ class DriftMemoryCard extends StatelessWidget { color: Colors.black, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(25.0)), - side: BorderSide( - color: Colors.black, - width: 1.0, - ), + side: BorderSide(color: Colors.black, width: 1.0), ), clipBehavior: Clip.hardEdge, child: Stack( children: [ - SizedBox.expand( - child: _BlurredBackdrop(asset: asset), - ), + SizedBox.expand(child: _BlurredBackdrop(asset: asset)), LayoutBuilder( builder: (context, constraints) { // Determine the fit using the aspect ratio @@ -55,11 +50,7 @@ class DriftMemoryCard extends StatelessWidget { } if (asset.isImage) { - return FullImage( - asset, - fit: fit, - size: const Size(double.infinity, double.infinity), - ); + return FullImage(asset, fit: fit, size: const Size(double.infinity, double.infinity)); } else { return SizedBox( width: context.width, @@ -69,11 +60,7 @@ class DriftMemoryCard extends StatelessWidget { asset: asset, showControls: false, playbackDelayFactor: 2, - image: FullImage( - asset, - size: Size(context.width, context.height), - fit: BoxFit.contain, - ), + image: FullImage(asset, size: Size(context.width, context.height), fit: BoxFit.contain), ), ); } @@ -85,10 +72,7 @@ class DriftMemoryCard extends StatelessWidget { bottom: 18.0, child: Text( title, - style: context.textTheme.headlineMedium?.copyWith( - color: Colors.white, - fontWeight: FontWeight.w500, - ), + style: context.textTheme.headlineMedium?.copyWith(color: Colors.white, fontWeight: FontWeight.w500), ), ), ], @@ -109,16 +93,9 @@ class _BlurredBackdrop extends HookWidget { // Use a nice cheap blur hash image decoration return Container( decoration: BoxDecoration( - image: DecorationImage( - image: MemoryImage( - blurhash, - ), - fit: BoxFit.cover, - ), - ), - child: Container( - color: Colors.black.withValues(alpha: 0.2), + image: DecorationImage(image: MemoryImage(blurhash), fit: BoxFit.cover), ), + child: Container(color: Colors.black.withValues(alpha: 0.2)), ); } else { // Fall back to using a more expensive image filtered @@ -129,16 +106,11 @@ class _BlurredBackdrop extends HookWidget { child: Container( decoration: BoxDecoration( image: DecorationImage( - image: getFullImageProvider( - asset, - size: Size(context.width, context.height), - ), + image: getFullImageProvider(asset, size: Size(context.width, context.height)), fit: BoxFit.cover, ), ), - child: Container( - color: Colors.black.withValues(alpha: 0.2), - ), + child: Container(color: Colors.black.withValues(alpha: 0.2)), ), ); } diff --git a/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart b/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart index 4863b60aa..e2bc59b4c 100644 --- a/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart +++ b/mobile/lib/presentation/widgets/memory/memory_lane.widget.dart @@ -17,17 +17,13 @@ class DriftMemoryLane extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return ConstrainedBox( - constraints: const BoxConstraints( - maxHeight: 200, - ), + constraints: const BoxConstraints(maxHeight: 200), child: CarouselView( itemExtent: 145.0, shrinkExtent: 1.0, elevation: 2, backgroundColor: Colors.black, - overlayColor: WidgetStateProperty.all( - Colors.white.withValues(alpha: 0.1), - ), + overlayColor: WidgetStateProperty.all(Colors.white.withValues(alpha: 0.1)), onTap: (index) { ref.read(hapticFeedbackProvider.notifier).heavyImpact(); @@ -40,12 +36,7 @@ class DriftMemoryLane extends ConsumerWidget { } } - context.pushRoute( - DriftMemoryRoute( - memories: memories, - memoryIndex: index, - ), - ); + context.pushRoute(DriftMemoryRoute(memories: memories, memoryIndex: index)); }, children: memories.map((memory) => DriftMemoryCard(memory: memory)).toList(), ), @@ -54,53 +45,33 @@ class DriftMemoryLane extends ConsumerWidget { } class DriftMemoryCard extends ConsumerWidget { - const DriftMemoryCard({ - super.key, - required this.memory, - }); + const DriftMemoryCard({super.key, required this.memory}); final DriftMemory memory; @override Widget build(BuildContext context, WidgetRef ref) { final yearsAgo = DateTime.now().year - memory.data.year; - final title = 'years_ago'.t( - context: context, - args: { - 'years': yearsAgo.toString(), - }, - ); + final title = 'years_ago'.t(context: context, args: {'years': yearsAgo.toString()}); return Center( child: Stack( children: [ ColorFiltered( - colorFilter: ColorFilter.mode( - Colors.black.withValues(alpha: 0.2), - BlendMode.darken, - ), + colorFilter: ColorFilter.mode(Colors.black.withValues(alpha: 0.2), BlendMode.darken), child: SizedBox( width: 205, height: 200, - child: Thumbnail( - remoteId: memory.assets[0].id, - fit: BoxFit.cover, - ), + child: Thumbnail(remoteId: memory.assets[0].id, fit: BoxFit.cover), ), ), Positioned( bottom: 16, left: 16, child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 114, - ), + constraints: const BoxConstraints(maxWidth: 114), child: Text( title, - style: const TextStyle( - fontWeight: FontWeight.w600, - color: Colors.white, - fontSize: 15, - ), + style: const TextStyle(fontWeight: FontWeight.w600, color: Colors.white, fontSize: 15), ), ), ), diff --git a/mobile/lib/presentation/widgets/remote_album/drift_album_option.widget.dart b/mobile/lib/presentation/widgets/remote_album/drift_album_option.widget.dart index 81989b263..c08348e2a 100644 --- a/mobile/lib/presentation/widgets/remote_album/drift_album_option.widget.dart +++ b/mobile/lib/presentation/widgets/remote_album/drift_album_option.widget.dart @@ -25,9 +25,7 @@ class DriftRemoteAlbumOption extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - TextStyle textStyle = Theme.of(context).textTheme.bodyLarge!.copyWith( - fontWeight: FontWeight.w600, - ); + TextStyle textStyle = Theme.of(context).textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w600); return SafeArea( child: Padding( @@ -38,72 +36,46 @@ class DriftRemoteAlbumOption extends ConsumerWidget { if (onEditAlbum != null) ListTile( leading: const Icon(Icons.edit), - title: Text( - 'edit_album'.t(context: context), - style: textStyle, - ), + title: Text('edit_album'.t(context: context), style: textStyle), onTap: onEditAlbum, ), if (onAddPhotos != null) ListTile( leading: const Icon(Icons.add_a_photo), - title: Text( - 'add_photos'.t(context: context), - style: textStyle, - ), + title: Text('add_photos'.t(context: context), style: textStyle), onTap: onAddPhotos, ), if (onAddUsers != null) ListTile( leading: const Icon(Icons.group_add), - title: Text( - 'album_viewer_page_share_add_users'.t(context: context), - style: textStyle, - ), + title: Text('album_viewer_page_share_add_users'.t(context: context), style: textStyle), onTap: onAddUsers, ), if (onLeaveAlbum != null) ListTile( leading: const Icon(Icons.person_remove_rounded), - title: Text( - 'leave_album'.t(context: context), - style: textStyle, - ), + title: Text('leave_album'.t(context: context), style: textStyle), onTap: onLeaveAlbum, ), if (onToggleAlbumOrder != null) ListTile( leading: const Icon(Icons.swap_vert_rounded), - title: Text( - 'change_display_order'.t(context: context), - style: textStyle, - ), + title: Text('change_display_order'.t(context: context), style: textStyle), onTap: onToggleAlbumOrder, ), if (onCreateSharedLink != null) ListTile( leading: const Icon(Icons.link), - title: Text( - 'create_shared_link'.t(context: context), - style: textStyle, - ), + title: Text('create_shared_link'.t(context: context), style: textStyle), onTap: onCreateSharedLink, ), if (onDeleteAlbum != null) ...[ - const Divider( - indent: 16, - endIndent: 16, - ), + const Divider(indent: 16, endIndent: 16), ListTile( - leading: Icon( - Icons.delete, - color: context.isDarkTheme ? Colors.red[400] : Colors.red[800], - ), + leading: Icon(Icons.delete, color: context.isDarkTheme ? Colors.red[400] : Colors.red[800]), title: Text( 'delete_album'.t(context: context), - style: textStyle.copyWith( - color: context.isDarkTheme ? Colors.red[400] : Colors.red[800], - ), + style: textStyle.copyWith(color: context.isDarkTheme ? Colors.red[400] : Colors.red[800]), ), onTap: onDeleteAlbum, ), diff --git a/mobile/lib/presentation/widgets/timeline/fixed/row.dart b/mobile/lib/presentation/widgets/timeline/fixed/row.dart index 24f3c9712..3fe3cea3c 100644 --- a/mobile/lib/presentation/widgets/timeline/fixed/row.dart +++ b/mobile/lib/presentation/widgets/timeline/fixed/row.dart @@ -16,11 +16,7 @@ class FixedTimelineRow extends MultiChildRenderObjectWidget { @override RenderObject createRenderObject(BuildContext context) { - return RenderFixedRow( - dimension: dimension, - spacing: spacing, - textDirection: textDirection, - ); + return RenderFixedRow(dimension: dimension, spacing: spacing, textDirection: textDirection); } @override @@ -50,9 +46,9 @@ class RenderFixedRow extends RenderBox required double dimension, required double spacing, required TextDirection textDirection, - }) : _dimension = dimension, - _spacing = spacing, - _textDirection = textDirection { + }) : _dimension = dimension, + _spacing = spacing, + _textDirection = textDirection { addAll(children); } diff --git a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart index 88d113dcd..ea5f55b35 100644 --- a/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart +++ b/mobile/lib/presentation/widgets/timeline/fixed/segment.model.dart @@ -33,8 +33,8 @@ class FixedSegment extends Segment { required super.headerExtent, required super.spacing, required super.header, - }) : assert(tileHeight != 0), - mainAxisExtend = tileHeight + spacing; + }) : assert(tileHeight != 0), + mainAxisExtend = tileHeight + spacing; @override double indexToLayoutOffset(int index) { @@ -64,12 +64,7 @@ class FixedSegment extends Segment { final numberOfAssets = math.min(columnCount, assetCount - assetIndex); if (index == firstIndex) { - return TimelineHeader( - bucket: bucket, - header: header, - height: headerExtent, - assetOffset: firstAssetIndex, - ); + return TimelineHeader(bucket: bucket, header: header, height: headerExtent, assetOffset: firstAssetIndex); } return _FixedSegmentRow( @@ -104,10 +99,7 @@ class _FixedSegmentRow extends ConsumerWidget { } if (timelineService.hasRange(assetIndex, assetCount)) { - return _buildAssetRow( - context, - timelineService.getAssets(assetIndex, assetCount), - ); + return _buildAssetRow(context, timelineService.getAssets(assetIndex, assetCount)); } return FutureBuilder>( @@ -122,12 +114,7 @@ class _FixedSegmentRow extends ConsumerWidget { } Widget _buildPlaceholder(BuildContext context) { - return SegmentBuilder.buildPlaceholder( - context, - assetCount, - size: Size.square(tileHeight), - spacing: spacing, - ); + return SegmentBuilder.buildPlaceholder(context, assetCount, size: Size.square(tileHeight), spacing: spacing); } Widget _buildAssetRow(BuildContext context, List assets) { @@ -137,11 +124,7 @@ class _FixedSegmentRow extends ConsumerWidget { textDirection: Directionality.of(context), children: [ for (int i = 0; i < assets.length; i++) - _AssetTileWidget( - key: ValueKey(assets[i].heroTag), - asset: assets[i], - assetIndex: assetIndex + i, - ), + _AssetTileWidget(key: ValueKey(assets[i].heroTag), asset: assets[i], assetIndex: assetIndex + i), ], ); } @@ -151,19 +134,9 @@ class _AssetTileWidget extends ConsumerWidget { final BaseAsset asset; final int assetIndex; - const _AssetTileWidget({ - super.key, - required this.asset, - required this.assetIndex, - }); + const _AssetTileWidget({super.key, required this.asset, required this.assetIndex}); - Future _handleOnTap( - BuildContext ctx, - WidgetRef ref, - int assetIndex, - BaseAsset asset, - int? heroOffset, - ) async { + Future _handleOnTap(BuildContext ctx, WidgetRef ref, int assetIndex, BaseAsset asset, int? heroOffset) async { final multiSelectState = ref.read(multiSelectProvider); if (multiSelectState.forceEnable || multiSelectState.isEnabled) { @@ -192,11 +165,7 @@ class _AssetTileWidget extends ConsumerWidget { } bool _getLockSelectionStatus(WidgetRef ref) { - final lockSelectionAssets = ref.read( - multiSelectProvider.select( - (state) => state.lockedSelectionAssets, - ), - ); + final lockSelectionAssets = ref.read(multiSelectProvider.select((state) => state.lockedSelectionAssets)); if (lockSelectionAssets.isEmpty) { return false; @@ -210,9 +179,7 @@ class _AssetTileWidget extends ConsumerWidget { final heroOffset = TabsRouterScope.of(context)?.controller.activeIndex ?? 0; final lockSelection = _getLockSelectionStatus(ref); - final showStorageIndicator = ref.watch( - timelineArgsProvider.select((args) => args.showStorageIndicator), - ); + final showStorageIndicator = ref.watch(timelineArgsProvider.select((args) => args.showStorageIndicator)); return RepaintBoundary( child: GestureDetector( diff --git a/mobile/lib/presentation/widgets/timeline/fixed/segment_builder.dart b/mobile/lib/presentation/widgets/timeline/fixed/segment_builder.dart index 5e260a4e6..b65582f97 100644 --- a/mobile/lib/presentation/widgets/timeline/fixed/segment_builder.dart +++ b/mobile/lib/presentation/widgets/timeline/fixed/segment_builder.dart @@ -35,8 +35,7 @@ class FixedSegmentBuilder extends SegmentBuilder { final timelineHeader = switch (groupBy) { GroupAssetsBy.month => HeaderType.month, - GroupAssetsBy.day || - GroupAssetsBy.auto => + GroupAssetsBy.day || GroupAssetsBy.auto => bucket is TimeBucket && bucket.date.month != previousDate?.month ? HeaderType.monthAndDay : HeaderType.day, GroupAssetsBy.none => HeaderType.none, }; diff --git a/mobile/lib/presentation/widgets/timeline/header.widget.dart b/mobile/lib/presentation/widgets/timeline/header.widget.dart index da48acd7d..b8c6668a3 100644 --- a/mobile/lib/presentation/widgets/timeline/header.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/header.widget.dart @@ -47,11 +47,7 @@ class TimelineHeader extends StatelessWidget { final isDayHeader = header == HeaderType.day || header == HeaderType.monthAndDay; return Padding( - padding: EdgeInsets.only( - top: isMonthHeader ? 8.0 : 0.0, - left: 12.0, - right: 12.0, - ), + padding: EdgeInsets.only(top: isMonthHeader ? 8.0 : 0.0, left: 12.0, right: 12.0), child: SizedBox( height: height, child: Column( @@ -61,32 +57,17 @@ class TimelineHeader extends StatelessWidget { if (isMonthHeader) Row( children: [ - Text( - _formatMonth(context, date), - style: context.textTheme.labelLarge?.copyWith(fontSize: 24), - ), + Text(_formatMonth(context, date), style: context.textTheme.labelLarge?.copyWith(fontSize: 24)), const Spacer(), - if (header != HeaderType.monthAndDay) - _BulkSelectIconButton( - bucket: bucket, - assetOffset: assetOffset, - ), + if (header != HeaderType.monthAndDay) _BulkSelectIconButton(bucket: bucket, assetOffset: assetOffset), ], ), if (isDayHeader) Row( children: [ - Text( - _formatDay(context, date), - style: context.textTheme.labelLarge?.copyWith( - fontSize: 15, - ), - ), + Text(_formatDay(context, date), style: context.textTheme.labelLarge?.copyWith(fontSize: 15)), const Spacer(), - _BulkSelectIconButton( - bucket: bucket, - assetOffset: assetOffset, - ), + _BulkSelectIconButton(bucket: bucket, assetOffset: assetOffset), ], ), ], @@ -100,10 +81,7 @@ class _BulkSelectIconButton extends ConsumerWidget { final Bucket bucket; final int assetOffset; - const _BulkSelectIconButton({ - required this.bucket, - required this.assetOffset, - }); + const _BulkSelectIconButton({required this.bucket, required this.assetOffset}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -118,23 +96,12 @@ class _BulkSelectIconButton extends ConsumerWidget { return IconButton( onPressed: () { - ref.read(multiSelectProvider.notifier).toggleBucketSelection( - assetOffset, - bucket.assetCount, - ); + ref.read(multiSelectProvider.notifier).toggleBucketSelection(assetOffset, bucket.assetCount); ref.read(hapticFeedbackProvider.notifier).heavyImpact(); }, icon: isAllSelected - ? Icon( - Icons.check_circle_rounded, - size: 26, - color: context.primaryColor, - ) - : Icon( - Icons.check_circle_outline_rounded, - size: 26, - color: context.colorScheme.onSurfaceSecondary, - ), + ? Icon(Icons.check_circle_rounded, size: 26, color: context.primaryColor) + : Icon(Icons.check_circle_outline_rounded, size: 26, color: context.colorScheme.onSurfaceSecondary), ); } } diff --git a/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart b/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart index 6d23f169b..be1d0f087 100644 --- a/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/scrubber.widget.dart @@ -43,10 +43,7 @@ class Scrubber extends ConsumerStatefulWidget { ConsumerState createState() => ScrubberState(); } -List<_Segment> _buildSegments({ - required List layoutSegments, - required double timelineHeight, -}) { +List<_Segment> _buildSegments({required List layoutSegments, required double timelineHeight}) { const double offsetThreshold = 20.0; final segments = <_Segment>[]; @@ -66,14 +63,7 @@ List<_Segment> _buildSegments({ final showSegment = lastOffset + offsetThreshold <= startOffset && (lastDate == null || date.year != lastDate.year); - segments.add( - _Segment( - date: date, - startOffset: startOffset, - scrollLabel: label, - showSegment: showSegment, - ), - ); + segments.add(_Segment(date: date, startOffset: startOffset, scrollLabel: label, showSegment: showSegment)); lastDate = date; if (showSegment) { lastOffset = startOffset; @@ -109,27 +99,12 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi void initState() { super.initState(); _isDragging = false; - _segments = _buildSegments( - layoutSegments: widget.layoutSegments, - timelineHeight: _scrubberHeight, - ); - _thumbAnimationController = AnimationController( - vsync: this, - duration: kTimelineScrubberFadeInDuration, - ); - _thumbAnimation = CurvedAnimation( - parent: _thumbAnimationController, - curve: Curves.fastEaseInToSlowEaseOut, - ); - _labelAnimationController = AnimationController( - vsync: this, - duration: kTimelineScrubberFadeInDuration, - ); + _segments = _buildSegments(layoutSegments: widget.layoutSegments, timelineHeight: _scrubberHeight); + _thumbAnimationController = AnimationController(vsync: this, duration: kTimelineScrubberFadeInDuration); + _thumbAnimation = CurvedAnimation(parent: _thumbAnimationController, curve: Curves.fastEaseInToSlowEaseOut); + _labelAnimationController = AnimationController(vsync: this, duration: kTimelineScrubberFadeInDuration); - _labelAnimation = CurvedAnimation( - parent: _labelAnimationController, - curve: Curves.fastOutSlowIn, - ); + _labelAnimation = CurvedAnimation(parent: _labelAnimationController, curve: Curves.fastOutSlowIn); } @override @@ -143,10 +118,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi super.didUpdateWidget(oldWidget); if (oldWidget.layoutSegments.lastOrNull?.endOffset != widget.layoutSegments.lastOrNull?.endOffset) { - _segments = _buildSegments( - layoutSegments: widget.layoutSegments, - timelineHeight: _scrubberHeight, - ); + _segments = _buildSegments(layoutSegments: widget.layoutSegments, timelineHeight: _scrubberHeight); } } @@ -276,12 +248,10 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi } int _findLayoutSegmentIndex(_Segment segment) { - return widget.layoutSegments.indexWhere( - (layoutSegment) { - final bucket = layoutSegment.bucket as TimeBucket; - return bucket.date.year == segment.date.year && bucket.date.month == segment.date.month; - }, - ); + return widget.layoutSegments.indexWhere((layoutSegment) { + final bucket = layoutSegment.bucket as TimeBucket; + return bucket.date.year == segment.date.year && bucket.date.month == segment.date.month; + }); } void _scrollToLayoutSegment(int layoutSegmentIndex) { @@ -311,19 +281,13 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi if (_scrollController.hasClients == true) { // Cache to avoid multiple calls to [_currentOffset] final scrollOffset = _currentOffset; - final labelText = _segments - .lastWhereOrNull( - (segment) => segment.startOffset <= scrollOffset, - ) - ?.scrollLabel ?? + final labelText = + _segments.lastWhereOrNull((segment) => segment.startOffset <= scrollOffset)?.scrollLabel ?? _segments.firstOrNull?.scrollLabel; label = labelText != null ? Text( labelText, - style: ctx.textTheme.bodyLarge?.copyWith( - color: Colors.white, - fontWeight: FontWeight.bold, - ), + style: ctx.textTheme.bodyLarge?.copyWith(color: Colors.white, fontWeight: FontWeight.bold), ) : null; } @@ -351,11 +315,7 @@ class ScrubberState extends ConsumerState with TickerProviderStateMixi onVerticalDragStart: _onDragStart, onVerticalDragUpdate: _onDragUpdate, onVerticalDragEnd: _onDragEnd, - child: _Scrubber( - thumbAnimation: _thumbAnimation, - labelAnimation: _labelAnimation, - label: label, - ), + child: _Scrubber(thumbAnimation: _thumbAnimation, labelAnimation: _labelAnimation, label: label), ), ), ), @@ -370,12 +330,7 @@ class _SegmentsLayer extends StatelessWidget { final double topPadding; final bool isDragging; - const _SegmentsLayer({ - super.key, - required this.segments, - required this.topPadding, - required this.isDragging, - }); + const _SegmentsLayer({super.key, required this.segments, required this.topPadding, required this.isDragging}); @override Widget build(BuildContext context) { @@ -389,9 +344,7 @@ class _SegmentsLayer extends StatelessWidget { key: ValueKey('segment_${segment.date.millisecondsSinceEpoch}'), top: topPadding + segment.startOffset, end: 100, - child: RepaintBoundary( - child: _SegmentWidget(segment), - ), + child: RepaintBoundary(child: _SegmentWidget(segment)), ), ) .toList(), @@ -419,10 +372,7 @@ class _SegmentWidget extends StatelessWidget { alignment: Alignment.center, child: Text( _segment.date.year.toString(), - style: context.textTheme.labelMedium?.copyWith( - fontFamily: "OverpassMono", - fontWeight: FontWeight.w600, - ), + style: context.textTheme.labelMedium?.copyWith(fontFamily: "OverpassMono", fontWeight: FontWeight.w600), ), ), ), @@ -436,11 +386,7 @@ class _ScrollLabel extends StatelessWidget { final Color backgroundColor; final Animation animation; - const _ScrollLabel({ - required this.label, - required this.backgroundColor, - required this.animation, - }); + const _ScrollLabel({required this.label, required this.backgroundColor, required this.animation}); @override Widget build(BuildContext context) { @@ -471,16 +417,13 @@ class _Scrubber extends StatelessWidget { final Animation thumbAnimation; final Animation labelAnimation; - const _Scrubber({ - this.label, - required this.thumbAnimation, - required this.labelAnimation, - }); + const _Scrubber({this.label, required this.thumbAnimation, required this.labelAnimation}); @override Widget build(BuildContext context) { - final backgroundColor = - context.isDarkTheme ? context.colorScheme.primary.darken(amount: .5) : context.colorScheme.primary; + final backgroundColor = context.isDarkTheme + ? context.colorScheme.primary.darken(amount: .5) + : context.colorScheme.primary; return _SlideFadeTransition( animation: thumbAnimation, @@ -488,12 +431,7 @@ class _Scrubber extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, children: [ - if (label != null) - _ScrollLabel( - label: label!, - backgroundColor: backgroundColor, - animation: labelAnimation, - ), + if (label != null) _ScrollLabel(label: label!, backgroundColor: backgroundColor, animation: labelAnimation), _CircularThumb(backgroundColor), ], ), @@ -519,9 +457,7 @@ class _CircularThumb extends StatelessWidget { topRight: Radius.circular(4.0), bottomRight: Radius.circular(4.0), ), - child: Container( - constraints: BoxConstraints.tight(const Size(48.0 * 0.6, 48.0)), - ), + child: Container(constraints: BoxConstraints.tight(const Size(48.0 * 0.6, 48.0))), ), ); } @@ -543,14 +479,8 @@ class _ArrowPainter extends CustomPainter { final baseX = size.width / 2; final baseY = size.height / 2; - canvas.drawPath( - _trianglePath(Offset(baseX, baseY - 2.0), width, height, true), - paint, - ); - canvas.drawPath( - _trianglePath(Offset(baseX, baseY + 2.0), width, height, false), - paint, - ); + canvas.drawPath(_trianglePath(Offset(baseX, baseY - 2.0), width, height, true), paint); + canvas.drawPath(_trianglePath(Offset(baseX, baseY + 2.0), width, height, false), paint); } static Path _trianglePath(Offset o, double width, double height, bool isUp) { @@ -566,11 +496,9 @@ class _SlideFadeTransition extends StatelessWidget { final Animation _animation; final Widget _child; - const _SlideFadeTransition({ - required Animation animation, - required Widget child, - }) : _animation = animation, - _child = child; + const _SlideFadeTransition({required Animation animation, required Widget child}) + : _animation = animation, + _child = child; @override Widget build(BuildContext context) { @@ -578,14 +506,8 @@ class _SlideFadeTransition extends StatelessWidget { animation: _animation, builder: (context, child) => _animation.value == 0.0 ? const SizedBox() : child!, child: SlideTransition( - position: Tween( - begin: const Offset(0.3, 0.0), - end: const Offset(0.0, 0.0), - ).animate(_animation), - child: FadeTransition( - opacity: _animation, - child: _child, - ), + position: Tween(begin: const Offset(0.3, 0.0), end: const Offset(0.0, 0.0)).animate(_animation), + child: FadeTransition(opacity: _animation, child: _child), ), ); } @@ -597,19 +519,9 @@ class _Segment { final String scrollLabel; final bool showSegment; - const _Segment({ - required this.date, - required this.startOffset, - required this.scrollLabel, - this.showSegment = false, - }); + const _Segment({required this.date, required this.startOffset, required this.scrollLabel, this.showSegment = false}); - _Segment copyWith({ - DateTime? date, - double? startOffset, - String? scrollLabel, - bool? showSegment, - }) { + _Segment copyWith({DateTime? date, double? startOffset, String? scrollLabel, bool? showSegment}) { return _Segment( date: date ?? this.date, startOffset: startOffset ?? this.startOffset, diff --git a/mobile/lib/presentation/widgets/timeline/segment.model.dart b/mobile/lib/presentation/widgets/timeline/segment.model.dart index 6a20db4c9..bc5f97487 100644 --- a/mobile/lib/presentation/widgets/timeline/segment.model.dart +++ b/mobile/lib/presentation/widgets/timeline/segment.model.dart @@ -37,8 +37,8 @@ abstract class Segment { required this.headerExtent, required this.spacing, required this.header, - }) : gridIndex = firstIndex + 1, - gridOffset = startOffset + headerExtent + spacing; + }) : gridIndex = firstIndex + 1, + gridOffset = startOffset + headerExtent + spacing; bool containsIndex(int index) => firstIndex <= index && index <= lastIndex; diff --git a/mobile/lib/presentation/widgets/timeline/segment_builder.dart b/mobile/lib/presentation/widgets/timeline/segment_builder.dart index a746eab24..c80595a44 100644 --- a/mobile/lib/presentation/widgets/timeline/segment_builder.dart +++ b/mobile/lib/presentation/widgets/timeline/segment_builder.dart @@ -9,34 +9,26 @@ abstract class SegmentBuilder { final double spacing; final GroupAssetsBy groupBy; - const SegmentBuilder({ - required this.buckets, - this.spacing = kTimelineSpacing, - this.groupBy = GroupAssetsBy.day, - }); + const SegmentBuilder({required this.buckets, this.spacing = kTimelineSpacing, this.groupBy = GroupAssetsBy.day}); static double headerExtent(HeaderType header) => switch (header) { - HeaderType.month => kTimelineHeaderExtent, - HeaderType.day => kTimelineHeaderExtent * 0.90, - HeaderType.monthAndDay => kTimelineHeaderExtent * 1.6, - HeaderType.none => 0.0, - }; + HeaderType.month => kTimelineHeaderExtent, + HeaderType.day => kTimelineHeaderExtent * 0.90, + HeaderType.monthAndDay => kTimelineHeaderExtent * 1.6, + HeaderType.none => 0.0, + }; static Widget buildPlaceholder( BuildContext context, int count, { Size size = const Size.square(kTimelineFixedTileExtent), double spacing = kTimelineSpacing, - }) => - RepaintBoundary( - child: FixedTimelineRow( - dimension: size.height, - spacing: spacing, - textDirection: Directionality.of(context), - children: List.generate( - count, - (_) => ThumbnailPlaceholder(width: size.width, height: size.height), - ), - ), - ); + }) => RepaintBoundary( + child: FixedTimelineRow( + dimension: size.height, + spacing: spacing, + textDirection: Directionality.of(context), + children: List.generate(count, (_) => ThumbnailPlaceholder(width: size.width, height: size.height)), + ), + ); } diff --git a/mobile/lib/presentation/widgets/timeline/timeline.state.dart b/mobile/lib/presentation/widgets/timeline/timeline.state.dart index cdf79239d..ad3ae3ccf 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.state.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.state.dart @@ -54,10 +54,7 @@ class TimelineState { final bool isScrubbing; final bool isScrolling; - const TimelineState({ - this.isScrubbing = false, - this.isScrolling = false, - }); + const TimelineState({this.isScrubbing = false, this.isScrolling = false}); bool get isInteracting => isScrubbing || isScrolling; @@ -70,10 +67,7 @@ class TimelineState { int get hashCode => isScrubbing.hashCode ^ isScrolling.hashCode; TimelineState copyWith({bool? isScrubbing, bool? isScrolling}) { - return TimelineState( - isScrubbing: isScrubbing ?? this.isScrubbing, - isScrolling: isScrolling ?? this.isScrolling, - ); + return TimelineState(isScrubbing: isScrubbing ?? this.isScrubbing, isScrolling: isScrolling ?? this.isScrolling); } } @@ -89,38 +83,30 @@ class TimelineStateNotifier extends Notifier { } @override - TimelineState build() => const TimelineState( - isScrubbing: false, - isScrolling: false, - ); + TimelineState build() => const TimelineState(isScrubbing: false, isScrolling: false); } // This provider watches the buckets from the timeline service & args and serves the segments. // It should be used only after the timeline service and timeline args provider is overridden -final timelineSegmentProvider = StreamProvider.autoDispose>( - (ref) async* { - final args = ref.watch(timelineArgsProvider); - final columnCount = args.columnCount; - final spacing = args.spacing; - final availableTileWidth = args.maxWidth - (spacing * (columnCount - 1)); - final tileExtent = math.max(0, availableTileWidth) / columnCount; +final timelineSegmentProvider = StreamProvider.autoDispose>((ref) async* { + final args = ref.watch(timelineArgsProvider); + final columnCount = args.columnCount; + final spacing = args.spacing; + final availableTileWidth = args.maxWidth - (spacing * (columnCount - 1)); + final tileExtent = math.max(0, availableTileWidth) / columnCount; - final groupBy = args.groupBy ?? GroupAssetsBy.values[ref.watch(settingsProvider).get(Setting.groupAssetsBy)]; + final groupBy = args.groupBy ?? GroupAssetsBy.values[ref.watch(settingsProvider).get(Setting.groupAssetsBy)]; - final timelineService = ref.watch(timelineServiceProvider); - yield* timelineService.watchBuckets().map((buckets) { - return FixedSegmentBuilder( - buckets: buckets, - tileHeight: tileExtent, - columnCount: columnCount, - spacing: spacing, - groupBy: groupBy, - ).generate(); - }); - }, - dependencies: [timelineServiceProvider, timelineArgsProvider], -); + final timelineService = ref.watch(timelineServiceProvider); + yield* timelineService.watchBuckets().map((buckets) { + return FixedSegmentBuilder( + buckets: buckets, + tileHeight: tileExtent, + columnCount: columnCount, + spacing: spacing, + groupBy: groupBy, + ).generate(); + }); +}, dependencies: [timelineServiceProvider, timelineArgsProvider]); -final timelineStateProvider = NotifierProvider( - TimelineStateNotifier.new, -); +final timelineStateProvider = NotifierProvider(TimelineStateNotifier.new); diff --git a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart index 59cc018b2..26799580a 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart @@ -29,11 +29,7 @@ class Timeline extends StatelessWidget { this.topSliverWidgetHeight, this.showStorageIndicator = false, this.withStack = false, - this.appBar = const ImmichSliverAppBar( - floating: true, - pinned: false, - snap: false, - ), + this.appBar = const ImmichSliverAppBar(floating: true, pinned: false, snap: false), this.bottomSheet = const GeneralBottomSheet(), this.groupBy, }); @@ -57,9 +53,7 @@ class Timeline extends StatelessWidget { (ref) => TimelineArgs( maxWidth: constraints.maxWidth, maxHeight: constraints.maxHeight, - columnCount: ref.watch( - settingsProvider.select((s) => s.get(Setting.tilesPerRow)), - ), + columnCount: ref.watch(settingsProvider.select((s) => s.get(Setting.tilesPerRow))), showStorageIndicator: showStorageIndicator, withStack: withStack, groupBy: groupBy, @@ -79,12 +73,7 @@ class Timeline extends StatelessWidget { } class _SliverTimeline extends ConsumerStatefulWidget { - const _SliverTimeline({ - this.topSliverWidget, - this.topSliverWidgetHeight, - this.appBar, - this.bottomSheet, - }); + const _SliverTimeline({this.topSliverWidget, this.topSliverWidgetHeight, this.appBar, this.bottomSheet}); final Widget? topSliverWidget; final double? topSliverWidgetHeight; @@ -108,11 +97,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { void _onEvent(Event event) { switch (event) { case ScrollToTopEvent(): - _scrollController.animateTo( - 0, - duration: const Duration(milliseconds: 250), - curve: Curves.easeInOut, - ); + _scrollController.animateTo(0, duration: const Duration(milliseconds: 250), curve: Curves.easeInOut); case ScrollToDateEvent scrollToDateEvent: _scrollToDate(scrollToDateEvent.date); case TimelineReloadEvent(): @@ -143,7 +128,8 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { }); // If exact date not found, try to find the closest month - final fallbackSegment = targetSegment ?? + final fallbackSegment = + targetSegment ?? segments.firstWhereOrNull((segment) { if (segment.bucket is TimeBucket) { final segmentDate = (segment.bucket as TimeBucket).date; @@ -168,9 +154,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { Widget build(BuildContext _) { final asyncSegments = ref.watch(timelineSegmentProvider); final maxHeight = ref.watch(timelineArgsProvider.select((args) => args.maxHeight)); - final isSelectionMode = ref.watch( - multiSelectProvider.select((s) => s.forceEnable), - ); + final isSelectionMode = ref.watch(multiSelectProvider.select((s) => s.forceEnable)); return asyncSegments.widgetWhen( onData: (segments) { @@ -211,42 +195,26 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { addRepaintBoundaries: false, ), ), - const SliverPadding( - padding: EdgeInsets.only( - bottom: scrubberBottomPadding, - ), - ), + const SliverPadding(padding: EdgeInsets.only(bottom: scrubberBottomPadding)), ], ), ), if (!isSelectionMode) ...[ Consumer( builder: (_, consumerRef, child) { - final isMultiSelectEnabled = consumerRef.watch( - multiSelectProvider.select( - (s) => s.isEnabled, - ), - ); + final isMultiSelectEnabled = consumerRef.watch(multiSelectProvider.select((s) => s.isEnabled)); if (isMultiSelectEnabled) { return child!; } return const SizedBox.shrink(); }, - child: const Positioned( - top: 60, - left: 25, - child: _MultiSelectStatusButton(), - ), + child: const Positioned(top: 60, left: 25, child: _MultiSelectStatusButton()), ), if (widget.bottomSheet != null) Consumer( builder: (_, consumerRef, child) { - final isMultiSelectEnabled = consumerRef.watch( - multiSelectProvider.select( - (s) => s.isEnabled, - ), - ); + final isMultiSelectEnabled = consumerRef.watch(multiSelectProvider.select((s) => s.isEnabled)); if (isMultiSelectEnabled) { return child!; @@ -267,22 +235,14 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { class _SliverSegmentedList extends SliverMultiBoxAdaptorWidget { final List _segments; - const _SliverSegmentedList({ - required List segments, - required super.delegate, - }) : _segments = segments; + const _SliverSegmentedList({required List segments, required super.delegate}) : _segments = segments; @override - _RenderSliverTimelineBoxAdaptor createRenderObject(BuildContext context) => _RenderSliverTimelineBoxAdaptor( - childManager: context as SliverMultiBoxAdaptorElement, - segments: _segments, - ); + _RenderSliverTimelineBoxAdaptor createRenderObject(BuildContext context) => + _RenderSliverTimelineBoxAdaptor(childManager: context as SliverMultiBoxAdaptorElement, segments: _segments); @override - void updateRenderObject( - BuildContext context, - _RenderSliverTimelineBoxAdaptor renderObject, - ) { + void updateRenderObject(BuildContext context, _RenderSliverTimelineBoxAdaptor renderObject) { renderObject.segments = _segments; } } @@ -299,10 +259,8 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor { markNeedsLayout(); } - _RenderSliverTimelineBoxAdaptor({ - required super.childManager, - required List segments, - }) : _segments = segments; + _RenderSliverTimelineBoxAdaptor({required super.childManager, required List segments}) + : _segments = segments; int getMinChildIndexForScrollOffset(double offset) => _segments.findByOffset(offset)?.getMinChildIndexForScrollOffset(offset) ?? 0; @@ -335,16 +293,18 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor { final int firstRequiredChildIndex = getMinChildIndexForScrollOffset(scrollOffset); // Find the index of the last child that should be visible or in the trailing cache area. - final int? lastRequiredChildIndex = - targetScrollOffset.isFinite ? getMaxChildIndexForScrollOffset(targetScrollOffset) : null; + final int? lastRequiredChildIndex = targetScrollOffset.isFinite + ? getMaxChildIndexForScrollOffset(targetScrollOffset) + : null; // Remove children that are no longer visible or within the cache area. if (firstChild == null) { collectGarbage(0, 0); } else { final int leadingChildrenToRemove = calculateLeadingGarbage(firstIndex: firstRequiredChildIndex); - final int trailingChildrenToRemove = - lastRequiredChildIndex == null ? 0 : calculateTrailingGarbage(lastIndex: lastRequiredChildIndex); + final int trailingChildrenToRemove = lastRequiredChildIndex == null + ? 0 + : calculateTrailingGarbage(lastIndex: lastRequiredChildIndex); collectGarbage(leadingChildrenToRemove, trailingChildrenToRemove); } @@ -352,10 +312,7 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor { // try to add the first child needed for the current scroll offset. if (firstChild == null) { final double firstChildLayoutOffset = indexToLayoutOffset(firstRequiredChildIndex); - final bool childAdded = addInitialChild( - index: firstRequiredChildIndex, - layoutOffset: firstChildLayoutOffset, - ); + final bool childAdded = addInitialChild(index: firstRequiredChildIndex, layoutOffset: firstChildLayoutOffset); if (!childAdded) { // There are either no children, or we are past the end of all our children. @@ -408,16 +365,15 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor { // until we reach the [lastRequiredChildIndex] or run out of children. double calculatedMaxScrollOffset = double.infinity; - for (int currentIndex = indexOf(mostRecentlyLaidOutChild!) + 1; - lastRequiredChildIndex == null || currentIndex <= lastRequiredChildIndex; - ++currentIndex) { + for ( + int currentIndex = indexOf(mostRecentlyLaidOutChild!) + 1; + lastRequiredChildIndex == null || currentIndex <= lastRequiredChildIndex; + ++currentIndex + ) { RenderBox? child = childAfter(mostRecentlyLaidOutChild!); if (child == null || indexOf(child) != currentIndex) { - child = insertAndLayoutChild( - childConstraints, - after: mostRecentlyLaidOutChild, - ); + child = insertAndLayoutChild(childConstraints, after: mostRecentlyLaidOutChild); if (child == null) { final Segment? segment = _segments.findByIndex(currentIndex) ?? _segments.lastOrNull; calculatedMaxScrollOffset = segment?.indexToLayoutOffset(currentIndex) ?? computeMaxScrollOffset(); @@ -443,30 +399,18 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor { ); assert(debugAssertChildListIsNonEmptyAndContiguous()); assert(indexOf(firstChild!) == firstRequiredChildIndex); - assert( - lastRequiredChildIndex == null || lastLaidOutChildIndex <= lastRequiredChildIndex, - ); + assert(lastRequiredChildIndex == null || lastLaidOutChildIndex <= lastRequiredChildIndex); - calculatedMaxScrollOffset = math.min( - calculatedMaxScrollOffset, - estimateMaxScrollOffset(), - ); + calculatedMaxScrollOffset = math.min(calculatedMaxScrollOffset, estimateMaxScrollOffset()); - final double paintExtent = calculatePaintOffset( - constraints, - from: leadingScrollOffset, - to: trailingScrollOffset, - ); + final double paintExtent = calculatePaintOffset(constraints, from: leadingScrollOffset, to: trailingScrollOffset); - final double cacheExtent = calculateCacheOffset( - constraints, - from: leadingScrollOffset, - to: trailingScrollOffset, - ); + final double cacheExtent = calculateCacheOffset(constraints, from: leadingScrollOffset, to: trailingScrollOffset); final double targetEndScrollOffsetForPaint = constraints.scrollOffset + constraints.remainingPaintExtent; - final int? targetLastIndexForPaint = - targetEndScrollOffsetForPaint.isFinite ? getMaxChildIndexForScrollOffset(targetEndScrollOffsetForPaint) : null; + final int? targetLastIndexForPaint = targetEndScrollOffsetForPaint.isFinite + ? getMaxChildIndexForScrollOffset(targetEndScrollOffsetForPaint) + : null; final maxPaintExtent = math.max(paintExtent, calculatedMaxScrollOffset); @@ -477,7 +421,8 @@ class _RenderSliverTimelineBoxAdaptor extends RenderSliverMultiBoxAdaptor { // Indicates if there's content scrolled off-screen. // This is true if the last child needed for painting is actually laid out, // or if the first child is partially visible. - hasVisualOverflow: (targetLastIndexForPaint != null && lastLaidOutChildIndex >= targetLastIndexForPaint) || + hasVisualOverflow: + (targetLastIndexForPaint != null && lastLaidOutChildIndex >= targetLastIndexForPaint) || constraints.scrollOffset > 0.0, cacheExtent: cacheExtent, ); @@ -500,16 +445,10 @@ class _MultiSelectStatusButton extends ConsumerWidget { final selectCount = ref.watch(multiSelectProvider.select((s) => s.selectedAssets.length)); return ElevatedButton.icon( onPressed: () => ref.read(multiSelectProvider.notifier).reset(), - icon: Icon( - Icons.close_rounded, - color: context.colorScheme.onPrimary, - ), + icon: Icon(Icons.close_rounded, color: context.colorScheme.onPrimary), label: Text( selectCount.toString(), - style: context.textTheme.titleMedium?.copyWith( - height: 2.5, - color: context.colorScheme.onPrimary, - ), + style: context.textTheme.titleMedium?.copyWith(height: 2.5, color: context.colorScheme.onPrimary), ), ); } diff --git a/mobile/lib/providers/activity.provider.dart b/mobile/lib/providers/activity.provider.dart index 38b8caaed..a867a5a28 100644 --- a/mobile/lib/providers/activity.provider.dart +++ b/mobile/lib/providers/activity.provider.dart @@ -36,12 +36,9 @@ class AlbumActivity extends _$AlbumActivity { } Future addComment(String comment) async { - final activity = await ref.watch(activityServiceProvider).addActivity( - albumId, - ActivityType.comment, - assetId: assetId, - comment: comment, - ); + final activity = await ref + .watch(activityServiceProvider) + .addActivity(albumId, ActivityType.comment, assetId: assetId, comment: comment); if (activity.hasValue) { final activities = state.valueOrNull ?? []; diff --git a/mobile/lib/providers/activity.provider.g.dart b/mobile/lib/providers/activity.provider.g.dart index af574b991aeee89e443e9c9d22110066afc67637..dc927795f85196af5fdd1fc8c70ada9a22d584ba 100644 GIT binary patch delta 387 zcmeyN_e^&~IE!j7=6@^} zObUdQPflT16M!2AHDmHx_Ex2WqWrSVl++?UxGX{hV%6q!4n-yrE(IV+ttd&&ODP7k zf!xUxxYQ;K2+2*}Bf>d(Ia{Z?1|fIEYJ&7mp2ICYd4mAkSnek-QUrb1rK97sM;oV-9(Y_gn? O=;ZUFuP5&m+YbQr6@$?L delta 529 zcmaE+`$KO-IEyit0uTh36lLb6D$#1vxfgO_LkAHoAgYBzRWAN}(hpvsf=aGp{7I zC@(Qb18BnJEN+d-CISkRg9PL!pXOGd{DE6*@*M$bKB(hB0SW|@jd`qvAxwLPywaQ; zsPyDg9_`7~1q3Fq1Jc)dG$;S#v6^hgD>FHOSBh0Z0T{rOC$dXS<`fXvJe9YRaq>QP znaR5RoGhT=pKQi2M=%6sHdpbhFfjqcV~(H?Gbk7)mkNqWz+LB)SzKb{m|T)smRVA1 OXE)he^vz@qv3&q@Gn9D% diff --git a/mobile/lib/providers/activity_statistics.provider.g.dart b/mobile/lib/providers/activity_statistics.provider.g.dart index d2de32c0aab1cc29439ea25933569567255bbc35..83d887f6dc07b265bc9b460191c49f759499d19d 100644 GIT binary patch delta 308 zcmeCu|ERmcokcykq$o2lT_G_isWjI!MMohTB4DqOSX`W1;+YbwY0Xv3#WlH~&26#^ zm)7PtES5|PgfvYKX4e*g8woXO@ytlXZ9v zCMN;qDtLJ(xAWRgKE^9G`K+Mi=D)nN87I%>SDk!}Uk;n2#Wu?dtY@2iT5LZ62%2g4 delta 426 zcmeyU+oiw3oyC+(0SJOiiZb)k6%uojN^?C^bQGeIMC}z4i;GiBfWkn*SWRoLS}v~1 zjcjg{TUoU>-(#_4(nC^Agb|a?*|lZCS`^@_VO)qslYInbCwH<}K-{LFP*9X#mYI@T zqz7{!R5?N%;Xnn2&B`1s%m$>nDOPi`FSqpMG;a0D?g9#vS8~fwKE|yx`2)B9 diff --git a/mobile/lib/providers/album/album.provider.dart b/mobile/lib/providers/album/album.provider.dart index ae565d20d..35634d77c 100644 --- a/mobile/lib/providers/album/album.provider.dart +++ b/mobile/lib/providers/album/album.provider.dart @@ -35,31 +35,15 @@ class AlbumNotifier extends StateNotifier> { Future deleteAlbum(Album album) => albumService.deleteAlbum(album); - Future createAlbum( - String albumTitle, - Set assets, - ) => - albumService.createAlbum(albumTitle, assets, []); + Future createAlbum(String albumTitle, Set assets) => albumService.createAlbum(albumTitle, assets, []); - Future getAlbumByName( - String albumName, { - bool? remote, - bool? shared, - bool? owner, - }) => - albumService.getAlbumByName( - albumName, - remote: remote, - shared: shared, - owner: owner, - ); + Future getAlbumByName(String albumName, {bool? remote, bool? shared, bool? owner}) => + albumService.getAlbumByName(albumName, remote: remote, shared: shared, owner: owner); /// Create an album on the server with the same name as the selected album for backup /// First this will check if the album already exists on the server with name /// If it does not exist, it will create the album on the server - Future createSyncAlbum( - String albumName, - ) async { + Future createSyncAlbum(String albumName) async { final album = await getAlbumByName(albumName, remote: true, owner: true); if (album != null) { return; @@ -105,10 +89,7 @@ class AlbumNotifier extends StateNotifier> { return await albumService.removeAsset(album, assets); } - Future setActivitystatus( - Album album, - bool enabled, - ) { + Future setActivitystatus(Album album, bool enabled) { return albumService.setActivityStatus(album, enabled); } @@ -126,10 +107,7 @@ class AlbumNotifier extends StateNotifier> { } final albumProvider = StateNotifierProvider.autoDispose>((ref) { - return AlbumNotifier( - ref.watch(albumServiceProvider), - ref, - ); + return AlbumNotifier(ref.watch(albumServiceProvider), ref); }); final albumWatcher = StreamProvider.autoDispose.family((ref, id) async* { diff --git a/mobile/lib/providers/album/album_sort_by_options.provider.dart b/mobile/lib/providers/album/album_sort_by_options.provider.dart index 6e1669fae..3dd09f128 100644 --- a/mobile/lib/providers/album/album_sort_by_options.provider.dart +++ b/mobile/lib/providers/album/album_sort_by_options.provider.dart @@ -75,22 +75,10 @@ class _AlbumSortHandlers { enum AlbumSortMode { title(1, "library_page_sort_title", _AlbumSortHandlers.title), assetCount(4, "library_page_sort_asset_count", _AlbumSortHandlers.assetCount), - lastModified( - 3, - "library_page_sort_last_modified", - _AlbumSortHandlers.lastModified, - ), + lastModified(3, "library_page_sort_last_modified", _AlbumSortHandlers.lastModified), created(0, "library_page_sort_created", _AlbumSortHandlers.created), - mostRecent( - 2, - "sort_recent", - _AlbumSortHandlers.mostRecent, - ), - mostOldest( - 5, - "sort_oldest", - _AlbumSortHandlers.mostOldest, - ); + mostRecent(2, "sort_recent", _AlbumSortHandlers.mostRecent), + mostOldest(5, "sort_oldest", _AlbumSortHandlers.mostOldest); final int storeIndex; final String label; @@ -104,18 +92,12 @@ class AlbumSortByOptions extends _$AlbumSortByOptions { @override AlbumSortMode build() { final sortOpt = ref.watch(appSettingsServiceProvider).getSetting(AppSettingsEnum.selectedAlbumSortOrder); - return AlbumSortMode.values.firstWhere( - (e) => e.storeIndex == sortOpt, - orElse: () => AlbumSortMode.title, - ); + return AlbumSortMode.values.firstWhere((e) => e.storeIndex == sortOpt, orElse: () => AlbumSortMode.title); } void changeSortMode(AlbumSortMode sortOption) { state = sortOption; - ref.watch(appSettingsServiceProvider).setSetting( - AppSettingsEnum.selectedAlbumSortOrder, - sortOption.storeIndex, - ); + ref.watch(appSettingsServiceProvider).setSetting(AppSettingsEnum.selectedAlbumSortOrder, sortOption.storeIndex); } } diff --git a/mobile/lib/providers/album/album_sort_by_options.provider.g.dart b/mobile/lib/providers/album/album_sort_by_options.provider.g.dart index ba20e7eb66c42ee03dd54e9e9594839aa01fc829..750329c9d591abd8250d24231a62a3bb4a2e4041 100644 GIT binary patch delta 187 zcmbQubDL*_6cdwz!ej|186E{7$V<#kwNfZjpS+Gyid|iY3nVr { } } -final albumTitleProvider = StateNotifierProvider( - (ref) => AlbumTitleNotifier(), -); +final albumTitleProvider = StateNotifierProvider((ref) => AlbumTitleNotifier()); diff --git a/mobile/lib/providers/album/album_viewer.provider.dart b/mobile/lib/providers/album/album_viewer.provider.dart index afae154cd..f4ce04746 100644 --- a/mobile/lib/providers/album/album_viewer.provider.dart +++ b/mobile/lib/providers/album/album_viewer.provider.dart @@ -5,13 +5,7 @@ import 'package:immich_mobile/services/album.service.dart'; class AlbumViewerNotifier extends StateNotifier { AlbumViewerNotifier(this.ref) - : super( - const AlbumViewerPageState( - editTitleText: "", - isEditAlbum: false, - editDescriptionText: "", - ), - ); + : super(const AlbumViewerPageState(editTitleText: "", isEditAlbum: false, editDescriptionText: "")); final Ref ref; @@ -40,17 +34,10 @@ class AlbumViewerNotifier extends StateNotifier { } void resetState() { - state = state.copyWith( - editTitleText: "", - isEditAlbum: false, - editDescriptionText: "", - ); + state = state.copyWith(editTitleText: "", isEditAlbum: false, editDescriptionText: ""); } - Future changeAlbumTitle( - Album album, - String newAlbumTitle, - ) async { + Future changeAlbumTitle(Album album, String newAlbumTitle) async { AlbumService service = ref.watch(albumServiceProvider); bool isSuccess = await service.changeTitleAlbum(album, newAlbumTitle); @@ -65,16 +52,10 @@ class AlbumViewerNotifier extends StateNotifier { return false; } - Future changeAlbumDescription( - Album album, - String newAlbumDescription, - ) async { + Future changeAlbumDescription(Album album, String newAlbumDescription) async { AlbumService service = ref.watch(albumServiceProvider); - bool isSuccess = await service.changeDescriptionAlbum( - album, - newAlbumDescription, - ); + bool isSuccess = await service.changeDescriptionAlbum(album, newAlbumDescription); if (isSuccess) { state = state.copyWith(editDescriptionText: "", isEditAlbum: false); diff --git a/mobile/lib/providers/album/current_album.provider.g.dart b/mobile/lib/providers/album/current_album.provider.g.dart index 60ebe3e33329e7ff6df2102967aa5cec557e2801..b6d079231f41d8553858afee252acd43555806be 100644 GIT binary patch delta 143 zcmdnR{(ybMOGYULAaE`%DoV{Oam-07&DG0GE!W`!iBA5_sLTYUWSFEU+cN0|fCWJk z3JUfLd8IiyNCH+0@hZtkrg$V4XFyC*P)JEFNX<)0%}dTqEw%z{gqlB}Ntp#?+T=q_ FKL9S9C&T~% delta 107 zcmaFBzKeasOGX*z(xRf&yb{Npq|#iyywq|XE(L|W#N1RXg(CII6BtEQ)IlOCsY#{j z?x`itMX8A;sloZBMaiiiiNzUKKsg|o?98Ocu3)c_SDKSExra%TF=g^aCeg`