w_tools 2.0.0
w_tools: ^2.0.0 copied to clipboard
聚合 8 个子包的 Flutter 工具库:涵盖 UI 组件、表单、网络、Toast、二维码、地图与核心工具,帮助开发者快速构建高质量的 Flutter 应用。
2.0.0 #
根包 2.0.0 是聚合版的首个 Major:8 个子包各自以
1.0.0独立发布,本节记录随聚合版带入根包的变更与迁移要求。
w_tools(根包) #
- Breaking: 根包由「单体工具库」改为「8 个子包的聚合包」:依赖
w_tools_core/w_tools_app/w_tools_form/w_tools_ui/w_tools_api/w_tools_toast/w_tools_map/w_tools_qr(^1.0.0),通过package:w_tools/w.dart统一导出;实现代码移至各子包,根包只保留WConfig聚合配置兼容层 - 根包不再直接依赖
get/dio/flutter_screenutil等第三方库(改由各子包承担);需要WApp启动器时get仍随w_tools_app传递引入
w_tools_app #
- Breaking:
WApp.run()在未调用init()时抛StateError(此前会静默继续, 导致 .env 未加载、业务服务未就绪等难以定位的启动时序问题)。迁移方式:改用await app.start(...),或保证run()之前已await app.init() - 新增
WApp.start():一站式启动入口(等价于await init()+run()), 避免调用方遗漏init() - 新增
WAppPlugin.dependsOn:声明插件初始化依赖,init()按依赖分层执行 (同层并行、跨层串行);依赖了未注册的插件名或存在循环依赖时抛StateError WApp.init()改为幂等:重复调用只执行一次插件onInit,避免与start()混用时重复初始化- 修正
WAppPlugin的生命周期文档注释:实际顺序为「ensureInitialized → 系统设置 → 插件 onInit → customTasks → onLazyInit → runApp」,原注释把系统设置与 onInit 写反了 - 补充
WApp生命周期与插件依赖分层的单元测试(9 个用例) - 新增
WApp.systemUiOverlayStyle:可配置状态栏 / 导航栏样式,默认沿用原硬编码样式,置null表示不干预 - Breaking:
WGet重命名为WRoute(文件get.dart→route.dart),类名与「路由操作」职责对齐,并与WRouteObserver形成命名配对 - Breaking:
WRoute.removeRouteUntil重命名为WRoute.removeRoutesAfter:语义为「移除指定路由之上的路由(保留其本身)」,且无匹配时不再清空全部,改为不执行任何操作 - Breaking:
WRoute.routes由可变列表改为只读快照;路由记录改由WRoute.addRoute/WRoute.removeRoute/WRoute.clearRoutes维护 - Breaking:
WRoute方法改名:removeRouteIfExistByName→removeRouteIfExists(修正语法)、until→popUntilRoute、bottomSheet→showBottomSheet - Breaking:
WGetXRouterObserver→WRouteObserver(去掉类名中的 "GetX";该类本身并不依赖 GetX) - Breaking:
WLanguage.getCurrentLanguageName()/getCurrentLocale()改为 getter:currentLanguageName/currentLocale - Breaking:
WRoute.showBottomSheet拆出为独立工具类WBottomSheet.show(),WRoute回归纯路由工具 - Breaking:
WAppPlugin.wrapBuilder()重命名为builderWrapper(改为 getter;与wrapApp()区分:前者提供 builder 包裹,后者包裹整个 app) WApp配置从「私有字段 + setter/getter」改为公开字段(读取/赋值用法不变);另新增只读 getterplugins/isInitializedWApp.run()参数校验异常由Exception改为StateError;移除未知路由静默回落首页的onGenerateRoute- Breaking:
WStateConfig重命名为WAppConfig(文件state_config.dart→app_config.dart),与子包w_tools_app对齐,统一W<子包>Config家族 WLanguage.listenLanguageChange返回StreamSubscription<String>,支持调用方取消订阅以避免内存泄漏WLanguage.supportedLanguages改为实时读取WAppConfig,运行期新增语言立即可用- 消除语言状态的「双真相源」:
WLanguage.changeLanguage现在会同步写回WAppConfig.currentLanguage(唯一真源),WLanguage.currentLanguage也改为直接读取它 WAppConfig.supportedLanguages改为「只读 getter(不可变快照)+ 拷贝式 setter」,禁止就地修改、避免外部 map 与内部状态别名WAppPlugin由abstract class改为abstract mixin class:插件可同时继承其他基类(class X extends Base with WAppPlugin);extends/implements用法保持兼容- 修复
WRouteObserver未处理didReplace/didRemove导致的路由记录漂移:Navigator.pushReplacement(或removeRoute)之后WRoute.routes会残留旧路由 / 缺失新路由,进而使removeRoutesAfter/removeRouteIfExists定位错误 - 修复
WRoute.popUntilRoute在目标路由不存在时会弹空整个路由栈(Get.until委托Navigator.popUntil,条件永不满足即持续 pop);现改为先行校验、不存在则不动作,与removeRoutesAfter语义一致
w_tools_core #
- 修复
WEncrypt.base64Decode对非 ASCII 内容(中文、emoji)解码乱码的问题:改用utf8.decode替换String.fromCharCodes WEncrypt.aesEncrypt未显式传入 IV 时改用IV.fromSecureRandom(16)生成安全随机 IV,不再依赖IV.fromLength的版本相关语义(该方法在encrypt5.0.1 为全零、5.0.3 起才改为安全随机;当前解析版本 5.0.3 已安全,本次为显式加固)- 新增测试:默认 IV 长度为 16 字节、非全零,且两次加密的 IV 不同
- 修复
WAsync.runWithRetry最终失败时onError被调用两次的问题(内部先上报、_executeWithLoading再上报) WAsync.runAllWithConcurrency增加concurrency >= 1校验并抛出ArgumentError,避免并发数小于 1 时批次大小为 0 导致死循环- 修复
WAsyncConfig并发执行时加载状态提前结束的问题:onLoadingStart/onLoadingEnd改为按活动操作数合并(0→1 触发开始、1→0 触发结束),共享同一配置的并发操作不再提前隐藏 loading - Breaking:
WAsync.waitWithConcurrency/WAsyncConfig.waitWithConcurrency更名为runAllWithConcurrency,并改为接收Iterable<Future<T> Function()>任务工厂,仅在并发槽位可用时调用,从而真正限制同时执行的任务数(此前传入的 Future 已全部启动,只限制了等待批次) WCancelToken.addListener在 token 已取消时会立即以取消原因回调;cancel()改为遍历回调副本,允许回调内部增删监听WAsync的onLoadingStart/onLoadingEnd/onError回调若自身抛异常会被忽略,不再破坏「不向调用方抛出」的约定WAsync.runWithRetry在重试等待期间响应取消,不再等待完整retryDelayWAsync.runWithRetry仅对task抛出的业务异常(Exception)重试;onSuccess抛出的异常不再触发重试,避免重复执行有副作用的请求WAsync.runWithRetry/WAsyncConfig.runWithRetry新增可选参数retryIf,可按异常类型过滤重试范围;不传时保持「重试所有Exception」的行为WAsync在操作开始前已取消时直接返回 null,不再触发onLoadingStart/onLoadingEnd(避免 loading 闪烁)WAsync.runWithTimeout/any文档补充:超时或被淘汰的 Future 不会被取消,仍会继续执行;any空集合返回 null- Breaking:
WAsync不再把编程错误(Error,如TypeError/StateError)当作业务异常:Error会原样向上抛出且不触发onError,runWithRetry也不再重试Error(此前会被静默吞掉并重试,掩盖真实缺陷);Exception的处理行为不变 WAsync.wait/WAsync.any在等待期间响应取消:cancel()后立即返回 null,不再等到全部 / 首个 Future 完成;已启动的 Future 仍会继续执行- Breaking:
WAsync.sequence/WAsyncConfig.sequence的tasks参数由List放宽为Iterable(List仍可直接传入);WAsync增加私有构造以禁止实例化(与 core 其它纯静态工具类一致) WAsync.runWithRetry增加retryCount >= 0/retryDelay >= 0校验,WAsync.runWithTimeout增加timeout >= 0校验,非法值以失败的 Future 抛出ArgumentErrorWAsync.any空集合直接返回 null,不再触发一次无意义的 loading 开始 / 结束回调- 测试补充:
fallbackOnError优先级、copyWith、retryCount = 0、参数校验、sequence遇错停止、runAllWithConcurrency取消后不再启动新任务、any空集合不触发 loading - 修复正数类正则接受 0 的问题:
positiveNumber/positiveInteger/positiveDecimal现在排除 0,与WValidator.isPositive/isValidPositiveInteger/isValidPositiveDecimal语义一致 WValidator.isNumeric/isPositive/isNonNegative现在拒绝NaN/Infinity,只接受有限数字- 修正
WHash.hashPassword文档:实现为加盐单轮 SHA-256(非 HMAC-SHA256),并注明不适用于高安全密码存储,高安全场景请使用 bcrypt / Argon2 - 修复邮箱正则未以
$结尾导致的「前缀匹配」问题(如a@example.com<script>此前可通过);字符集收敛为[a-zA-Z0-9._%+-],与WValidator.isValidEmail一致 - 修复日期校验:
WValidator.isValidDate/isValidDateTime现在会校验真实日期范围(2023-02-30、2023-13-01、2023-00-10不再通过;闰年2024-02-29正常通过) - Breaking:
WStorage读取方法(getString/getInt/getBool/getDouble/getStringList/getObject/containsKey/allKeys)在未初始化时抛出StateError(此前静默返回默认值,导致「未初始化」被误判为「没有数据」);allKeys()返回类型由Set<String>?改为Set<String> - Breaking:
WToken移除独立的静态内存缓存,getToken/getRefreshToken直接读取WStorage(SharedPreferences 本身已有内存缓存);因此WStorage.clear()后不再返回残留 token WToken.saveToken在未传过期时间时会清除旧的过期时间,避免新 token 沿用旧的过期状态WLogger.setLevel/WLogger.turnOff复用既有PrettyPrinter,不再重置方法栈、行宽、时间格式等输出配置;Level类型改为从w_tools_core直接导出,调用方无需再单独依赖logger包- 测试补充:
onError单次上报、并发数校验、真实日期、邮箱整串匹配、token 与存储同步、Level导出 - Breaking: 移除
WSecret聚合层(WHash/WEncrypt已覆盖其全部能力),请直接使用这两个类 - Breaking:
WFuture更名为WAsync,WFutureConfig更名为WAsyncConfig;同时移除空实现的WAsync.cleanup() - Breaking: 移除
WRegExpStringExtension(与WRegExp静态方法 1:1 重复),统一使用WRegExp的静态方法或WValidator WAsyncConfig新增any(),与WAsync.any对齐- Breaking: 移除
WCancelToken.onceCancel:其实现与addListener完全相同;cancel()触发后会清空全部回调,所有回调本就只执行一次 - Breaking:
WUx.debounce/WUx.throttle返回WCancellableAction(仍可直接调用),支持cancel()取消尚未触发的回调;smoothScrollToTop/smoothScrollToBottom在 controller 未挂载时直接返回 - Breaking:
WCountdown命名与行为调整:isRun→isRunning、countdown→totalSeconds(只读 getter,由start决定)、remaining()→formatRemaining()(remainingSeconds不变);start(second <= 0)立即完成并回调callback(0)/onComplete(0);pause()取消内部定时器、resume()重新开始计时,暂停期间不再每秒空转 WRegExp.extractBirthdayFromIdCard/formatDate增加真实日期校验;银行卡 Luhn 校验请使用WValidator.isValidBankCardWMapExtension.sortedByKeys对非Comparable键回退到字符串排序,避免运行期类型转换失败;merge注明原地修改、不可变 Map 会抛UnsupportedErrorWPlatformType新增fuchsia,TargetPlatform.fuchsia不再落到unknown- 纯静态工具类(
WHash/WEncrypt/WValidator/WPlatform/WStorage/WLogger/WRegExp/WRegExpPattern/WRegExpPreset)禁止实例化 WStorage.getObject注明仅支持jsonDecode可直接得到的类型- 测试补充:
WAsyncConfig.any、debounce/throttle取消、start(0)立即完成、非法日期提取/格式化、fuchsia枚举 - Breaking:
WRegExp收敛为「正则模式 + 匹配 / 提取 / 格式化」:移除全部validateXxx(校验统一使用WValidator),getXxxMatch更名为firstXxxMatch WValidator新增isValidChineseName/isValidPositiveInteger/isValidDecimal/isValidPositiveDecimal/isValidPostalCode/isValidMacAddress;原validateNumber/validateInteger/validatePositiveNumber分别由isNumeric/isInteger/isPositive承接,validatePassword/validateBankCard由isValidPassword/isValidBankCard(规则更严格)承接- Breaking: 其他命名统一:
WUX→WUx、WRegExpStr→WRegExpPattern、WRegExpCategory→WRegExpPreset(other→misc)、WHash.bytesMD5→bytesMd5、WEncrypt.generateIV→generateIv、WValidator.isValidIp→isValidIpv4、WRegExp.ipV4→ipv4、WAsync.one/oneWithRetry/oneWithTimeout/series→run/runWithRetry/runWithTimeout/sequence、WStorage.getKeys→allKeys、WCountdownRemainingType.s/ms→seconds/minutesSeconds - Breaking: 回调与工具命名统一:
WAsyncConfig.loadingCallback/loadingCompleteCallback/errorHandler→onLoadingStart/onLoadingEnd/fallbackOnError;WCancelToken.addCancelCallback/removeCancelCallback/dispose→addListener/removeListener/clearListeners;WValidator.isNotEmpty→isNotBlank,preventSqlInjection/preventXss→escapeSql/stripHtml;WLogger.measurePerformance→measureSync;WPlatform.executePlatformAction→runForPlatform;移除不可达的WPlatformType.unknown WCancelToken的取消原因与回调参数类型由dynamic收紧为Object?(源码兼容);WAsync各执行方法的func参数名统一为task(位置参数,调用方式不变)- Breaking: 内部文件
src/utils/async.dart更名为async_task.dart,避免与dart:async同名带来的阅读混淆;WAsync等公开 API 仍由w_tools_core.dart导出,仅影响直接 importsrc/utils/async.dart的代码
w_tools_api #
- Breaking: 移除
WCookieInterceptor(原实现仅覆盖简单同域场景:无法处理 cookie 删除、value含=会丢失、忽略Path/Domain/Expires等属性)。需要 Cookie 管理请使用社区包dio_cookie_manager - Breaking: 移除
HttpConfig,配置直接收敛到 Dio 的BaseOptions(WApiConfig.httpConfig→WApiConfig.baseOptions;DioRegistry.forBaseUrl(config:)→options:)。DioRegistry会复制传入的BaseOptions并注入baseUrl,避免实例间共享可变配置;原securityHeaders一并移除(安全响应头应由服务端下发,客户端无法施加,且 Web 端会触发 CORS 预检) - Breaking:
WTokenInterceptor三个回调改名以体现真实语义:onRequestOptions→configureRequest、onResponseOptions→configureResponse、onErrorOptions→observeError(前两者可修改请求/响应,后者仅观测) - Breaking: 移除未使用的公开 typedef
LibLogPrint(仅被私有方法使用,参数类型改为内联void Function(String)) - Breaking:
DioRegistry.forBaseUrl将interceptors与applyInterceptors合并为单个interceptors(原两参数最终被拼接为同一列表,无功能差异;挂载顺序由调用方决定) - Breaking:
DioUtil重命名为DioRegistry(文件clients/dio_util.dart→clients/dio_registry.dart),更贴合其「按baseUrl登记/检索 Dio 实例」的职责 - Breaking:
WTokenInterceptor.onAuthError重命名为tokenRefresher,与tokenGetter/tokenClearer构成齐整命名家族 - Breaking:
WApiConfig的日志回调logDHandler/logEHandler展开为logDebugHandler/logErrorHandler(去掉晦涩缩写) WTokenInterceptor.observeError不再与 401 刷新互斥:错误观测回调与 token 刷新可同时生效(此前传入该回调会静默禁用自动刷新)WTokenInterceptor并发 401 共享同一次刷新(single-flight),避免重复调用tokenRefresherWTokenInterceptor捕获tokenRefresher抛出的异常,请求以原错误结束,不再逃逸出拦截器链- 修复
WLogInterceptor打印响应体可能导致请求失败的问题:此前用response.toString()+ 手动jsonDecode,遇到 JSON 数组(如["a","b"]→[a, b])会抛FormatException使成功请求变为失败;现改为直接安全格式化response.data - 修复
WTokenInterceptor401 重试对FormData请求失效的问题:重放前自动clone(),避免 dioFormData.finalize()二次调用抛StateError;Stream请求体无法重放时放弃重试并记录日志
w_tools_ui #
- 修复
WImage的 Base64 分支错误不可达:!snapshot.hasData判断先于snapshot.hasError,导致解码失败时始终返回占位图,errorWidget与失败状态回调永不触发 - 修复
WImageConfig.fitCenter()误设为BoxFit.none(与fitNone()重复)的问题,改为BoxFit.contain - 修复
WRowButtonsController构造参数animationDuration在构造函数末尾被无条件覆盖、导致外部传值失效的问题 - 修复
WRowButtons的overScroll先放宽边界又被二次clamp收回、始终无效的问题 - 修复
WButtonConfig静态缓存返回共享可变实例、调用方链式修改会污染后续使用者的共享状态问题:getCachedConfig现返回副本;新增WButtonConfig.copy() - 修复
WTabBar硬编码NeverScrollableScrollPhysics与isScrollable配置矛盾、导致isScrollable: true仍无法横向滚动的问题 - 修复
GlobalKey.rect()返回局部坐标(paintBounds)的问题,改为返回全局坐标系下的边界矩形,与offset()语义一致 - 修正
HexColor.fromHex文档:原称支持#RRGGBBAA,实际按AARRGGBB(alpha 在前)解析,与Color(0xAARRGGBB)/toHex一致 - 全包文档注释统一为 Dart 内联引用风格(
[x]),去除 Javadoc 风格的@param/@return/@throws/@description(约 438 处),并移除 setter 上错误的「@return配置实例,用于链式调用」 - 修正失实/过时注释:
WImage条件导入说明、WImageConfigFileIO→WImageConfigIO、WKeepAliveWrapper生命周期回调语义、WImageCacheManager内存警告监听说明、WAppBar标题优先级、WListView背景色默认值与特性描述、WStep.build误称的「缓存计算结果」 - Breaking: 移除顶层便捷常量
h/w/s(它们经 barrel 全局导出,极易与使用者代码中的同名变量冲突)。请改用WSizeBox.height/WSizeBox.width/WSizeBox.size - Breaking: 4 个「依赖 ui 组件」的扩展统一改为
WUi*Extension命名:WFormStringExtension→WUiStringExtension、WFormWidgetExtension→WUiWidgetExtension、WFormStrutStyleExtension→WUiStrutStyleExtension、WFormTextStyleExtension→WUiTextStyleExtension(原WForm前缀易被误解为w_tools_form子包) - Breaking:
WNotificationListener→WNotificationListenerBuilder(该类并非 Widget,需.build()才产出NotificationListener);其便捷扩展WNotificationListenerExtension→WNotificationListenerBuilderExtension,getternotificationListener→notificationListenerBuilder - Breaking: 私有化内部 State 类型:
WListViewState→_WListViewState、WNetworkImageWithRetryState→_WNetworkImageWithRetryState(后者的currentRetryCount一并私有化),与包内其它 State 的可见性约定保持一致 - 内部结构调整(不影响 barrel 使用者):
extensions/只保留扩展方法,纯工具类WPadding、WSizeBox与WRow/WColumn便捷工厂移至utils/;extensions/image_extension.dart重命名为extensions/image.dart - Breaking:
WTextConfig/WRichTextConfig的weight(int?)重命名为fontWeightByNumber(int?),消除与fontWeight(FontWeight?)的撞名(原weight的形参名恰好也叫fontWeight,极易误用) - Breaking: 移除
WTextConfig/WRichTextConfig的family别名 setter(与fontFamily完全重复) - Breaking:
WButtonConfig.buildTextButton()重命名为buildText() - Breaking: 移除
WImageConfig.buildImage()(与build()参数、返回和实现完全等价) - Breaking:
WScaffoldConfig.build()返回类型由Widget收敛为WScaffold(与其它 Config 的build()约定一致) - Breaking:
WImageGlobalConfig.setGlobalConfig()重命名为configure()(原名称中 "Global" 重复出现两次) - Breaking: 移除
WNavController.setIndex()(与currentIndexsetter 完全重复) - Breaking:
WKeepAliveWrapper.onKeepAlive重命名为onDeactivated(实际在组件被移出 widget 树时触发,原名与触发时机不符) - Breaking: 移除
WNavBar.vsync参数(该字段从未被使用;TickerProvider由调用方创建WNavController时提供),并去掉_WNavBarState上无用的TickerProviderStateMixin - 修复
WKeepAliveWrapper运行期把keepAlive由true改为false时不生效的问题:didUpdateWidget中改为调用updateKeepAlive()通知AutomaticKeepAliveClientMixin重新计算保活状态(此前该覆写为空实现) - 修复
WNavBar在卸载时释放外部传入的WNavController的问题:组件现在只移除监听,controller 生命周期归还调用方;同时支持运行期替换 controller,并在异步onItemTap返回后判断mounted - 修复
WListView把外层widget.key传给内部滚动组件的问题:调用方传入GlobalKey时不再产生重复 key 崩溃 - 修复
WImage在build中反复创建 Future(本地资源读取 / Base64 解码 / 文件存在检查)导致的重复 IO、重复解码与状态回调:WImage改为 StatefulWidget 缓存 Future,加载状态按变化去重;文件图片分支改为内部状态组件 - 修复
WNetworkImageWithRetry在 errorWidget 多次构建时重复调度重试、以及imageUrl/ 重试参数变化后本地重试计数与状态不复位的问题 - 修复
WImageCacheManager清理逻辑:此前单一维度(数量或内存)超限时会清空整个缓存;现按最近访问时间精确清理至上限,超过单张内存上限的图片不再入缓存 WListView:带头部 / 尾部时 padding 与 itemExtent 生效;重叠偏移导致itemExtent非正时钳制为 1px;精确缓存路径补充AutomaticKeepAlive祖先,保活不再失效;支持运行期替换 controllerWRowButtons:居中滚动改用视口相对坐标(RenderAbstractViewport),列表不在屏幕原点时不再偏移;支持运行期替换 controller 与动态挂载onScrollWRichText未显式配置textScaler时跟随系统字体缩放(此前固定noScaling)WNavController.animateTo现在会应用传入的curve(此前始终使用构造时的easeInOut)WText未配置字体相关样式时不再设置强制 strut,避免继承到的大字号被默认 strut 裁切WNotificationListenerBuilder:onNotification与onNotificationPercentage现在可同时生效;不可滚动(maxScrollExtent == 0)时百分比回调为 0,不再产生NaNWGradientCircularProgressIndicator新增radius/strokeWidth断言,并钳制asin入参,避免非法参数产生NaN变换- Web 平台的文件图片分支现在会使用自定义
errorWidget(此前始终返回默认错误占位) WImageGlobalConfig正式接入:默认占位符 / 错误占位符会被WImage读取,maxCacheSize/maxCacheMemory会同步到WImageCacheManagerWImageConfig的placeholder/errorWidget/borderRadius/border/boxShadow/margin/paddingsetter 支持传null清除;border类型放宽为BoxBorder?WAppBar默认返回图标改为Icons.arrow_back(此前未配置时为不可见的空按钮),并补充返回按钮语义;移除空的initStateWButton补充button/enabled语义、鼠标光标,并支持 Enter / Space 键盘激活WRowButtons的选项补充button/selected/enabled语义WTabBarConfig新增copy()/copyWith()- 修复
num.toThousand/num.toCurrency对科学计数法(如1e+21、1.5e-7)无法正确分组的问题:先展开为普通十进制再添加分隔符;NaN/Infinity原样返回
w_tools_form #
- 修复
WFormDatePicker(原FormBuilderDatePicker)选中日期后公开的onChanged永不触发的问题:改用didChange(setValue不会回调widget.onChanged) - 修复
WFormDatePicker在enabled: false时仍可弹出选择器的问题 - 修复
WFormDatePicker初始值超出[firstDate, lastDate]区间时触发框架 assert 崩溃的问题(现先 clamp 再传入) - 修复
WFormDatePicker对无法解析的存量值抛FormatException的问题(改为安全解析,失败按无初始值处理),并统一显示与解析所用 locale(去掉硬编码en_US) - 修复
WFormMultiDropdown在非String泛型下的运行时崩溃:移除形同虚设的泛型参数,值类型统一为String - 修复
WFormMultiDropdown禁用项把「已选中」覆盖为禁用样式、且已选中的禁用项仍可点击的问题(显示上选中优先,点击上禁用优先) - 修复
WFormData.onChange仅对String记录输入状态、导致isAllEntered对数字/日期/集合等字段恒为false的问题 WFormValidator.validate()支持配置校验范围与提示策略:新增WFormValidatorConfig.continueOnError(默认false即短路校验,遇首个失败项返回;置true改为全量校验,遍历全部校验项并为所有失败项设置边框错误)、notifyAllErrors(默认false时customErrorCallback只对首个失败项触发,置true则每个失败项都触发);autofocus仅作用于第一个失败项- 新增
WFormValidator.errors:只读的{字段名: 错误文本}集合,每次校验后刷新,便于汇总展示全部错误(短路模式只含短路前的失败项) - 修复短路校验提前返回、或中途关闭
showBorderError时后续字段残留上一次边框错误的问题:现在校验开始时会清除本次参与校验字段的旧边框错误 - 修复校验通过时对已无错误字段重复
setState造成的无意义重建:WFormBorderState.setError在状态无变化时直接返回,并将原先两次setState合并为一次 - 修复
WFormBorder在isTransparentBackground: true时连错误装饰一起关掉的问题:装饰判断改为「错误态优先于透明背景」,校验失败的红框不再因背景透明而丢失 - 修复
WFormBorderWithData在enableFocusBorder由true改为false后边框卡在聚焦装饰的问题:关闭后不再向WFormBorder传递聚焦态,并在didUpdateWidget中复位 - 修复
WFormBorder的hintTextList在运行期变更后不生效的问题:非错误态下父级传入新的提示文本时,会在didUpdateWidget中同步更新展示 - 修复直接使用
WFormBorder(未包在WFormBorderWithData中)时不继承WFormBuilder.formBorderConfig的问题:配置解析下沉到WFormBorder自身,显式config优先,否则读取祖先 builder 的配置;继承配置的变更通过didChangeDependencies响应 - 新增
WFormReadOnlyScope:WFormBorderWithData通过 InheritedWidget 下发只读状态,withFormBorder(readOnly: true)现在可穿透Padding/Center/ 自定义组件等任意包装,并覆盖WFormMultiDropdown/WFormCheckbox/WFormRadioGroup/WFormButton(此前只影响WFormTextField/WFormDropdown) - 修复
withFormBorder通过重建 widget 树传递只读导致的属性丢失:Container的width/height/transform/transformAlignment/clipBehavior不再被丢弃;同时删除整个_processWidgetTree(约 145 行),Row 子树不再被重建 WFormBorder改为按内容快照判断配置是否变化:配置被原地修改(替换某个装饰或构建器)后,只要组件随后发生重建即可生效(此前仅比较实例身份,原地修改永远不会生效)- 补充配置变更语义文档:
WFormBorderConfig按引用被捕获,立即生效需替换实例(copyWith);copyWith的 null 表示「保持不变」,清空字段请使用 setter(cfg.copy()..errorDecoration = null) - Breaking: 移除未使用的
WFormBorder.tag与WFormBorderConfig.configForTagCallback:该标签配置机制从未通过withFormBorder/WFormBorderWithData暴露,全仓库无调用方 WFormBorderDecoration.border类型由Border?放宽为BoxBorder?,支持BorderDirectional(RTL 场景)WFormBorderState的装饰缓存合并为单一缓存键记录:修正「透明态装饰为 null」时缓存永不命中、每次 build 都重算的问题- 边框组件的参数校验异常类型调整:
withFormBorder的 name 为空改为ArgumentError,未找到WFormBuilder改为StateError - 补充
withFormBorder/WFormBorderWithData.name的语义文档:注册键需全局唯一;单字段场景应与内部字段名一致,复合容器场景作为分组名 - Breaking:
formBorderConfig从WFormData迁移到WFormBuilder:WFormData({formBorderConfig})→WFormBuilder(formData: ..., formBorderConfig: ...),边框配置与autovalidateMode等同属 UI 层配置,归位到 builder。迁移后_WFormDataInherited.updateShouldNotify会比较边框配置,配合WFormBorderState.didUpdateWidget重新解析,运行期修改formBorderConfig可实时生效(此前挂在WFormData上因实例身份比较,修改永远不会传播) - Breaking: 移除边框内置默认主题(不再提供默认装饰与默认文案构建器):
WFormBorderConfig的所有装饰与文案构建器默认均为 null,未配置的状态不渲染任何装饰、未配置的文案构建器不渲染提示/错误文本。此前「不传配置也能得到白底 / 灰边 / 红框」的隐式默认不再存在,请通过WFormBuilder.formBorderConfig或WFormBorder(config: ...)显式配置 WFormBorderConfig构造器不再内置默认值(字段默认 null);hintBuilder/errorBuildersetter 参数放宽为可空,对应字段去掉late,消除空配置下的LateInitializationError隐患- 新增 text_field 的 action 插件化管道:
WFormTextFieldScope+ 只读接口WFormTextFieldData(暴露value/hasText/readOnly/isPasswordVisible/valueListenable/clear()/togglePasswordVisibility()),用户自定义 action 与预置 action 走完全相同的公开接口 - 新增预置 action:
WFormTextFieldPasswordToggle(密码可见性切换)、WFormTextFieldClearButton(清空按钮,支持onCleared回调与icon覆盖;点击热区与图标渲染尺寸一致,不额外包裹尺寸约束) - 新增
WFormBorderLayout布局策略:边框与消息的组装方式可替换。内置WFormBorderLayout.column(边框在上、消息在下,可配置间距与对齐),并支持WFormBorderLayout.builder(...)函数式实现或继承基类自定义;布局输入通过WFormBorderLayoutData暴露子组件、消息、错误/只读态与圆角 WFormBorder默认布局新增 4px 消息间距并显式左对齐(此前消息紧贴边框);内部Container改为DecoratedBox,减少无谓的中间层WFormBorderConfig新增layout字段(setter /copyWith同步),运行期替换布局同样通过内容快照生效WFormTextFieldData新增obscureTextgetter,供自定义 action 判断当前是否为密码模式- 新增
WFormDefaults.clearButtonIcon:清空按钮的全局默认图标 - Breaking: 密码可见性图标不再占用
InputDecoration.suffixIcon:改由actions中的WFormTextFieldPasswordToggle提供;移除WFormTextFieldConfig.obscureTextIcon/obscureTextVisibleIconsetter,图标统一由WFormDefaults.obscureTextIcon/obscureTextVisibleIcon配置 - 移除
actions遍历中多余的一层Container(height, alignment)(Row默认垂直居中、外层容器已设高度):涉及WFormTextField/WFormButton/WFormDropdown/WFormMultiDropdown - 修复
WDividerInputFormatter在first >= rear时多插分隔符(first == rear会产生前导分隔符)的问题 - Breaking:
FormBuilderDatePicker重命名为WFormDatePicker - Breaking:
WFormMultiDropdown<T>改为非泛型WFormMultiDropdown(items为Map<String, String>、initialValue为Set<String>?、onChanged为ValueChanged<Set<String>>) - Breaking:
CustomPopupRoute重命名为WFormPopupRoute;顶层函数showPopup(...)改为WFormPopup.show(...) - Breaking:
WFormDefaults.obscureTextIconOn重命名为obscureTextVisibleIcon(含WFormTextFieldConfig与根包WConfig中的同名成员) - Breaking:
WFormCheckboxConfig.disableIcon重命名为disabledIcon(语法化,与selectedIcon/unselectedIcon命名体系对齐) - Breaking:
WFormCheckboxConfig.spacing/WFormRadioGroupConfig.spacing重命名为iconSpacing(明确为"图标与文本之间的间距",与iconYOffset构成icon*命名族) - 修复
WFormCustomValidator.custom(...)无法对空值做校验的问题:BaseValidator在checkNullOrEmpty: false时会对空值直接放行,自定义函数收不到null、因而无法实现「必填」等规则;现覆写validate,把原始值(含null)完整交给自定义函数处理 - Breaking:
WCustomValidator重命名为WFormCustomValidator,与包内「公开 API 统一WForm前缀」的约定对齐 - Breaking: 校验器三个类去掉冗余复数:
WFormValidators→WFormValidator、WFormValidatorsItem→WFormValidatorItem、WFormValidatorsConfig→WFormValidatorConfig - Breaking:
WFormValidatorItem.autoFocus重命名为autofocus,对齐 Flutter SDK 的autofocus命名 - Breaking:
WFormValidatorConfig.customErrorHandler重命名为customErrorCallback,与itemValidationCallback的后缀统一 - 内部文件重命名(不影响 barrel 使用者):
validators.dart→validator.dart(承载WFormValidator家族),自定义校验器扩展移至custom_validator.dart - 修复
Row.withFormBorder()(WFormRowBorderExtension)的重建缺陷:Stack的clipBehavior不再被硬编码为Clip.hardEdge、内部子组件的key不再丢失、readOnly: false时不再把内部WFormDropdown的enabled: false强制改回true、Container不再用constraints的最大值覆写宽高、WFormDropdown<String>的类型实参不再被擦除为dynamic - Breaking:
RowBorderedExtension重命名为WFormRowBorderExtension,与包内「公开扩展统一WForm前缀」的约定对齐 - Breaking: 删除
WFormData.isShowErrorStyle/formShowErrorStyle(只写不读的半成品机制),以及WFormMultiDropdownConfig.contentPadding/popUpLayerTitleStyle/popUpLayerTitlePadding(配置齐全但从未渲染) - Breaking: 删除
WFormMultiDropdownConfig.buildBordered()中从未被使用的hintText参数(提示文案请使用hintTextList) WFormButtonConfig/WFormCheckboxConfig/WFormRadioGroupConfig/WFormValidatorConfig补齐copy()/copyWith()WFormTextFieldConfig.buildBordered/WFormDropdownConfig.buildBordered不再改写共享 Config(改为在副本上操作),避免污染后续build()WFormTextField补充didUpdateWidget:父级更换focusNode时同步更新并正确释放自建节点(避免泄漏)- 全包文档注释统一为 Dart 内联风格(去除 Javadoc 风格的
@param/@return),并修正失实/复制粘贴注释(WFormDatePicker类文档原整段复制自DropdownButton) - 梳理
w_tools_form注释:删除与字段文档重复的构造器参数清单、复述代码的行内注释,setter 统一为「设置 xxx」表述,并修正WFormDropdown.hint/hintText等失实说明 - 新增
WFormBuilder.requireOf(BuildContext):缺少WFormBuilder祖先时抛StateError;WFormDropdown/WFormMultiDropdown/WFormTextField/WFormBorderWithData统一复用,并移除无效的visitAncestorElements兜底与dynamic类型(未找到 builder 的异常类型由Exception统一为StateError) WFormMultiDropdown的默认图标改为读取WFormDefaults:复选框使用checkboxUnselectedIcon/checkboxSelectedIcon(与WFormCheckbox一致),下拉箭头使用dropdownIcon(仍保留iconSize/ 图标颜色配置)- 修复
WFormRadioGroup点击选项时重复调用setValue与didChange的问题(只调用didChange),并让StrutStyle补上fontWeight,避免文本度量不一致 WFormRadioGroup选项改为明确的单列Column布局(原Wrap+Expanded实际只会排成单列),并为每个选项补充Semantics:checked/inMutuallyExclusiveGroup/enabled,读屏可识别单选状态WFormDropdownConfig.buildBordered/WFormMultiDropdownConfig.buildBordered新增readOnly参数:为 true 时内层控件不可交互、外层使用只读装饰(原enabled: false行为保持不变)- 修复
WFormTextField在外层只读作用域(如withFormBorder(readOnly: true))下WFormTextFieldData.readOnly仍为 false 的问题:清空按钮不再显示、clear()在只读时不执行;WFormTextFieldScope.updateShouldNotify现在同时比较只读状态,作用域切换后 action 会正确刷新 WFormTextFieldPasswordToggle仅在密码模式(obscureText: true)下显示,避免普通文本框出现无效的眼睛图标- 修复
WFormDatePicker点击「取消」时清空已有日期值的问题(取消与主动清空现在区分开) - 修复
WFormCheckbox在字段值为 null 时点击无响应的问题(现在按false处理并正常切换) WFormCheckbox/WFormRadioGroup/WFormDatePicker变更时同步调用WFormData.onChange:formEntered输入状态与边框错误清理现在覆盖所有字段类型(此前仅 text / dropdown / multi / button 接入)WFormCheckbox/WFormRadioGroup/WFormMultiDropdown新增 widget 级enabled参数(null 时读取配置),与WFormDropdown对齐;三者的Config.build()也支持传入enabled。WFormMultiDropdownConfig.buildBordered同步新增enabled覆盖参数- Breaking:
WFormDatePicker新增WFormDatePickerConfig:原构造器上的decoration/icon/iconSize/iconDisabledColor/iconEnabledColor/style迁移到配置类;字段值由 locale 相关的DateFormat.yMEd()文本改为 ISOyyyy-MM-dd,显示格式通过displayFormat(默认yMMMMd)与当前 locale 决定;新增容器能力与buildBordered WFormCheckboxConfig/WFormRadioGroupConfig新增容器能力:height/width/leading/actions/containerDecoration/containerMargin/containerPadding,并新增buildBordered;Breaking:WFormRadioGroupConfig.padding重命名为containerPaddingWFormButtonConfig新增buildBordered- 可访问性补充:
WFormCheckbox增加checked/enabled语义;WFormMultiDropdown/WFormDatePicker增加按钮与启用状态语义;日期图标颜色文档明确为“仅作用于默认图标” WFormTextField的WFormData改为在didChangeDependencies中跟随WFormBuilder更新,避免替换formData实例后仍写入旧对象;清空改为写入null(与初始值语义一致);StrutStyle补fontWeight/forceStrutHeightWFormButton的didChange回调不再先setValue再didChange,避免重复通知表单WFormMultiDropdown/WFormDatePicker的InputDecorator补isEmpty,传入带labelText的InputDecoration时浮动标签行为正确;补充值/选项匹配关系的文档(dropdown 值必须存在于items,multi 的未知值忽略显示但保留在值中)- 修复
WFormPopup在极小视口或锚点越界时可能产生负数约束、触发BoxConstraints断言的问题:上下可用空间与宽度统一钳制为不小于 0 WFormPopup的展开动画改用SizeTransition,不再二次约束子组件高度,避免非滚动内容在heightFactor较小时溢出;同时删除内部的_RenderHeightFactorBox/_HeightFactorBox(约 80 行)- 移除
WFormPopup定位对kToolbarHeight的硬编码假设:上方可用空间只扣除安全区,适配无 AppBar / 自定义 AppBar 的页面 WFormPopup.show改为返回Future<T?>,新增WFormPopup.hide(context, [result])支持关闭时回传结果;新增anchorContext(精确指定锚点)与rootNavigator参数WFormPopup键盘适配:底部可用空间合并MediaQuery.viewInsets.bottom,键盘弹起时弹层会自动选择更合适的显示方向WFormPopup增加重复打开保护:同一Navigator已有弹层时忽略后续show;锚点尚未完成布局时抛StateError,替代此前的空断言WFormPopup.show/WFormPopupRoute新增width(默认与锚点同宽)、backgroundColor、borderRadius、settings,弹层外观与路由观测能力可配置;文档补充「位置仅在打开时计算,锚点滚动后不自动跟随」- 修复
WFormMultiDropdown弹层选项在外部值回填 / 重置后选中态不更新的问题:_WFormMultiDropdownItemState.didUpdateWidget中按status重新同步本地选中态 - Breaking:
WFormMultiDropdown的字段值由逗号分隔的String改为Set<String>:initialValue/onChanged/build/buildBordered同步调整;disabledKeys由逗号字符串改为Set<String>。此前键或禁用项包含逗号时会解析错乱,现已消除该限制 WFormMultiDropdownConfig新增hintText,WFormMultiDropdown新增hintText/width参数:未选择时的占位文本可配置(默认仍为ALL),width参数优先于config.width- Breaking:
WFormMultiDropdownConfig的复选框图标配置改名,与下拉箭头icon区分:unselectedIcon/selectedIcon/disabledIcon→checkboxUnselectedIcon/checkboxSelectedIcon/checkboxDisabledIcon - Breaking:
WFormRadioGroup的构建器参数改名:itemBuilder→titleBuilder、itemChildBuilder→itemExtraBuilder,明确「标题」与「选项下方附加内容」的职责 WFormDropdownConfig新增enabled;WFormDropdown.enabled、WFormDropdownConfig.build/buildBordered的enabled参数改为可空,null 时读取配置值(与WFormMultiDropdown/WFormRadioGroup的配置形态对齐)- Breaking:
WFormConfig重命名为WFormDefaults(文件form_config.dart→form_defaults.dart),明确其职责是「可替换的全局默认值」,避免与各组件自身的WForm*Config混淆 - Breaking:
WTextInputFormatter重命名为WInputFormatters(文件input_formatter.dart→input_formatters.dart),与类中收纳多个格式化器的职责一致 - 内部目录重组(不影响 barrel 使用者):
components/inputs/按职责拆分为fields/(输入字段)、border/(边框与布局策略)、validation/(校验器);data.dart→form_data.dart;utils/popup.dart移至components/popup.dart WFormButton点击后同步调用WFormData.onChange:formEntered输入状态与边框错误清理现在覆盖按钮字段WFormButton交互重构:点击区域改用Material+InkWell(水波纹反馈、键盘焦点、鼠标光标),禁用态内容半透明;并补充button/enabled语义WFormButtonConfig的可选项 setter 参数放宽为可空(null表示清空),与其它字段配置对齐;buildBordered改为经公开 setter 清空内层装饰WFormButtonConfig新增width;WFormButton新增validator/focusNode,build/buildBordered同步透传- 修复
WFormDatePicker未继承外层WFormReadOnlyScope的问题:withFormBorder(readOnly: true)等场景下不再可点击弹出选择器,Semantics.enabled与默认图标颜色同步为禁用态 - 修复
WFormBorderConfig.copyWith()/copy()丢失自定义layout的问题:副本现在保留原布局,并支持通过copyWith(layout: ...)覆盖 - Breaking:
WInputFormatters.phone()返回类型由List改为List<TextInputFormatter>,可直接赋给inputFormatters,无需手动cast - 修复
WFormCheckbox/WFormRadioGroup/WFormDatePicker/WFormButton在表单reset()后formEntered不同步的问题:输入状态统一在didChange中维护,交互与重置走同一条路径;同时WFormData.onChange将布尔值false视为未输入(此前false != null会被误判为已输入) - 统一
WFormDropdown/WFormMultiDropdown/WFormTextField的buildBorderedname 校验:空名称改抛ArgumentError(此前抛通用Exception) - 配置 setter 可空性补齐:
WFormRadioGroupConfig.lineSpacing、WFormMultiDropdownConfig.disabledKeys/iconSize、WFormDatePickerConfig.decoration/iconSize现在均可传null清空或恢复默认 - 修复输入格式化器在删除字符时光标错误右移的问题:仅在文本长度增加(新增字符)时调整光标;
WDividerInputFormatter的多字符分隔符改用startsWith判断 WFormMultiDropdown弹层选项补充checked/enabled语义;自定义icon现在也会套用IconTheme,iconSize/iconEnabledColor/iconDisabledColor对自定义图标生效WFormCheckbox/WFormRadioGroup/WFormDatePicker/WFormMultiDropdown的可点击区域补充鼠标光标(启用为 click、禁用为 basic)WFormPopup.hide新增rootNavigator参数;未指定width时内容撑满锚点宽度,与文档描述一致;补充重复show的返回值说明WFormData.isAllEntered忽略已卸载字段残留在formEntered中的陈旧记录,避免字段移除后恒为 falseWFormValidator.errors改为返回只读快照,后续校验不再修改已持有的结果- 配置能力补齐:
WFormTextFieldConfig新增width;WFormButtonConfig.build新增enabled覆盖;WFormDropdown/WFormMultiDropdown/WFormTextField新增validator透传 WFormDropdown的选项文本StrutStyle改为按style构造字体信息,避免大字号被裁切WFormBorderDecoration.copyWith/withBorder的边框参数放宽为BoxBorder?,支持BorderDirectionalWFormBorderWithData的焦点回调补充mounted判断,避免销毁阶段触发setStateWFormCheckbox/WFormRadioGroup新增validator透传(widget 构造器与Config.build/buildBordered),至此全部字段组件均支持字段级校验器- 新增
WFormValidatorItem.field(name):校验项可引用字段自身声明的validator。WFormValidator.validate()直接执行该 validator(不写入字段errorText,避免与InputDecoration双通道),并把错误统一写入errors、边框错误与既有回调,短路 / 全量 / 跳过 / 自动聚焦语义与自定义校验项一致;字段未注册或未声明 validator 时视为通过 WFormValidatorItem.validatorBuilder改为可空(WFormValidatorItem.field模式下为 null),现有自定义校验项用法不受影响- 统一错误通道:
WFormValidator不再写入字段errorText,错误文案只由WFormBorder展示,避免InputDecoration与边框双通道重复;直接调用formKey.currentState.validate()时仍保留原生字段错误展示(仅 text / dropdown 渲染文案)
w_tools_qr #
- 依赖升级:
qr_code_scanner_plus由 2.1.1 升至 2.1.2,修复 iOS 在 resume 期间退出扫码页导致的崩溃 - 暂不升级 2.2.0+:其要求 Flutter ≥3.44 / iOS ≥13 / AGP 9,属于平台级 Breaking 变更,待下游工程基线确认后再评估(pubspec 已限制为
>=2.1.2 <2.2.0) - 修复默认配置下
onScanned永不触发的问题:此前用「边框颜色是否变化」判断是否已扫码,而borderColor与checkedBorderColor默认同为红色,首次扫描会直接暂停相机且不回调。现改用独立的已扫码状态判断 - 新增
WQrView.scanOnce(默认 true):为 false 时持续回调onScanned,且不暂停相机 - 新增
WQrViewState.restartScan():重置边框与已扫码状态并恢复相机,支持再次扫码;WQrView的 State 类型由私有改为公开,可通过GlobalKey<WQrViewState>调用 - Breaking:
WQrView.onQRViewCreated的回调参数由QRViewController改为新增的WQrController。WQrController.scannedDataStream为广播流,可与onScanned同时监听(原插件的单订阅流在调用方自行监听时会抛Bad state) - 新增
WQrView.cameraFacing/formatsAllowed/overlayMargin/onError参数,补齐插件常用的相机与条码格式配置 - 应用生命周期:进入后台自动暂停相机,回到前台恢复;单次扫描已完成时不会自动恢复
- 连续扫描模式新增
scanInterval(默认Duration.zero):按条码内容与时间窗去重,避免同一码高频回调 cameraFacing/formatsAllowed运行期变化会重建平台视图并重置扫描状态(此前只在创建时生效)- 修复在
onScanned内调用restartScan时pauseCamera晚于resumeCamera、导致相机仍处于暂停的问题:现在先暂停再回调 - 相机操作与扫描流的异步异常不再成为未处理异常:统一通过
onError上报,未提供时交给FlutterError.reportError WQrViewOverlayShape构造函数改为const,默认扫描框样式可编译期复用- Breaking:
WQrView.checkedBorderColor默认值由红色改为绿色,扫码成功后默认能看到边框反馈 - 新增
WQrView.showOverlay(默认 true):为 false 时全屏扫描,不绘制扫描框 onQRViewCreated回调自身抛出的异常现在通过onError上报;Widget 销毁后的错误回调会被丢弃- 源文件按职责拆分为
qr_view.dart/qr_controller.dart/qr_overlay_shape.dart,公开 API 不变 - 补充控制器生命周期说明:平台视图重建后旧控制器失效;
resumeCamera不重置scanOnce锁定,重新扫码需调用WQrViewState.restartScan - barrel 文件转出
Barcode/BarcodeFormat/CameraException/CameraFacing/SystemFeatures,调用方无需额外依赖qr_code_scanner_plus - 补充扫码流程、连续扫描、
restartScan时序、生命周期暂停/恢复、视图重建、scanInterval去重、扫描框显示开关、回调异常隔离、广播流多监听、相机错误上报与无权限回调的测试
w_tools_toast #
WToastConfig.duration默认值由800ms调整为2s,与文档描述一致WToastConfig.backgroundColor/onClose现在会透传到成功 / 错误 / 警告 / 加载 / 自定义提示(此前配置无效)toastBuilder通过新增的showCustom()生效;showSuccess/showError/showWarning/showLoading在未设置对应 builder 时使用默认样式(文本 / 转圈 + 文本),不再抛ArgumentError- 新增
WToastConfig.onError:BotToast 初始化失败等异常可通过该回调观测(此前被静默吞掉) - 明确加载提示为全局唯一(跨
WToastConfig实例共享),showLoading会先关闭上一个 loading - 新增
WToast.showText()与WToastConfig.showText():直接使用 BotToast 文本提示,未指定的样式参数沿用 BotToast 默认值;WToastConfig.showText()会把backgroundColor作为气泡底色 - 新增
WToast.hideAll()与WToastConfig.hideAll():一次性清理文本 / 加载 / 自定义全部提示(WToastConfig.hideAll()同时重置全局加载状态) - 新增
WToastConfig.copy()/copyWith():与ui/form的 Config 约定保持一致,参数为 null 表示沿用原值 WToast.showCustomDialog()现在会捕获toastBuilder构建阶段抛出的异常并交给onError(此前只捕获 BotToast 调用阶段的异常)- 统一注释风格:
toast.dart的 Javadoc@param/@return改为 Dart 文档注释,并补充onClose延迟 1 毫秒回调的原因说明 - 测试新增
copy/copyWith、文本提示渲染 / 对齐 / 点击关闭 / 自动关闭 / 气泡底色、showSuccess渲染与对齐等用例
构建 #
- 各 pubspec 的 SDK 下界改为「逐包真实下界」:
form/ 根包为^3.10.0+flutter >=3.38.0(由flutter_form_builder/form_builder_validators决定);ui为^3.6.0+flutter >=3.27.0;其余 6 个子包为^3.6.0+flutter >=3.27.0(受resolution: workspace的sdk >=^3.6.0要求约束,Dart 3.6 对应 Flutter 3.27) WListView用cacheExtent替代ScrollCacheExtent,w_tools_ui的最低 Flutter 版本从 3.44 降至 3.27- 根包
dev_dependencies新增bot_toast,供 toast 的 widget 测试使用 - 8 个子包完成 pub.dev 发布准备:各自新增 README / CHANGELOG / LICENSE,补充
homepage/repository/issue_tracker/topics,并移除publish_to: none;根包仍保持私有聚合
文档 #
- README 新增「依赖与子包说明」:明确
w_tools_app强依赖 GetX 且不可替换, 仅需组件/工具的项目请按需导入子包(避免被拖入 GetX) - README「快速开始」改用
start(),并补充「生命周期与插件」章节与自定义插件示例 - README「安装」区分「发布前接入(path / Git)」与「发布后从 pub.dev 安装」;8 个子包可独立发布,根包不发布
WAppPlugin文档补充builderWrapper/wrapApp的插入位置图与选择规则,并说明与WApp.builder/WApp.appWrapper字段的等价关系
1.0.8 #
- Breaking:
WRowButtonsController.initialIndex从int(默认 0)改为int?(默认 null),支持无预选状态 - Breaking:
WRowButtonsController.index返回类型从int改为int? - Breaking:
WRowButtonsController.selectedIndexNotifier类型从ValueNotifier<int>改为ValueNotifier<int?> - 新增
WRowButtonsController.deselect()方法,可将选中状态重置为 null - 补充
WRowButtonsController及WRowButtons的单元测试和 Widget 测试
1.0.7 #
- 优化多个组件和工具类的代码质量
- 更新依赖版本
- 修复已知问题
1.0.6 #
- 修改了 WConfig 类,将 token 相关的键名从 const 改为私有变量 + 公共 getter 的形式
- 为 WConfig 类添加了 set 方法,用于设置 token 相关的键名,并且在已经赋值的情况下抛出异常
- 在 WConfigSetup 类中添加了对应的 setter 方法,以便通过链式调用设置这些键名
- 整理了 widget.dart 文件中的 withContainer 方法,修复了缩进并添加了文档注释
- 移除了 widget.dart 文件中不必要的导入
- 检查了 WListViewConfig 类的 copyWith 方法,确保所有属性都被正确复制
1.0.4 #
- 重构 WToastConfig 类,移除默认实现,使其更加灵活
- 将构建器中的 String 类型参数改为 Object? 类型,支持传递任意类型对象
- 移除 WToastConfig 中的静态方法,改为实例方法
- 优化加载状态管理,每个实例管理自己的加载状态
- 更新相关文档和示例
1.0.3 #
- 优化 WToastConfig 类,使其更加配置驱动
- 移除 WToastConfig 中的默认实现,让用户完全自定义 UI
- 更新相关文档和示例
1.0.2 #
- 优化了多个组件的配置类,添加了 copy 和 copyWith 方法
- 增强了 WFormMultiDropdown 组件,添加了更多自定义选项
- 优化了 WRichText 组件的性能
- 修复了多个组件中的小问题
- 更新了文档
1.0.1 #
- 修复了部分组件的文档注释
- 优化了部分组件的性能
- 更新了 README.md
1.0.0 #
- 初始版本发布
- 包含完整的组件库、工具类和扩展功能
- 支持配置驱动的开发模式
- 提供丰富的 UI 组件和实用工具