fluiver 4.0.0
fluiver: ^4.0.0 copied to clipboard
Flutter SDK gap-fillers — scope function, DateTime predicates, listeners, Grid, debounce/throttle. Ships an LLM skill for agent-friendly coding.
Changelog #
4.0.0 #
Strips every API whose job the framework or core libraries already do — fluiver keeps only genuine gaps.
-
Removed —
AppLifecycleObserver. The framework'sAppLifecycleListeneris the same wrapper with more granular callbacks:AppLifecycleListener(onStateChange: (s) => ...). -
Removed —
DateTime.toTimeOfDay(). Identical to the framework'sTimeOfDay.fromDateTime(dt). -
Removed —
Map.any/Map.every/Map.firstWhereOrNull. Sugar overmap.entries:entries.any((e) => ...),entries.every((e) => ...), andentries.firstWhereOrNull(...)viapackage:collection. -
Renamed —
LocaleObserver→LocaleListener,BrightnessObserver→BrightnessListener, matching the framework'sAppLifecycleListenernaming. -
Breaking —
FlexGridis nowGrid(RenderFlexGrid→RenderGrid), configured by the sameSliverGridDelegatefamily asGridViewfor DX and agent predictability:Grid(gridDelegate: ...)takes any delegate (custom ones included),Grid.count(...)/Grid.extent(...)mirrorGridView.count/GridView.extent. MigrateFlexGrid(crossAxisCount: 3, ...)→Grid.count(crossAxisCount: 3, ...); the delegate'smainAxisExtentoverrideschildAspectRatio(theGridViewcontract, replacing the old additive behavior). -
Added —
Gridcovers whatGridView(shrinkWrap: true)cannot: real intrinsics (no hard-coded estimates; unbounded extents shrink-wrap to child intrinsics), exactcomputeDryLayoutandcomputeDryBaseline, first-child baseline,debugFillProperties, RTL cross-axis reversal matchingGridView, a descriptiveFlutterErrorunder an unbounded cross axis, and degenerate constraints clamping cells to zero instead of negative. -
Breaking —
platformDispatch'smacOSparameter is nowmacos, matching its all-lowercase siblings (android,ios,linux, …) — the name agents and autocomplete-blind humans guess first. -
Breaking —
NetworkProbe.hasConnection→checkConnection(verb — it's an async probe, not a cheap property). Gainshost/port(default unchanged:1.0.0.1:53) for self-hosted probe endpoints, its first tests, and the defaulttimeoutrises 2s → 3s so a lossy mobile network surviving two SYN retransmits still reportstrue. -
Changed —
RenderGridandTickerBuilderinternals follow framework conventions: getter/field/setter property clusters, delegate relayout viaSliverGridDelegate.shouldRelayout, named tick handler created ininitState(side effects moved out of thesetStateclosure). -
Changed —
unawaited_futures/discarded_futureslints disabled package-wide: fire-and-forget futures in sync lifecycle methods are dropped bare, framework-style;NetworkProbenow awaitssocket.close()before reporting reachability. -
Fixed —
TextEditingController.setTextAndCaretnow clampscaretto0..text.lengthinstead of producing an out-of-range selection. -
Changed —
LRUCachethrowsArgumentErrorformaxEntries <= 0in all build modes (was a debug-only assert). -
Changed —
FastHash.fnv1aiterates code units by index, avoiding an iterator allocation per call. -
Changed —
FastHash.fnv1anow runs on Wasm builds (native 64-bit ints there); only JS web throwsUnsupportedError. -
Changed —
Debounce/Throttle*dispose()drops pending task references (no closure retention), and calling a disposed instance throwsFlutterErrorin debug mode. -
Changed — a
GridgivenEdgeInsetsDirectionalpadding with no ambientDirectionalitynow asserts in debug mode (framework behavior) instead of silently resolving as LTR. -
Fixed — an empty
Grid's cross-axis intrinsics no longer include phantomcrossAxisSpacing; they report padding only. -
Fixed —
windowed(0)(andstep: 0) now throwsRangeError: size: must be > 0instead of a misleading-1message. -
Changed — dropped the unused
metadependency.
Kept deliberately, verified against Flutter 3.41 / Dart 3.11: truncateTime() (unlike DateUtils.dateOnly it preserves UTC-ness), windowed (package:collection only has non-overlapping slices), timeoutOrNull (package:async has no equivalent), Map.where/whereKeyType/whereValueType (return a Map, narrow the static type), separated (Flex spacing only covers blank gaps, not separator widgets), byNameOrNull (core's asNameMap()[name] allocates a map per lookup and spells a simple scan sideways).
3.3.0 #
- Added —
ScrollTrackingExpandablewidget: animated expand/collapse that keeps the growing bottom edge visible in the nearestScrollablewhile expanding, withscrollOffsetfor extra breathing room below.
3.2.3 #
- Fixed — SDK compatibility fix in
NetworkProbeby replacing type-directed enum shorthand.IPv4with fully qualified enum reference. - Fixed — Rescheduling timing bug in
ThrottleLatest. - Fixed — Memory leak in
ThrottleLastby clearing callback references post-execution. - Fixed — Native resource leak in
TickerBuilderby disposing of ticker binding resources properly. - Fixed — Exception safety in
DisposableBagto prevent a single failing disposer from blocking subsequent disposers, raisingDisposableBagExceptioncontaining all errors at the end. - Fixed — Timezone-safety alignment in
DateTimeCheck.age()andTimeOfDayOnDate.onDate(). - Added — Intrinsic height and width measurement calculations on
FlexGrid's customRenderBox(RenderFlexGrid). - Changed — Optimized lookup efficiency in
Map.entryOfand generic compile-safety inEnumIndexComparable.
3.2.2 #
- Fixed —
FastHash.fnv1a's 64-bit offset-basis literal broke compilation on web targets (includingflutter widget-preview). Now split into web-representable halves (bit-exact on the VM); throwsUnsupportedErroron web instead of corrupting hashes.
3.2.1 #
- Changed — Dropped
@useResultfromObject.let; the result can now be safely ignored (e.g. side-effecting transforms) without an analyzer warning. - Changed — LLM artifact moved from a path-scoped rule to a description-triggered skill (
tool/claude/flutter-fluiver/SKILL.md); loaded by relevance instead of on everylib//test/file.
3.2.0 #
- Added —
LRUCache.putIfAbsent(K key, V Function() ifAbsent). Lazy compute on miss; hit promotes the entry to most-recently-used. - Added —
DisposableBag.addAll(Iterable<FutureOr<void> Function()>). Bulk-register disposers; same semantics as repeatedadd. - Changed — Rule file no-overlap callout narrowed to
package:collectionandpackage:async.
3.1.0 #
- Added —
Color.darken([amount]),Color.lighten([amount]),Color.contrastText. HSL-based;contrastTextpicks black or white via luminance. - Added —
ScrollController.atTop,.atBottom,.animateToTop({duration, curve}),.animateToBottom({duration, curve}).hasClients-safe. - Added —
Future<T>.timeoutOrNull(Duration)→Future<T?>. Null on timeout, errors still propagate. - Added —
Iterable<E>.windowed(int size, {int step = 1}). Stepped sliding window; drops partial trailing window. - Added —
TextEditingController.setTextAndCaret(String, {int? caret}). Avoids thecontroller.text = ...caret-reset papercut. - Changed — LLM artifact moved from
rules/fluiver.mdtorules/flutter-fluiver.md. Namespaced with theflutter-prefix. - Removed —
PaddedFlex/PaddedRow/PaddedColumnwidgets. UsePadding(padding: ..., child: Column(children: [...]))/Row— LLMs reach for this natively. - Removed —
IterableEnum.byNameOrElse(name, orElse: ...). UseEnum.values.byNameOrNull(name) ?? .fallback— Dart shorthand handles the fallback.
3.0.0 #
Breaking — utility-library pivot. The "single-dot shortcut" framing collided with LLM-assisted development: agents do not know the extensions exist, default to stdlib forms, and teaching the API costs input tokens on every turn. The sugar layer had to go. What remains is substance — things the SDK is genuinely missing. Ships a compact rule file at rules/fluiver.md for consumer projects to load into their LLM agent.
- Removed —
extensions/build_context.dart(context.primaryColor,context.titleLargeTextStyle,context.screenWidth,context.isThemeDark, …). UseTheme.of(context).colorScheme.primary,Theme.of(context).textTheme.titleLarge,MediaQuery.sizeOf(context).width,Theme.of(context).brightness == Brightness.dark. - Removed —
extensions/text_style.dart(withColor,withWeight400,withSize,withUnderline, …). Usestyle.copyWith(color: ..., fontWeight: FontWeight.w400, fontSize: ...). - Removed —
extensions/edge_insets.dart(addLeft,onlyTop,setRight,withStatusBarMargin, …). UseEdgeInsets.only(...),.copyWith(...),MediaQuery.viewPaddingOf(context).top. - Removed —
extensions/border_radius.dart(addAll,onlyTopLeft,setBottomRight, …). UseBorderRadius.only(...),.copyWith(...). - Removed —
extensions/bool.dart(toInt). Useb ? 1 : 0. - Removed —
extensions/date_time.dartarithmetic (addYears,addMonths,addWeeks,addDays,addHours,addMinutes,addSeconds). Usedt.add(Duration(days: N))/DateTime(y + n, m, d). - Removed —
extensions/key.dart(validateAndSaveonGlobalKey<FormFieldState<T>>). Useif (k.currentState!.validate()) k.currentState!.save();. - Removed —
extensions/flutter_enums.dart(Axis.reverse,TextDirection.reverse,Brightness.reverse,Orientation.reverse). Use inline ternary. - Removed —
extensions/string.dart(capitalize,capitalizeAll,initials,safeSubstring). Inline. - Renamed —
fastHash(s)→FastHash.fnv1a(s). Namespace, algorithm-named, future-proof for other hashes. - Renamed —
hasDeviceConnection()→NetworkProbe.hasConnection({timeout}). Namespaced;timeoutis now configurable. - Renamed —
platformSpecific<T>(...)→platformDispatch<T>(...). Clearer name; matchescompute/dispatchmental model. - Renamed —
disabledInputCounterBuilder→TextFieldBuilders.disabledCounter. Namespaced; room for moreTextFieldhelpers. - Renamed —
TimeOfDay.todayAt()→TimeOfDay.onDate(DateTime date). Takes the calendar day explicitly — testable, no hiddenDateTime.now(). - Fixed —
Map.entryOf(k)distinguishes "key absent" from "key present with null value"; previously returnednullfor both.{'a': null}.entryOf('a')now returnsMapEntry('a', null). - Fixed —
DateTime.isTomorrow/isYesterdayusedDuration(days: 1)(24h), which crosses DST fall-back days incorrectly. Now uses calendar-day arithmetic (DateTime(y, m, d ± 1)). - Fixed —
NetworkProbe.hasConnectionshort-circuits totrueon web (previousdart:io.Socketcall would have thrown at runtime), narrows its catch toSocketException/TimeoutException(no more swallowing programming bugs), and exposes the timeout as a parameter. - Fixed —
PaddedFlex.textDirection/textBaselinedefault tonull—Flexresolves from ambientDirectionality. Previously hardcodedTextDirection.ltrbroke RTL layouts. - Fixed —
TickerBuilder.initStatecallssuper.initState()before starting the ticker. - Fixed —
ThrottleLast._lastinitialized to a no-op closure instead oflate VoidCallback. - Fixed —
Let<T>extension is now bounded toT extends Object, so.letno longer pollutes autocomplete on nullable receivers. Use?.let(...)for null-aware chaining. - Added —
LRUCache<K, V>(maxEntries: N). Bounded least-recently-used cache; O(1) reads / writes / eviction; reads / writes promote. - Added —
DisposableBag. Collectdispose/cancel/closeclosures and flush in registration order with a singledispose(). Idempotent; adding after dispose runs the closure immediately. - Added —
rules/fluiver.md. Compact rule file for LLM agents; documents the surviving API surface and steers away from removed identifiers.
2.4.3 #
- Removed
StreamWhereType(duplicatesdart:async). - Renamed
inToday→todayAt, fixedBuildContextsColorSchemetypo. - Doc fixes.
2.4.2 #
- Removed
is*enum getters; use shorthand comparisons (x == .ltr). - Improved
hasDeviceConnection(socket + timeout). - Added
disabledInputCounterBuilder.
2.4.1 #
- Broadened SDK constraint to
>=3.10.0 <4.0.0.
2.4.0 #
- Added
platformSpecificutility. - Modernized observers to use
PlatformDispatcher. - Adopted shorthand enum values throughout.
- Fixed
ThrottleLasttask execution.
2.3.0 #
- Added
indexparameter toIterable.separated. - Added
letscope extension onObject. - Renamed
deviceHasConnection→hasDeviceConnection. - Added
fastHash.
2.2.0 #
- Removed
Iterableextensions that duplicatepackage:collection. - Renamed
Iterable.separate→Iterable.separated.
2.1.0 #
- Added
PaddedFlex,PaddedRow,PaddedColumn.
2.0.0 #
- Breaking:
FlexGridrewritten asMultiChildRenderObjectWidget. - Added
FlexGrid.padding, all M3ColorSchemecontext getters. - Removed
BezierSquircleBorder. Min SDK Dart 3.0.0.
1.2.0 #
- Added
ColorSchemecontext getters,BezierSquircleBorder,StreamWhereType.
1.1.1 #
- Added
TickerBuilder.onTick.
1.1.0 #
- Added
TickerBuilder.
1.0.1 #
- Updated
MediaQuerylookups; removedelementAtOrNull,singleOrNull(now in core).
1.0.0 #
- Initial release.