18 changed files with 511 additions and 57 deletions
			
			
		@ -1,3 +1,6 @@
					 | 
				
			||||
org.gradle.jvmargs=-Xmx1536M | 
				
			||||
android.useAndroidX=true | 
				
			||||
android.enableJetifier=true | 
				
			||||
flutter.minSdkVersion=19 | 
				
			||||
flutter.targetSdkVersion=33 | 
				
			||||
flutter.compileSdkVersion=33 | 
				
			||||
@ -1,8 +1,66 @@
					 | 
				
			||||
import 'package:flutter/widgets.dart'; | 
				
			||||
import 'package:scoped_model/scoped_model.dart'; | 
				
			||||
import 'package:battery_plus/battery_plus.dart'; | 
				
			||||
 | 
				
			||||
/// Model for [BatteryPlusPage] | 
				
			||||
class BatteryPlusModel extends Model { | 
				
			||||
  /// Get [ScopedModel] | 
				
			||||
  static BatteryPlusModel of(BuildContext context) => ScopedModel.of<BatteryPlusModel>(context); | 
				
			||||
 | 
				
			||||
  final _battery = Battery(); | 
				
			||||
 | 
				
			||||
  /// Error | 
				
			||||
  String? _error; | 
				
			||||
 | 
				
			||||
  /// Public error | 
				
			||||
  String? get error => _error; | 
				
			||||
 | 
				
			||||
  /// Public error | 
				
			||||
  bool get isError => _error != null; | 
				
			||||
 | 
				
			||||
  /// Get battery level in percent 0-100 | 
				
			||||
  Future<int?> getBatteryLevel() async { | 
				
			||||
    try { | 
				
			||||
      return await _battery.batteryLevel; | 
				
			||||
    } catch (e, s) { | 
				
			||||
      _error = e.toString(); | 
				
			||||
      debugPrintStack(stackTrace: s); | 
				
			||||
    } | 
				
			||||
    return null; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  /// Get status | 
				
			||||
  Future<BatteryState?> getBatteryState() async { | 
				
			||||
    try { | 
				
			||||
      return await _battery.batteryState; | 
				
			||||
    } catch (e, s) { | 
				
			||||
      _error = e.toString(); | 
				
			||||
      debugPrintStack(stackTrace: s); | 
				
			||||
    } | 
				
			||||
    return null; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  /// Check is enable save mode | 
				
			||||
  Future<bool?> isInBatterySaveMode() async { | 
				
			||||
    try { | 
				
			||||
      return await _battery.isInBatterySaveMode; | 
				
			||||
    } catch (e, s) { | 
				
			||||
      _error = e.toString(); | 
				
			||||
      debugPrintStack(stackTrace: s); | 
				
			||||
    } | 
				
			||||
    return null; | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  /// Stream change state | 
				
			||||
  Stream<BatteryState> onBatteryStateChanged() async* { | 
				
			||||
    try { | 
				
			||||
      yield await _battery.batteryState; | 
				
			||||
      await for (final state in _battery.onBatteryStateChanged) { | 
				
			||||
        yield state; | 
				
			||||
      } | 
				
			||||
    } catch (e, s) { | 
				
			||||
      _error = e.toString(); | 
				
			||||
      debugPrintStack(stackTrace: s); | 
				
			||||
    } | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,39 @@
					 | 
				
			||||
import 'package:flutter/material.dart'; | 
				
			||||
import 'package:flutter_example_packages/theme/radius.dart'; | 
				
			||||
import 'package:flutter_example_packages/widgets/texts/export.dart'; | 
				
			||||
 | 
				
			||||
/// Alert | 
				
			||||
class BlockAlert extends StatelessWidget { | 
				
			||||
  const BlockAlert( | 
				
			||||
    this.text, { | 
				
			||||
    super.key, | 
				
			||||
    this.color = Colors.redAccent, | 
				
			||||
    this.padding = const EdgeInsets.only(bottom: 20), | 
				
			||||
  }); | 
				
			||||
 | 
				
			||||
  final EdgeInsets padding; | 
				
			||||
  final Color color; | 
				
			||||
  final String? text; | 
				
			||||
 | 
				
			||||
  @override | 
				
			||||
  Widget build(BuildContext context) { | 
				
			||||
    return Visibility( | 
				
			||||
      visible: text != null, | 
				
			||||
      child: Padding( | 
				
			||||
        padding: padding, | 
				
			||||
        child: Container( | 
				
			||||
          width: double.infinity, | 
				
			||||
          padding: const EdgeInsets.all(10), | 
				
			||||
          decoration: BoxDecoration( | 
				
			||||
            color: color, | 
				
			||||
            borderRadius: AppRadius.small, | 
				
			||||
          ), | 
				
			||||
          child: TextBodyMedium( | 
				
			||||
            '$text', | 
				
			||||
            color: Colors.white, | 
				
			||||
          ), | 
				
			||||
        ), | 
				
			||||
      ), | 
				
			||||
    ); | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,64 @@
					 | 
				
			||||
import 'package:flutter/material.dart'; | 
				
			||||
import 'package:flutter_example_packages/base/package/package.dart'; | 
				
			||||
import 'package:flutter_example_packages/theme/radius.dart'; | 
				
			||||
import 'package:flutter_example_packages/widgets/base/export.dart'; | 
				
			||||
import 'package:flutter_example_packages/widgets/texts/export.dart'; | 
				
			||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | 
				
			||||
 | 
				
			||||
/// Block info package in page | 
				
			||||
class BlockInfoPackage extends AppStatelessWidget { | 
				
			||||
  const BlockInfoPackage( | 
				
			||||
    this.package, { | 
				
			||||
    super.key, | 
				
			||||
  }); | 
				
			||||
 | 
				
			||||
  final Package package; | 
				
			||||
 | 
				
			||||
  @override | 
				
			||||
  Widget buildWide( | 
				
			||||
    BuildContext context, | 
				
			||||
    MediaQueryData media, | 
				
			||||
    AppLocalizations l10n, | 
				
			||||
  ) { | 
				
			||||
    return Container( | 
				
			||||
      padding: const EdgeInsets.all(12), | 
				
			||||
      margin: const EdgeInsets.only(bottom: 20), | 
				
			||||
      decoration: BoxDecoration( | 
				
			||||
        color: Colors.grey.shade200, | 
				
			||||
        borderRadius: AppRadius.small, | 
				
			||||
      ), | 
				
			||||
      child: Column( | 
				
			||||
        children: [ | 
				
			||||
          TextBodyMedium(package.desc), | 
				
			||||
          const SizedBox(height: 8), | 
				
			||||
          Divider( | 
				
			||||
            height: 1, | 
				
			||||
            color: Colors.grey.shade400, | 
				
			||||
          ), | 
				
			||||
          const SizedBox(height: 8), | 
				
			||||
          Row( | 
				
			||||
            children: [ | 
				
			||||
              const Icon(Icons.verified, size: 14, color: Colors.green), | 
				
			||||
              const SizedBox(width: 6), | 
				
			||||
              TextBodySmall(package.version), | 
				
			||||
              const SizedBox(width: 10), | 
				
			||||
              Icon( | 
				
			||||
                Icons.auto_awesome_motion, | 
				
			||||
                size: 14, | 
				
			||||
                color: package.isPlatformDependent | 
				
			||||
                    ? Colors.deepOrange | 
				
			||||
                    : Colors.blueAccent, | 
				
			||||
              ), | 
				
			||||
              const SizedBox(width: 6), | 
				
			||||
              TextBodySmall( | 
				
			||||
                package.isPlatformDependent | 
				
			||||
                    ? l10n.homeListStateDependent | 
				
			||||
                    : l10n.homeListStateIndependent, | 
				
			||||
              ), | 
				
			||||
            ], | 
				
			||||
          ), | 
				
			||||
        ], | 
				
			||||
      ), | 
				
			||||
    ); | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
@ -0,0 +1,74 @@
					 | 
				
			||||
import 'package:flutter/material.dart'; | 
				
			||||
import 'package:flutter_example_packages/widgets/base/export.dart'; | 
				
			||||
import 'package:flutter_example_packages/widgets/texts/export.dart'; | 
				
			||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; | 
				
			||||
 | 
				
			||||
/// Block list item | 
				
			||||
class BlockItem<T> extends AppStatelessWidget { | 
				
			||||
  const BlockItem({ | 
				
			||||
    super.key, | 
				
			||||
    required this.title, | 
				
			||||
    required this.desc, | 
				
			||||
    this.future, | 
				
			||||
    this.stream, | 
				
			||||
    this.builder, | 
				
			||||
  }); | 
				
			||||
 | 
				
			||||
  final String title; | 
				
			||||
  final String desc; | 
				
			||||
  final Stream<T>? stream; | 
				
			||||
  final Future<T>? future; | 
				
			||||
  final Function(T)? builder; | 
				
			||||
 | 
				
			||||
  AsyncWidgetBuilder<T> get widgetBuilder => | 
				
			||||
      (BuildContext context, AsyncSnapshot<T> snapshot) { | 
				
			||||
        return Column( | 
				
			||||
          crossAxisAlignment: CrossAxisAlignment.start, | 
				
			||||
          children: [ | 
				
			||||
            TextTitleSmall(title), | 
				
			||||
            const SizedBox(height: 8), | 
				
			||||
            TextBodySmall(desc), | 
				
			||||
            const SizedBox(height: 8), | 
				
			||||
            if (snapshot.hasData) | 
				
			||||
              TextBodyMedium( | 
				
			||||
                snapshot.data == null | 
				
			||||
                    ? '-' | 
				
			||||
                    : (builder == null | 
				
			||||
                        ? snapshot.data.toString() | 
				
			||||
                        : builder?.call(snapshot.data as T)), | 
				
			||||
              ), | 
				
			||||
            if (!snapshot.hasData) | 
				
			||||
              const SizedBox( | 
				
			||||
                width: 16, | 
				
			||||
                height: 16, | 
				
			||||
                child: CircularProgressIndicator( | 
				
			||||
                  color: Colors.blueAccent, | 
				
			||||
                  strokeWidth: 2, | 
				
			||||
                ), | 
				
			||||
              ), | 
				
			||||
            const SizedBox(height: 20), | 
				
			||||
          ], | 
				
			||||
        ); | 
				
			||||
      }; | 
				
			||||
 | 
				
			||||
  @override | 
				
			||||
  Widget buildWide( | 
				
			||||
    BuildContext context, | 
				
			||||
    MediaQueryData media, | 
				
			||||
    AppLocalizations l10n, | 
				
			||||
  ) { | 
				
			||||
    if (stream != null) { | 
				
			||||
      return StreamBuilder( | 
				
			||||
        stream: stream, | 
				
			||||
        builder: widgetBuilder, | 
				
			||||
      ); | 
				
			||||
    } | 
				
			||||
    if (future != null) { | 
				
			||||
      return FutureBuilder<T>( | 
				
			||||
        future: future, | 
				
			||||
        builder: widgetBuilder, | 
				
			||||
      ); | 
				
			||||
    } | 
				
			||||
    throw "Please enter a value stream or future"; | 
				
			||||
  } | 
				
			||||
} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue