feat: unified shell, diagnostics pack, native Office, sticky board
All checks were successful
CI / Windows build (push) Successful in 14m22s
All checks were successful
CI / Windows build (push) Successful in 14m22s
Make Surface remote debugging and classroom workflows viable: always-on structured logs with one-click zip export, a single AppShell chrome, OOXML PPTX/DOCX annotation without LibreOffice, and a first-class sticky board. Also drop spike/legacy ink widgets and tighten pen feel (predictor, PenInfoHistory, page-tile layer). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
61
lib/editor/pdf/page_tile_layer.dart
Normal file
61
lib/editor/pdf/page_tile_layer.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
// Double-buffer helper on top of [PageTileCache] to kill zoom white-flash:
|
||||
// keep painting the last good tile while a higher-DPI raster is in flight.
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'page_tile_cache.dart';
|
||||
|
||||
/// Holds the "last good" page image for the currently visible page so a zoom
|
||||
/// settle never exposes an empty frame (plan W2 / R11).
|
||||
class PageTileLayer extends ChangeNotifier {
|
||||
PageTileLayer({PageTileCache? cache}) : _cache = cache ?? PageTileCache();
|
||||
|
||||
final PageTileCache _cache;
|
||||
ui.Image? _lastGood;
|
||||
TileKey? _lastKey;
|
||||
|
||||
PageTileCache get cache => _cache;
|
||||
ui.Image? get lastGood => _lastGood;
|
||||
TileKey? get lastKey => _lastKey;
|
||||
|
||||
/// Snap continuous zoom to a coarse DPI bucket (avoids a tile per frame).
|
||||
static int dpiBucketFor(double zoom, {double baseDpi = 96, double step = 0.5}) {
|
||||
final raw = zoom / step;
|
||||
final snapped = raw.round().clamp(1, 16);
|
||||
return (snapped * step * baseDpi).round();
|
||||
}
|
||||
|
||||
/// Promote [image] as the last-good tile for [key].
|
||||
void put(TileKey key, ui.Image image) {
|
||||
_cache.put(key, image);
|
||||
_lastGood = image;
|
||||
_lastKey = key;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Prefer exact bucket; else fall back to last-good so zoom never blanks.
|
||||
ui.Image? resolve(TileKey key) {
|
||||
final hit = _cache.get(key);
|
||||
if (hit != null) {
|
||||
_lastGood = hit;
|
||||
_lastKey = key;
|
||||
return hit;
|
||||
}
|
||||
return _lastGood;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_lastGood = null;
|
||||
_lastKey = null;
|
||||
_cache.dispose();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
clear();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user