mobile: show thumbhash on scroll
This commit is contained in:
parent
c08d9a7001
commit
ce2ecbea40
2 changed files with 61 additions and 60 deletions
mobile/lib
|
@ -4,6 +4,7 @@ import 'dart:math';
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_thumbhash/flutter_thumbhash.dart';
|
||||
import 'package:immich_mobile/modules/asset_viewer/providers/scroll_notifier.provider.dart';
|
||||
import 'package:immich_mobile/modules/home/ui/asset_grid/thumbnail_image.dart';
|
||||
import 'package:immich_mobile/shared/models/asset.dart';
|
||||
|
@ -120,33 +121,55 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
|
|||
assets.firstWhereOrNull((e) => !_selectedAssets.contains(e)) == null;
|
||||
}
|
||||
|
||||
Widget _buildThumbnailOrPlaceholder(Asset asset, int index) {
|
||||
return ThumbnailImage(
|
||||
asset: asset,
|
||||
index: index,
|
||||
loadAsset: widget.renderList.loadAsset,
|
||||
totalAssets: widget.renderList.totalAssets,
|
||||
multiselectEnabled: widget.selectionActive,
|
||||
isSelected: widget.selectionActive && _selectedAssets.contains(asset),
|
||||
onSelect: () => _selectAssets([asset]),
|
||||
onDeselect: widget.canDeselect ||
|
||||
widget.preselectedAssets == null ||
|
||||
!widget.preselectedAssets!.contains(asset)
|
||||
? () => _deselectAssets([asset])
|
||||
: null,
|
||||
useGrayBoxPlaceholder: true,
|
||||
showStorageIndicator: widget.showStorageIndicator,
|
||||
heroOffset: widget.heroOffset,
|
||||
showStack: widget.showStack,
|
||||
Widget _getPlaceholder(Asset asset) {
|
||||
if (asset.thumbhash != null) {
|
||||
return FittedBox(
|
||||
fit: BoxFit.fill,
|
||||
child: Image(
|
||||
image: ThumbHash.fromIntList(asset.thumbhash!).toImage(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Container(
|
||||
color: Colors.grey,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildThumbnailOrPlaceholder(
|
||||
Asset asset,
|
||||
int index,
|
||||
bool isScrolling,
|
||||
) {
|
||||
return isScrolling
|
||||
? _getPlaceholder(asset)
|
||||
: ThumbnailImage(
|
||||
asset: asset,
|
||||
index: index,
|
||||
loadAsset: widget.renderList.loadAsset,
|
||||
totalAssets: widget.renderList.totalAssets,
|
||||
multiselectEnabled: widget.selectionActive,
|
||||
isSelected:
|
||||
widget.selectionActive && _selectedAssets.contains(asset),
|
||||
onSelect: () => _selectAssets([asset]),
|
||||
onDeselect: widget.canDeselect ||
|
||||
widget.preselectedAssets == null ||
|
||||
!widget.preselectedAssets!.contains(asset)
|
||||
? () => _deselectAssets([asset])
|
||||
: null,
|
||||
useGrayBoxPlaceholder: true,
|
||||
showStorageIndicator: widget.showStorageIndicator,
|
||||
heroOffset: widget.heroOffset,
|
||||
showStack: widget.showStack,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAssetRow(
|
||||
Key key,
|
||||
BuildContext context,
|
||||
List<Asset> assets,
|
||||
int absoluteOffset,
|
||||
double width,
|
||||
bool isScrolling,
|
||||
) {
|
||||
// Default: All assets have the same width
|
||||
final widthDistribution = List.filled(assets.length, 1.0);
|
||||
|
@ -185,7 +208,11 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
|
|||
bottom: widget.margin,
|
||||
right: last ? 0.0 : widget.margin,
|
||||
),
|
||||
child: _buildThumbnailOrPlaceholder(asset, absoluteOffset + index),
|
||||
child: _buildThumbnailOrPlaceholder(
|
||||
asset,
|
||||
absoluteOffset + index,
|
||||
isScrolling,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
|
@ -224,25 +251,6 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildPlaceHolderRow(Key key, int num, double width, double height) {
|
||||
return Row(
|
||||
key: key,
|
||||
children: [
|
||||
for (int i = 0; i < num; i++)
|
||||
Container(
|
||||
key: ValueKey(i),
|
||||
width: width,
|
||||
height: height,
|
||||
margin: EdgeInsets.only(
|
||||
bottom: widget.margin,
|
||||
right: i + 1 == num ? 0.0 : widget.margin,
|
||||
),
|
||||
color: Colors.grey,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSection(
|
||||
BuildContext context,
|
||||
RenderAssetGridElement section,
|
||||
|
@ -254,9 +262,8 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
|
|||
widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow;
|
||||
final rows =
|
||||
(section.count + widget.assetsPerRow - 1) ~/ widget.assetsPerRow;
|
||||
final List<Asset> assetsToRender = scrolling
|
||||
? []
|
||||
: widget.renderList.loadAssets(section.offset, section.count);
|
||||
final List<Asset> assetsToRender =
|
||||
widget.renderList.loadAssets(section.offset, section.count);
|
||||
return Column(
|
||||
key: ValueKey(section.offset),
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -274,25 +281,17 @@ class ImmichAssetGridViewState extends State<ImmichAssetGridView> {
|
|||
.loadAssets(section.offset, section.totalCount),
|
||||
),
|
||||
for (int i = 0; i < rows; i++)
|
||||
scrolling
|
||||
? _buildPlaceHolderRow(
|
||||
ValueKey(i),
|
||||
i + 1 == rows
|
||||
? section.count - i * widget.assetsPerRow
|
||||
: widget.assetsPerRow,
|
||||
width,
|
||||
width,
|
||||
)
|
||||
: _buildAssetRow(
|
||||
ValueKey(i),
|
||||
context,
|
||||
assetsToRender.nestedSlice(
|
||||
i * widget.assetsPerRow,
|
||||
min((i + 1) * widget.assetsPerRow, section.count),
|
||||
),
|
||||
section.offset + i * widget.assetsPerRow,
|
||||
width,
|
||||
),
|
||||
_buildAssetRow(
|
||||
ValueKey(i),
|
||||
context,
|
||||
assetsToRender.nestedSlice(
|
||||
i * widget.assetsPerRow,
|
||||
min((i + 1) * widget.assetsPerRow, section.count),
|
||||
),
|
||||
section.offset + i * widget.assetsPerRow,
|
||||
width,
|
||||
scrolling,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
|
|
@ -123,6 +123,8 @@ class ImmichImage extends StatelessWidget {
|
|||
cacheKey: getThumbnailCacheKey(asset, type: type),
|
||||
),
|
||||
fit: fit,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
syncDuration: const Duration(milliseconds: 500),
|
||||
placeholder: placeholderWidget,
|
||||
errorBuilder: (context, error) {
|
||||
if (error is HttpExceptionWithStatus &&
|
||||
|
|
Loading…
Add table
Reference in a new issue