Skip to content

Commit

Permalink
feat: Add initial brand support (#431)
Browse files Browse the repository at this point in the history
* feat: Add brands to store brand-related ThemeData.

* feat: Add BrandBloc to manage brand state.

* test: Add tests for BrandBloc.

* test: Improve test description.

* chore: Use proper doc syntax.

* feat: Create `catalyst_voices_brands` package to manage brands and themes.

* chore: Replace `builder` with `home`.

* chore: Update `catalyst_voices_brands` deps.

* chore: Update generated models.

* chore: Update generated code.

* chore: Rename `dummy` theme into `fallback`.
  • Loading branch information
coire1 authored May 7, 2024
1 parent 424975e commit bfec640
Show file tree
Hide file tree
Showing 17 changed files with 373 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'brand_bloc.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'package:bloc/bloc.dart';
import 'package:catalyst_voices_brands/catalyst_voices_brands.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';

part 'brand_event.dart';
part 'brand_state.dart';

/// [BrandBloc] is a Bloc responsible for managing the brand state.
///
/// This Bloc listens for [BrandEvent]s and updates the [BrandState]
/// accordingly.
/// The [BrandState] can be consumed by the [MaterialApp] to build the
/// appropriate [ThemeData] based on the [BrandKey] stored in the state.
///
/// To build the appropriate [ThemeData] based on the [BrandKey] is
/// possible to use the [ThemeBuilder] utility form the `catalyst_voices_brands`
/// package.
///
/// The [BrandChangedEvent] accepts a [BrandKey] a simple enum that
/// contains all possible brands/themes.
///
/// To trigger the theme change is just necessary to dispatch the
/// [BrandChangedEvent] with the appropriate key:
///
/// ```dart
/// context.read<BrandBloc>().add(
/// const BrandChangedEvent(BrandKey.catalyst),
/// );
/// ```
///
/// Usage example:
///
/// ```dart
/// BlocProvider(
/// create: (context) => BrandBloc(),
/// child: BlocBuilder<BrandBloc, BrandState>(
/// builder: (context, state) {
/// return MaterialApp(
/// home: Builder(
/// builder: (context) => Scaffold(
/// body: Row(
/// children: [
/// MaterialButton(
/// color: Theme.of(context).primaryColor,
/// onPressed: () {
/// context.read<BrandBloc>().add(
/// const BrandChangedEvent(BrandKey.catalyst),
/// );
/// },
/// child: const Text('Switch to Catalyst Theme'),
/// ),
/// ],
/// ),
/// ),
/// ),
/// theme: ThemeBuilder.buildTheme(state.brandKey),
/// );
/// },
/// ),
/// );
/// ```
final class BrandBloc extends Bloc<BrandEvent, BrandState> {
BrandBloc() : super(const BrandState()) {
on<BrandChangedEvent>(_onBrandChanged);
}

void _onBrandChanged(
BrandChangedEvent event,
Emitter<BrandState> emit,
) {
emit(BrandState(brandKey: event.brand));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
part of 'brand_bloc.dart';

sealed class BrandEvent extends Equatable {
const BrandEvent();

@override
List<Object> get props => [];
}

final class BrandChangedEvent extends BrandEvent {
final BrandKey brand;

const BrandChangedEvent(this.brand);

@override
List<Object> get props => [brand];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
part of 'brand_bloc.dart';

final class BrandState extends Equatable {
final BrandKey? brandKey;

const BrandState({BrandKey? brandKey})
: brandKey = brandKey ?? BrandKey.catalyst;

@override
List<Object> get props => [brandKey ?? ''];
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export 'authentication/authentication.dart';
export 'brand/brand.dart';
export 'login/login.dart';
5 changes: 5 additions & 0 deletions catalyst_voices/packages/catalyst_voices_blocs/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ environment:
dependencies:
bloc: ^8.1.2
bloc_concurrency: ^0.2.2
catalyst_voices_brands:
path: ../catalyst_voices_brands
catalyst_voices_models:
path: ../catalyst_voices_models
catalyst_voices_repositories:
Expand All @@ -30,4 +32,7 @@ dev_dependencies:
bloc_test: ^9.1.4
catalyst_analysis:
path: ../../../catalyst_voices_packages/catalyst_analysis
flutter_bloc: ^8.1.5
flutter_test:
sdk: flutter
test: ^1.24.9
44 changes: 44 additions & 0 deletions catalyst_voices/packages/catalyst_voices_brands/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# VSCode related
.vscode/*

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
pubspec.lock

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Test related
coverage
1 change: 1 addition & 0 deletions catalyst_voices/packages/catalyst_voices_brands/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Catalyst Voices Brands
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
include: package:catalyst_analysis/analysis_options.1.0.0.yaml

analyzer:
exclude: [
build/**,
lib/*.g.dart,
lib/generated/**
]

linter:
rules:
public_member_api_docs: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
library catalyst_voices_brands;

export 'src/catalyst_voices_brands.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// Simple Enum to store all possible Brands.
enum BrandKey {
catalyst,
fallback,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'brands/brands.dart';
export 'theme_builder/theme_builder.dart';
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:catalyst_voices_brands/src/brands/brands.dart';
import 'package:catalyst_voices_brands/src/themes/catalyst.dart';
import 'package:catalyst_voices_brands/src/themes/fallback.dart';
import 'package:flutter/material.dart';

/// A utility class to build themes dynamically based on brand keys.
///
/// [buildTheme] can be used to obtain the corresponding theme data for the
/// [BrandKey] passed to the method.
///
/// For each brand there is a specific key defined in the [BrandKey] enum
/// and a corresponding [ThemeData] in the `themes` folder.
///
/// [buildTheme] defaults to the [catalyst] theme.
class ThemeBuilder {
static ThemeData buildTheme(BrandKey? brandKey) {
switch (brandKey) {
case BrandKey.catalyst:
return catalyst;
case BrandKey.fallback:
return fallback;
case null:
return catalyst;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:catalyst_voices_assets/catalyst_voices_assets.dart';
import 'package:flutter/material.dart';

/// [ThemeData] for the `catalyst` brand.
final ThemeData catalyst = ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: VoicesColors.blue,
primary: VoicesColors.blue,
),
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import 'package:flutter/material.dart';

/// [ThemeData] for the `fallback` brand.
final ThemeData fallback = ThemeData(useMaterial3: true);
24 changes: 24 additions & 0 deletions catalyst_voices/packages/catalyst_voices_brands/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: catalyst_voices_brands
description: Catalyst Voices Brands.
version: 0.1.0+1
publish_to: none

environment:
sdk: ">=3.3.0 <4.0.0"
flutter: 3.19.5

dependencies:
catalyst_voices_assets:
path: ../catalyst_voices_assets
flutter:
sdk: flutter

dev_dependencies:
catalyst_analysis:
path: ../../../catalyst_voices_packages/catalyst_analysis
catalyst_voices_blocs:
path: ../catalyst_voices_blocs
flutter_bloc: ^8.1.5
flutter_test:
sdk: flutter
test: ^1.24.9
Loading

0 comments on commit bfec640

Please sign in to comment.