fluxy 1.1.0
fluxy: ^1.1.0 copied to clipboard
Core engine of the Fluxy framework including UI, state management, HTTP, and motion.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:fluxy/fluxy.dart';
import 'package:fluxy_connectivity/fluxy_connectivity.dart';
import 'package:fluxy_haptics/fluxy_haptics.dart';
import 'package:fluxy_device/fluxy_device.dart';
import 'package:fluxy_logger/fluxy_logger.dart';
import 'package:fluxy_websocket/fluxy_websocket.dart';
import 'package:fluxy_sync/fluxy_sync.dart';
import 'package:fluxy_presence/fluxy_presence.dart';
import 'package:fluxy_geo/fluxy_geo.dart';
import 'core/registry/fluxy_registry.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 1. Setup the registry (The "Right Way")
Fluxy.registerRegistry(() => registerFluxyPlugins());
// 2. Scan and register all modules
Fluxy.autoRegister();
// 3. Manual registration for any custom/local plugins
Fluxy.register(FluxyHapticsPlugin());
Fluxy.register(FluxyDevicePlugin());
Fluxy.register(FluxyLoggerPlugin());
// 4. POWER ON the engine (Initializes all plugins in strict order)
await Fluxy.init();
FluxyVault.init(salt: 'fluxy_example_secure_salt_2026'); // Secondary Layer
runApp(Fluxy.debug(child: FluxyExampleApp()));
}
class FluxyExampleApp extends StatelessWidget {
const FluxyExampleApp({super.key});
@override
Widget build(BuildContext context) {
return FluxyApp(
title: 'Fluxy Framework Example',
theme: ThemeData(
primarySwatch: Colors.blue,
useMaterial3: true,
),
home: const FluxyErrorBoundary(child: HomePage()),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// Reactive state with persistence
final counter = flux(0, key: 'counter', persist: true, label: 'counter_value');
final userName = flux('', key: 'user_name', persist: true, label: 'user_name');
final isConnected = flux(true, key: 'connection_status', label: 'is_connected');
final connectionType = flux(
FluxyConnectionType.none,
key: 'connection_type',
label: 'connection_type',
fromJson: (j) => FluxyConnectionType.values.byName(j as String),
);
final isAuthenticated = flux(false, key: 'auth_status', label: 'is_authenticated');
Map<String, dynamic>? _savedSnapshot;
// NEW: Resource Management Demo
final activeUsers = flux(0);
final resourceStatus = flux('Sleeping');
late final mockGps = FluxyResource<String>(
name: 'Industrial GPS Engine',
onStart: () async {
resourceStatus.value = 'WAKING UP...';
await Future.delayed(const Duration(seconds: 1));
resourceStatus.value = 'ACTIVE (10Hz Polling)';
return 'GPS_INSTANCE_ID_001';
},
onStop: (instance) async {
resourceStatus.value = 'ENTERING DEEP SLEEP...';
await Future.delayed(const Duration(milliseconds: 500));
resourceStatus.value = 'Sleeping';
},
idleTimeout: const Duration(seconds: 3), // Faster for demo
);
@override
void initState() {
super.initState();
_initializeConnectivity();
}
void _initializeConnectivity() {
// The "Right Way": Use the Unified Platform API (Fx.platform)
final connectivity = Fx.platform.connectivity;
if (connectivity != null) {
// Set initial values
isConnected.value = connectivity.isOnline.value;
connectionType.value = connectivity.connectionType.value;
// Create reactive subscription to connectivity changes
FluxEffect(() {
isConnected.value = connectivity.isOnline.value;
connectionType.value = connectivity.connectionType.value;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Fx.text('Fluxy Framework Demo')
.style(FxStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)),
backgroundColor: Colors.blue.shade600,
actions: [
Fx(() => Fx.icon(
isConnected.value ? Icons.wifi : Icons.wifi_off,
color: isConnected.value ? Colors.green : Colors.red,
))
],
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Fx.col(
gap: 24,
children: [
// User Authentication Section
_buildAuthSection(),
// Counter Demo Section
_buildCounterSection(),
// Connectivity Demo Section
_buildConnectivitySection(),
// Storage Demo Section
_buildStorageSection(),
// Platform Features Section
_buildPlatformSection(),
// Biometric Section
_buildBiometricSection(),
// Industrial Control Center (Kill Switches)
_buildControlCenterSection(),
// NEW: Haptics Demo Section
_buildHapticsSection(),
// NEW: Device Info Section
_buildDeviceSection(),
// NEW: Logger Audit Section
_buildLoggerSection(),
// NEW: Real-Time & Advanced Sections
_buildWebSocketSection(),
_buildSyncSection(),
_buildPresenceSection(),
Fx.feature('geo', child: _buildGeoSection()),
_buildBridgeSection(),
_buildResourceSection(),
_buildObservabilitySection(),
// NEW: Programmatic Snapshots Demo
_buildSnapshotSection(),
Fx.feature('security', child: _buildSecuritySection()),
_buildStabilitySection(),
],
),
),
);
}
Widget _buildSnapshotSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.teal.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.teal.shade200),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Programmatic Snapshots').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.teal.shade800,
),
),
Fx.text('Capture the state of all labeled signals and restore it instantly.').muted(),
Fx.row(
gap: 12,
children: [
Expanded(
child: Fx.primaryButton(
'Capture',
onTap: () {
_savedSnapshot = FluxRegistry.captureSnapshot();
Fx.toast.success('Snapshot Saved Locally');
},
),
),
Expanded(
child: Fx.outlineButton(
'Restore',
onTap: () {
if (_savedSnapshot != null) {
FluxRegistry.restoreSnapshot(_savedSnapshot!);
Fx.toast.info('State Restored');
} else {
Fx.toast.error('No Snapshot Found');
}
},
),
),
],
),
],
),
);
}
Widget _buildWebSocketSection() {
final ws = Fluxy.use<FluxyWebSocketPlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.blue.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.blue.shade200),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('WebSocket (Real-Time)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx(
() => Fx.text('Status: ${ws.status.value.name.toUpperCase()}')
.style(
FxStyle(
color: ws.status.value == FluxySocketStatus.connected
? Colors.green
: Colors.red,
fontWeight: FontWeight.bold,
),
),
),
Fx.secondaryButton(
'Connect',
onTap: () => ws.connect('wss://echo.websocket.org'),
),
],
),
Fx.row(
gap: 12,
children: [
Expanded(
child: Fx.secondaryButton(
'Send Hello',
onTap: () => ws.send({'type': 'hello', 'data': 'Fluxy Echo'}),
),
),
Fx.dangerButton('Disconnect', onTap: ws.disconnect),
],
),
],
),
);
}
Widget _buildSyncSection() {
final sync = Fluxy.use<FluxySyncPlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.orange.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.orange.shade200),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Sync Engine (Offline-First)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.orange.shade800,
),
),
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx(() => Fx.text('Pending Tasks: ${sync.pendingCount.value}')),
Fx(
() => Fx.text(
sync.isSyncing.value ? '🔄 Syncing...' : '✅ Idle',
).style(FxStyle(color: Colors.orange.shade700)),
),
],
),
Fx.primaryButton(
'Add Mock Task',
onTap: () {
sync.queue(
'POST',
'/api/profile',
body: {
'name': 'Fluxy User',
'ts': DateTime.now().toIso8601String(),
},
);
},
),
],
),
);
}
Widget _buildPresenceSection() {
final presence = Fluxy.use<FluxyPresencePlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.purple.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.purple.shade200),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Presence & Collaboration').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.purple.shade800,
),
),
Fx(() {
final userList = presence.users.value;
return Fx.text('Online Users: ${userList.length}');
}),
Fx.row(
gap: 12,
children: [
Fx.secondaryButton(
'Set Online',
onTap: () => presence.setOnline(true),
),
Fx.secondaryButton(
'Set Typing',
onTap: () => presence.setTyping(true),
),
],
),
Fx(() {
final typing = presence.typingUsers.value;
if (typing.isEmpty) return const SizedBox.shrink();
return Fx.text('Someone is typing...').style(
FxStyle(
fontSize: 12,
color: Colors.purple,
fontStyle: FontStyle.italic,
),
);
}),
],
),
);
}
Widget _buildGeoSection() {
final geo = Fluxy.use<FluxyGeoPlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.teal.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.teal.shade200),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Geo & Geofencing').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.teal.shade800,
),
),
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx(
() => Fx.text(
geo.isTracking.value ? '🛰️ Tracking On' : '🛰️ Offline',
),
),
Fx.secondaryButton(
geo.isTracking.value ? 'Stop' : 'Start',
onTap: () async {
if (geo.isTracking.value) {
geo.stopTracking();
} else {
try {
await geo.startTracking();
geo.addGeofence('hq', 0.0, 0.0, 100.0); // Mock Geofence
} catch (e) {
Fx.toast.error(
e.toString().replaceAll('Exception: ', ''),
);
}
}
},
),
],
),
Fx(
() => Fx.col(
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Lat: ${geo.latitude.value.toStringAsFixed(4)}'),
Fx.text('Lng: ${geo.longitude.value.toStringAsFixed(4)}'),
Fx.text(
'Active Geofences: ${geo.activeGeofences.value.join(", ")}',
).style(
FxStyle(
color: Colors.teal.shade700,
fontWeight: FontWeight.bold,
),
),
],
),
),
],
),
);
}
Widget _buildBridgeSection() {
final timerSignal = flux(0);
return Fx.box(
style: FxStyle(
backgroundColor: Colors.blue.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Stream Bridge (Async Integration)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
Fx.text(
'Fluxy bridges native Dart Streams into reactive Signals flawlessly.',
),
Fx.row(
gap: 12,
children: [
Fx.icon(Icons.timer_outlined, color: Colors.blue),
Fx(
() =>
Fx.text('Live Timer Stream: ${timerSignal.value}s').bold(),
),
],
),
Fx.primaryButton(
'START BRIDGE',
onTap: () {
// Bridge a standard Dart Stream to a Fluxy Signal
Stream.periodic(const Duration(seconds: 1), (i) => i + 1)
.take(10) // Only for 10 seconds to avoid memory leaks in demo
.listen((val) => timerSignal.value = val);
Fx.toast.info('Stream Bridged for 10s');
},
),
],
),
);
}
Widget _buildResourceSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.indigo.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.indigo.shade100),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Managed Resource (Battery Save)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.indigo.shade800,
),
),
Fx.text('Automatic "Graceful Sleep" when features are unused.'),
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx(
() => Fx.text('Hardware Status: ${resourceStatus.value}').style(
FxStyle(
fontWeight: FontWeight.bold,
color: resourceStatus.value.contains('ACTIVE')
? Colors.green
: Colors.grey,
),
),
),
Fx(
() => Fx.box(
style: FxStyle(
backgroundColor: Colors.indigo,
borderRadius: BorderRadius.circular(20),
padding: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 4,
),
),
child: Fx.text(
activeUsers.value.toString(),
).color(Colors.white).bold(),
),
),
],
),
Fx.row(
gap: 10,
children: [
Fx.secondaryButton(
'SIMULATE USER IN',
onTap: () async {
activeUsers.value++;
await mockGps.acquire();
},
).expanded(),
Fx.outlineButton(
'SIMULATE USER OUT',
onTap: () {
if (activeUsers.value > 0) {
activeUsers.value--;
mockGps.release();
}
},
).expanded(),
],
),
Fx.text(
'Try removing all users and wait 3 seconds to see "Deep Sleep".',
).font.xs().muted(),
],
),
);
}
Widget _buildObservabilitySection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.black,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx.text('Fluxy X-Ray (Observability)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.greenAccent,
),
),
Fx.badge(
child: Fx.text('LIVE').font.xs().bold(),
color: Colors.red,
),
],
),
Fx.text('Real-time Signal Churn & Rebuild Audit').color(Colors.grey),
Fx.box(
style: FxStyle(
backgroundColor: Colors.white10,
borderRadius: BorderRadius.circular(8),
padding: const EdgeInsets.all(12),
width: double.infinity,
),
child: Fx(() {
final signals = FluxyObservability.signalStats;
final rebuilds = FluxyObservability.rebuildStats;
if (signals.isEmpty && rebuilds.isEmpty) {
return Fx.text(
'Interact with the app to see metrics...',
).color(Colors.grey);
}
return Fx.col(
gap: 8,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text(
'Signal Activity',
).bold().color(Colors.greenAccent).font.xs(),
...signals.entries
.take(3)
.map(
(e) => Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx.text(e.key).color(Colors.white70).font.xs(),
Fx.text(
'${e.value} updates',
).color(Colors.white).bold().font.xs(),
],
),
),
const Divider(color: Colors.white24),
Fx.text(
'Widget Rebuilds',
).bold().color(Colors.orangeAccent).font.xs(),
...rebuilds.entries
.take(3)
.map(
(e) => Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx.text(e.key).color(Colors.white70).font.xs(),
Fx.text(
'${e.value} frames',
).color(Colors.white).bold().font.xs(),
],
),
),
],
);
}),
),
Fx.row(
gap: 10,
children: [
Fx.outlineButton(
'CLEAR STATS',
onTap: FluxyObservability.clear,
).expanded(),
Fx.primaryButton(
'SIMULATE CHURN',
onTap: () {
// Create a burst of state changes to test the engine
for (int i = 0; i < 50; i++) {
counter.value++;
}
},
).expanded(),
],
),
],
),
);
}
Widget _buildSecuritySection() {
final vaultInput = flux('');
final decryptedData = flux('No data decrypted');
return Fx.box(
style: FxStyle(
backgroundColor: Colors.blueGrey.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Industrial Security Vault').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blueGrey.shade800,
),
),
Fx.text('Hardware-backed storage with secondary scrambling.'),
Fx.input(signal: vaultInput, placeholder: 'Enter secret data...'),
Fx.row(
gap: 10,
children: [
Fx.primaryButton(
'SECURE RECORD',
onTap: () async {
if (vaultInput.value.isNotEmpty) {
await FluxyVault.write('secret_token', vaultInput.value);
Fx.toast.success('Layered Encryption Applied');
vaultInput.value = '';
}
},
).expanded(),
Fx.outlineButton(
'RETRIEVE',
onTap: () async {
final data = await FluxyVault.read('secret_token');
decryptedData.value = data ?? 'Not Found';
},
).expanded(),
],
),
Fx(
() => Fx.text(
'Decrypted: ${decryptedData.value}',
).italic().color(Colors.blueGrey.shade700),
),
],
),
);
}
Widget _buildStabilitySection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.orange.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Stability Engine (Crash-Free)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.orange.shade800,
),
),
Fx.text('The framework intercepts crashes to maintain uptime.'),
Fx.dangerButton(
'TRIGGER LAYOUT CRASH',
onTap: () {
// This would normally cause a red screen
FluxyError.report(
'SIMULATED_INDUSTRIAL_FAILURE',
StackTrace.current,
);
},
).w(double.infinity),
],
),
);
}
Widget _buildHapticsSection() {
final haptics = Fluxy.use<FluxyHapticsPlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Haptic Feedback (Sensory)').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
Fx.row(
gap: 12,
children: [
Fx.secondaryButton('Light', onTap: haptics.light),
Fx.secondaryButton('Medium', onTap: haptics.medium),
Fx.secondaryButton('Heavy', onTap: haptics.heavy),
],
),
Fx.row(
gap: 12,
children: [
Fx.successButton('Success', onTap: haptics.success),
Fx.dangerButton('Error', onTap: haptics.error),
Fx.primaryButton('Selection', onTap: haptics.selection),
],
),
],
),
);
}
Widget _buildDeviceSection() {
final device = Fluxy.use<FluxyDevicePlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Device & Environment').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
Fx(() => Fx.text('App Version: ${device.appVersion.value}')),
Fx(() {
final info = device.meta.value;
if (info.isEmpty) return Fx.text('Loading device info...');
return Fx.col(
alignItems: CrossAxisAlignment.start,
children: info.entries
.map((e) => Fx.text('${e.key}: ${e.value}'))
.toList(),
);
}),
],
),
);
}
Widget _buildLoggerSection() {
final logger = Fluxy.use<FluxyLoggerPlugin>();
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx.text('Logger Audit pipeline').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
Fx.textButton('Clear', onTap: logger.clear),
],
),
Fx.secondaryButton(
'Generate Log',
onTap: () {
logger.sys('User triggered manual log entry', tag: 'EXAMPLE');
},
),
Fx.box(
style: FxStyle(
backgroundColor: Colors.black.withOpacity(0.05),
borderRadius: BorderRadius.circular(8),
padding: const EdgeInsets.all(8),
width: double.infinity,
height: 150,
),
child: Fx(() {
final logs = logger.logs.value;
if (logs.isEmpty) return Fx.text('No logs yet.');
return ListView.builder(
itemCount: logs.length,
itemBuilder: (context, index) {
final log =
logs[logs.length - 1 - index]; // Show latest first
return Fx.text(
log,
).style(FxStyle(fontSize: 10, color: Colors.grey.shade800));
},
);
}),
),
],
),
);
}
Widget _buildAuthSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Authentication Demo')
.style(FxStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.blue.shade800)),
Fx(() => Fx.text(
isAuthenticated.value ? 'Authenticated' : 'Not Authenticated',
).style(FxStyle(color: isAuthenticated.value ? Colors.green : Colors.red))),
Fx.row(
gap: 12,
children: [
Fx.primaryButton('Login', onTap: _handleLogin),
Fx.dangerButton('Logout', onTap: _handleLogout),
],
),
],
),
);
}
Widget _buildCounterSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Reactive State Demo')
.style(FxStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.blue.shade800)),
Fx(() => Fx.text('Counter: ${counter.value}')
.style(FxStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.blue.shade600))),
Fx.row(
gap: 12,
children: [
Fx.primaryButton(
'Increment',
onTap: () {
counter.value++;
Fluxy.use<FluxyHapticsPlugin>().light();
Fluxy.use<FluxyLoggerPlugin>().sys(
'Counter incremented to ${counter.value}',
tag: 'COUNTER',
);
},
),
Fx.secondaryButton(
'Decrement',
onTap: () {
counter.value--;
Fluxy.use<FluxyHapticsPlugin>().selection();
},
),
Fx.textButton('Reset', onTap: () => counter.value = 0),
],
),
],
),
);
}
Widget _buildConnectivitySection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Connectivity Demo').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.blue.shade800,
),
),
Fx.row(
gap: 28,
children: [
Fx(
() => Fx.icon(
isConnected.value ? Icons.wifi : Icons.wifi_off,
color: isConnected.value ? Colors.green : Colors.red,
size: 32,
),
),
Fx.col(
alignItems: CrossAxisAlignment.start,
children: [
Fx(
() => Fx.text(
isConnected.value ? 'Online' : 'Offline',
).style(FxStyle(fontSize: 20, fontWeight: FontWeight.bold)),
),
Fx(
() => Fx.text(
'Type: ${connectionType.value.name.toUpperCase()}',
).style(FxStyle(color: Colors.grey.shade600)),
),
],
),
],
),
Fx.primaryButton(
'Re-check Connection',
onTap: () async {
final connectivity = Fx.platform.connectivity;
if (connectivity != null) {
final result = await connectivity.check();
Fx.toast.info(
'Connection refreshed: ${result ? "Online" : "Offline"}',
);
}
},
),
],
),
);
}
Widget _buildStorageSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Storage Demo')
.style(FxStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.blue.shade800)),
Fx.field(
label: 'Enter your name',
signal: userName,
placeholder: 'Type your name here...',
),
Fx(() => Fx.text('Stored Name: ${userName.value.isEmpty ? 'None' : userName.value}')
.style(FxStyle(color: Colors.grey.shade700))),
],
),
);
}
Widget _buildPlatformSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Platform Features')
.style(FxStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.blue.shade800)),
Fx.row(
gap: 12,
children: [
Fx.secondaryButton('Check Permissions', onTap: _checkPermissions),
Fx.secondaryButton('Get Platform Info', onTap: _getPlatformInfo),
],
),
],
),
);
}
Widget _buildBiometricSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.grey.shade100,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Biometric Authentication')
.style(FxStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.blue.shade800)),
Fx.successButton('Authenticate with Biometrics', onTap: _authenticateWithBiometrics),
],
),
);
}
Widget _buildControlCenterSection() {
return Fx.box(
style: FxStyle(
backgroundColor: Colors.red.shade50,
borderRadius: BorderRadius.circular(12),
padding: const EdgeInsets.all(16),
border: Border.all(color: Colors.red.shade200),
),
child: Fx.col(
gap: 12,
alignItems: CrossAxisAlignment.start,
children: [
Fx.text('Industrial Control Center').style(
FxStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red.shade900,
),
),
Fx.text('Emergency Kill-Switch (Production Safety)').font.xs().bold(),
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx.text('Geo Module'),
Fx(
() => Fx.icon(
FluxyFeatureToggle.isEnabled('geo')
? Icons.check_circle
: Icons.dangerous,
color: FluxyFeatureToggle.isEnabled('geo')
? Colors.green
: Colors.red,
),
),
Fx(
() => Fx.secondaryButton(
FluxyFeatureToggle.isEnabled('geo')
? 'KILL GEO'
: 'RESTORE GEO',
onTap: () {
if (FluxyFeatureToggle.isEnabled('geo')) {
FluxyFeatureToggle.kill('geo');
} else {
FluxyFeatureToggle.restore('geo');
}
},
),
),
],
),
Fx.row(
justify: MainAxisAlignment.spaceBetween,
children: [
Fx.text('Security Module'),
Fx(
() => Fx.icon(
FluxyFeatureToggle.isEnabled('security')
? Icons.check_circle
: Icons.dangerous,
color: FluxyFeatureToggle.isEnabled('security')
? Colors.green
: Colors.red,
),
),
Fx(
() => Fx.secondaryButton(
FluxyFeatureToggle.isEnabled('security')
? 'KILL SECURITY'
: 'RESTORE SECURITY',
onTap: () {
if (FluxyFeatureToggle.isEnabled('security')) {
FluxyFeatureToggle.kill('security');
} else {
FluxyFeatureToggle.restore('security');
}
},
),
),
],
),
],
),
);
}
void _handleLogin() {
// Simulate login
userName.value = 'John Doe';
isAuthenticated.value = true;
Fx.toast.success('Logged in successfully!');
}
void _handleLogout() {
// Simulate logout
userName.value = '';
isAuthenticated.value = false;
Fx.toast.error('Logged out successfully!');
}
void _checkPermissions() async {
// Simulate permission checking
Fx.toast.info('Camera: Granted, Storage: Granted');
}
void _getPlatformInfo() async {
// Simulate platform info
Fx.toast('Platform: Android, Version: 13');
}
void _authenticateWithBiometrics() async {
// Simulate biometric authentication
Fx.toast.success('Biometric authentication successful!');
}
}