feat: home grid
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/domain/models/render_list_element.model.dart';
|
||||
import 'package:immich_mobile/presentation/components/image/immich_image.widget.dart';
|
||||
import 'package:immich_mobile/service_locator.dart';
|
||||
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
|
||||
|
||||
class ImAssetGrid extends StatelessWidget {
|
||||
const ImAssetGrid({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return StreamBuilder(
|
||||
stream: di<IAssetRepository>().getRenderList(),
|
||||
builder: (_, renderSnap) {
|
||||
final renderList = renderSnap.data;
|
||||
if (renderList == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final elements = renderList.elements;
|
||||
return ScrollablePositionedList.builder(
|
||||
itemCount: elements.length,
|
||||
itemBuilder: (_, sectionIndex) {
|
||||
final section = elements[sectionIndex];
|
||||
|
||||
return switch (section) {
|
||||
RenderListMonthHeaderElement() => Text(section.header),
|
||||
RenderListDayHeaderElement() => Text(section.header),
|
||||
RenderListAssetElement() => FutureBuilder(
|
||||
future: renderList.loadAssets(
|
||||
section.assetOffset,
|
||||
section.assetCount,
|
||||
),
|
||||
builder: (_, assetsSnap) {
|
||||
final assets = assetsSnap.data;
|
||||
if (assets == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return GridView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
),
|
||||
itemBuilder: (_, i) {
|
||||
return SizedBox.square(
|
||||
dimension: 200,
|
||||
// ignore: avoid-unsafe-collection-methods
|
||||
child: ImImage(assets.elementAt(i)),
|
||||
);
|
||||
},
|
||||
itemCount: section.assetCount,
|
||||
);
|
||||
},
|
||||
),
|
||||
};
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:immich_mobile/domain/models/asset.model.dart';
|
||||
import 'package:immich_mobile/service_locator.dart';
|
||||
import 'package:immich_mobile/utils/immich_api_client.dart';
|
||||
import 'package:immich_mobile/utils/immich_image_url_helper.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
class ImImage extends StatelessWidget {
|
||||
final Asset asset;
|
||||
final double? width;
|
||||
final double? height;
|
||||
|
||||
const ImImage(this.asset, {this.width, this.height, super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CachedNetworkImage(
|
||||
imageUrl: ImImageUrlHelper.getThumbnailUrl(asset),
|
||||
httpHeaders: di<ImmichApiClient>().headers,
|
||||
cacheKey: ImImageUrlHelper.getThumbnailUrl(asset),
|
||||
width: width,
|
||||
height: height,
|
||||
// keeping memCacheWidth, memCacheHeight, maxWidthDiskCache and
|
||||
// maxHeightDiskCache = null allows to simply store the webp thumbnail
|
||||
// from the server and use it for all rendered thumbnail sizes
|
||||
fit: BoxFit.cover,
|
||||
fadeInDuration: const Duration(milliseconds: 250),
|
||||
progressIndicatorBuilder: (_, url, downloadProgress) {
|
||||
// Show loading if desired
|
||||
return const SizedBox.square(
|
||||
dimension: 250,
|
||||
child: DecoratedBox(decoration: BoxDecoration(color: Colors.grey)),
|
||||
);
|
||||
},
|
||||
errorWidget: (_, url, error) {
|
||||
if (error is HttpExceptionWithStatus &&
|
||||
error.statusCode >= 400 &&
|
||||
error.statusCode < 500) {
|
||||
CachedNetworkImage.evictFromCache(url);
|
||||
}
|
||||
return Icon(
|
||||
Symbols.image_not_supported_rounded,
|
||||
color: Theme.of(context).primaryColor,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:immich_mobile/domain/services/sync.service.dart';
|
||||
import 'package:immich_mobile/presentation/modules/common/states/current_user.state.dart';
|
||||
import 'package:immich_mobile/service_locator.dart';
|
||||
import 'package:immich_mobile/presentation/components/grid/immich_asset_grid.widget.dart';
|
||||
|
||||
@RoutePage()
|
||||
class HomePage extends StatelessWidget {
|
||||
@@ -10,12 +8,6 @@ class HomePage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: () => di<SyncService>()
|
||||
.doFullSyncForUserDrift(di<CurrentUserCubit>().state),
|
||||
child: const Text('Sync'),
|
||||
),
|
||||
);
|
||||
return const ImAssetGrid();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/asset.interface.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/store.interface.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/user.interface.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
@@ -135,7 +136,8 @@ class LoginPageCubit extends Cubit<LoginPageState> with LogContext {
|
||||
// Register user
|
||||
ServiceLocator.registerCurrentUser(user);
|
||||
await di<IUserRepository>().add(user);
|
||||
// Sync assets in background
|
||||
// Remove and Sync assets in background
|
||||
await di<IAssetRepository>().clearAll();
|
||||
unawaited(di<SyncService>().doFullSyncForUserDrift(user));
|
||||
|
||||
emit(state.copyWith(
|
||||
|
||||
Reference in New Issue
Block a user