refactor(mobile): introduce Album & User classes (#1561)

replace usages of AlbumResponseDto with Album
replace usages of UserResponseDto with User
This commit is contained in:
Fynn Petersen-Frey
2023-02-06 08:13:32 +01:00
committed by GitHub
parent 527aa61a87
commit 2139853dd9
25 changed files with 475 additions and 255 deletions

View File

@@ -19,11 +19,10 @@ import 'package:immich_mobile/modules/album/ui/album_viewer_thumbnail.dart';
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/asset.dart';
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
import 'package:immich_mobile/shared/ui/immich_sliver_persistent_app_bar_delegate.dart';
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
import 'package:openapi/api.dart';
class AlbumViewerPage extends HookConsumerWidget {
final String albumId;
@@ -34,16 +33,16 @@ class AlbumViewerPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
FocusNode titleFocusNode = useFocusNode();
ScrollController scrollController = useScrollController();
var albumInfo = ref.watch(sharedAlbumDetailProvider(albumId));
final album = ref.watch(sharedAlbumDetailProvider(albumId));
final userId = ref.watch(authenticationProvider).userId;
/// Find out if the assets in album exist on the device
/// If they exist, add to selected asset state to show they are already selected.
void onAddPhotosPressed(AlbumResponseDto albumInfo) async {
void onAddPhotosPressed(Album albumInfo) async {
if (albumInfo.assets.isNotEmpty == true) {
ref.watch(assetSelectionProvider.notifier).addNewAssets(
albumInfo.assets.map((e) => Asset.remote(e)).toList(),
albumInfo.assets,
);
}
@@ -60,7 +59,7 @@ class AlbumViewerPage extends HookConsumerWidget {
var addAssetsResult =
await ref.watch(albumServiceProvider).addAdditionalAssetToAlbum(
returnPayload.selectedAdditionalAsset,
albumId,
albumInfo,
);
if (addAssetsResult != null &&
@@ -78,10 +77,10 @@ class AlbumViewerPage extends HookConsumerWidget {
}
}
void onAddUsersPressed(AlbumResponseDto albumInfo) async {
void onAddUsersPressed(Album album) async {
List<String>? sharedUserIds =
await AutoRouter.of(context).push<List<String>?>(
SelectAdditionalUserForSharingRoute(albumInfo: albumInfo),
SelectAdditionalUserForSharingRoute(album: album),
);
if (sharedUserIds != null) {
@@ -89,7 +88,7 @@ class AlbumViewerPage extends HookConsumerWidget {
var isSuccess = await ref
.watch(albumServiceProvider)
.addAdditionalUserToAlbum(sharedUserIds, albumId);
.addAdditionalUserToAlbum(sharedUserIds, album);
if (isSuccess) {
ref.invalidate(sharedAlbumDetailProvider(albumId));
@@ -99,18 +98,18 @@ class AlbumViewerPage extends HookConsumerWidget {
}
}
Widget buildTitle(AlbumResponseDto albumInfo) {
Widget buildTitle(Album album) {
return Padding(
padding: const EdgeInsets.only(left: 8, right: 8, top: 16),
child: userId == albumInfo.ownerId
child: userId == album.ownerId
? AlbumViewerEditableTitle(
albumInfo: albumInfo,
album: album,
titleFocusNode: titleFocusNode,
)
: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
albumInfo.albumName,
album.name,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
@@ -120,30 +119,22 @@ class AlbumViewerPage extends HookConsumerWidget {
);
}
Widget buildAlbumDateRange(AlbumResponseDto albumInfo) {
String startDate = "";
DateTime parsedStartDate =
DateTime.parse(albumInfo.assets.first.createdAt);
DateTime parsedEndDate = DateTime.parse(
albumInfo.assets.last.createdAt,
); //Need default.
if (parsedStartDate.year == parsedEndDate.year) {
startDate = DateFormat('LLL d').format(parsedStartDate);
} else {
startDate = DateFormat('LLL d, y').format(parsedStartDate);
}
String endDate = DateFormat('LLL d, y').format(parsedEndDate);
Widget buildAlbumDateRange(Album album) {
final DateTime startDate = album.assets.first.createdAt;
final DateTime endDate = album.assets.last.createdAt; //Need default.
final String startDateText =
DateFormat(startDate.year == endDate.year ? 'LLL d' : 'LLL d, y')
.format(startDate);
final String endDateText = DateFormat('LLL d, y').format(endDate);
return Padding(
padding: EdgeInsets.only(
left: 16.0,
top: 8.0,
bottom: albumInfo.shared ? 0.0 : 8.0,
bottom: album.shared ? 0.0 : 8.0,
),
child: Text(
"$startDate-$endDate",
"$startDateText-$endDateText",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
@@ -153,15 +144,14 @@ class AlbumViewerPage extends HookConsumerWidget {
);
}
Widget buildHeader(AlbumResponseDto albumInfo) {
Widget buildHeader(Album album) {
return SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
buildTitle(albumInfo),
if (albumInfo.assets.isNotEmpty == true)
buildAlbumDateRange(albumInfo),
if (albumInfo.shared)
buildTitle(album),
if (album.assets.isNotEmpty == true) buildAlbumDateRange(album),
if (album.shared)
SizedBox(
height: 60,
child: ListView.builder(
@@ -185,7 +175,7 @@ class AlbumViewerPage extends HookConsumerWidget {
),
);
}),
itemCount: albumInfo.sharedUsers.length,
itemCount: album.sharedUsers.length,
),
)
],
@@ -193,12 +183,12 @@ class AlbumViewerPage extends HookConsumerWidget {
);
}
Widget buildImageGrid(AlbumResponseDto albumInfo) {
Widget buildImageGrid(Album album) {
final appSettingService = ref.watch(appSettingsServiceProvider);
final bool showStorageIndicator =
appSettingService.getSetting(AppSettingsEnum.storageIndicator);
if (albumInfo.assets.isNotEmpty) {
if (album.assets.isNotEmpty) {
return SliverPadding(
padding: const EdgeInsets.only(top: 10.0),
sliver: SliverGrid(
@@ -211,13 +201,12 @@ class AlbumViewerPage extends HookConsumerWidget {
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return AlbumViewerThumbnail(
asset: Asset.remote(albumInfo.assets[index]),
assetList:
albumInfo.assets.map((e) => Asset.remote(e)).toList(),
asset: album.assets[index],
assetList: album.assets,
showStorageIndicator: showStorageIndicator,
);
},
childCount: albumInfo.assetCount,
childCount: album.assetCount,
),
),
);
@@ -225,7 +214,7 @@ class AlbumViewerPage extends HookConsumerWidget {
return const SliverToBoxAdapter();
}
Widget buildControlButton(AlbumResponseDto albumInfo) {
Widget buildControlButton(Album album) {
return Padding(
padding: const EdgeInsets.only(left: 16.0, top: 8, bottom: 8),
child: SizedBox(
@@ -235,13 +224,13 @@ class AlbumViewerPage extends HookConsumerWidget {
children: [
AlbumActionOutlinedButton(
iconData: Icons.add_photo_alternate_outlined,
onPressed: () => onAddPhotosPressed(albumInfo),
onPressed: () => onAddPhotosPressed(album),
labelText: "share_add_photos".tr(),
),
if (userId == albumInfo.ownerId)
if (userId == album.ownerId)
AlbumActionOutlinedButton(
iconData: Icons.person_add_alt_rounded,
onPressed: () => onAddUsersPressed(albumInfo),
onPressed: () => onAddUsersPressed(album),
labelText: "album_viewer_page_share_add_users".tr(),
),
],
@@ -251,7 +240,10 @@ class AlbumViewerPage extends HookConsumerWidget {
}
Future<bool> onWillPop() async {
final isMultiselectEnable = ref.read(assetSelectionProvider).selectedAssetsInAlbumViewer.isNotEmpty;
final isMultiselectEnable = ref
.read(assetSelectionProvider)
.selectedAssetsInAlbumViewer
.isNotEmpty;
if (isMultiselectEnable) {
ref.watch(assetSelectionProvider.notifier).removeAll();
return false;
@@ -260,7 +252,7 @@ class AlbumViewerPage extends HookConsumerWidget {
return true;
}
Widget buildBody(AlbumResponseDto albumInfo) {
Widget buildBody(Album album) {
return WillPopScope(
onWillPop: onWillPop,
child: GestureDetector(
@@ -274,7 +266,7 @@ class AlbumViewerPage extends HookConsumerWidget {
child: CustomScrollView(
controller: scrollController,
slivers: [
buildHeader(albumInfo),
buildHeader(album),
SliverPersistentHeader(
pinned: true,
delegate: ImmichSliverPersistentAppBarDelegate(
@@ -282,11 +274,11 @@ class AlbumViewerPage extends HookConsumerWidget {
maxHeight: 50,
child: Container(
color: Theme.of(context).scaffoldBackgroundColor,
child: buildControlButton(albumInfo),
child: buildControlButton(album),
),
),
),
buildImageGrid(albumInfo)
buildImageGrid(album)
],
),
),
@@ -295,13 +287,12 @@ class AlbumViewerPage extends HookConsumerWidget {
}
return Scaffold(
appBar: albumInfo.when(
data: (AlbumResponseDto? data) {
appBar: album.when(
data: (Album? data) {
if (data != null) {
return AlbumViewerAppbar(
albumInfo: data,
album: data,
userId: userId,
albumId: albumId,
);
}
return null;
@@ -309,7 +300,7 @@ class AlbumViewerPage extends HookConsumerWidget {
error: (e, _) => null,
loading: () => null,
),
body: albumInfo.when(
body: album.when(
data: (albumInfo) => albumInfo != null
? buildBody(albumInfo)
: const Center(

View File

@@ -7,7 +7,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/album.provider.dart';
import 'package:immich_mobile/modules/album/ui/album_thumbnail_card.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:openapi/api.dart';
import 'package:immich_mobile/shared/models/album.dart';
class LibraryPage extends HookConsumerWidget {
const LibraryPage({Key? key}) : super(key: key);
@@ -41,11 +41,11 @@ class LibraryPage extends HookConsumerWidget {
final selectedAlbumSortOrder = useState(0);
List<AlbumResponseDto> sortedAlbums() {
List<Album> sortedAlbums() {
if (selectedAlbumSortOrder.value == 0) {
return albums.sortedBy((album) => album.createdAt).reversed.toList();
}
return albums.sortedBy((album) => album.albumName);
return albums.sortedBy((album) => album.name);
}
Widget buildSortButton() {

View File

@@ -4,27 +4,28 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart';
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
import 'package:openapi/api.dart';
class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
final AlbumResponseDto albumInfo;
final Album album;
const SelectAdditionalUserForSharingPage({Key? key, required this.albumInfo})
const SelectAdditionalUserForSharingPage({Key? key, required this.album})
: super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
AsyncValue<List<UserResponseDto>> suggestedShareUsers =
final AsyncValue<List<User>> suggestedShareUsers =
ref.watch(suggestedSharedUsersProvider);
final sharedUsersList = useState<Set<UserResponseDto>>({});
final sharedUsersList = useState<Set<User>>({});
addNewUsersHandler() {
AutoRouter.of(context)
.pop(sharedUsersList.value.map((e) => e.id).toList());
}
buildTileIcon(UserResponseDto user) {
buildTileIcon(User user) {
if (sharedUsersList.value.contains(user)) {
return CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
@@ -42,7 +43,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
}
}
buildUserList(List<UserResponseDto> users) {
buildUserList(List<User> users) {
List<Widget> usersChip = [];
for (var user in sharedUsersList.value) {
@@ -140,9 +141,9 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
),
body: suggestedShareUsers.when(
data: (users) {
for (var sharedUsers in albumInfo.sharedUsers) {
for (var sharedUsers in album.sharedUsers) {
users.removeWhere(
(u) => u.id == sharedUsers.id || u.id == albumInfo.ownerId,
(u) => u.id == sharedUsers.id || u.id == album.ownerId,
);
}

View File

@@ -8,16 +8,16 @@ import 'package:immich_mobile/modules/album/providers/asset_selection.provider.d
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
import 'package:immich_mobile/modules/album/providers/suggested_shared_users.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
import 'package:openapi/api.dart';
class SelectUserForSharingPage extends HookConsumerWidget {
const SelectUserForSharingPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final sharedUsersList = useState<Set<UserResponseDto>>({});
AsyncValue<List<UserResponseDto>> suggestedShareUsers =
final sharedUsersList = useState<Set<User>>({});
AsyncValue<List<User>> suggestedShareUsers =
ref.watch(suggestedSharedUsersProvider);
createSharedAlbum() async {
@@ -25,7 +25,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
await ref.watch(sharedAlbumProvider.notifier).createSharedAlbum(
ref.watch(albumTitleProvider),
ref.watch(assetSelectionProvider).selectedNewAssetsForAlbum,
sharedUsersList.value.map((userInfo) => userInfo.id).toList(),
sharedUsersList.value,
);
if (newAlbum != null) {
@@ -44,7 +44,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
);
}
buildTileIcon(UserResponseDto user) {
buildTileIcon(User user) {
if (sharedUsersList.value.contains(user)) {
return CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
@@ -62,7 +62,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
}
}
buildUserList(List<UserResponseDto> users) {
buildUserList(List<User> users) {
List<Widget> usersChip = [];
for (var user in sharedUsersList.value) {

View File

@@ -9,8 +9,8 @@ import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/album/providers/shared_album.provider.dart';
import 'package:immich_mobile/modules/album/ui/sharing_sliver_appbar.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/album.dart';
import 'package:immich_mobile/utils/image_url_builder.dart';
import 'package:openapi/api.dart';
class SharingPage extends HookConsumerWidget {
const SharingPage({Key? key}) : super(key: key);
@@ -18,7 +18,7 @@ class SharingPage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
var box = Hive.box(userInfoBox);
final List<AlbumResponseDto> sharedAlbums = ref.watch(sharedAlbumProvider);
final List<Album> sharedAlbums = ref.watch(sharedAlbumProvider);
useEffect(
() {
@@ -52,7 +52,7 @@ class SharingPage extends HookConsumerWidget {
),
),
title: Text(
sharedAlbums[index].albumName,
sharedAlbums[index].name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(