Workbook (multi-sheet)
final wb = BCellWorkbook(sheets: [
BCellSheet(name: 'People', columns: cols, rows: rows, tabColor: Color(0xFF2196F3)),
BCellSheet(name: 'Budget', columns: cols2, rows: rows2),
]);
Column(children: [
Expanded(child: BCellWorkbookView(workbook: wb)),
BCellSheetTabBar(workbook: wb),
]);
wb.setProtected(i, true); wb.setHidden(i, true);
final json = jsonEncode(wb.toJson());
final restored = BCellWorkbook.fromJson(jsonDecode(json));
// Encrypt (AES-256-GCM, password-derived key):
final blob = wb.toEncryptedBytes('pw'); wb.loadEncryptedBytes(blob, 'pw');
// Version history:
wb.saveVersion(); wb.versions; wb.restoreVersion(0);
// Shared 3-way merge:
final conflicts = wb.mergeChanges(base: baseJson, theirs: theirJson);
Encryption notes: the blob is AES-256-GCM with a PBKDF2-derived key and a
random per-file salt + nonce, so the same workbook never encrypts to the
same bytes. A wrong password or a tampered byte throws
BCellDecryptException (authenticated — never silent garbage); a
non-encrypted file throws FormatException. decryptWorkbook(bytes, pw)
returns a new workbook; loadEncryptedBytes loads in place.
Merge notes: mergeChanges is cell-level three-way against the shared
base snapshot — a cell only the other copy changed lands here; a cell
both copies changed differently keeps the local value and comes back as a
BCellMergeConflict(sheet, rowIdx, field, base/mine/theirs) so you can
offer "take theirs". Rows/sheets the other copy added come along; rows
align by index, deletions don't propagate.
See every feature live with its calling code:
cd widgetbook && flutter run -d chrome.