starter_kit_flutter 1.0.2
starter_kit_flutter: ^1.0.2 copied to clipboard
A batteries-included foundational Flutter package for networking, connectivity, storage, theming, app updates, and core utilities.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:starter_kit_flutter/starter_kit_flutter.dart';
void main() {
runApp(
StarterKitApp(
config: StarterKitConfig(
storageConfig: const StorageConfig(
keyPrefix: 'example_',
),
themeConfig: const ThemeConfig(
defaultThemeMode: ThemeMode.system,
),
modules: const StarterKitModulesConfig(
// Example: enable only what you need for this app.
network: StarterKitModuleMode.stub,
storage: StarterKitModuleMode.enabled,
theme: StarterKitModuleMode.enabled,
connectivity: StarterKitModuleMode.enabled,
updater: StarterKitModuleMode.disabled,
featureFlags: StarterKitModuleMode.enabled,
),
featureFlagConfig: const FeatureFlagConfig(
initialFlags: {
'promo_banner': true,
},
),
ui: const StarterKitUiConfig(
showConnectivityBanner: true,
showForceUpdateScreen: false,
showMaintenanceScreen: false,
enableGlobalLoader: true,
enableDevPanel: true,
devPanelTrigger: DevPanelTrigger.both,
),
designSystemConfig: const DesignSystemConfig(
spacing: DesignSpacingConfig(
xxs: 4,
xs: 8,
sm: 12,
md: 16,
lg: 20,
xl: 24,
xxl: 32,
section: 40,
),
radius: DesignRadiusConfig(
sm: 8,
md: 12,
lg: 16,
xl: 24,
),
typography: DesignTypographyConfig(
titleLargeSize: 24,
bodyLargeSize: 16,
bodyMediumSize: 14,
),
),
),
appBuilder: (context, data) {
return MaterialApp(
navigatorKey: data.navigatorKey,
theme: data.lightTheme,
darkTheme: data.darkTheme,
themeMode: data.themeMode,
home: const ExampleHomePage(),
);
},
),
);
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key});
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
bool _loading = false;
String _status = 'Ready';
String _savedName = 'No value saved yet';
Future<void> _saveName() async {
setState(() {
_loading = true;
_status = 'Saving name...';
});
final result =
await StarterKit.I.storage.setString('name', 'StarterKit Dev');
result.fold(
(error) {
setState(() {
_status = 'Save failed: ${error.message}';
});
},
(_) {
setState(() {
_status = 'Name saved successfully';
});
},
);
setState(() {
_loading = false;
});
}
Future<void> _readName() async {
setState(() {
_loading = true;
_status = 'Reading name...';
});
final result = await StarterKit.I.storage.getString('name');
result.fold(
(error) {
setState(() {
_status = 'Read failed: ${error.message}';
_savedName = 'No saved name';
});
},
(value) {
setState(() {
_status = 'Name loaded';
_savedName = value;
});
},
);
setState(() {
_loading = false;
});
}
Future<void> _toggleTheme() async {
final result = await StarterKit.I.theme.toggleTheme();
result.fold(
(error) {
setState(() {
_status = 'Theme toggle failed: ${error.message}';
});
},
(_) {
setState(() {
_status = 'Theme toggled';
});
},
);
}
Future<void> _checkConnectivity() async {
final state = await StarterKit.I.connectivity.checkConnection();
setState(() {
_status = 'Connectivity: $state';
});
}
Future<void> _showNetworkStubBehavior() async {
final result = await StarterKit.I.network.get<Map<String, dynamic>>(
'/users/1',
fromJson: (json) => json as Map<String, dynamic>,
);
result.fold(
(error) {
setState(() {
_status = 'Network (stub): ${error.message}';
});
},
(data) {
setState(() {
_status = 'Network success: $data';
});
},
);
}
@override
Widget build(BuildContext context) {
final spacing = context.dsSpacing;
final radius = context.dsRadius;
final shadow = context.dsShadow;
final body = Scaffold(
appBar: AppBar(
title: const Text('StarterKit Example'),
),
body: Padding(
padding: EdgeInsets.all(spacing.md),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Status: $_status'),
const VSpace(DesignSpacingSize.xs),
Text('Saved name: $_savedName'),
const VSpace(DesignSpacingSize.md),
Container(
width: double.infinity,
padding: EdgeInsets.all(spacing.sm),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceContainerHighest,
borderRadius: BorderRadius.circular(radius.md),
boxShadow: shadow.low,
),
child: Text(
'Design-system tokens are active: spacing, radius, shadows and typography.',
style: context.textTheme.bodyMedium,
),
),
const VSpace(DesignSpacingSize.md),
StarterKitSlot(
featureFlag: 'promo_banner',
flaggedChild: Card(
child: Padding(
padding: EdgeInsets.all(spacing.sm),
child: Text(
'Feature-flagged promo banner (flag: promo_banner)',
style: context.textTheme.bodyMedium,
),
),
),
fallback: Text(
'Promo banner hidden (flag off)',
style: context.textTheme.labelMedium,
),
child: const SizedBox.shrink(),
),
const VSpace(DesignSpacingSize.md),
Wrap(
spacing: spacing.sm,
runSpacing: spacing.sm,
children: [
ElevatedButton(
onPressed: _saveName,
child: const Text('Save Name'),
),
ElevatedButton(
onPressed: _readName,
child: const Text('Read Name'),
),
ElevatedButton(
onPressed: _toggleTheme,
child: const Text('Toggle Theme'),
),
ElevatedButton(
onPressed: _checkConnectivity,
child: const Text('Check Connectivity'),
),
ElevatedButton(
onPressed: _showNetworkStubBehavior,
child: const Text('Try Network Call'),
),
],
),
const VSpace(DesignSpacingSize.md),
const Text(
'This example enables storage/theme/connectivity, '
'stubs network, and disables updater from one place.',
),
const VSpace(DesignSpacingSize.sm),
Row(
children: const [
Text('Using spacing widgets:'),
HSpace(DesignSpacingSize.xs),
Text('VSpace/HSpace'),
HSpace(DesignSpacingSize.xs),
Text('SKSizedBox.h16/w16'),
],
),
SKSizedBox.h16,
],
),
),
);
return StarterKit.builder(
child: body,
isLoading: _loading,
);
}
}