89 lines
2.9 KiB
Dart
89 lines
2.9 KiB
Dart
import 'package:aves/model/entry/entry.dart';
|
|
import 'package:aves/model/viewer/view_state.dart';
|
|
import 'package:aves/widgets/viewer/view/controller.dart';
|
|
import 'package:aves_magnifier/aves_magnifier.dart';
|
|
import 'package:collection/collection.dart';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:leak_tracker/leak_tracker.dart';
|
|
|
|
class ViewStateConductor {
|
|
final List<ViewStateController> _controllers = [];
|
|
Size _viewportSize = Size.zero;
|
|
|
|
static const maxControllerCount = 3;
|
|
|
|
ViewStateConductor() {
|
|
if (kFlutterMemoryAllocationsEnabled) {
|
|
LeakTracking.dispatchObjectCreated(
|
|
library: 'aves',
|
|
className: '$ViewStateConductor',
|
|
object: this,
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> dispose() async {
|
|
if (kFlutterMemoryAllocationsEnabled) {
|
|
LeakTracking.dispatchObjectDisposed(object: this);
|
|
}
|
|
_controllers.forEach((v) => v.dispose());
|
|
_controllers.clear();
|
|
}
|
|
|
|
set viewportSize(Size size) => _viewportSize = size;
|
|
|
|
ViewStateController getOrCreateController(AvesEntry entry) {
|
|
// Identificazione robusta anche per remoti (uri può essere null):
|
|
// usa SEMPRE (id, pageId) come chiave logica del controller.
|
|
var controller = getController(entry);
|
|
if (controller != null) {
|
|
_controllers.remove(controller);
|
|
} else {
|
|
// inizializza lo stato per combaciare lo stato iniziale del magnifier
|
|
const initialScale = ScaleLevel(ref: ScaleReference.contained);
|
|
final initialValue = ViewState(
|
|
position: Offset.zero,
|
|
scale: ScaleBoundaries(
|
|
allowOriginalScaleBeyondRange: true,
|
|
minScale: initialScale,
|
|
maxScale: initialScale,
|
|
initialScale: initialScale,
|
|
viewportSize: _viewportSize,
|
|
contentSize: entry.displaySize,
|
|
).initialScale,
|
|
viewportSize: _viewportSize,
|
|
contentSize: entry.displaySize,
|
|
);
|
|
controller = ViewStateController(
|
|
entry: entry,
|
|
viewStateNotifier: ValueNotifier<ViewState>(initialValue),
|
|
);
|
|
}
|
|
_controllers.insert(0, controller);
|
|
while (_controllers.length > maxControllerCount) {
|
|
_controllers.removeLast().dispose();
|
|
}
|
|
return controller;
|
|
}
|
|
|
|
ViewStateController? getController(AvesEntry entry) {
|
|
// Confronto per (id, pageId) invece di (uri, pageId)
|
|
return _controllers.firstWhereOrNull(
|
|
(c) => c.entry.id == entry.id && c.entry.pageId == entry.pageId,
|
|
);
|
|
}
|
|
|
|
void reset(AvesEntry entry) {
|
|
// Reset per id (gli uri remoti possono essere null, quindi non affidabili)
|
|
final ids = <int>{
|
|
entry.id,
|
|
...?entry.stackedEntries?.map((e) => e.id),
|
|
};
|
|
final entryControllers = _controllers.where((v) => ids.contains(v.entry.id)).toSet();
|
|
entryControllers.forEach((controller) {
|
|
_controllers.remove(controller);
|
|
controller.dispose();
|
|
});
|
|
}
|
|
}
|