Releases: tomkat-cr/genericsuite-mobile
Releases · tomkat-cr/genericsuite-mobile
Release list
0.5.0
[0.5.0] - 2026-08-30
Added
childComponents(1-N relationships) support in the Flutter CRUD Editor: child components declared in the frontend JSON config render as tappable sections in the edit form, open full-screen with the parent row asparentData, and supportchild_listingeditors witharrayandtablesubtypes (including the<array_name>/<array_name>_oldwrite payloads), matching the genericsuite-fe CRUD Editor behavior [GS-261].- Apple-clean theme tokens in
theme_config_defaults.dart(accentColor,borderRadius12px,fontFamily/textThemetypography tokens with Inter via google_fonts, near-blacktextColor, iOS system semantic colors) plus adefaultThemeParamsmerge contract so apps override only the keys they need [GS-261]. shadcn_ui(flutter-shadcn-ui port) now owns the widget-tree root viaShadApp.custom;CreateGsAppbuilds the MaterialApp theme from the GenericSuite tokens; Save/Cancel form buttons use ShadButton [GS-261].buildGsShadTheme()buildsShadThemeDatafrom GenericSuite theme tokens; newshadColorSchemeNametheme param selects the shadcn base scheme (greendefault; anyShadColorScheme.fromNamevalue), withaccentColoroverridingprimary/ringand GS surface/text/error tokens applied viacopyWith[GS-261].- "lint" and "test" commands to Makefile.
- Test coverage for the project [GS-327].
Changed
- Default accent color changed from blue to green; app bar and drawer default to white surfaces with near-black text; genericsuite_flutter version bumped to 0.5.0 [GS-261].
- README.md detailed configuration instructions moved to the GS Basecamp documentation [GS-261].
Fixed
- http_service.dart [GS-327]:
- getJwtPayload uses ascii.decode(...) instead of utf8.decode(...) to decode the JWT payload. Any claim with non-ASCII characters throws FormatException, breaking login-gate checks, loadConfig(), and current_user_service.dart.
- No .timeout(...) on any http.get/post/put/delete/patch call (unlike ip_address_service.dart, which correctly uses one), so a hung connection stalls the caller indefinitely.
- The 200/201 success path (json.decode(response.body) also has no try/catch, unlike the error branch. Debug flags (debugJwtToken, debugConfigValues) would print full JWTs/API keys if ever flipped on (currently const false, compiled out); query-string builder encodes values but not keys.
- Add type annotations to bToA(str).
- create_gs_app.dart: payload["exp"] * 1000 has no null-check; a token whose payload lacks exp (or a malformed token where getJwtPayload returns {}) throws synchronously in build(), crashing app startup instead of falling back to LoginPage. Verified by direct read [GS-327].
- crud_editor.dart [GS-327]:
- _saveItem: when isCreation && editorConfig['createReenter'] is true after a successful save, the method returns without calling setState(); _isLoading was flipped to true via setState but is reset with a bare assignment, so the loading spinner can stick indefinitely.
- No mounted checks after await before setState/_setStateAndShowMessages calls (e.g. in _buildListItem's onTap, initState's _loadConfig().then); navigating away mid-request can throw "setState() called after dispose()".
- json.decode(localApiResp['resultset']) in _loadSelectedItem has no try/catch unlike the equivalent in _loadItems, and int.parse(...['rows_affected']) is unguarded.
- _getSelectFieldsOptions — sequential await in a loop instead of Future.wait, serializing network calls unnecessarily.
- crud_editor_commons.dart [GS-327]:
- (buildChildRowToSave): indexes editorConfig['parentData'][keyPair['parentElementName']] with no null check.
- parentData can be empty/missing (e.g. _setEndpointFilter silently no-ops), so saving/deleting on a child_listing editor can throw NoSuchMethodError.
- form_field_service.dart [GS-327]:
- select and select_component cases set DropdownButtonFormField.initialValue without checking the value exists among items, unlike the select_table case which correctly guards with containsKey(...) ? value : null.
- Stale/edited data crashes the form on open. Number/integer fields call double.parse/int.parse directly in onChanged on every keystroke; clearing the field or typing ./- throws uncaught FormatException while typing.
- TextEditingController(text: ...) is instantiated inline in build() for most field types and never disposed (e.g. L126, 219, 310, 346, 380, 419, 545, 594, 659); every rebuild leaks the old controller and resets cursor/focus for all fields on screen.
- app_drawer.dart [GS-327]:
- Icon(item['callable']['icon']) throws if item['element'] isn't a key in callables; no fallback/guard.
- _loadConfig().then(...) has no error handling; exceptions become unhandled async errors instead of showing the drawer's error UI.
- error_reporter_widget.dart: ScaffoldMessenger.of(context).showSnackBar(...) is called synchronously inside build(). Verified by direct read — this is a known Flutter anti-pattern (mutating overlay state during build) and should be deferred via addPostFrameCallback, as homepage.dart does elsewhere.
- login.dart [GS-327]:
- _usernameController/_passwordController are created but the widget has no dispose() override, leaking both TextEditingControllers.
- apiResponse['resultset']['token'] is accessed with no null-check on resultset. "password" field lacks autocorrect: false / enableSuggestions: false.
- current_user_service.dart: if (data['error'] == 'Not Found') can never be true since http_service.dart always sets error to a bool; this branch is dead code [GS-327].
- logout_service.dart: storage.delete(...) calls for jwt/api_key/user_data aren't awaited before navigating away; app kill right after logout can leave stale credentials in secure storage [GS-327].
- routing_services.dart: Added item['callable']['type'] = 'async' (default) | 'sync' to allow sync/async function calls and handle code change made to logout_service.dart [GS-327].
- locator_service.dart: registerLazySingleton has no isRegistered guard; re-invoking setup (hot restart, remount, tests) throws on duplicate registration [GS-327].
- timestamp_utilities.dart: 12-hour formatting doesn't special-case midnight; hour 0 renders as "0:MM AM" instead of "12:MM AM" [GS-327].
- homepage.dart: loadHomeData(true) called directly as the FutureBuilder's future: inside build() re-triggers the API call on every rebuild before data is loaded [GS-327].
- deviceid_service.dart: implicit ordering dependency on setupStorageLocator() having run first [GS-327].
- back_button.dart: Navigator.of(context, rootNavigator: true).pop(context) passing context as the pop result looks unintentional [GS-327].
- CRUD Editor save froze the spinner and aborted the write (
_zOrderIndex != nullinoverlay.dart):_runApiCallreplaced the form withCircularProgressIndicator, disposing dropdown/popup OverlayPortals while they were still hiding. The form/list now stays mounted under a loading overlay, and AppBar "Save" goes throughDataFormBody.submit()so child rows persist the values on screen [GS-261]. suggestion_dropdown: typed text is now stored in the in-memory row (selectedItem) on change and Save, matching genericsuite-fe. Picking a suggestion still copies related API fields and also writes the form field name [GS-261].suggestion_dropdown: suggestion rows are read the same way CRUD listings decoderesultset(already-decoded list, JSON string, or nested{resultset: [...]}), so the overlay can show options when the API returns rows [GS-261].suggestion_dropdown: picking a suggestion no longer copies related-table keys (_id,name, …) onto the saved row. Only the form field andautocomplete_fieldsare written, matching genericsuite-fe [GS-261].- Password field shows SHA-256 hash instead of plain text. The initial password must be blank [GS-261].
Removed
flutter_project_templatedirectory. Use genericsuite-mobile-exampleapp instead [GS-261].
[0.4.2] - 2026-04-20
Added
- AGENTS.md, GEMINI.md, and CLAUDE.md files to provide context and instructions to AI Coding Assistants [GS-303].
- Add SAST testing [GS-315].
select_tablefield type in the Flutter CRUD editor: listing and read-only form show the related record description (backend{field}_descriptionwith client-side cached fallback); create/edit renders a dropdown populated from the related table [GS-259].
Change
- Minor fixes on README.md files
- License changed to MIT [FA-244].
- Update .gitignore to include AI agent directories [GS-303].
Fixes
- Improve error handling in create_gs_app.dart and ip_address_service.dart for better stability and fix Flutter web deployment to bootstrap [GS-252].
[0.4.1] - 2026-02-15
Added
- Implement
getStoragemethod inAppCallablesSuperto provide a customizableFlutterSecureStorageinstance [GS-261].
[0.4.0] - 2026-02-14
Added
- Add
devtools_options.yamlto the project [GS-261]. - Add
newUserJsonFileNameparameter inlogin.dart"params" map so the "onboarding_users.json" configuration can be customized [GS-261].
Changed
- Rename
locatortostorageLocatorforFlutterSecureStorageaccess [GS-261]. - Update widget key syntax on autocomplete_service.dart and form_field_service.dart [GS-261].
[0.3.1] - 2026-02-13
Fixed
- On "genericsuite_flutter":
- Fix
CreateGsAppwidget to properly initialize the app and display the main screen [GS-261].
- Fix
[0.3.0] - 2026-02-13
Added
- On "genericsuite_flutter":
- Introduce
AppCallablesSuperlocator to centralize app navigation and callbacks [GS-261]. - Introduce
routing_servicesto have routeItem() available beyond the AppDrawer widget [GS-261]. - Introduce
CreateGsAppto standardize the app boots...
- Introduce