Use fl_lib stores, widgets, utils, and extensions in Flutter apps. Use when requests mention fl_lib APIs or integration.
./export_all.dart in the fl_lib root.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
Before running runApp, you must initialize the Paths utility:
void main() async {
// Initialize fl_lib Paths
await Paths.init();
runApp(MyApp());
}
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();
}
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 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.
The core interface for all stores. Key features include:
get<T>, set<T>, remove, clear, keys.StoreFromObj and StoreToObj.getAll() stream support.lastUpdateTs automatically (optional).A wrapper around SharedPreferences for storing simple key-value pairs (settings, flags, etc.).
Must be initialized before use, typically in main.dart.
await PrefStore.shared.init(prefix: 'my_app_');
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');
},
);
bool, double, int, String, List<String>.Map<String, dynamic> is automatically JSON encoded/decoded.fromObj and toObj converters.Uses flutter_secure_storage to store sensitive data (passwords, tokens).
Includes built-in JSON support extensions.
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),
);
SecureStoreProps.bakPwd: Backup password.SecureStoreProps.hivePwd: Encryption key for HiveStore (managed automatically).A NoSQL-like store using hive_ce (Community Edition).
Key Feature: Automatic encryption management via SecureStore.
final myStore = HiveStore('my_box');
await myStore.init(); // Handles encryption key generation/retrieval automatically
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']);
HiveStore checks SecureStore for an existing encryption key.SecureStore (under SecureStoreProps.hivePwd).fl_lib provides a rich collection of production-ready widgets, focusing on responsiveness, adaptability, and common UI patterns.
A powerful, responsive multi-column reorderable list that adapts to screen width.
useMasonry: true (default): Waterfall/Masonry layout (minimizes vertical gaps).useMasonry: false (or rowMajor: true): Aligned row-major grid (preserves order).animationDuration: Insert/Remove animations.dropAnimationDuration: Drag-and-drop settle animations.insertCurve / removeCurve: Customizable curves.draggingChildOpacity).AdaptiveReorderableList.separated constructor.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,
)
A high-level wrapper around TextField designed to reduce boilerplate.
CardX for consistent styling. Use noWrap: true to disable.obscureText: true, automatically adds a visibility toggle icon.PrefProps.imeSuggestions.AdaptiveTextSelectionToolbar by default.Input(
label: 'Password',
obscureText: true,
icon: Icons.lock,
onChanged: (val) => print(val),
// Validators/Error text
errorText: _errorMsg,
// Custom actions
onSubmitted: (val) => _submit(),
)
Standardized loading indicators to ensure consistency across the app.
SizedLoading.small: 25x25 (e.g., inside buttons)SizedLoading.medium: 45x45 (e.g., card loading)SizedLoading.large: 65x65 (e.g., page loading)// Custom size with padding
SizedLoading(30, padding: 5)
// Custom builder (e.g., linear)
SizedLoading(
100,
builder: SizedLoading.linearBuilder
)
Card widget with better defaults for the design system.src/view/widget/btn).flutter_markdown with custom styling.fl_lib provides a robust set of utility classes for ID generation, cryptography, and UI/System integration.
A lightweight, high-performance ID generator based on the Snowflake algorithm (timestamp + sequence).
// Generate
final id = SnowflakeLite.generate();
// Decode
final (timestamp, seq) = SnowflakeLite.decode(id)!;
Generates shorter, URL-friendly IDs based on timestamp and randomness.
final shortId = ShortId.generate();
A secure encryption utility class designed for sensitive data storage.
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();
Helper for dynamic font loading.
// Load font from a local file path
await FontUtils.loadFrom('/path/to/font.ttf');
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 provides a comprehensive set of Dart extensions to reduce boilerplate and enhance developer productivity.
Found in src/core/ext/ctx/common.dart and dialog.dart.
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
Using responsive_framework:
context.responsiveBreakpoints; // Raw data
context.isMobile; // Phone or Mobile breakpoint
context.isDesktop; // Desktop or Tablet breakpoint
// 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,
);
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: ...)
Found in src/core/ext/string.dart.
'hello'.capitalize; // "Hello"
'#FF0000'.fromColorHex; // Color(0xFFFF0000)
'https://example.com'.isUrl;
'https://example.com'.launchUrl();
'/path/to'.joinPath('file.txt');
'/path/to/file.txt'.getFileName(); // "file.txt"
'/path/to/file.txt'.getFileName(withoutExtension: true); // "file"
'2023-01-01'.parseDateTime();
'1672531200000'.parseTimestamp();
'https://img.com/a.png'.imageProvider; // Handles Network, Asset, and File automatically
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
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
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