Skip to content

Commit

Permalink
Freezed
Browse files Browse the repository at this point in the history
  • Loading branch information
Carapacik committed Nov 15, 2023
1 parent dc11b96 commit a5a5c82
Show file tree
Hide file tree
Showing 6 changed files with 958 additions and 295 deletions.
181 changes: 19 additions & 162 deletions lib/src/feature/app/logic/dictionary_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,158 +1,27 @@
import 'dart:ui';

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

/// {@template dictionary_state}
/// Dictionary state
/// {@endtemplate}
@immutable
sealed class DictionaryState extends _DictionaryStateBase {
/// {@macro dictionary_state}
const DictionaryState();
part 'dictionary_bloc.freezed.dart';

/// The state machine is idling (i.e. doing nothing)
const factory DictionaryState.idle({
required Locale dictionary,
}) = _DictionaryStateIdle;

/// The state machine is in progress (i.e. doing something)
const factory DictionaryState.inProgress({
required Locale dictionary,
}) = _DictionaryStateInProgress;
/// Locale event for [DictionaryBloc]
@Freezed()
sealed class DictionaryEvent with _$DictionaryEvent {
/// Updates the dictionary with the given [dictionary].
const factory DictionaryEvent.update({required Locale dictionary}) = _DictionaryEventUpdate;
}

/// {@macro dictionary_state}
///
/// This state is used when the
/// state machine is idling (i.e. doing nothing)
final class _DictionaryStateIdle extends DictionaryState {
const _DictionaryStateIdle({
required this.dictionary,
});

@override
final Locale dictionary;

@override
String toString() => 'DictionaryState.idle(dictionary: $dictionary)';

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

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

/// {@macro dictionary_state}
///
/// This state is used when the
/// state machine is in progress (i.e. doing something)
final class _DictionaryStateInProgress extends DictionaryState {
const _DictionaryStateInProgress({
required this.dictionary,
});

@override
final Locale dictionary;

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

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

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

abstract base class _DictionaryStateBase {
const _DictionaryStateBase();

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

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

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

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

/// Updates the app's dictionary with the given Dictionary.
const factory DictionaryEvent.update(Locale dictionary) = _DictionaryEventUpdate;
}

/// This event is used when the
/// dictionary is updated
final class _DictionaryEventUpdate extends DictionaryEvent {
const _DictionaryEventUpdate(this.dictionary);

/// The new dictionary
final Locale dictionary;

@override
String toString() => 'DictionaryEvent.update(dictionary: $dictionary)';

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

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

abstract base class _DictionaryEventBase {
const _DictionaryEventBase();

T map<T>({
required PatternMatch<T, _DictionaryEventUpdate> update,
}) =>
switch (this) {
final _DictionaryEventUpdate event => update(event),
_ => throw AssertionError('Unknown event: $this'),
};
/// Dictionary state for [DictionaryBloc]
@Freezed()
sealed class DictionaryState with _$DictionaryState {
/// Initial state of the dictionary bloc.
const factory DictionaryState.idle({required Locale dictionary}) = _DictionaryStateIdle;

T maybeMap<T>({
required PatternMatch<T, _DictionaryEventUpdate>? update,
required T orElse,
}) =>
map(
update: update ?? (_) => orElse,
);
/// State when the dictionary is being updated.
const factory DictionaryState.inProgress({required Locale dictionary}) = _DictionaryStateInProgress;
}

/// Business Logic Component (BLoC) for managing the app's dictionary.
Expand All @@ -168,19 +37,10 @@ class DictionaryBloc extends Bloc<DictionaryEvent, DictionaryState> {
///
/// Responds to [DictionaryEvent.update] events by calling [_update] to update the
/// dictionary state.
DictionaryBloc({
required DictionaryRepository dictionaryRepository,
}) : _dictionaryRepository = dictionaryRepository,
super(
DictionaryState.idle(
dictionary: dictionaryRepository.loadDictionaryFromCache() ?? const Locale('en'),
),
) {
on<DictionaryEvent>(
(event, emit) async => event.map(
update: (e) => _update(e, emit),
),
);
DictionaryBloc({required DictionaryRepository dictionaryRepository})
: _dictionaryRepository = dictionaryRepository,
super(DictionaryState.idle(dictionary: dictionaryRepository.loadDictionaryFromCache() ?? const Locale('en'))) {
on<DictionaryEvent>((event, emit) async => event.map(update: (e) => _update(e, emit)));
}

final DictionaryRepository _dictionaryRepository;
Expand All @@ -195,10 +55,7 @@ class DictionaryBloc extends Bloc<DictionaryEvent, DictionaryState> {
/// error and emits a [DictionaryState.idle] state with default dictionary of 'en'.
///
/// Throws any error that occurs during the update.
Future<void> _update(
_DictionaryEventUpdate event,
Emitter<DictionaryState> emit,
) async {
Future<void> _update(_DictionaryEventUpdate event, Emitter<DictionaryState> emit) async {
try {
emit(const DictionaryState.inProgress(dictionary: Locale('en')));
await _dictionaryRepository.setDictionary(event.dictionary);
Expand Down
Loading

0 comments on commit a5a5c82

Please sign in to comment.