mirror of
https://github.com/immich-app/immich.git
synced 2025-08-11 09:16:31 -04:00
preserve subtree
not growable minor cleanup
This commit is contained in:
parent
4f19dacecd
commit
be0fe36210
@ -59,7 +59,7 @@ private open class ThumbnailsPigeonCodec : StandardMessageCodec() {
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface ThumbnailApi {
|
||||
fun setThumbnailToBuffer(assetId: String, width: Long, height: Long, callback: (Result<Map<String, Long>>) -> Unit)
|
||||
fun getThumbnailBuffer(assetId: String, width: Long, height: Long, callback: (Result<Map<String, Long>>) -> Unit)
|
||||
|
||||
companion object {
|
||||
/** The codec used by ThumbnailApi. */
|
||||
@ -71,14 +71,14 @@ interface ThumbnailApi {
|
||||
fun setUp(binaryMessenger: BinaryMessenger, api: ThumbnailApi?, messageChannelSuffix: String = "") {
|
||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ThumbnailApi.setThumbnailToBuffer$separatedMessageChannelSuffix", codec)
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.ThumbnailApi.getThumbnailBuffer$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val assetIdArg = args[0] as String
|
||||
val widthArg = args[1] as Long
|
||||
val heightArg = args[2] as Long
|
||||
api.setThumbnailToBuffer(assetIdArg, widthArg, heightArg) { result: Result<Map<String, Long>> ->
|
||||
api.getThumbnailBuffer(assetIdArg, widthArg, heightArg) { result: Result<Map<String, Long>> ->
|
||||
val error = result.exceptionOrNull()
|
||||
if (error != null) {
|
||||
reply.reply(ThumbnailsPigeonUtils.wrapError(error))
|
||||
|
@ -49,19 +49,19 @@ class ThumbnailsImpl(context: Context) : ThumbnailApi {
|
||||
external fun wrapAsBuffer(address: Long, capacity: Int): ByteBuffer
|
||||
}
|
||||
|
||||
override fun setThumbnailToBuffer(
|
||||
override fun getThumbnailBuffer(
|
||||
assetId: String, width: Long, height: Long, callback: (Result<Map<String, Long>>) -> Unit
|
||||
) {
|
||||
threadPool.execute {
|
||||
try {
|
||||
setThumbnailToBufferInternal(assetId, width, height, callback)
|
||||
getThumbnailBufferInternal(assetId, width, height, callback)
|
||||
} catch (e: Exception) {
|
||||
callback(Result.failure(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setThumbnailToBufferInternal(
|
||||
private fun getThumbnailBufferInternal(
|
||||
assetId: String, width: Long, height: Long, callback: (Result<Map<String, Long>>) -> Unit
|
||||
) {
|
||||
val targetWidth = width.toInt()
|
||||
|
@ -70,7 +70,7 @@ class ThumbnailsPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol ThumbnailApi {
|
||||
func setThumbnailToBuffer(assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
||||
func getThumbnailBuffer(assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
||||
}
|
||||
|
||||
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
|
||||
@ -79,14 +79,14 @@ class ThumbnailApiSetup {
|
||||
/// Sets up an instance of `ThumbnailApi` to handle messages through the `binaryMessenger`.
|
||||
static func setUp(binaryMessenger: FlutterBinaryMessenger, api: ThumbnailApi?, messageChannelSuffix: String = "") {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let setThumbnailToBufferChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ThumbnailApi.setThumbnailToBuffer\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
let getThumbnailBufferChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.ThumbnailApi.getThumbnailBuffer\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
setThumbnailToBufferChannel.setMessageHandler { message, reply in
|
||||
getThumbnailBufferChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let assetIdArg = args[0] as! String
|
||||
let widthArg = args[1] as! Int64
|
||||
let heightArg = args[2] as! Int64
|
||||
api.setThumbnailToBuffer(assetId: assetIdArg, width: widthArg, height: heightArg) { result in
|
||||
api.getThumbnailBuffer(assetId: assetIdArg, width: widthArg, height: heightArg) { result in
|
||||
switch result {
|
||||
case .success(let res):
|
||||
reply(wrapResult(res))
|
||||
@ -96,7 +96,7 @@ class ThumbnailApiSetup {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setThumbnailToBufferChannel.setMessageHandler(nil)
|
||||
getThumbnailBufferChannel.setMessageHandler(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ class ThumbnailApiImpl: ThumbnailApi {
|
||||
private static let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
private static let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue).rawValue
|
||||
|
||||
func setThumbnailToBuffer(assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], any Error>) -> Void) {
|
||||
func getThumbnailBuffer(assetId: String, width: Int64, height: Int64, completion: @escaping (Result<[String: Int64], any Error>) -> Void) {
|
||||
Self.processingQueue.async {
|
||||
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: Self.fetchOptions).firstObject
|
||||
else { completion(.failure(PigeonError(code: "", message: "Could not get asset data for \(assetId)", details: nil))); return }
|
||||
|
@ -11,7 +11,7 @@ class AssetMediaRepository {
|
||||
const AssetMediaRepository();
|
||||
|
||||
Future<ui.Codec> getLocalThumbnail(String localId, ui.Size size) async {
|
||||
final info = await thumbnailApi.setThumbnailToBuffer(
|
||||
final info = await thumbnailApi.getThumbnailBuffer(
|
||||
localId,
|
||||
width: size.width.toInt(),
|
||||
height: size.height.toInt(),
|
||||
|
28
mobile/lib/platform/thumbnail_api.g.dart
generated
28
mobile/lib/platform/thumbnail_api.g.dart
generated
@ -40,34 +40,25 @@ class ThumbnailApi {
|
||||
/// Constructor for [ThumbnailApi]. The [binaryMessenger] named argument is
|
||||
/// available for dependency injection. If it is left null, the default
|
||||
/// BinaryMessenger will be used which routes to the host platform.
|
||||
ThumbnailApi(
|
||||
{BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||
pigeonVar_messageChannelSuffix =
|
||||
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||
ThumbnailApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''})
|
||||
: pigeonVar_binaryMessenger = binaryMessenger,
|
||||
pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||
final BinaryMessenger? pigeonVar_binaryMessenger;
|
||||
|
||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||
|
||||
final String pigeonVar_messageChannelSuffix;
|
||||
|
||||
Future<Map<String, int>> setThumbnailToBuffer(
|
||||
String assetId, {
|
||||
required int width,
|
||||
required int height,
|
||||
}) async {
|
||||
Future<Map<String, int>> getThumbnailBuffer(String assetId, {required int width, required int height}) async {
|
||||
final String pigeonVar_channelName =
|
||||
'dev.flutter.pigeon.immich_mobile.ThumbnailApi.setThumbnailToBuffer$pigeonVar_messageChannelSuffix';
|
||||
final BasicMessageChannel<Object?> pigeonVar_channel =
|
||||
BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.immich_mobile.ThumbnailApi.getThumbnailBuffer$pigeonVar_messageChannelSuffix';
|
||||
final BasicMessageChannel<Object?> pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
pigeonVar_channelName,
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture =
|
||||
pigeonVar_channel.send(<Object?>[assetId, width, height]);
|
||||
final List<Object?>? pigeonVar_replyList =
|
||||
await pigeonVar_sendFuture as List<Object?>?;
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[assetId, width, height]);
|
||||
final List<Object?>? pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
if (pigeonVar_replyList == null) {
|
||||
throw _createConnectionError(pigeonVar_channelName);
|
||||
} else if (pigeonVar_replyList.length > 1) {
|
||||
@ -82,8 +73,7 @@ class ThumbnailApi {
|
||||
message: 'Host platform returned null value for non-null return value.',
|
||||
);
|
||||
} else {
|
||||
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)!
|
||||
.cast<String, int>();
|
||||
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)!.cast<String, int>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ ImageProvider getThumbnailImageProvider({BaseAsset? asset, String? remoteId, Siz
|
||||
|
||||
if (_shouldUseLocalAsset(asset!)) {
|
||||
final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).localId!;
|
||||
return LocalThumbProvider(id: id, updatedAt: asset.updatedAt, size: size);
|
||||
return LocalThumbProvider(id: id, size: size);
|
||||
}
|
||||
|
||||
final String assetId;
|
||||
|
@ -10,9 +10,8 @@ class LocalThumbProvider extends ImageProvider<LocalThumbProvider> {
|
||||
|
||||
final String id;
|
||||
final Size size;
|
||||
final DateTime? updatedAt;
|
||||
|
||||
const LocalThumbProvider({required this.id, required this.size, this.updatedAt});
|
||||
const LocalThumbProvider({required this.id, required this.size});
|
||||
|
||||
@override
|
||||
Future<LocalThumbProvider> obtainKey(ImageConfiguration configuration) {
|
||||
@ -25,7 +24,6 @@ class LocalThumbProvider extends ImageProvider<LocalThumbProvider> {
|
||||
_codec(key),
|
||||
informationCollector: () => <DiagnosticsNode>[
|
||||
DiagnosticsProperty<String>('Id', key.id),
|
||||
DiagnosticsProperty<DateTime>('Updated at', key.updatedAt),
|
||||
DiagnosticsProperty<Size>('Size', key.size),
|
||||
],
|
||||
);
|
||||
@ -40,13 +38,13 @@ class LocalThumbProvider extends ImageProvider<LocalThumbProvider> {
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is LocalThumbProvider) {
|
||||
return id == other.id && size == other.size && updatedAt == other.updatedAt;
|
||||
return id == other.id && size == other.size;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode ^ updatedAt.hashCode;
|
||||
int get hashCode => id.hashCode ^ size.hashCode;
|
||||
}
|
||||
|
||||
class LocalFullImageProvider extends ImageProvider<LocalFullImageProvider> {
|
||||
|
@ -112,20 +112,9 @@ class _FixedSegmentRow extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final timelineService = ref.read(timelineServiceProvider);
|
||||
|
||||
if (timelineService.hasRange(assetIndex, assetCount)) {
|
||||
return _buildAssetRow(context, timelineService.getAssets(assetIndex, assetCount), timelineService);
|
||||
}
|
||||
|
||||
try {
|
||||
final assets = timelineService.getAssets(assetIndex, assetCount);
|
||||
return FutureBuilder<List<BaseAsset>>(
|
||||
future: null,
|
||||
initialData: assets,
|
||||
builder: (context, snapshot) {
|
||||
return _buildAssetRow(context, snapshot.data, timelineService);
|
||||
},
|
||||
);
|
||||
return _buildAssetRow(context, assets, timelineService);
|
||||
} catch (e) {
|
||||
return FutureBuilder<List<BaseAsset>>(
|
||||
future: timelineService.loadAssets(assetIndex, assetCount),
|
||||
@ -137,22 +126,21 @@ class _FixedSegmentRow extends ConsumerWidget {
|
||||
}
|
||||
|
||||
Widget _buildAssetRow(BuildContext context, List<BaseAsset>? assets, TimelineService timelineService) {
|
||||
final assetIndex = this.assetIndex;
|
||||
return FixedTimelineRow(
|
||||
dimension: tileHeight,
|
||||
spacing: spacing,
|
||||
textDirection: Directionality.of(context),
|
||||
children: [
|
||||
for (int i = 0; i < assetCount; i++)
|
||||
TimelineAssetIndexWrapper(
|
||||
assetIndex: assetIndex + i,
|
||||
segmentIndex: 0, // For simplicity, using 0 for now
|
||||
child: _AssetTileWidget(
|
||||
key: ValueKey(i.hashCode ^ (assetIndex + i).hashCode ^ timelineService.hashCode),
|
||||
asset: assets == null ? null : assets[i],
|
||||
assetIndex: assetIndex + i,
|
||||
),
|
||||
),
|
||||
],
|
||||
children: List.generate(assetCount, (i) {
|
||||
final curAssetIndex = assetIndex + i;
|
||||
return TimelineAssetIndexWrapper(
|
||||
// this key is intentionally generic to preserve the state of the widget and its subtree
|
||||
key: ValueKey(i.hashCode ^ timelineService.hashCode),
|
||||
assetIndex: curAssetIndex,
|
||||
segmentIndex: 0, // For simplicity, using 0 for now
|
||||
child: _AssetTileWidget(asset: assets?[i], assetIndex: curAssetIndex),
|
||||
);
|
||||
}, growable: false),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -161,7 +149,7 @@ class _AssetTileWidget extends ConsumerWidget {
|
||||
final BaseAsset? asset;
|
||||
final int assetIndex;
|
||||
|
||||
const _AssetTileWidget({super.key, required this.asset, required this.assetIndex});
|
||||
const _AssetTileWidget({required this.asset, required this.assetIndex});
|
||||
|
||||
Future _handleOnTap(BuildContext ctx, WidgetRef ref, int assetIndex, BaseAsset asset, int? heroOffset) async {
|
||||
final multiSelectState = ref.read(multiSelectProvider);
|
||||
|
@ -101,7 +101,6 @@ class _SliverTimeline extends ConsumerStatefulWidget {
|
||||
class _SliverTimelineState extends ConsumerState<_SliverTimeline> {
|
||||
final _scrollController = ScrollController();
|
||||
StreamSubscription? _eventSubscription;
|
||||
// late final KeepAliveLink asyncSegmentsLink;
|
||||
|
||||
// Drag selection state
|
||||
bool _dragging = false;
|
||||
|
@ -15,7 +15,7 @@ import 'package:pigeon/pigeon.dart';
|
||||
@HostApi()
|
||||
abstract class ThumbnailApi {
|
||||
@async
|
||||
Map<String, int> setThumbnailToBuffer(
|
||||
Map<String, int> getThumbnailBuffer(
|
||||
String assetId, {
|
||||
required int width,
|
||||
required int height,
|
||||
|
Loading…
x
Reference in New Issue
Block a user