Refactor mobile to use OpenApi generated SDK (#336)

This commit is contained in:
Alex
2022-07-13 07:23:48 -05:00
committed by GitHub
parent d69470e207
commit ae7e582ec8
276 changed files with 14513 additions and 3003 deletions

View File

@@ -7,7 +7,6 @@ import 'package:immich_mobile/constants/immich_colors.dart';
import 'package:immich_mobile/modules/home/ui/draggable_scrollbar.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/modules/sharing/models/asset_selection_page_result.model.dart';
import 'package:immich_mobile/modules/sharing/models/shared_album.model.dart';
import 'package:immich_mobile/modules/sharing/providers/asset_selection.provider.dart';
import 'package:immich_mobile/modules/sharing/providers/shared_album.provider.dart';
import 'package:immich_mobile/modules/sharing/services/shared_album.service.dart';
@@ -19,7 +18,7 @@ import 'package:immich_mobile/routing/router.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:intl/intl.dart';
import 'package:openapi/api.dart';
class AlbumViewerPage extends HookConsumerWidget {
final String albumId;
@@ -30,18 +29,18 @@ class AlbumViewerPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
FocusNode titleFocusNode = useFocusNode();
ScrollController scrollController = useScrollController();
AsyncValue<SharedAlbum> albumInfo =
AsyncValue<AlbumResponseDto?> albumInfo =
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(SharedAlbum albumInfo) async {
if (albumInfo.assets?.isNotEmpty == true) {
void _onAddPhotosPressed(AlbumResponseDto albumInfo) async {
if (albumInfo.assets.isNotEmpty == true) {
ref
.watch(assetSelectionProvider.notifier)
.addNewAssets(albumInfo.assets!.toList());
.addNewAssets(albumInfo.assets.toList());
}
ref.watch(assetSelectionProvider.notifier).setIsAlbumExist(true);
@@ -57,7 +56,9 @@ class AlbumViewerPage extends HookConsumerWidget {
var isSuccess = await ref
.watch(sharedAlbumServiceProvider)
.addAdditionalAssetToAlbum(
returnPayload.selectedAdditionalAsset, albumId);
returnPayload.selectedAdditionalAsset,
albumId,
);
if (isSuccess) {
ref.refresh(sharedAlbumDetailProvider(albumId));
@@ -72,10 +73,11 @@ class AlbumViewerPage extends HookConsumerWidget {
}
}
void _onAddUsersPressed(SharedAlbum albumInfo) async {
List<String>? sharedUserIds = await AutoRouter.of(context)
.push<List<String>?>(
SelectAdditionalUserForSharingRoute(albumInfo: albumInfo));
void _onAddUsersPressed(AlbumResponseDto albumInfo) async {
List<String>? sharedUserIds =
await AutoRouter.of(context).push<List<String>?>(
SelectAdditionalUserForSharingRoute(albumInfo: albumInfo),
);
if (sharedUserIds != null) {
ImmichLoadingOverlayController.appLoader.show();
@@ -92,7 +94,7 @@ class AlbumViewerPage extends HookConsumerWidget {
}
}
Widget _buildTitle(SharedAlbum albumInfo) {
Widget _buildTitle(AlbumResponseDto albumInfo) {
return Padding(
padding: const EdgeInsets.only(left: 8, right: 8, top: 16),
child: userId == albumInfo.ownerId
@@ -102,19 +104,24 @@ class AlbumViewerPage extends HookConsumerWidget {
)
: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(albumInfo.albumName,
style: const TextStyle(
fontSize: 24, fontWeight: FontWeight.bold)),
child: Text(
albumInfo.albumName,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
);
}
Widget _buildAlbumDateRange(SharedAlbum albumInfo) {
Widget _buildAlbumDateRange(AlbumResponseDto albumInfo) {
String startDate = "";
DateTime parsedStartDate =
DateTime.parse(albumInfo.assets!.first.createdAt);
DateTime.parse(albumInfo.assets.first.createdAt);
DateTime parsedEndDate = DateTime.parse(
albumInfo.assets?.last.createdAt ?? '11111111'); //Need default.
albumInfo.assets.last.createdAt,
); //Need default.
if (parsedStartDate.year == parsedEndDate.year) {
startDate = DateFormat('LLL d').format(parsedStartDate);
@@ -129,18 +136,21 @@ class AlbumViewerPage extends HookConsumerWidget {
child: Text(
"$startDate-$endDate",
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.bold, color: Colors.grey),
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.grey,
),
),
);
}
Widget _buildHeader(SharedAlbum albumInfo) {
Widget _buildHeader(AlbumResponseDto albumInfo) {
return SliverToBoxAdapter(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildTitle(albumInfo),
if (albumInfo.assets?.isNotEmpty == true)
if (albumInfo.assets.isNotEmpty == true)
_buildAlbumDateRange(albumInfo),
SizedBox(
height: 60,
@@ -172,8 +182,8 @@ class AlbumViewerPage extends HookConsumerWidget {
);
}
Widget _buildImageGrid(SharedAlbum albumInfo) {
if (albumInfo.assets?.isNotEmpty == true) {
Widget _buildImageGrid(AlbumResponseDto albumInfo) {
if (albumInfo.assets.isNotEmpty) {
return SliverPadding(
padding: const EdgeInsets.only(top: 10.0),
sliver: SliverGrid(
@@ -184,9 +194,9 @@ class AlbumViewerPage extends HookConsumerWidget {
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return AlbumViewerThumbnail(asset: albumInfo.assets![index]);
return AlbumViewerThumbnail(asset: albumInfo.assets[index]);
},
childCount: albumInfo.assets?.length,
childCount: albumInfo.assets.length,
),
),
);
@@ -194,7 +204,7 @@ class AlbumViewerPage extends HookConsumerWidget {
return const SliverToBoxAdapter();
}
Widget _buildControlButton(SharedAlbum albumInfo) {
Widget _buildControlButton(AlbumResponseDto albumInfo) {
return Padding(
padding: const EdgeInsets.only(left: 16.0, top: 8, bottom: 8),
child: SizedBox(
@@ -219,7 +229,7 @@ class AlbumViewerPage extends HookConsumerWidget {
);
}
Widget _buildBody(SharedAlbum albumInfo) {
Widget _buildBody(AlbumResponseDto albumInfo) {
return GestureDetector(
onTap: () {
titleFocusNode.unfocus();
@@ -252,9 +262,16 @@ class AlbumViewerPage extends HookConsumerWidget {
return Scaffold(
appBar: AlbumViewerAppbar(
albumInfo: albumInfo, userId: userId, albumId: albumId),
albumInfo: albumInfo,
userId: userId,
albumId: albumId,
),
body: albumInfo.when(
data: (albumInfo) => _buildBody(albumInfo),
data: (albumInfo) => albumInfo != null
? _buildBody(albumInfo)
: const Center(
child: CircularProgressIndicator(),
),
error: (e, _) => Center(child: Text("Error loading album info $e")),
loading: () => const Center(
child: ImmichLoadingIndicator(),

View File

@@ -56,10 +56,11 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
left: 10,
),
child: AlbumTitleTextField(
isAlbumTitleEmpty: isAlbumTitleEmpty,
albumTitleTextFieldFocusNode: albumTitleTextFieldFocusNode,
albumTitleController: albumTitleController,
isAlbumTitleTextFieldFocus: isAlbumTitleTextFieldFocus),
isAlbumTitleEmpty: isAlbumTitleEmpty,
albumTitleTextFieldFocusNode: albumTitleTextFieldFocusNode,
albumTitleController: albumTitleController,
isAlbumTitleTextFieldFocus: isAlbumTitleTextFieldFocus,
),
);
}
@@ -67,8 +68,8 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
if (selectedAssets.isEmpty) {
return SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.only(top: 200, left: 18),
child: Text(
padding: const EdgeInsets.only(top: 200, left: 18),
child: const Text(
'create_shared_album_page_share_add_assets',
style: TextStyle(fontSize: 12),
).tr(),
@@ -86,13 +87,16 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
padding: const EdgeInsets.only(top: 16, left: 18, right: 18),
child: OutlinedButton.icon(
style: OutlinedButton.styleFrom(
alignment: Alignment.centerLeft,
padding:
const EdgeInsets.symmetric(vertical: 22, horizontal: 16),
side: const BorderSide(
color: Color.fromARGB(255, 206, 206, 206)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5))),
alignment: Alignment.centerLeft,
padding:
const EdgeInsets.symmetric(vertical: 22, horizontal: 16),
side: const BorderSide(
color: Color.fromARGB(255, 206, 206, 206),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
),
onPressed: _onSelectPhotosButtonPressed,
icon: const Icon(Icons.add_rounded),
label: Padding(
@@ -100,9 +104,10 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
child: Text(
'create_shared_album_page_share_select_photos',
style: TextStyle(
fontSize: 16,
color: Colors.grey[700],
fontWeight: FontWeight.bold),
fontSize: 16,
color: Colors.grey[700],
fontWeight: FontWeight.bold,
),
).tr(),
),
),
@@ -147,7 +152,8 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
return GestureDetector(
onTap: _onBackgroundTapped,
child: SharedAlbumThumbnailImage(
asset: selectedAssets.toList()[index]),
asset: selectedAssets.toList()[index],
),
);
},
childCount: selectedAssets.length,
@@ -160,58 +166,60 @@ class CreateSharedAlbumPage extends HookConsumerWidget {
}
return Scaffold(
appBar: AppBar(
elevation: 0,
centerTitle: false,
leading: IconButton(
onPressed: () {
ref.watch(assetSelectionProvider.notifier).removeAll();
AutoRouter.of(context).pop();
},
icon: const Icon(Icons.close_rounded)),
title: const Text(
'share_create_album',
style: TextStyle(color: Colors.black),
).tr(),
actions: [
TextButton(
onPressed: albumTitleController.text.isNotEmpty
? _showSelectUserPage
: null,
child: Text(
'create_shared_album_page_share'.tr(),
style: TextStyle(
fontWeight: FontWeight.bold,
appBar: AppBar(
elevation: 0,
centerTitle: false,
leading: IconButton(
onPressed: () {
ref.watch(assetSelectionProvider.notifier).removeAll();
AutoRouter.of(context).pop();
},
icon: const Icon(Icons.close_rounded),
),
title: const Text(
'share_create_album',
style: TextStyle(color: Colors.black),
).tr(),
actions: [
TextButton(
onPressed: albumTitleController.text.isNotEmpty
? _showSelectUserPage
: null,
child: Text(
'create_shared_album_page_share'.tr(),
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
],
),
body: GestureDetector(
onTap: _onBackgroundTapped,
child: CustomScrollView(
slivers: [
SliverAppBar(
elevation: 5,
automaticallyImplyLeading: false,
// leading: Container(),
pinned: true,
floating: false,
bottom: PreferredSize(
preferredSize: const Size.fromHeight(66.0),
child: Column(
children: [
_buildTitleInputField(),
if (selectedAssets.isNotEmpty) _buildControlButton(),
],
),
),
),
_buildTitle(),
_buildSelectPhotosButton(),
_buildSelectedImageGrid(),
],
),
body: GestureDetector(
onTap: _onBackgroundTapped,
child: CustomScrollView(
slivers: [
SliverAppBar(
elevation: 5,
automaticallyImplyLeading: false,
// leading: Container(),
pinned: true,
floating: false,
bottom: PreferredSize(
preferredSize: const Size.fromHeight(66.0),
child: Column(
children: [
_buildTitleInputField(),
if (selectedAssets.isNotEmpty) _buildControlButton(),
],
),
),
),
_buildTitle(),
_buildSelectPhotosButton(),
_buildSelectedImageGrid(),
],
),
));
),
);
}
}

View File

@@ -3,29 +3,28 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/sharing/models/shared_album.model.dart';
import 'package:immich_mobile/modules/sharing/providers/suggested_shared_users.provider.dart';
import 'package:immich_mobile/shared/models/user.model.dart';
import 'package:immich_mobile/shared/ui/immich_loading_indicator.dart';
import 'package:openapi/api.dart';
class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
final SharedAlbum albumInfo;
final AlbumResponseDto albumInfo;
const SelectAdditionalUserForSharingPage({Key? key, required this.albumInfo})
: super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
AsyncValue<List<User>> suggestedShareUsers =
AsyncValue<List<UserResponseDto>> suggestedShareUsers =
ref.watch(suggestedSharedUsersProvider);
final sharedUsersList = useState<Set<User>>({});
final sharedUsersList = useState<Set<UserResponseDto>>({});
_addNewUsersHandler() {
AutoRouter.of(context)
.pop(sharedUsersList.value.map((e) => e.id).toList());
}
_buildTileIcon(User user) {
_buildTileIcon(UserResponseDto user) {
if (sharedUsersList.value.contains(user)) {
return CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
@@ -43,7 +42,7 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
}
}
_buildUserList(List<User> users) {
_buildUserList(List<UserResponseDto> users) {
List<Widget> usersChip = [];
for (var user in sharedUsersList.value) {
@@ -55,9 +54,10 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
label: Text(
user.email,
style: const TextStyle(
fontSize: 12,
color: Colors.black87,
fontWeight: FontWeight.bold),
fontSize: 12,
color: Colors.black87,
fontWeight: FontWeight.bold,
),
),
),
),
@@ -70,13 +70,14 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
children: [...usersChip],
),
Padding(
padding: EdgeInsets.all(16.0),
padding: const EdgeInsets.all(16.0),
child: Text(
'select_additional_user_for_sharing_page_suggestions'.tr(),
style: TextStyle(
fontSize: 14,
color: Colors.grey,
fontWeight: FontWeight.bold),
style: const TextStyle(
fontSize: 14,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
),
),
ListView.builder(
@@ -87,13 +88,16 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
title: Text(
users[index].email,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.bold),
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 = {
@@ -139,7 +143,8 @@ class SelectAdditionalUserForSharingPage extends HookConsumerWidget {
data: (users) {
for (var sharedUsers in albumInfo.sharedUsers) {
users.removeWhere(
(u) => u.id == sharedUsers.id || u.id == albumInfo.ownerId);
(u) => u.id == sharedUsers.id || u.id == albumInfo.ownerId,
);
}
return _buildUserList(users);

View File

@@ -9,15 +9,16 @@ import 'package:immich_mobile/modules/sharing/providers/shared_album.provider.da
import 'package:immich_mobile/modules/sharing/providers/suggested_shared_users.provider.dart';
import 'package:immich_mobile/modules/sharing/services/shared_album.service.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/shared/models/user.model.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<User>>({});
AsyncValue<List<User>> suggestedShareUsers =
final sharedUsersList = useState<Set<UserResponseDto>>({});
AsyncValue<List<UserResponseDto>> suggestedShareUsers =
ref.watch(suggestedSharedUsersProvider);
_createSharedAlbum() async {
@@ -37,10 +38,14 @@ class SelectUserForSharingPage extends HookConsumerWidget {
.navigate(const TabControllerRoute(children: [SharingRoute()]));
}
ScaffoldMessenger(child: SnackBar(content: Text('select_user_for_sharing_page_err_album').tr()));
ScaffoldMessenger(
child: SnackBar(
content: const Text('select_user_for_sharing_page_err_album').tr(),
),
);
}
_buildTileIcon(User user) {
_buildTileIcon(UserResponseDto user) {
if (sharedUsersList.value.contains(user)) {
return CircleAvatar(
backgroundColor: Theme.of(context).primaryColor,
@@ -58,7 +63,7 @@ class SelectUserForSharingPage extends HookConsumerWidget {
}
}
_buildUserList(List<User> users) {
_buildUserList(List<UserResponseDto> users) {
List<Widget> usersChip = [];
for (var user in sharedUsersList.value) {
@@ -70,9 +75,10 @@ class SelectUserForSharingPage extends HookConsumerWidget {
label: Text(
user.email,
style: const TextStyle(
fontSize: 12,
color: Colors.black87,
fontWeight: FontWeight.bold),
fontSize: 12,
color: Colors.black87,
fontWeight: FontWeight.bold,
),
),
),
),
@@ -85,13 +91,14 @@ class SelectUserForSharingPage extends HookConsumerWidget {
children: [...usersChip],
),
Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'share_suggestions',
padding: const EdgeInsets.all(16.0),
child: const Text(
'select_user_for_sharing_page_share_suggestions',
style: TextStyle(
fontSize: 14,
color: Colors.grey,
fontWeight: FontWeight.bold),
fontSize: 14,
color: Colors.grey,
fontWeight: FontWeight.bold,
),
).tr(),
),
ListView.builder(
@@ -102,13 +109,16 @@ class SelectUserForSharingPage extends HookConsumerWidget {
title: Text(
users[index].email,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.bold),
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 = {
@@ -141,12 +151,13 @@ class SelectUserForSharingPage extends HookConsumerWidget {
),
actions: [
TextButton(
onPressed:
sharedUsersList.value.isEmpty ? null : _createSharedAlbum,
child: const Text(
"share_create_album",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr())
onPressed:
sharedUsersList.value.isEmpty ? null : _createSharedAlbum,
child: const Text(
"share_create_album",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr(),
)
],
),
body: suggestedShareUsers.when(

View File

@@ -5,10 +5,10 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/sharing/models/shared_album.model.dart';
import 'package:immich_mobile/modules/sharing/providers/shared_album.provider.dart';
import 'package:immich_mobile/modules/sharing/ui/sharing_sliver_appbar.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:openapi/api.dart';
import 'package:transparent_image/transparent_image.dart';
class SharingPage extends HookConsumerWidget {
@@ -18,13 +18,16 @@ class SharingPage extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
var box = Hive.box(userInfoBox);
var thumbnailRequestUrl = '${box.get(serverEndpointKey)}/asset/thumbnail';
final List<SharedAlbum> sharedAlbums = ref.watch(sharedAlbumProvider);
final List<AlbumResponseDto> sharedAlbums = ref.watch(sharedAlbumProvider);
useEffect(() {
ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums();
useEffect(
() {
ref.read(sharedAlbumProvider.notifier).getAllSharedAlbums();
return null;
}, []);
return null;
},
[],
);
_buildAlbumList() {
return SliverList(
@@ -60,9 +63,10 @@ class SharingPage extends HookConsumerWidget {
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.grey.shade800),
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.grey.shade800,
),
),
onTap: () {
AutoRouter.of(context)
@@ -133,9 +137,9 @@ class SharingPage extends HookConsumerWidget {
slivers: [
const SharingSliverAppBar(),
SliverPadding(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 12),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
sliver: SliverToBoxAdapter(
child: Text(
child: const Text(
"sharing_page_album",
style: TextStyle(
fontWeight: FontWeight.bold,