58 lines
1.9 KiB
Dart
58 lines
1.9 KiB
Dart
import 'package:flutter/widgets.dart';
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
|
|
part 'page_dimensions_provider.g.dart';
|
|
|
|
/// Threshold: images with aspect ratio >= this are considered double-page spreads.
|
|
const double doublePageAspectRatio = 1.0;
|
|
|
|
/// Stores resolved dimensions for a single page image.
|
|
class PageDimension {
|
|
final int width;
|
|
final int height;
|
|
|
|
const PageDimension({required this.width, required this.height});
|
|
|
|
double get aspectRatio => height > 0 ? width / height : 0;
|
|
bool get isDoublePage => aspectRatio >= doublePageAspectRatio;
|
|
}
|
|
|
|
/// Provider that caches page dimensions for a publication.
|
|
/// Parameterized by publication ID so each publication has its own cache.
|
|
@riverpod
|
|
class PageDimensionsNotifier extends _$PageDimensionsNotifier {
|
|
@override
|
|
Map<int, PageDimension> build(String publicationId) {
|
|
return {};
|
|
}
|
|
|
|
/// Resolve dimensions for a page from its [imageProvider].
|
|
/// Returns immediately if already cached. Otherwise resolves asynchronously
|
|
/// and updates state when done.
|
|
void resolvePage(int pageIndex, ImageProvider imageProvider) {
|
|
if (state.containsKey(pageIndex)) return;
|
|
|
|
final stream = imageProvider.resolve(ImageConfiguration.empty);
|
|
late ImageStreamListener listener;
|
|
listener = ImageStreamListener(
|
|
(ImageInfo info, bool synchronousCall) {
|
|
final image = info.image;
|
|
final dim = PageDimension(
|
|
width: image.width,
|
|
height: image.height,
|
|
);
|
|
state = {...state, pageIndex: dim};
|
|
image.dispose();
|
|
stream.removeListener(listener);
|
|
},
|
|
onError: (exception, stackTrace) {
|
|
// Failed to resolve — leave uncached, will be treated as portrait
|
|
stream.removeListener(listener);
|
|
},
|
|
);
|
|
stream.addListener(listener);
|
|
}
|
|
|
|
/// Check if a page's dimensions have been resolved.
|
|
bool hasPage(int pageIndex) => state.containsKey(pageIndex);
|
|
}
|