Agent skill
use-fllib
Use fl_lib stores, widgets, utils, and extensions in Flutter apps. Use when requests mention fl_lib APIs or integration.
Install this agent skill to your Project
npx add-skill https://github.com/lollipopkit/cc-skills/tree/main/use-fllib
SKILL.md
Use fl_lib
When to use
- Use when the user asks about fl_lib setup, localization, or Paths init.
- Use when requests mention PrefStore, SecureStore, HiveStore, AdaptiveReorderableList, Input, SizedLoading, or fl_lib extensions/utils.
Instructions
- Setup: Follow the fl_lib Setup & Usage section below for dependency, Paths init, and localization wiring.
- Stores: Use the right store for the data type; see the fl_lib Stores section below. Prefer PrefStore for settings, SecureStore for secrets, HiveStore for structured caching.
- Widgets: Prefer fl_lib widgets for common UI patterns; see the fl_lib Widgets section below.
- Utils & extensions: Use provided helpers for IDs, crypto, UI/system, and convenience APIs; see the fl_lib Utils and fl_lib Extensions sections below.
- Library changes: If modifying fl_lib itself, run
./export_all.dartin the fl_lib root.
Requirements
fl_lib usage
- Foundation: Use fl_lib as the common library when it is already part of the project.
- Storage: Use PrefStore for key-value settings and SecureStore for sensitive data; use HiveStore for local structured caching.
fl_lib Setup & Usage
Installation
Add the dependency to your pubspec.yaml pointing to the GitHub repository:
dependencies:
fl_lib:
git:
url: https://github.com/lppcg/fl_lib.git
ref: main
Initialization
Before running runApp, you must initialize the Paths utility:
void main() async {
// Initialize fl_lib Paths
await Paths.init();
runApp(MyApp());
}
Localization
Configure localizationsDelegates in your MaterialApp to include LibLocalizations.delegate. This ensures fl_lib's internal widgets and utilities are properly localized.
MaterialApp(
localizationsDelegates: const [
LibLocalizations.delegate,
...AppLocalizations.localizationsDelegates,
],
supportedLocales: AppLocalizations.supportedLocales,
)
In your main app widget (e.g., in didChangeDependencies), call context.setLibL10n() only in root Widget to synchronize localization settings:
@override
void didChangeDependencies() {
super.didChangeDependencies();
context.setLibL10n();
}
Maintenance
If you are modifying fl_lib itself (e.g., adding new files), remember to run the ./export_all.dart script in the fl_lib root to update exports.
fl_lib Stores
fl_lib provides three types of stores for different persistence needs: PrefStore, SecureStore, and HiveStore.
All stores implement the Store interface, providing a unified API for data access.
Store Interface
The core interface for all stores. Key features include:
- Unified API:
get<T>,set<T>,remove,clear,keys. - Type Safety: Automatic conversion support via
StoreFromObjandStoreToObj. - Reactive:
getAll()stream support. - Metadata: Tracks
lastUpdateTsautomatically (optional).
PrefStore
A wrapper around SharedPreferences for storing simple key-value pairs (settings, flags, etc.).
Initialization
Must be initialized before use, typically in main.dart.
await PrefStore.shared.init(prefix: 'my_app_');
Usage
Define properties using PrefProp or PrefPropDefault for type safety.
Recommended pattern: Define all prefs in a static class or extension.
// Define properties
abstract class Prefs {
// Simple property, nullable
static const userToken = PrefProp<String>('user_token');
// Property with default value, non-nullable
static const isDarkMode = PrefPropDefault<bool>('is_dark_mode', false);
// Custom object with JSON serialization
static final userProfile = PrefProp<UserProfile>(
'user_profile',
fromObj: (json) => UserProfile.fromJson(json),
toObj: (obj) => obj.toJson(),
);
}
// Read
final isDark = Prefs.isDarkMode.get(); // Returns bool
final token = Prefs.userToken.get(); // Returns String?
// Write
await Prefs.isDarkMode.set(true);
await Prefs.userToken.set('xyz-123');
// Listen (Reactive)
return ValueListenableBuilder(
valueListenable: Prefs.isDarkMode.listenable(),
builder: (context, value, child) {
return Text('Dark Mode: $value');
},
);
Supported Types
- Native:
bool,double,int,String,List<String>. - JSON:
Map<String, dynamic>is automatically JSON encoded/decoded. - Custom: Use
fromObjandtoObjconverters.
SecureStore
Uses flutter_secure_storage to store sensitive data (passwords, tokens).
Includes built-in JSON support extensions.
Usage
Access via SecureStore static methods or SecureProp.
// Define secure property
static const apiToken = SecureProp('api_token');
// Read/Write
await apiToken.write('secret_token');
final token = await apiToken.read();
// Direct usage with JSON extensions
await SecureStore.storage.writeJson(
'user_creds',
credsObj,
(c) => c.toJson(),
);
final creds = await SecureStore.storage.readJson(
'user_creds',
(json) => Credentials.fromJson(json),
);
Built-in Props
SecureStoreProps.bakPwd: Backup password.SecureStoreProps.hivePwd: Encryption key for HiveStore (managed automatically).
HiveStore
A NoSQL-like store using hive_ce (Community Edition).
Key Feature: Automatic encryption management via SecureStore.
Initialization
final myStore = HiveStore('my_box');
await myStore.init(); // Handles encryption key generation/retrieval automatically
Usage
Use HiveProp or HivePropDefault.
final cacheProp = myStore.propertyDefault<int>('cache_count', 0);
// Read/Write
cacheProp.put(42);
final count = cacheProp.fetch(); // or .get()
// List Property
final logs = myStore.listProperty<String>('logs');
logs.put(['log1', 'log2']);
Encryption Logic
HiveStorechecksSecureStorefor an existing encryption key.- If missing, generates a new secure key.
- Saves the key to
SecureStore(underSecureStoreProps.hivePwd). - Opens the Hive box using this key.
- Auto-migrates from unencrypted to encrypted if an old unencrypted box exists.
fl_lib Widgets
fl_lib provides a rich collection of production-ready widgets, focusing on responsiveness, adaptability, and common UI patterns.
AdaptiveReorderableList
A powerful, responsive multi-column reorderable list that adapts to screen width.
Features
- Responsive Layout: Automatically calculates column count based on available width.
- Dual Layout Modes:
useMasonry: true(default): Waterfall/Masonry layout (minimizes vertical gaps).useMasonry: false(orrowMajor: true): Aligned row-major grid (preserves order).
- Animations:
animationDuration: Insert/Remove animations.dropAnimationDuration: Drag-and-drop settle animations.insertCurve/removeCurve: Customizable curves.
- Drag & Drop: Long-press to drag. Includes feedback opacity (
draggingChildOpacity). - Separators: Supports
AdaptiveReorderableList.separatedconstructor.
Usage
AdaptiveReorderableList.builder<String>(
items: myItems,
itemKey: (item) => item.id,
itemBuilder: (context, item, index, animation) {
return SizeTransition(
sizeFactor: animation,
child: MyCard(item),
);
},
onReorderComplete: (newItems) {
setState(() => myItems = newItems);
},
// Optional customizations
maxColumns: 4,
columnWidth: 300,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
)
Input
A high-level wrapper around TextField designed to reduce boilerplate.
Key Features
- Auto-Card Wrapping: By default, wraps input in a
CardXfor consistent styling. UsenoWrap: trueto disable. - Password Toggle: If
obscureText: true, automatically adds a visibility toggle icon. - Reactive IME: Respects global IME suggestions setting via
PrefProps.imeSuggestions. - Context Menu: Uses
AdaptiveTextSelectionToolbarby default.
Usage
Input(
label: 'Password',
obscureText: true,
icon: Icons.lock,
onChanged: (val) => print(val),
// Validators/Error text
errorText: _errorMsg,
// Custom actions
onSubmitted: (val) => _submit(),
)
SizedLoading
Standardized loading indicators to ensure consistency across the app.
Predefined Sizes
SizedLoading.small: 25x25 (e.g., inside buttons)SizedLoading.medium: 45x45 (e.g., card loading)SizedLoading.large: 65x65 (e.g., page loading)
Custom Usage
// Custom size with padding
SizedLoading(30, padding: 5)
// Custom builder (e.g., linear)
SizedLoading(
100,
builder: SizedLoading.linearBuilder
)
Other Notable Widgets
Layout & Containers
- AdaptiveList: Similar to reorderable list but static.
- CardX: An extended
Cardwidget with better defaults for the design system. - Split: A split-view widget for resizable panes.
- VirtualWindowFrame: For desktop apps, handles custom window frame rendering.
Interactive
- Btn: Standardized buttons (implementations in
src/view/widget/btn). - Choice: Chip-like selection widgets.
- ColorPicker: A simple color selection widget.
- SlideTrans: Slide transition wrapper.
Content
- Markdown: Wrapper for
flutter_markdownwith custom styling. - Tag: Tag/Badge component.
- Turnstile: Cloudflare Turnstile integration widget.
fl_lib Utils
fl_lib provides a robust set of utility classes for ID generation, cryptography, and UI/System integration.
ID Generation
SnowflakeLite
A lightweight, high-performance ID generator based on the Snowflake algorithm (timestamp + sequence).
- Structure: 66 bits (54 bit timestamp + 12 bit sequence).
- Format: Radix-36 string (alphanumeric).
- Use Case: Primary keys, sortable unique IDs.
// Generate
final id = SnowflakeLite.generate();
// Decode
final (timestamp, seq) = SnowflakeLite.decode(id)!;
ShortId
Generates shorter, URL-friendly IDs based on timestamp and randomness.
- Format: Custom base64-like string (a-Z, 0-9, -, +).
- Use Case: Public facing IDs, shareable links.
final shortId = ShortId.generate();
Cryptography
Cryptor
A secure encryption utility class designed for sensitive data storage.
- Algorithm: AES-GCM (Authenticated Encryption).
- Key Derivation: PBKDF2 (SHA-256, 100k iterations).
- Structure:
Header+Salt+Nonce+Ciphertext+AuthTag.
// Encrypt
final encrypted = Cryptor.encrypt('my_secret_data', 'my_password');
// Decrypt
final decrypted = Cryptor.decrypt(encrypted, 'my_password');
// Verification
final isEnc = Cryptor.isEncrypted(someString);
// Test Helper
final randPwd = Cryptor.generatePassword();
UI & System Utils
FontUtils
Helper for dynamic font loading.
// Load font from a local file path
await FontUtils.loadFrom('/path/to/font.ttf');
SystemUIs
Manages system UI overlays and window configurations for different platforms.
// Android: Transparent Navigation Bar (Edge-to-Edge)
SystemUIs.setTransparentNavigationBar(context);
// Toggle Status Bar
SystemUIs.switchStatusBar(hide: true); // Immersive Sticky
SystemUIs.switchStatusBar(hide: false); // Edge-to-Edge
// Desktop: Window Initialization
await SystemUIs.initDesktopWindow(
hideTitleBar: true,
size: Size(800, 600),
position: Offset.zero,
);
fl_lib Extensions
fl_lib provides a comprehensive set of Dart extensions to reduce boilerplate and enhance developer productivity.
BuildContext Extensions
Found in src/core/ext/ctx/common.dart and dialog.dart.
Navigation & Theme
context.pop(); // Safer Navigator.pop
context.canPop; // Check if can pop
context.theme; // Theme.of(context)
context.isDark; // Check brightness
context.mediaQuery; // MediaQuery.of(context)
context.windowSize; // MediaQuery.sizeOf(context) (Optimized)
context.libL10n; // Access library localization
Responsive Design
Using responsive_framework:
context.responsiveBreakpoints; // Raw data
context.isMobile; // Phone or Mobile breakpoint
context.isDesktop; // Desktop or Tablet breakpoint
Dialogs & Overlays
// Show a consistent rounded dialog
await context.showRoundDialog(
title: 'Hello',
child: Text('Content'),
actions: [TextButton(child: Text('OK'))], // Or use Btnx.cancelOks
);
// Show loading dialog with async task
await context.showLoadingDialog(
fn: () async => await doSomething(),
);
// Show password input dialog
final pwd = await context.showPwdDialog(title: 'Enter Password');
// Show pickers
final selected = await context.showPickDialog(
items: ['A', 'B', 'C'],
multi: true,
);
Widget Extensions
Found in src/core/ext/widget.dart. Use these for cleaner UI code.
Text('Hello')
.center() // Center(child: ...)
.paddingAll(8) // Padding(padding: EdgeInsets.all(8), child: ...)
.paddingSymmetric(horizontal: 16)
.expanded(flex: 2) // Expanded(flex: 2, child: ...)
.tap(onTap: () => print('tapped')); // InkWell wrapper with throttle
// Sliver conversion
Container().sliver(); // SliverToBoxAdapter(child: ...)
String Extensions
Found in src/core/ext/string.dart.
Manipulation & Validation
'hello'.capitalize; // "Hello"
'#FF0000'.fromColorHex; // Color(0xFFFF0000)
'https://example.com'.isUrl;
'https://example.com'.launchUrl();
Path & File
'/path/to'.joinPath('file.txt');
'/path/to/file.txt'.getFileName(); // "file.txt"
'/path/to/file.txt'.getFileName(withoutExtension: true); // "file"
DateTime Parsing
'2023-01-01'.parseDateTime();
'1672531200000'.parseTimestamp();
Image Provider
'https://img.com/a.png'.imageProvider; // Handles Network, Asset, and File automatically
Collection Extensions
Found in src/core/ext/iter.dart.
// List
[1, 2, 3].joinWith(0); // [1, 0, 2, 0, 3]
// Iterable Null Safety
list.firstOrNull;
list.firstWhereOrNull((e) => e > 5);
list.nullOrEmpty; // Checks if null or empty
DateTime Extensions
Found in src/core/ext/datetime.dart.
final now = DateTime.now();
now.hourMinute; // "14:30"
now.ymd(); // "2023-05-20"
now.hms(); // "14:30:45"
now.simple(); // Smart format: "14:30", "Yesterday 14:30", or "5-20"
DateTimeX.timestamp; // Current millis
Riverpod & State Extensions
Found in src/core/ext/ctx/common.dart.
// In ConsumerState
refSafe; // Returns ref only if mounted
contextSafe; // Returns context only if mounted
setStateSafe(() {}); // setState only if mounted
Example prompts
- "Wire fl_lib localization and Paths init in main.dart"
- "Store auth tokens using SecureStore and preferences using PrefStore"
- "Build a responsive grid with AdaptiveReorderableList"
- "Use fl_lib context extensions to show a loading dialog"
- "Generate IDs with SnowflakeLite and ShortId"
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
gh-cli
Interact with GitHub repositories, PRs, and issues using the `gh` CLI. Use when the user asks to "list PRs", "check out PR", "view issue", or "create release".
use-zfeats
Plan and execute complex features using markdown checklists. Use when the user asks to "plan a feature", "create a checklist", or "break down a task".
supabase-rest
Inspect Supabase database schemas and data. Use when the user asks to "check table", "list columns", or "query data" in Supabase. READ-ONLY.
flutter-std
Build and debug Flutter/Dart apps with Riverpod (codegen), Freezed, and GoRouter. Use when implementing Flutter features, running apps, hot reload/restart, or debugging UI.
context7-mcp
Retrieve official library documentation and API references. Use when the user asks for "docs", "API signature", "usage examples", or "how to use" a specific package.
edit-article
Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
Didn't find tool you were looking for?