feat: unified shell, diagnostics pack, native Office, sticky board
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:
2026-08-05 17:55:27 +08:00
parent 3cabc7e074
commit d346cc2670
49 changed files with 2883 additions and 2515 deletions

View File

@@ -1,5 +1,6 @@
import 'dart:io';
import '../diagnostics/badnote_log.dart';
import '../editor/persistence/sidecar_repository.dart';
import '../models/note.dart';
import '../models/pen_tool.dart';
@@ -16,6 +17,10 @@ class OcrService {
/// working. [note.id] is the synthetic note path, which is exactly the
/// `sourceFilePath` the editor opened its [SidecarRepository] with.
Future<void> processNote(Note note) async {
BadNoteLog.instance.info(LogSubsystem.diag, 'ocr_start', fields: {
'note': note.id,
'strokes': note.strokes.length,
});
final parts = <String>[];
for (final stroke in note.strokes) {
@@ -41,12 +46,18 @@ class OcrService {
final recognized = await OcrEngine.recognizeImage(png);
if (recognized != null && recognized.isNotEmpty) {
parts.add(recognized);
BadNoteLog.instance.info(LogSubsystem.diag, 'ocr_handwriting', fields: {
'chars': recognized.length,
});
}
}
}
final combined = parts.join(' ').trim();
if (combined.isEmpty) return;
if (combined.isEmpty) {
BadNoteLog.instance.debug(LogSubsystem.diag, 'ocr_empty');
return;
}
// Persist into the note's sidecar so the vault-scan search index finds it.
// Prefer the editor's already-open repo (same in-memory sidecar — no race);