commonkit 0.1.6 copy "commonkit: ^0.1.6" to clipboard
commonkit: ^0.1.6 copied to clipboard

CommonKit: Lightweight, WASM-compatible package with widgets, helpers, and extensions for streamlined app development, UI components, and utilities.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:commonkit/commonkit.dart';
import 'dart:io' if (dart.library.io) 'dart:io';
import 'package:image_picker/image_picker.dart'
    if (dart.library.io) 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart'
    if (dart.library.io) 'package:permission_handler/permission_handler.dart';

/// Initializes the app with global configuration and runs the [CommonKitExampleApp].
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize storage for non-web platforms (WASM-safe)
  if (!kIsWeb) {
    await StorageHelper.init();
  }

  // Set up global configuration with theme, API base URL, and session data
  await GlobalConfig().init(
    baseUrl: 'https://jsonplaceholder.typicode.com',
    variables: {'apiKey': '12345'},
    isDebugMode: true,
    theme: CommonKitTheme(
      primaryColor: Colors.teal,
      secondaryColor: Colors.grey[800]!,
      accentColor: Colors.tealAccent,
      backgroundColor: Colors.grey[900]!,
      textColor: Colors.white,
      highContrast: true,
      isDarkMode: true,
      borderRadius: 12.0,
      animationDuration: Duration(milliseconds: 400),
    ),
    locale: Locale('en', 'US'),
    apiTimeout: Duration(seconds: 20),
    environment: 'development',
    isAnalyticsEnabled: false,
  );

  runApp(const CommonKitExampleApp());
}

/// The main application demonstrating `commonkit` features.
///
/// This app provides a tabbed interface to test widgets, helpers, extensions, and
/// configurations, with full WASM compatibility for web platforms. Non-web features
/// (e.g., file uploads, directory management) are disabled on web with user-friendly
/// feedback via toasts.
///
/// Run this app to explore:
/// - Themed UI with `CommonKitTheme`
/// - Network requests and image caching
/// - Session management and form validation
/// - Clipboard, animations, and more
class CommonKitExampleApp extends StatelessWidget {
  const CommonKitExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    final theme = GlobalConfig().theme ?? CommonKitTheme();
    return MaterialApp(
      theme: ThemeData(
        primaryColor: theme.primaryColor,
        scaffoldBackgroundColor: theme.backgroundColor,
        textTheme: TextTheme(
          bodyMedium:
              theme.bodyTextStyle ??
              TextStyle(color: theme.textColor, fontSize: 16),
          titleLarge:
              theme.headingTextStyle ??
              TextStyle(
                color: theme.textColor,
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
        ),
        buttonTheme: ButtonThemeData(
          textTheme: ButtonTextTheme.primary,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(theme.borderRadius),
          ),
        ),
        brightness: theme.isDarkMode ? Brightness.dark : Brightness.light,
      ),
      home: const ExamplePage(),
    );
  }
}

/// A tabbed page showcasing `commonkit` features in an organized, user-friendly way.
///
/// Tabs include:
/// - **Network & Media**: Test network requests, image caching, and file uploads.
/// - **Session & Forms**: Explore session management and form validation.
/// - **System & Utils**: Try directory management, permissions, clipboard, and animations.
///
/// Each feature includes status updates and toasts for clear feedback, with non-web
/// features disabled on WASM platforms.
class ExamplePage extends StatefulWidget {
  const ExamplePage({super.key});

  @override
  State<ExamplePage> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage>
    with SingleTickerProviderStateMixin {
  // Helpers and managers
  final _networkHelper = NetworkHelper();
  final _directoryManager = kIsWeb ? null : DirectoryManager();
  final _sessionManager = SessionManager();
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  String _status = 'Ready';
  bool _isLoading = false;

  // Animation controller for fade effects
  late AnimationController _animationController;
  late Animation<double> _fadeAnimation;

  @override
  void initState() {
    super.initState();
    // Initialize animation for UI effects
    _animationController = AnimationController(
      vsync: this,
      duration:
          GlobalConfig().theme?.animationDuration ??
          Duration(milliseconds: 400),
    );
    _fadeAnimation = CurvedAnimation(
      parent: _animationController,
      curve: Curves.easeInOut,
    );
    _animationController.forward();

    // Preload an image to demonstrate ImageCacheHelper
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _preloadImage();
    });
  }

  @override
  void dispose() {
    _emailController.dispose();
    _animationController.dispose();
    super.dispose();
  }

  /// Preloads a sample image for performance
  Future<void> _preloadImage() async {
    if (!mounted) return;
    setState(() => _status = 'Preloading image...');
    final failed = await ImageCacheHelper.preloadImages(
      ['https://via.placeholder.com/150'],
      context,
      onProgress:
          (loaded, total) => setState(() => _status = 'Images: $loaded/$total'),
    );
    if (!mounted) return;
    setState(
      () =>
          _status =
              failed.isEmpty ? 'Image preloaded' : 'Preload failed: $failed',
    );
    if (failed.isEmpty) {
      showToast(context, message: 'Image Cached');
    }
  }

  /// Tests a network GET request
  Future<void> _testNetwork() async {
    if (!mounted) return;
    setState(() {
      _isLoading = true;
      _status = 'Fetching data...';
    });
    try {
      final data = await _networkHelper.get('/posts/1');
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Title: ${(data['title'] as String).capitalize()}';
      });
      Logger.info('Network test succeeded');
      showToast(context, message: 'Network Success');
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Network Error: $e';
      });
      Logger.error('Network test failed', e);
      showCustomDialog(context, title: 'Error', content: e.toString());
    }
  }

  /// Tests file upload with ImagePicker (non-web only)
  Future<void> _testFileUpload() async {
    if (kIsWeb) {
      setState(() => _status = 'File upload not supported on web');
      showToast(context, message: 'Feature unavailable on web');
      return;
    }
    setState(() {
      _isLoading = true;
      _status = 'Picking image...';
    });
    try {
      final picker = ImagePicker();
      final pickedFile = await picker.pickImage(source: ImageSource.gallery);
      if (pickedFile == null) {
        if (!mounted) return;
        setState(() {
          _isLoading = false;
          _status = 'No image selected';
        });
        return;
      }
      final file = File(pickedFile.path);
      setState(() => _status = 'Uploading...');
      final data = await _networkHelper.post(
        '/upload',
        body: {'title': 'Example Upload'},
        files: [file],
      );
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Upload: $data';
      });
      Logger.info('File upload succeeded');
      showToast(context, message: 'Upload Success');
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Upload Error: $e';
      });
      Logger.error('File upload failed', e);
      showToast(context, message: 'Upload Error');
    }
  }

  /// Tests directory management (non-web only)
  Future<void> _testDirectory() async {
    if (kIsWeb || _directoryManager == null) {
      setState(() => _status = 'Directory management not supported on web');
      showToast(context, message: 'Feature unavailable on web');
      return;
    }
    setState(() {
      _isLoading = true;
      _status = 'Creating directory...';
    });
    try {
      final dir = await _directoryManager.createDirectory('example_dir');
      await _directoryManager.createFile(
        'example_dir/test.txt',
        content: 'Example',
      );
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Directory: ${dir.path}';
      });
      Logger.info('Directory test succeeded');
      showToast(context, message: 'Directory Created');
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Directory Error: $e';
      });
      Logger.error('Directory test failed', e);
      showToast(context, message: 'Directory Error');
    }
  }

  /// Tests clipboard operations
  Future<void> _testClipboard() async {
    setState(() => _status = 'Testing clipboard...');
    try {
      await ClipboardManager.copy('Example Text');
      final pasted = await ClipboardManager.paste();
      if (!mounted) return;
      setState(() => _status = 'Clipboard: $pasted');
      Logger.info('Clipboard test succeeded');
      showToast(context, message: 'Copied and Pasted');
    } catch (e) {
      if (!mounted) return;
      setState(() => _status = 'Clipboard Error: $e');
      Logger.error('Clipboard test failed', e);
      showToast(context, message: 'Clipboard Error');
    }
  }

  /// Tests permission handling (non-web only)
  Future<void> _testPermission() async {
    if (kIsWeb) {
      setState(() => _status = 'Permissions not supported on web');
      showToast(context, message: 'Feature unavailable on web');
      return;
    }
    setState(() {
      _isLoading = true;
      _status = 'Requesting permission...';
    });
    try {
      final granted = await PermissionManager.request(Permission.storage);
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Permission: ${granted ? "Granted" : "Denied"}';
      });
      Logger.info('Permission test: ${granted ? "Granted" : "Denied"}');
      showCustomDialog(
        context,
        title: 'Permission',
        content: granted ? 'Storage granted' : 'Storage denied',
        negativeText: granted ? null : 'Settings',
        onNegative: granted ? null : () => PermissionManager.openSettings(),
      );
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Permission Error: $e';
      });
      Logger.error('Permission test failed', e);
      showToast(context, message: 'Permission Error');
    }
  }

  /// Tests session management with login/logout
  Future<void> _testSession() async {
    setState(() {
      _isLoading = true;
      _status = 'Logging in...';
    });
    try {
      await _sessionManager.login(
        username: 'test_user',
        password: 'password123',
      );
      await GlobalConfig().updateSession(
        username: 'test_user',
        token: 'abc123',
        expiry: DateTime.now().add(Duration(days: 1)),
      );
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Logged in as ${GlobalConfig().username}';
      });
      Logger.info('Session test succeeded');
      showToast(context, message: 'Login Success');
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Session Error: $e';
      });
      Logger.error('Session test failed', e);
      showToast(context, message: 'Login Error');
    }
  }

  /// Tests form validation with email input
  Future<void> _testValidation() async {
    if (_formKey.currentState!.validate()) {
      setState(() => _status = 'Email valid: ${_emailController.text}');
      showToast(context, message: 'Validation Success');
    } else {
      setState(() => _status = 'Invalid email');
      showToast(context, message: 'Validation Failed');
    }
  }

  /// Tests image picking with ImagePicker (non-web only)
  Future<void> _testImagePicker() async {
    if (kIsWeb) {
      setState(() => _status = 'Image picker not supported on web');
      showToast(context, message: 'Feature unavailable on web');
      return;
    }
    setState(() {
      _isLoading = true;
      _status = 'Picking image...';
    });
    try {
      final picker = ImagePicker();
      final pickedFile = await picker.pickImage(source: ImageSource.gallery);
      if (pickedFile == null) {
        if (!mounted) return;
        setState(() {
          _isLoading = false;
          _status = 'No image selected';
        });
        return;
      }
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Image: ${pickedFile.path}';
      });
      Logger.info('Image picker succeeded');
      showToast(context, message: 'Image Picked');
    } catch (e) {
      if (!mounted) return;
      setState(() {
        _isLoading = false;
        _status = 'Image Picker Error: $e';
      });
      Logger.error('Image picker failed', e);
      showToast(context, message: 'Image Picker Error');
    }
  }

  /// Tests animation helper with a fade effect
  Future<void> _testAnimation() async {
    setState(() => _status = 'Starting animation...');
    _animationController.reset();
    await _animationController.forward();
    if (!mounted) return;
    setState(() => _status = 'Animation completed');
    showToast(context, message: 'Animation Success');
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            'CommonKit Demo',
            style: Theme.of(context).textTheme.titleLarge,
          ),
          bottom: const TabBar(
            tabs: [
              Tab(text: 'Network & Media'),
              Tab(text: 'Session & Forms'),
              Tab(text: 'System & Utils'),
            ],
          ),
        ),
        body: Stack(
          children: [
            TabBarView(
              children: [
                // Network & Media Tab
                SingleChildScrollView(
                  padding: const EdgeInsets.all(16.0),
                  child: FadeTransition(
                    opacity: _fadeAnimation,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'Test network, images, and uploads',
                          style: Theme.of(context).textTheme.titleLarge,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Network Request',
                          onPressed: _testNetwork,
                          icon: Icons.network_check,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test File Upload',
                          onPressed: _testFileUpload,
                          icon: Icons.upload_file,
                          isDisabled: kIsWeb,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Image Picker',
                          onPressed: _testImagePicker,
                          icon: Icons.image,
                          isDisabled: kIsWeb,
                        ),
                        const SizedBox(height: 16),
                        Image.network(
                          'https://via.placeholder.com/150',
                          width: 150,
                          height: 150,
                          loadingBuilder:
                              (context, child, progress) =>
                                  progress == null
                                      ? child
                                      : const CircularProgressIndicator(),
                        ),
                        const SizedBox(height: 16),
                        Text(
                          'Status: $_status',
                          style: Theme.of(context).textTheme.bodyMedium,
                        ),
                      ],
                    ),
                  ),
                ),
                // Session & Forms Tab
                SingleChildScrollView(
                  padding: const EdgeInsets.all(16.0),
                  child: FadeTransition(
                    opacity: _fadeAnimation,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'Test session and validation',
                          style: Theme.of(context).textTheme.titleLarge,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Session Login',
                          onPressed: _testSession,
                          icon: Icons.person,
                        ),
                        const SizedBox(height: 16),
                        Form(
                          key: _formKey,
                          child: TextFormField(
                            controller: _emailController,
                            decoration: const InputDecoration(
                              labelText: 'Email',
                              border: OutlineInputBorder(),
                            ),
                            validator:
                                (value) =>
                                    Validators.email(value ?? '') != null
                                        ? null
                                        : 'Invalid email address',
                          ),
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Validate Email',
                          onPressed: _testValidation,
                          icon: Icons.check_circle,
                        ),
                        const SizedBox(height: 16),
                        Text(
                          'Status: $_status',
                          style: Theme.of(context).textTheme.bodyMedium,
                        ),
                      ],
                    ),
                  ),
                ),
                // System & Utils Tab
                SingleChildScrollView(
                  padding: const EdgeInsets.all(16.0),
                  child: FadeTransition(
                    opacity: _fadeAnimation,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'Test system features and utilities',
                          style: Theme.of(context).textTheme.titleLarge,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Directory Management',
                          onPressed: _testDirectory,
                          icon: Icons.folder,
                          isDisabled: kIsWeb,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Permission',
                          onPressed: _testPermission,
                          icon: Icons.security,
                          isDisabled: kIsWeb,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Clipboard',
                          onPressed: _testClipboard,
                          icon: Icons.copy,
                        ),
                        const SizedBox(height: 16),
                        CustomButton(
                          text: 'Test Animation',
                          onPressed: _testAnimation,
                          icon: Icons.animation,
                        ),
                        const SizedBox(height: 16),
                        Text(
                          'Status: $_status',
                          style: Theme.of(context).textTheme.bodyMedium,
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
            if (_isLoading)
              LoadingOverlay(
                isLoading: _isLoading,
                overlayColor: GlobalConfig().theme?.loadingOverlayColor,
                progressIndicatorColor:
                    GlobalConfig().theme?.loadingSpinnerColor,
              ),
          ],
        ),
      ),
    );
  }
}
2
likes
155
points
91
downloads

Publisher

unverified uploader

Weekly Downloads

CommonKit: Lightweight, WASM-compatible package with widgets, helpers, and extensions for streamlined app development, UI components, and utilities.

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, flutter_cache_manager, http, image_picker, intl, path_provider, permission_handler, shared_preferences

More

Packages that depend on commonkit