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

@@ -15,7 +15,9 @@ class ControlBottomAppBar extends StatelessWidget {
height: MediaQuery.of(context).size.height * 0.15,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15), topRight: Radius.circular(15)),
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
color: Colors.grey[300]?.withOpacity(0.98),
),
child: Column(
@@ -48,12 +50,12 @@ class ControlBottomAppBar extends StatelessWidget {
}
class ControlBoxButton extends StatelessWidget {
const ControlBoxButton(
{Key? key,
required this.label,
required this.iconData,
required this.onPressed})
: super(key: key);
const ControlBoxButton({
Key? key,
required this.label,
required this.iconData,
required this.onPressed,
}) : super(key: key);
final String label;
final IconData iconData;

View File

@@ -2,8 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
import 'package:immich_mobile/shared/models/immich_asset.model.dart';
import 'package:intl/intl.dart';
import 'package:openapi/api.dart';
class DailyTitleText extends ConsumerWidget {
const DailyTitleText({
@@ -13,14 +12,15 @@ class DailyTitleText extends ConsumerWidget {
}) : super(key: key);
final String isoDate;
final List<ImmichAsset> assetGroup;
final List<AssetResponseDto> assetGroup;
@override
Widget build(BuildContext context, WidgetRef ref) {
var currentYear = DateTime.now().year;
var groupYear = DateTime.parse(isoDate).year;
var formatDateTemplate =
currentYear == groupYear ? "daily_title_text_date".tr() : "daily_title_text_date_year".tr();
var formatDateTemplate = currentYear == groupYear
? "daily_title_text_date".tr()
: "daily_title_text_date_year".tr();
var dateText =
DateFormat(formatDateTemplate).format(DateTime.parse(isoDate));
var isMultiSelectEnable =
@@ -74,7 +74,11 @@ class DailyTitleText extends ConsumerWidget {
return SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.only(
top: 29.0, bottom: 29.0, left: 12.0, right: 12.0),
top: 29.0,
bottom: 29.0,
left: 12.0,
right: 12.0,
),
child: Row(
children: [
Text(

View File

@@ -29,15 +29,18 @@ class DisableMultiSelectButton extends ConsumerWidget {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: TextButton.icon(
onPressed: () {
onPressed();
},
icon: const Icon(Icons.close_rounded),
label: Text(
'$selectedItemCount',
style: const TextStyle(
fontWeight: FontWeight.w600, fontSize: 18),
)),
onPressed: () {
onPressed();
},
icon: const Icon(Icons.close_rounded),
label: Text(
'$selectedItemCount',
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18,
),
),
),
),
),
),

View File

@@ -118,20 +118,24 @@ class DraggableScrollbar extends StatefulWidget {
this.labelConstraints,
}) : assert(child.scrollDirection == Axis.vertical),
scrollThumbBuilder = _thumbSemicircleBuilder(
heightScrollThumb * 0.6, scrollThumbKey, alwaysVisibleScrollThumb),
heightScrollThumb * 0.6,
scrollThumbKey,
alwaysVisibleScrollThumb,
),
super(key: key);
@override
DraggableScrollbarState createState() => DraggableScrollbarState();
static buildScrollThumbAndLabel(
{required Widget scrollThumb,
required Color backgroundColor,
required Animation<double>? thumbAnimation,
required Animation<double>? labelAnimation,
required Text? labelText,
required BoxConstraints? labelConstraints,
required bool alwaysVisibleScrollThumb}) {
static buildScrollThumbAndLabel({
required Widget scrollThumb,
required Color backgroundColor,
required Animation<double>? thumbAnimation,
required Animation<double>? labelAnimation,
required Text? labelText,
required BoxConstraints? labelConstraints,
required bool alwaysVisibleScrollThumb,
}) {
var scrollThumbAndLabel = labelText == null
? scrollThumb
: Row(
@@ -158,7 +162,10 @@ class DraggableScrollbar extends StatefulWidget {
}
static ScrollThumbBuilder _thumbSemicircleBuilder(
double width, Key? scrollThumbKey, bool alwaysVisibleScrollThumb) {
double width,
Key? scrollThumbKey,
bool alwaysVisibleScrollThumb,
) {
return (
Color backgroundColor,
Animation<double> thumbAnimation,
@@ -198,7 +205,9 @@ class DraggableScrollbar extends StatefulWidget {
}
static ScrollThumbBuilder _thumbArrowBuilder(
Key? scrollThumbKey, bool alwaysVisibleScrollThumb) {
Key? scrollThumbKey,
bool alwaysVisibleScrollThumb,
) {
return (
Color backgroundColor,
Animation<double> thumbAnimation,
@@ -234,7 +243,9 @@ class DraggableScrollbar extends StatefulWidget {
}
static ScrollThumbBuilder _thumbRRectBuilder(
Key? scrollThumbKey, bool alwaysVisibleScrollThumb) {
Key? scrollThumbKey,
bool alwaysVisibleScrollThumb,
) {
return (
Color backgroundColor,
Animation<double> thumbAnimation,
@@ -372,42 +383,44 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
}
return LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
//print("LayoutBuilder constraints=$constraints");
builder: (BuildContext context, BoxConstraints constraints) {
//print("LayoutBuilder constraints=$constraints");
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
changePosition(notification);
return false;
},
child: Stack(
children: <Widget>[
RepaintBoundary(
child: widget.child,
),
RepaintBoundary(
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
changePosition(notification);
return false;
},
child: Stack(
children: <Widget>[
RepaintBoundary(
child: widget.child,
),
RepaintBoundary(
child: GestureDetector(
onVerticalDragStart: _onVerticalDragStart,
onVerticalDragUpdate: _onVerticalDragUpdate,
onVerticalDragEnd: _onVerticalDragEnd,
child: Container(
alignment: Alignment.topRight,
margin: EdgeInsets.only(top: _barOffset),
padding: widget.padding,
child: widget.scrollThumbBuilder(
widget.backgroundColor,
_thumbAnimation,
_labelAnimation,
widget.heightScrollThumb,
labelText: labelText,
labelConstraints: widget.labelConstraints,
onVerticalDragStart: _onVerticalDragStart,
onVerticalDragUpdate: _onVerticalDragUpdate,
onVerticalDragEnd: _onVerticalDragEnd,
child: Container(
alignment: Alignment.topRight,
margin: EdgeInsets.only(top: _barOffset),
padding: widget.padding,
child: widget.scrollThumbBuilder(
widget.backgroundColor,
_thumbAnimation,
_labelAnimation,
widget.heightScrollThumb,
labelText: labelText,
labelConstraints: widget.labelConstraints,
),
),
),
),
)),
],
),
);
});
],
),
);
},
);
}
//scroll bar has received notification that it's view was scrolled
@@ -498,7 +511,10 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
}
double viewDelta = getScrollViewDelta(
details.delta.dy, barMaxScrollExtent, viewMaxScrollExtent);
details.delta.dy,
barMaxScrollExtent,
viewMaxScrollExtent,
);
_viewOffset = widget.controller.position.pixels + viewDelta;
if (_viewOffset < widget.controller.position.minScrollExtent) {
@@ -579,7 +595,9 @@ class ArrowClipper extends CustomClipper<Path> {
path.lineTo(startPointX + arrowWidth, startPointY);
path.lineTo(startPointX + arrowWidth, startPointY + 1.0);
path.lineTo(
startPointX + arrowWidth / 2, startPointY - arrowWidth / 2 + 1.0);
startPointX + arrowWidth / 2,
startPointY - arrowWidth / 2 + 1.0,
);
path.lineTo(startPointX, startPointY + 1.0);
path.close();
@@ -589,7 +607,9 @@ class ArrowClipper extends CustomClipper<Path> {
path.lineTo(startPointX, startPointY);
path.lineTo(startPointX, startPointY - 1.0);
path.lineTo(
startPointX + arrowWidth / 2, startPointY + arrowWidth / 2 - 1.0);
startPointX + arrowWidth / 2,
startPointY + arrowWidth / 2 - 1.0,
);
path.lineTo(startPointX + arrowWidth, startPointY - 1.0);
path.close();

View File

@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/ui/thumbnail_image.dart';
import 'package:immich_mobile/shared/models/immich_asset.model.dart';
import 'package:openapi/api.dart';
class ImageGrid extends ConsumerWidget {
final List<ImmichAsset> assetGroup;
final List<AssetResponseDto> assetGroup;
const ImageGrid({Key? key, required this.assetGroup}) : super(key: key);
@@ -25,7 +25,7 @@ class ImageGrid extends ConsumerWidget {
child: Stack(
children: [
ThumbnailImage(asset: assetGroup[index]),
if (assetType != 'IMAGE')
if (assetType != AssetTypeEnum.IMAGE)
Positioned(
top: 5,
right: 5,

View File

@@ -31,7 +31,8 @@ class ImmichSliverAppBar extends ConsumerWidget {
pinned: false,
snap: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5))),
borderRadius: BorderRadius.all(Radius.circular(5)),
),
leading: Builder(
builder: (BuildContext context) {
return Stack(
@@ -99,7 +100,8 @@ class ImmichSliverAppBar extends ConsumerWidget {
child: CircularProgressIndicator(
strokeWidth: 1,
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor),
Theme.of(context).primaryColor,
),
),
),
),
@@ -117,7 +119,8 @@ class ImmichSliverAppBar extends ConsumerWidget {
Icons.cloud_off_rounded,
size: 8,
),
child: const Icon(Icons.backup_rounded)),
child: const Icon(Icons.backup_rounded),
),
onPressed: () async {
var onPop = await AutoRouter.of(context)
.push(const BackupControllerRoute());

View File

@@ -1,6 +1,5 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class MonthlyTitleText extends StatelessWidget {
const MonthlyTitleText({
@@ -12,7 +11,8 @@ class MonthlyTitleText extends StatelessWidget {
@override
Widget build(BuildContext context) {
var monthTitleText = DateFormat("monthly_title_text_date_format".tr()).format(DateTime.parse(isoDate));
var monthTitleText = DateFormat("monthly_title_text_date_format".tr())
.format(DateTime.parse(isoDate));
return SliverToBoxAdapter(
child: Padding(

View File

@@ -55,7 +55,8 @@ class ProfileDrawer extends HookConsumerWidget {
return CircleAvatar(
radius: 35,
backgroundImage: NetworkImage(
'$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}'),
'$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}',
),
backgroundColor: Colors.transparent,
);
} else {
@@ -71,7 +72,8 @@ class ProfileDrawer extends HookConsumerWidget {
return CircleAvatar(
radius: 35,
backgroundImage: NetworkImage(
'$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}'),
'$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}',
),
backgroundColor: Colors.transparent,
);
}
@@ -93,7 +95,10 @@ class ProfileDrawer extends HookConsumerWidget {
_pickUserProfileImage() async {
final XFile? image = await ImagePicker().pickImage(
source: ImageSource.gallery, maxHeight: 1024, maxWidth: 1024);
source: ImageSource.gallery,
maxHeight: 1024,
maxWidth: 1024,
);
if (image != null) {
var success =
@@ -101,16 +106,20 @@ class ProfileDrawer extends HookConsumerWidget {
if (success) {
ref.watch(authenticationProvider.notifier).updateUserProfileImagePath(
ref.read(uploadProfileImageProvider).profileImagePath);
ref.read(uploadProfileImageProvider).profileImagePath,
);
}
}
}
useEffect(() {
_getPackageInfo();
_buildUserProfileImage();
return null;
}, []);
useEffect(
() {
_getPackageInfo();
_buildUserProfileImage();
return null;
},
[],
);
return Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -186,9 +195,10 @@ class ProfileDrawer extends HookConsumerWidget {
title: const Text(
"profile_drawer_sign_out",
style: TextStyle(
color: Colors.black54,
fontSize: 14,
fontWeight: FontWeight.bold),
color: Colors.black54,
fontSize: 14,
fontWeight: FontWeight.bold,
),
).tr(),
onTap: () async {
bool res =
@@ -231,9 +241,10 @@ class ProfileDrawer extends HookConsumerWidget {
: "profile_drawer_client_server_up_to_date".tr(),
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w600),
fontSize: 11,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w600,
),
),
),
const Divider(),
@@ -271,7 +282,7 @@ class ProfileDrawer extends HookConsumerWidget {
),
),
Text(
"${serverInfoState.serverVersion.major}.${serverInfoState.serverVersion.minor}.${serverInfoState.serverVersion.patch}",
"${serverInfoState.serverVersion.major}.${serverInfoState.serverVersion.minor}.${serverInfoState.serverVersion.patch_}",
style: TextStyle(
fontSize: 11,
color: Colors.grey[500],

View File

@@ -8,11 +8,11 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/home/providers/home_page_state.provider.dart';
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
import 'package:immich_mobile/shared/models/immich_asset.model.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:openapi/api.dart';
class ThumbnailImage extends HookConsumerWidget {
final ImmichAsset asset;
final AssetResponseDto asset;
const ThumbnailImage({Key? key, required this.asset}) : super(key: key);
@@ -22,14 +22,13 @@ class ThumbnailImage extends HookConsumerWidget {
var box = Hive.box(userInfoBox);
var thumbnailRequestUrl =
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}&isThumb=true';
'${box.get(serverEndpointKey)}/asset/thumbnail/${asset.id}';
var selectedAsset = ref.watch(homePageStateProvider).selectedItems;
var isMultiSelectEnable =
ref.watch(homePageStateProvider).isMultiSelectEnable;
var deviceId = ref.watch(authenticationProvider).deviceId;
Widget _buildSelectionIcon(ImmichAsset asset) {
Widget _buildSelectionIcon(AssetResponseDto asset) {
if (selectedAsset.contains(asset)) {
return Icon(
Icons.check_circle,
@@ -61,7 +60,7 @@ class ThumbnailImage extends HookConsumerWidget {
.watch(homePageStateProvider.notifier)
.addSingleSelectedItem(asset);
} else {
if (asset.type == 'IMAGE') {
if (asset.type == AssetTypeEnum.IMAGE) {
AutoRouter.of(context).push(
ImageViewerRoute(
imageUrl:
@@ -74,9 +73,10 @@ class ThumbnailImage extends HookConsumerWidget {
} else {
AutoRouter.of(context).push(
VideoViewerRoute(
videoUrl:
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}',
asset: asset),
videoUrl:
'${box.get(serverEndpointKey)}/asset/file?aid=${asset.deviceAssetId}&did=${asset.deviceId}',
asset: asset,
),
);
}
}
@@ -94,14 +94,16 @@ class ThumbnailImage extends HookConsumerWidget {
decoration: BoxDecoration(
border: isMultiSelectEnable && selectedAsset.contains(asset)
? Border.all(
color: Theme.of(context).primaryColorLight, width: 10)
color: Theme.of(context).primaryColorLight,
width: 10,
)
: const Border(),
),
child: CachedNetworkImage(
cacheKey: "${asset.id}-${cacheKey.value}",
width: 300,
height: 300,
memCacheHeight: asset.type == 'IMAGE' ? 250 : 400,
memCacheHeight: asset.type == AssetTypeEnum.IMAGE ? 250 : 400,
fit: BoxFit.cover,
imageUrl: thumbnailRequestUrl,
httpHeaders: {
@@ -112,9 +114,11 @@ class ThumbnailImage extends HookConsumerWidget {
Transform.scale(
scale: 0.2,
child: CircularProgressIndicator(
value: downloadProgress.progress),
value: downloadProgress.progress,
),
),
errorWidget: (context, url, error) {
debugPrint("Error getting thumbnail $url = $error");
return Icon(
Icons.image_not_supported_outlined,
color: Theme.of(context).primaryColor,