Skip to content

Commit

Permalink
Added freezed & Refactored (#275)
Browse files Browse the repository at this point in the history
* Added freezed

- Refactored locale
- Added build.yaml

* Updated theme bloc

* Update action
  • Loading branch information
hawkkiller authored Nov 5, 2023
1 parent c133745 commit d50e244
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 271 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/code-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ jobs:
flutter pub global activate intl_utils
flutter pub global activate coverage
melos bootstrap
- name: 🦄 Generate Code
run: |
flutter pub global run intl_utils:generate
dart run build_runner build --delete-conflicting-outputs
- name: Install DCM
uses: CQLabs/setup-dcm@v1
Expand Down
9 changes: 9 additions & 0 deletions build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
targets:
$default:
builders:
freezed:
options:
when:
when: false
maybe_when: false
when_or_null: false
13 changes: 4 additions & 9 deletions lib/src/core/utils/extensions/context_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,17 @@ extension ContextExtension on BuildContext {
/// when that widget changes (or a new widget of that type is introduced,
/// or the widget goes away), this build context is rebuilt so that it can
/// obtain new values from that widget.
T? inhMaybeOf<T extends InheritedWidget>({
bool listen = true,
}) =>
listen
? dependOnInheritedWidgetOfExactType<T>()
: getInheritedWidgetOfExactType<T>();
T? inhMaybeOf<T extends InheritedWidget>({bool listen = true}) => listen
? dependOnInheritedWidgetOfExactType<T>()
: getInheritedWidgetOfExactType<T>();

/// Obtain the nearest widget of the given type T,
/// which must be the type of a concrete [InheritedWidget] subclass,
/// and register this build context with that widget such that
/// when that widget changes (or a new widget of that type is introduced,
/// or the widget goes away), this build context is rebuilt so that it can
/// obtain new values from that widget.
T inhOf<T extends InheritedWidget>({
bool listen = true,
}) =>
T inhOf<T extends InheritedWidget>({bool listen = true}) =>
inhMaybeOf<T>(listen: listen) ??
(throw ArgumentError(
'Out of scope, not found inherited widget '
Expand Down
153 changes: 16 additions & 137 deletions lib/src/feature/app/logic/locale_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,150 +1,29 @@
import 'dart:ui';

import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:sizzle_starter/src/core/utils/logger.dart';
import 'package:sizzle_starter/src/core/utils/pattern_match.dart';
import 'package:sizzle_starter/src/feature/app/data/locale_repository.dart';

/// {@template locale_state}
/// Locale state
/// {@endtemplate}
@immutable
sealed class LocaleState extends _LocaleStateBase {
/// {@macro locale_state}
const LocaleState();
part 'locale_bloc.freezed.dart';

/// The state machine is idling (i.e. doing nothing)
const factory LocaleState.idle({required Locale locale}) = _LocaleStateIdle;

/// The state machine is in progress (i.e. doing something)
const factory LocaleState.inProgress({required Locale locale}) =
_LocaleStateInProgress;
}

/// {@macro locale_state}
///
/// This state is used when the
/// state machine is idling (i.e. doing nothing)
final class _LocaleStateIdle extends LocaleState {
const _LocaleStateIdle({required this.locale});

@override
final Locale locale;

@override
String toString() => 'LocaleState.idle(locale: $locale)';

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is _LocaleStateIdle && locale == other.locale);

@override
int get hashCode => locale.hashCode;
/// Locale event for [LocaleBloc]
@freezed
sealed class LocaleEvent with _$LocaleEvent {
/// Updates the locale with the given [locale].
const factory LocaleEvent.update({required Locale locale}) =
_LocaleEventUpdate;
}

/// {@macro locale_state}
///
/// This state is used when the
/// state machine is in progress (i.e. doing something)
final class _LocaleStateInProgress extends LocaleState {
const _LocaleStateInProgress({required this.locale});

@override
final Locale locale;

@override
String toString() => 'LocaleState.inProgress()';

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is _LocaleStateInProgress && locale == other.locale);

@override
int get hashCode => locale.hashCode;
}

abstract base class _LocaleStateBase {
const _LocaleStateBase();

/// The current locale in state
Locale get locale;

T map<T>({
required PatternMatch<T, _LocaleStateIdle> idle,
required PatternMatch<T, _LocaleStateInProgress> inProgress,
}) =>
switch (this) {
final _LocaleStateIdle state => idle(state),
final _LocaleStateInProgress state => inProgress(state),
_ => throw AssertionError('Unknown state: $this'),
};
/// Locale state for [LocaleBloc]
@freezed
sealed class LocaleState with _$LocaleState {
/// Initial state of the locale bloc.
const factory LocaleState.idle({Locale? locale}) = _LocaleStateIdle;

T maybeMap<T>({
required PatternMatch<T, _LocaleStateIdle>? idle,
required PatternMatch<T, _LocaleStateInProgress>? inProgress,
required T orElse,
}) =>
map(
idle: idle ?? (_) => orElse,
inProgress: inProgress ?? (_) => orElse,
);
}

/// Sealed class representing events that can be sent to the [LocaleBloc].
///
/// Extends [_LocaleEventBase] to provide a common base class for all events.
///
/// Provides a single event, [LocaleEvent.update], which is used to update the
/// app's locale with the given [Locale].
@immutable
sealed class LocaleEvent extends _LocaleEventBase {
/// Creates a new [LocaleEvent].
///
/// Provides a common base class for all events that can be sent to the
/// [LocaleBloc].
const LocaleEvent();

/// Updates the app's locale with the given [Locale].
const factory LocaleEvent.update(Locale locale) = _LocaleEventUpdate;
}

/// This event is used when the
/// locale is updated
final class _LocaleEventUpdate extends LocaleEvent {
const _LocaleEventUpdate(this.locale);

/// The new locale
final Locale locale;

@override
String toString() => 'LocaleEvent.update(locale: $locale)';

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is _LocaleEventUpdate && locale == other.locale);

@override
int get hashCode => locale.hashCode;
}

abstract base class _LocaleEventBase {
const _LocaleEventBase();

T map<T>({required PatternMatch<T, _LocaleEventUpdate> update}) =>
switch (this) {
final _LocaleEventUpdate event => update(event),
_ => throw AssertionError('Unknown event: $this'),
};

T maybeMap<T>({
required PatternMatch<T, _LocaleEventUpdate>? update,
required T orElse,
}) =>
map(update: update ?? (_) => orElse);
/// State when the locale is being updated.
const factory LocaleState.inProgress({required Locale locale}) =
_LocaleStateInProgress;
}

/// Business Logic Component (BLoC) for managing the app's locale.
Expand Down
121 changes: 7 additions & 114 deletions lib/src/feature/app/logic/theme_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,140 +1,33 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:meta/meta.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:sizzle_starter/src/core/utils/logger.dart';
import 'package:sizzle_starter/src/core/utils/pattern_match.dart';
import 'package:sizzle_starter/src/feature/app/data/theme_repository.dart';
import 'package:sizzle_starter/src/feature/app/model/app_theme.dart';
import 'package:sizzle_starter/src/feature/app/widget/theme_scope.dart';

part 'theme_bloc.freezed.dart';

/// {@template theme_event}
/// Theme event
/// {@endtemplate}
@immutable
sealed class ThemeEvent with _ThemeEvent {
/// {@macro theme_event}
const ThemeEvent();

@freezed
sealed class ThemeEvent with _$ThemeEvent {
/// Update the theme
const factory ThemeEvent.update(AppTheme theme) = _ThemeEventUpdate;
}

final class _ThemeEventUpdate extends ThemeEvent {
final AppTheme theme;

const _ThemeEventUpdate(this.theme);

@override
String toString() => 'ThemeEvent.update(theme: $theme)';

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is _ThemeEventUpdate &&
runtimeType == other.runtimeType &&
theme == other.theme);

@override
int get hashCode => theme.hashCode;
}

abstract base mixin class _ThemeEvent {
const _ThemeEvent();

T map<T>({required PatternMatch<T, _ThemeEventUpdate> update}) =>
switch (this) {
final _ThemeEventUpdate event => update(event),
_ => throw AssertionError('Unknown event: $this'),
};

T maybeMap<T>({
required PatternMatch<T, _ThemeEventUpdate>? update,
required T orElse,
}) =>
map(update: update ?? (_) => orElse);
}

/// {@template theme_state}
/// Theme state
/// {@endtemplate}
@immutable
sealed class ThemeState with _ThemeState {
/// {@macro theme_state}
const ThemeState();

@freezed
sealed class ThemeState with _$ThemeState {
/// Idle state
const factory ThemeState.idle(AppTheme theme) = _ThemeStateIdle;

/// In Progress state
const factory ThemeState.inProgress(AppTheme theme) = _ThemeStateInProgress;
}

final class _ThemeStateIdle extends ThemeState {
@override
final AppTheme theme;

const _ThemeStateIdle(this.theme);

@override
String toString() => 'ThemeState.idle(theme: $theme)';

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is _ThemeStateIdle &&
runtimeType == other.runtimeType &&
theme == other.theme);

@override
int get hashCode => theme.hashCode;
}

final class _ThemeStateInProgress extends ThemeState {
@override
final AppTheme theme;

const _ThemeStateInProgress(this.theme);

@override
String toString() => 'ThemeState.inProgress(theme: $theme)';

@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is _ThemeStateInProgress &&
runtimeType == other.runtimeType &&
theme == other.theme);

@override
int get hashCode => theme.hashCode;
}

abstract base mixin class _ThemeState {
const _ThemeState();

/// Current theme
AppTheme get theme;

T map<T>({
required PatternMatch<T, _ThemeStateIdle> idle,
required PatternMatch<T, _ThemeStateInProgress> inProgress,
}) =>
switch (this) {
final _ThemeStateIdle state => idle(state),
final _ThemeStateInProgress state => inProgress(state),
_ => throw AssertionError('Unknown state: $this'),
};

T maybeMap<T>({
required PatternMatch<T, _ThemeStateIdle>? idle,
required PatternMatch<T, _ThemeStateInProgress>? inProgress,
required T orElse,
}) =>
map(
idle: idle ?? (_) => orElse,
inProgress: inProgress ?? (_) => orElse,
);
}

/// {@template theme_bloc}
/// Business logic components that can switch themes.
///
Expand Down
Loading

0 comments on commit d50e244

Please sign in to comment.