fr_mvvm_theme 0.1.0 copy "fr_mvvm_theme: ^0.1.0" to clipboard
fr_mvvm_theme: ^0.1.0 copied to clipboard

Theme switching helpers for FlowR MVVM Flutter apps, including theme models, ThemeExtension utilities, image scheme parsing, and menu UI.

example/lib/main.dart

import 'dart:convert' show jsonDecode;

import 'package:flowr/flowr_mvvm.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
import 'package:fr_mvvm_theme/fr_mvvm_theme.dart';
import 'package:json_annotation/json_annotation.dart';

part 'main.g.dart';

@JsonSerializable(converters: [FrColorCvt()])
class LoginPageTheme extends FrPageTheme<LoginPageTheme> {
  final Color welcomeColor;
  final String logoImg;

  const LoginPageTheme({required this.welcomeColor, required this.logoImg});

  factory LoginPageTheme.fromJson(Map<String, dynamic> json) =>
      _$LoginPageThemeFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$LoginPageThemeToJson(this);
}

@JsonSerializable(createToJson: false)
class AppTheme extends FrThemeModel {
  @JsonKey(name: 'login')
  final LoginPageTheme? loginPage;

  AppTheme({
    required super.themeId,
    super.startAt,
    super.endAt,
    super.priority = 0,
    this.loginPage,
  });

  factory AppTheme.fromJson(Map<String, dynamic> json) =>
      _$AppThemeFromJson(json);

  @override
  Map<String, dynamic> toJson() => {
    'themeId': themeId,
    'startAt': startAt,
    'endAt': endAt,
    'priority': priority,
    'login': loginPage,
  };

  LoginPageTheme get loginPageTheme =>
      loginPage ??
      (throw StateError('AppTheme.loginPage is required for this example.'));
}

final builtInTheme = AppTheme(
  themeId: 'built_in',
  loginPage: LoginPageTheme(
    welcomeColor: Colors.black87,
    logoImg: 'asset://assets/logo/built_in.png',
  ),
);

class AppThemeViewModel extends IThemeViewModel<AppTheme> {
  AppThemeViewModel() : super(builtInTheme) {
    loadThemeConfig(); // async auto load local/network theme config
  }

  // must has one built-in theme
  final List<AppTheme> _all = [builtInTheme];

  @override
  Iterable<AppTheme> get all => _all;

  // load theme from local config file
  Future<void> loadThemeConfig() async {
    final raw = await rootBundle.loadString('assets/theme_config.json');
    final theme = AppTheme.fromJson(jsonDecode(raw) as Map<String, dynamic>);
    _all.removeWhere((item) => item.themeId == theme.themeId);
    _all.add(theme);
    await updateTheme(theme);
  }
}

void main() {
  runApp(
    FrProvider.multi(
      [FrProvider((context) => AppThemeViewModel())],
      child: FrView<AppThemeViewModel, AppTheme>(
        builder: (context, state, _) {
          final pageTheme = state.data.loginPageTheme;
          return MaterialApp(
            theme: ThemeData(
              useMaterial3: true,
              colorScheme: ColorScheme.fromSeed(
                seedColor: pageTheme.welcomeColor,
              ),
              extensions: state.data.extensions,
            ),
            home: const Scaffold(body: Center(child: ThemePreview())),
          );
        },
      ),
    ),
  );
}

class ThemePreview extends StatelessWidget {
  const ThemePreview({super.key});

  @override
  Widget build(BuildContext context) => FrView<AppThemeViewModel, AppTheme>(
    builder: (context, state, _) {
      final pageTheme = context.ofThm<LoginPageTheme>();
      final colors = Theme.of(context).colorScheme;
      return Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          DecoratedBox(
            decoration: BoxDecoration(
              color: colors.primaryContainer,
              borderRadius: BorderRadius.circular(20),
              border: Border.all(color: colors.outlineVariant),
            ),
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Image(
                image: pageTheme.logoImg.asImageProvider,
                width: 72,
                height: 72,
                fit: BoxFit.contain,
              ),
            ),
          ),
          const SizedBox(height: 12),
          Text('themeId: ${state.data.themeId}'),
          Text(
            'seedColor: ${pageTheme.toJson()['welcomeColor']}',
            style: TextStyle(color: colors.primary),
          ),
          Text(
            'colorScheme.primary: ${colors.primary.toHexString}',
            style: TextStyle(color: colors.onSurfaceVariant),
          ),
          Text('logoImg: ${pageTheme.logoImg}'),
          const SizedBox(height: 16),
          FrThemeSwitchView<AppThemeViewModel, AppTheme>(
            buildAnchorTile: (context, theme) => Text(
              'ThemeID ${theme.themeId}',
              style: const TextStyle(color: Colors.black87),
            ),
          ),
        ],
      );
    },
  );
}
0
likes
160
points
138
downloads

Documentation

API reference

Publisher

verified publisherwyattcoder.top

Weekly Downloads

Theme switching helpers for FlowR MVVM Flutter apps, including theme models, ThemeExtension utilities, image scheme parsing, and menu UI.

Repository (GitHub)
View/report issues

Topics

#flowr #theme

License

MIT (license)

Dependencies

flowr, flutter, json_annotation

More

Packages that depend on fr_mvvm_theme