Skip to content

Commit 16b352b

Browse files
committed
feat: fetch word of the day
1 parent 6803745 commit 16b352b

22 files changed

+385
-29
lines changed

lib/app/view/app.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:qack/layout/device_info_setter.dart';
77
import 'package:qack/presentation/history/bloc/history_bloc.dart';
88
import 'package:qack/presentation/history/repositories/repositories.dart';
99
import 'package:qack/presentation/home/bloc/home_bloc.dart';
10+
import 'package:qack/presentation/home/cubit/word_of_the_day_cubit.dart';
1011
import 'package:qack/presentation/home/repositories/repositories.dart';
1112
import 'package:qack/presentation/landing/components/cubit/bottom_navigation_bar_cubit.dart';
1213
import 'package:qack/presentation/landing/view/landing_page.dart';
@@ -21,13 +22,15 @@ class App extends StatelessWidget {
2122
required this.secureStorage,
2223
required this.settingsBloc,
2324
required this.historyBloc,
25+
required this.wordOfTheDayCubit,
2426
required this.appDatabase,
2527
super.key,
2628
});
2729

2830
final FlutterSecureStorage secureStorage;
2931
final SettingsBloc settingsBloc;
3032
final HistoryBloc historyBloc;
33+
final WordOfTheDayCubit wordOfTheDayCubit;
3134
final AppDatabase appDatabase;
3235

3336
@override
@@ -47,15 +50,21 @@ class App extends StatelessWidget {
4750
child: _App(
4851
settingsBloc: settingsBloc,
4952
historyBloc: historyBloc,
53+
wordOfTheDayCubit: wordOfTheDayCubit,
5054
),
5155
);
5256
}
5357
}
5458

5559
class _App extends StatelessWidget {
56-
const _App({required this.settingsBloc, required this.historyBloc});
60+
const _App({
61+
required this.settingsBloc,
62+
required this.historyBloc,
63+
required this.wordOfTheDayCubit,
64+
});
5765
final SettingsBloc settingsBloc;
5866
final HistoryBloc historyBloc;
67+
final WordOfTheDayCubit wordOfTheDayCubit;
5968

6069
@override
6170
Widget build(BuildContext context) {
@@ -72,6 +81,7 @@ class _App extends StatelessWidget {
7281
BlocProvider(
7382
create: (context) => historyBloc,
7483
),
84+
BlocProvider(create: (context) => wordOfTheDayCubit),
7585
BlocProvider(create: (context) => BottomNavigationBarCubit()),
7686
],
7787
child: const AppView(),

lib/bootstrap.dart

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import 'package:http_client/http_client.dart';
99
import 'package:qack/constants/key_name.dart';
1010
import 'package:qack/presentation/history/bloc/history_bloc.dart';
1111
import 'package:qack/presentation/history/repositories/repositories.dart';
12+
import 'package:qack/presentation/home/cubit/word_of_the_day_cubit.dart';
13+
import 'package:qack/presentation/home/repositories/repositories.dart';
1214
import 'package:qack/presentation/settings/bloc/settings_bloc.dart';
1315
import 'package:qack/presentation/settings/respository/settings_repository.dart';
1416
import 'package:qack/utils/database/database.dart';
@@ -41,6 +43,7 @@ Future<void> bootstrap(
4143
FlutterSecureStorage secureStorage,
4244
SettingsBloc settingsBloc,
4345
HistoryBloc historyBloc,
46+
WordOfTheDayCubit wordOfTheDayCubit,
4447
AppDatabase appDatabase,
4548
) builder,
4649
) async {
@@ -53,6 +56,9 @@ Future<void> bootstrap(
5356
log(details.exceptionAsString(), stackTrace: details.stack);
5457
};
5558

59+
// Initialize HTTP repository
60+
GetIt.instance.registerLazySingleton<Http>(Http.new);
61+
5662
// Initialize local storage repository
5763
final appDatabase = AppDatabase();
5864

@@ -82,21 +88,38 @@ Future<void> bootstrap(
8288

8389
// Initialize settings bloc
8490
final settingsRepository = SettingsRepository(storage: secureStorage);
91+
92+
final translatorSettings = await settingsRepository.getAPIKey();
93+
8594
final settingsBloc = SettingsBloc(
8695
settingsRepository: settingsRepository,
8796
)..add(
88-
SettingsFetch(await settingsRepository.getAPIKey()),
97+
SettingsFetch(translatorSettings),
8998
);
9099

91100
// Initialize history bloc
92101
final historyBloc = HistoryBloc(
93102
HistoryRepository(appDatabase: appDatabase),
94103
)..add(const HistoryFetched());
95104

96-
// Initialize HTTP repository
97-
GetIt.instance.registerLazySingleton<Http>(Http.new);
105+
// Initialize word of the day cubit
106+
final wordOfTheDayCubit = WordOfTheDayCubit(
107+
const WordOfTheDayRepository(),
108+
deepSeekApiKey: translatorSettings.apiKeys[KeyNameConstants.deepSeek],
109+
// ignore: unawaited_futures
110+
);
111+
112+
await wordOfTheDayCubit.fetchWordOfTheDay();
98113

99114
Bloc.observer = const AppBlocObserver();
100115

101-
runApp(await builder(secureStorage, settingsBloc, historyBloc, appDatabase));
116+
runApp(
117+
await builder(
118+
secureStorage,
119+
settingsBloc,
120+
historyBloc,
121+
wordOfTheDayCubit,
122+
appDatabase,
123+
),
124+
);
102125
}

lib/main_development.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:qack/app/view/app.dart';
44
import 'package:qack/bootstrap.dart';
55
import 'package:qack/constants/key_name.dart';
66
import 'package:qack/presentation/history/bloc/history_bloc.dart';
7+
import 'package:qack/presentation/home/cubit/word_of_the_day_cubit.dart';
78
import 'package:qack/presentation/settings/bloc/settings_bloc.dart';
89
import 'package:qack/utils/database/database.dart';
910
import 'package:sentry_flutter/sentry_flutter.dart';
@@ -35,12 +36,14 @@ Future<void> main() async {
3536
FlutterSecureStorage secureStorage,
3637
SettingsBloc settingsBloc,
3738
HistoryBloc historyBloc,
39+
WordOfTheDayCubit wordOfTheDayCubit,
3840
AppDatabase appDatabase,
3941
) async {
4042
return App(
4143
secureStorage: secureStorage,
4244
settingsBloc: settingsBloc,
4345
historyBloc: historyBloc,
46+
wordOfTheDayCubit: wordOfTheDayCubit,
4447
appDatabase: appDatabase,
4548
);
4649
});

lib/main_production.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:qack/app/view/app.dart';
44
import 'package:qack/bootstrap.dart';
55
import 'package:qack/constants/constants.dart';
66
import 'package:qack/presentation/history/bloc/history_bloc.dart';
7+
import 'package:qack/presentation/home/cubit/word_of_the_day_cubit.dart';
78
import 'package:qack/presentation/settings/bloc/settings_bloc.dart';
89
import 'package:qack/utils/database/database.dart';
910
import 'package:sentry_flutter/sentry_flutter.dart';
@@ -34,12 +35,14 @@ Future<void> main() async {
3435
FlutterSecureStorage secureStorage,
3536
SettingsBloc settingsBloc,
3637
HistoryBloc historyBloc,
38+
WordOfTheDayCubit wordOfTheDayCubit,
3739
AppDatabase appDatabase,
3840
) async {
3941
return App(
4042
secureStorage: secureStorage,
4143
settingsBloc: settingsBloc,
4244
historyBloc: historyBloc,
45+
wordOfTheDayCubit: wordOfTheDayCubit,
4346
appDatabase: appDatabase,
4447
);
4548
});

lib/main_staging.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:qack/app/view/app.dart';
44
import 'package:qack/bootstrap.dart';
55
import 'package:qack/constants/constants.dart';
66
import 'package:qack/presentation/history/bloc/history_bloc.dart';
7+
import 'package:qack/presentation/home/cubit/word_of_the_day_cubit.dart';
78
import 'package:qack/presentation/settings/bloc/settings_bloc.dart';
89
import 'package:qack/utils/database/database.dart';
910
import 'package:sentry_flutter/sentry_flutter.dart';
@@ -34,12 +35,14 @@ Future<void> main() async {
3435
FlutterSecureStorage secureStorage,
3536
SettingsBloc settingsBloc,
3637
HistoryBloc historyBloc,
38+
WordOfTheDayCubit wordOfTheDayCubit,
3739
AppDatabase appDatabase,
3840
) async {
3941
return App(
4042
secureStorage: secureStorage,
4143
settingsBloc: settingsBloc,
4244
historyBloc: historyBloc,
45+
wordOfTheDayCubit: wordOfTheDayCubit,
4346
appDatabase: appDatabase,
4447
);
4548
});

lib/presentation/home/bloc/home_bloc.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
6464
// translator enabled
6565
if (settingsBloc.state.translatorSettings == null ||
6666
settingsBloc.state.translatorSettings!.enabledTranslators.isEmpty) {
67-
emit(state.error(const NoTranslatorEnabledException()));
67+
emit(state.failure(const NoTranslatorEnabledException()));
6868
return;
6969
}
7070

@@ -87,12 +87,12 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
8787
},
8888
onError: (e, stackTrace) {
8989
debugPrint('error: $e');
90-
return state.error(Exception(e));
90+
return state.failure(Exception(e));
9191
},
9292
);
9393
} on Exception catch (e) {
9494
debugPrint(e.toString());
95-
emit(state.error(e));
95+
emit(state.failure(e));
9696
}
9797
}
9898
}

lib/presentation/home/bloc/home_state.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ final class HomeState extends Equatable {
4141
/// This error is a general error in [HomeRepository]'s translateText method.
4242
/// It is not a translation error.
4343
/// See [BaseTranslationError] for translation errors.
44-
HomeState error(Exception e) => HomeState._(
44+
HomeState failure(Exception e) => HomeState._(
4545
translationDetails: translationDetails,
4646
status: HomeStatus.error,
4747
exception: e,

lib/presentation/home/components/translation_card.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class TranslationCardView extends StatelessWidget {
128128
translationText = 'Loading...';
129129
} else if (translationDetails.status == TranslationStatus.success) {
130130
translationText = translationDetails.translatedText!.outputText;
131-
} else if (translationDetails.status == TranslationStatus.error ||
131+
} else if (translationDetails.status == TranslationStatus.failure ||
132132
translationDetails.exception != null) {
133133
translationText =
134134
'Translation error: ${translationDetails.exception}';
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import 'package:bloc/bloc.dart';
2+
import 'package:equatable/equatable.dart';
3+
import 'package:freezed_annotation/freezed_annotation.dart';
4+
import 'package:qack/presentation/home/models/models.dart';
5+
import 'package:qack/presentation/home/repositories/repositories.dart';
6+
7+
part 'word_of_the_day_state.dart';
8+
9+
class WordOfTheDayCubit extends Cubit<WordOfTheDayState> {
10+
WordOfTheDayCubit(this.wordOfTheDayRepository, {required this.deepSeekApiKey})
11+
: super(const WordOfTheDayInitial());
12+
final WordOfTheDayRepository wordOfTheDayRepository;
13+
final String? deepSeekApiKey;
14+
15+
Future<void> fetchWordOfTheDay() async {
16+
try {
17+
if (deepSeekApiKey != null && deepSeekApiKey!.isNotEmpty) {
18+
final wordOfTheDay =
19+
await wordOfTheDayRepository.fetchWordOfTheDay(deepSeekApiKey!);
20+
21+
emit(WordOfTheDaySuccess(wordOfTheDay));
22+
}
23+
} on Exception catch (e) {
24+
emit(WordOfTheDayFailure(e));
25+
}
26+
}
27+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
part of 'word_of_the_day_cubit.dart';
2+
3+
@immutable
4+
sealed class WordOfTheDayState extends Equatable {
5+
const WordOfTheDayState(
6+
this.wordOfTheDay, {
7+
this.exception,
8+
});
9+
10+
final WordOfTheDay? wordOfTheDay;
11+
final Exception? exception;
12+
13+
@override
14+
List<Object?> get props => [wordOfTheDay, exception];
15+
}
16+
17+
final class WordOfTheDayInitial extends WordOfTheDayState {
18+
const WordOfTheDayInitial() : super(null);
19+
}
20+
21+
final class WordOfTheDayLoading extends WordOfTheDayState {
22+
const WordOfTheDayLoading() : super(null);
23+
}
24+
25+
final class WordOfTheDaySuccess extends WordOfTheDayState {
26+
const WordOfTheDaySuccess(super.wordOfTheDay);
27+
28+
WordOfTheDaySuccess copyWith({WordOfTheDay? wordOfTheDay}) {
29+
return WordOfTheDaySuccess(
30+
wordOfTheDay ?? this.wordOfTheDay!,
31+
);
32+
}
33+
}
34+
35+
final class WordOfTheDayFailure extends WordOfTheDayState {
36+
const WordOfTheDayFailure(Exception e) : super(null, exception: e);
37+
}

0 commit comments

Comments
 (0)