Published 2026-09-22
Darwin 4.0 based on serverpod.


Copied some classes from serverpod_auth_email_flutter and serverpod_auth_shared_flutter to pod_darwin_flutter/lib/src/serverpod/auth because the original packages used an old reference to file_picker that was incompatible to the version the entire codebase from work_dart uses.
The imcompatibility only showed up in desktop compilations of some flutter apps that use the file_picker package.
The copies were from version 3.4.11 so if you upgrade serverpod, these should probably be deleted.
Could have created tp_serverpod_auth_email_flutter and tp_serverpod_auth_shared_flutter in the third_party folder and patched them, but this was easier at the moment of writing this.
Serverpod client that exposes all server-side api calls.
Keeps track of and manages the signed-in state of the user.
The instance getter is removed, because the session manager as singleton creates a lot of problems when using multiple client instances.
All incoming notifications, messages and events (through the websocket connection) are relayed onto the local eventbus to be consumed by your application widgets (see ServerpodWidget).
Can also be used for inter-widget communication.
Access client, sessionManager and eventBus:
if (context.read<SessionManager>().isSignedIn) {
final String result = await context.read<Client>().example.hello('ruud');
context.read<EventBus>().fire(result);
}
The first widget after runApp in your main function that wraps a MaterialApp (MyApp).
Handles session status and receives/transmits incoming notifications, messages and events from the websocket connection onto the EventBus.
Your route pages must be wrapped in a ServerpodRouterWidget, or must contain a ServerpodRouterWidget as a child widget.
This widget routes you back to the login page if the server connection is terminated.
Must be a child below the MaterialApp node (MyApp), otherwise routing will fail.
For debugging you can define credentials in the file pod_darwin/pod_darwin.env with the following (or your own) contents:
{
"DEBUG_USER_NAME": "ruud",
"DEBUG_USER_EMAIL": "ruudvring@huighaverlag.nl",
"DEBUG_USER_PASSWORD": "bonzoklonzo"
}
https://ente.io/blog/tech/inherited-widgets/ https://docs.flutter.dev/development/data-and-backend/state-mgmt/options https://www.youtube.com/watch?v=LFcGPS6cGrY https://stackoverflow.com/questions/78278824/flutter-web-only-loads-app-update-after-second-reload https://www.perplexity.ai/search/using-google-fonts-is-a-privac-gQQ95laXROeOGrpMfkjwPw
// There is no built-in browser cache invalidation in Flutter web apps. // The following code is used to do the proper cache invalidation after the // application update. // // Related issues: // https://github.com/flutter/flutter/issues/149031 // https://github.com/flutter/flutter/issues/104509 // https://github.com/flutter/flutter/issues/63500 // // Resources: // https://docs.flutter.dev/platform-integration/web/initialization // https://stackoverflow.com/questions/78278824/flutter-web-only-loads-app-update-after-second-reload // https://medium.com/codebrew/how-to-prevent-cache-in-flutter-web-dead8c8d3730 // https://medium.com/@navidshokoufeh.dev/how-to-clear-cache-in-flutter-web-f86935b12248
desktop_drop dependency.HHMetadataEditorMultiComboBox: eliminated O(n×m) rebuild overhead by caching active DataObject list. The _transformValue method (called from build via label callback) was rebuilding the entire items list from JSON settings on every parent rebuild. Now builds cache once in initState and invalidates only when metadata definition settings change via didUpdateWidget. Reduces computation during rapid rebuilds by ~99% for typical configurations (100 items, 10 selections: 1,000 ops/frame → 10 ops/frame).HHMetadataEditorBrandList: cached expensive _columnWidths getter computation. The getter performed complex map/filter/transform operations (mapIndexed → where → map) on every build access. Introduced _cachedColumnWidths field with lazy computation via _computeColumnWidths() method. Cache is invalidated via _invalidateColumnWidthsCache() when column actives change (add/edit/remove column operations, setValue). Eliminates redundant computation when column configuration is stable across rebuilds.HHMetadataEditorFileType: removed redundant nested setState calls from the dropdown onChanged callback; state updates and widget.entity.setField(...) are now executed in a single setState closure.HHMetadataEditorFileType.getValue: fixed the dead null-branch logic so 'null' values are normalized cleanly before nullForEmpty() is applied.HHMetadataEditorFileType: replaced unchecked dynamic JSON casts in the getters (disabled, entity, hidden, metadataDefinition, viewtype) with safe, type-checked fallbacks.HHMetadataViewerFileType._ON_DownloadBlocksArchive: record.parentId! and record.id! were evaluated before the .toArchive() Future chain was created. A null value would throw synchronously, leaving busy.increment() without a matching busy.decrement() (the whenComplete was attached only to the inner chain). Fixed by null-checking parentId / id before touching the busy counter and moving busy.decrement() into a try/finally block that always runs.HHMetadataViewerFileType._renderGeneric: context.read<HHBusyModel>() was used inside build(), which does not subscribe the widget to HHBusyModel changes. The downloadable flag was therefore stale — a second long-press could fire while a download was still in progress. Changed to HHConsumer<HHBusyModel> so the widget rebuilds whenever the busy state changes.HHMetadataViewerLoginTime._timeFormatter: missing DateTime type guard mirrored a pre-existing guard in HHMetadataViewerPersistTime. If a DateTime was stored in the login-time field, the subsequent value as num cast would throw TypeError. Added the same if (value is DateTime) value = value.millisecondsSinceEpoch guard.HHMetadataViewerFileDrop, HHMetadataViewerFileType, HHMetadataViewerLoginTime, HHMetadataViewerPersistTime, HHMetadataViewerSystemDummy: all five property getters (disabled, entity, hidden, metadataDefinition, viewtype) used unchecked as casts on Map<String, dynamic> values. An unexpected type in the parameter map (e.g. server protocol change) would throw TypeError at render time with no recovery path. Replaced with is-checked reads that fall back to safe defaults.HHMetadataViewerFileDrop._renderGeneric, HHMetadataViewerSystemDummy._renderGeneric: tooltip label and placeholder colour now resolve hidden and metadataDefinition.name once as locals before building the widget, avoiding repeated getter-chain evaluation inside the HHTooltip label closure.HHMetadataViewerFileType._renderLabel: value and the translated tooltip string are now resolved once before building HHLabel, so the label and tooltip closures do not re-evaluate the full getter chain on every call.HHMetadataViewerPdflibBlocksFieldMapping: late final _model field was being reassigned in didUpdateWidget, causing a LateInitializationError crash every time the entity's field value changed. Changed to late with a _modelCreated guard that disposes the old provider before creating a new one.HHMetadataViewerDnaLink / HHMetadataViewerDnaLinks: _getFolderStack had no cycle detection; a circular parentId reference in server data would cause an infinite loop. Added a Set<int> visited guard that returns null on first repeated id.HHMetadataViewerStockItemViewer: missing didUpdateWidget override meant that switching to a different entity reused stale _title / _value data. Added override that re-fires the darwinStockItemHistoryPersister.find call when entity.id or metadataDefinition.name changes.HHMetadataViewerProductionTypeGroup: force-unwrap entity.id! inside _computeValue threw a Null check operator used on a null value error when the viewer was instantiated with a DarwinDummyRecord (null id). Added an early-return null guard.HHMetadataViewerDnaLink / HHMetadataViewerDnaLinks: empty setState(() {}) in _update() triggered an unnecessary widget rebuild when the value was not a resolvable record id. Removed the spurious rebuild.HHMetadataViewerPdflibBlocksTemplateLink: entity.setField(…) and _simpleCaching mutation were performed inside the setState callback (Flutter anti-pattern). Moved both side-effects outside setState; the callback now only updates _value.HHMetadataViewerBrandList: _columnWidths getter independently re-evaluated the items getter (JSON parse + repair), causing two JSON parses per render. Refactored to _columnWidthsFor(BrandListItems) method; _renderAsForm now parses items exactly once and passes the result to both column-width computation and row generation.HHMetadataViewerShopItemOrderButton / HHMetadataViewerShopUserItemOrderButton: default _onBeforeOrder callback used a Completer<void>()..complete() to create an already-resolved future. Replaced with Future<void>.value(). Removed now-unused dart:async import from both files.doc/METADATA_WIDGETS_OPTIMIZATION_SUMMARY.md - detailed performance optimization summary.doc/METADATA_WIDGETS_TESTING_GUIDE.md - manual testing guide for metadata widgets.context.read<T>() calls (85% reduction).monkey_patch for file_picker web upload handling.video_player dependency.HHListFilterSimple added removeAccents.google_fonts dependency due to GDPR concerns.spider.yaml with flutter_gen for asset constants.FilesStore does not react anymore for files in folders that were not previously requested by a user action. This prevents handling of files that were never requested and thus causing update storms.flutter_markdown (discontinued).flutter_markdown_plus.FileIo now uses file_saver package.HHPasswordInput reveal icon._client was not initialized.DataTable to DataGrid from pkg_data_grid (faster).get_it dependency.serverpod: 2.0.0.http dependency to dio.OK Ready anymore.tp_state_machine dependency.state_machine dependency.flutter_typeahead.ExpansionPanelList in imposition panels.imageId is now dynamic everywhere.async constructs.