flutter_spine 0.2.4
flutter_spine: ^0.2.4 copied to clipboard
Shared infrastructure for Flutter apps — MVVM base classes, effect bus, scaffold suite, network layer, and error model.
0.2.4 #
Changed #
- Breaking:
DioHttpConfig.authRefreshandDioHttpConfig.retryfields removed.AuthRefreshInterceptorandRetryInterceptorare no longer auto-registered byDioHttpClient.fromConfig(). Business code should explicitly add these interceptors viaDioHttpConfig.interceptors(forAuthTokenInterceptor/HttpLoggingInterceptor/EnvelopeUnwrapInterceptor) or by assembling aDioinstance withDioHttpClient.fromDio()(forAuthRefreshInterceptor/RetryInterceptorwhich require a Dio reference). - Built-in interceptor classes (
AuthTokenInterceptor,HttpLoggingInterceptor,EnvelopeUnwrapInterceptor,AuthRefreshInterceptor,RetryInterceptor,AuthRefreshConfig,RetryConfig) are preserved — business may still use them, just must register them explicitly. DioHttpConfig.interceptorsdoc updated to clarify it accepts any DioInterceptor(built-in or custom).
Added #
HttpClient.requestStream()— streaming request method for SSE / large file downloads / long-poll push. ReturnsStreamedHttpResponsewithstatusCode/headers/stream(Stream<List<int>>). Error normalization matchesrequest()— non-2xx / network errors / timeouts throwAppException.StreamedHttpResponse— immutable stream response wrapper withstatusCode,headers,stream,isSuccess, andheader()lookup.HttpResponseType.stream— new enum value; maps to Dio'sResponseType.stream.- 3 new tests in
dio_http_client_test.dartcovering stream response, 401 error, and cancelToken cancellation.
Docs #
- README §1.5 RetryInterceptor / §1.6 AuthRefreshInterceptor / §1.7 内置 Interceptor 速查 updated to show
DioHttpClient.fromDio()assembly pattern. - README §1.8 流式响应 / SSE added.
AiHelper/skills/flutter-core-http-setup/SKILL.mdupdated: removedauthRefresh/retryfields, added RetryInterceptor/AuthRefreshInterceptor assembly sections, added SSE/stream section.
Tests #
http_auth_refresh_interceptor_test.dartandhttp_retry_interceptor_test.dartrefactored to useDioHttpClient.fromDio()instead ofDioHttpConfig.authRefresh/.retry.
0.2.3 #
Fixed #
_defaultFactoryURL construction — switched to pure string operations to avoid Dart SDKUri.replace()port:0bug. Added scheme auto-correction (http→ws,https→wss) and port:0removal. Added step-by-step debug logging.isConnectAuthErrormissing fromWsModuleConfig— field was added toWsClientConfigbut not propagated throughWsModuleConfigconstructor,toConfig(), andtoConfigWith(), causing configuration loss when usingWsModuleRegistry.WsModuleConfigmissing reconnect fields —protocols,connectTimeout,baseReconnectDelay,maxReconnectDelay,maxReconnectAttempts,reconnectJitterRatiowere not inWsModuleConfig, preventingsharedWsConfigdefaults from reaching the finalWsClientConfig.- Connect auth refresh infinite loop —
_reconnectAttemptwas reset to 0 on every connect-level auth refresh, preventingmaxReconnectAttemptsfrom ever being reached. - EffectListener double-dispatch — root-level
EffectListenernow defaults tohandleDefaults: false.AppTabChildScaffoldandAppBottomSheetScaffoldsethandleDefaultEffects: false. OnlyAppPageScaffoldprocesses built-in effects, eliminating duplicate navigation/toast/dialog triggers. - DemosPage double-navigation (example) — parent route container now sets
handleDefaultEffects: falseto prevent processing effects emitted by child routes' ViewModels.
Example #
ws_modules.darttoken extracted to_currentTokenvariable —onAuthExpiredwrites back refreshed token,queryParamsProviderreads it on each connect/reconnect.demo_market_ws_page.dartrefactored to use globalmarketGatewayProviderinstead of self-built fake channel and hardcoded URL.
0.2.2 #
Added #
BaseWsGateway— abstract WebSocket gateway for business modules. Delegates connection lifecycle toWsClient; subclasses (Market / Asset / Swap) define type-safe subscription APIs and topic encoding.WsClientConfig.headersProvider— dynamic headers callback. Called on every connect / reconnect to fetch the latest token, eliminating the need to rebuild config after auth refresh.WsClientConfig.queryParamsProvider— dynamic query string callback. Same pattern asheadersProvider, for backends that pass auth tokens via URL query params (?token=xxx) instead of HTTP headers. Manual string concatenation avoids Dart SDKUri.replace()port:0bug.WsClientConfig.onAuthExpired+isAuthCloseCode— token expiry auto-refresh. When the server closes with an auth close code (e.g. 4001),DefaultWsClientcallsonAuthExpiredwith single-flight guarantee, then reconnects with the new token. Unsuccessful refresh transitions toWsFailed.WsClientConfig.isConnectAuthError— connection-level auth error detection. Handles HTTP 401/403 rejection during WebSocket upgrade handshake (complementsisAuthCloseCodewhich handles post-connect close frames). Defined externally via predicate so backend-specific error formats are not hardcoded.- Close code handling in
DefaultWsClient— normal close codes (1000, 1001) now transition toWsDisconnectedwithout triggering auto-reconnect. All other close codes continue to trigger standard reconnect. - Unified
IOWebSocketChannelin_defaultFactory— always usesIOWebSocketChannel.connect(), no longer implicitly switches betweenWebSocketChannel.connect()andIOWebSocketChannelbased on parameter presence. Behavior is now consistent regardless of whether headers/queryParams are configured. WsTopicRouter.simple()— factory constructor for standard pub/sub protocols where channel name equals topic name. Auto-generatestopicExtractor,subscribeFrameBuilder, andunsubscribeFrameBuilderfrom a singlechannelKeyparameter.WsModuleRegistry+WsModuleConfig— registration pattern for WebSocket modules. Each business module defines aWsModuleConfiginstance;WsModuleRegistry.build()maps URIs to configs, replacing hand-written if-else chains inwsConfigBuilderProvideroverrides.- CLI
ws-gatewaycommand —flutter_spine:new ws-gateway <name>generates topic / topic_router / ws_gateway / providers four-file scaffold.
Changed #
- Breaking:
WsClientConfig.headersreplaced byheadersProvider(Map<String, dynamic> Function()?). Existing code must change fromheaders: {'key': 'val'}toheadersProvider: () => {'key': 'val'}. WsClientConfigconstructor now acceptsheadersProvider,queryParamsProvider,onAuthExpired, andisAuthCloseCode(all optional)._defaultFactoryno longer branches on parameter presence — always constructsIOWebSocketChannelfor consistent behavior.
Tests #
- 9 new test cases for close code handling, auth refresh, and connect-level auth detection (40 total in
test/network/ws/).
Example #
demo_market_ws/— fullMarketWsGatewayimplementation: topic encoding/decode (MarketTopic), protocol adapter (marketTopicRouter), RiverpodStreamProvider.autoDispose.familyfor automatic subscription lifecycle, and interactive lifecycle demo page.demo_asset_ws/&demo_swap_ws/— showcase multi-module Gateway pattern. All three modules share the same auth/heartbeat/reconnect config via a_sharedWsConfigfactory inmain.dart, each overriding only its owntopicRouter.main.dartnow demonstratesFlutterSpineConfig.extraOverrideswithWsModuleRegistry.build()replacing the if-else chain.
0.1.2 #
Added #
PagedListView.scrollViewBuilder— embed the list in aCustomScrollViewwith extra slivers.PagedListView.enableLoadMore— disable load-more footer, keep only pull-to-refresh.AppListPageScaffold.scrollViewBuilder/enableLoadMore— forwarded toPagedListView.PagedScrollViewBuildertypedef.- Example demo pages:
/demos/paged-list,/demos/app-list.
Fixed #
DioExceptionType.transformTimeoutnot found with dio 5.9.x — replaced withdefault/_fallback for forward compatibility.
0.1.1 #
Added #
- Scaffold CLI (
flutter_spine:new). generator_templates.dart— riverpod_generator support.FeatureCommand—flutter_spine:new featureone-key whole feature generation.BootstrapCommand—flutter_spine:new bootstrapapp skeleton.FlutterCoreDiagnosticsBanner.MaterialDefaultEffectHandlerctor overrides.mixin-based API:ViewModelMixin,AsyncViewModelMixin, family variants.
Changed #
- CLI templates now use
{{Name}}/{{name}}/{{name_snake}}/{{name-kebab}}/{{Title}}naming conventions. - Renamed
FlutterCoretoFlutterSpine,FlutterCoreConfigtoFlutterSpineConfig.
0.1.0 #
- Initial release.
error/: sealedAppExceptionhierarchy +safeApiCallnormalization.network/:ChannelClientMethodChannel wrapper.pagination/:PagedState+PagedNotifierMixin(family + noArg).filter/:FilterNotifierbase class.presentation/:AsyncBuilder+AsyncValueextensions.logging/:AppLoggerinterface +PrettyAppLoggerimplementation.observers/:ErrorObserver(toast callback injection) +LogObserver.storage/:KeyValueStorageabstraction +HiveStorage+keyValueStorageProvider.theme/:AppThemeExtension+ThemeModeNotifier.utils/:num_ext,string_ext,date_ext,iterable_ext,context_ext.