916 lines
25 KiB
Dart
916 lines
25 KiB
Dart
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
|
|
import 'package:calibre_web_companion/core/services/widget_service.dart';
|
|
import 'package:calibre_web_companion/features/settings/bloc/settings_event.dart';
|
|
import 'package:calibre_web_companion/features/settings/bloc/settings_state.dart';
|
|
|
|
import 'package:calibre_web_companion/features/settings/data/models/book_details_action.dart';
|
|
import 'package:calibre_web_companion/features/settings/data/models/book_details_section.dart';
|
|
import 'package:calibre_web_companion/features/settings/data/models/discover_layout_config.dart';
|
|
import 'package:calibre_web_companion/features/settings/data/repositories/settings_repository.dart';
|
|
|
|
class SettingsBloc extends Bloc<SettingsEvent, SettingsState> {
|
|
final SettingsRepository repository;
|
|
final WidgetService widgetService;
|
|
|
|
SettingsBloc({required this.repository, required this.widgetService})
|
|
: super(const SettingsState()) {
|
|
on<LoadSettings>(_onLoadSettings);
|
|
on<SetThemeMode>(_onSetThemeMode);
|
|
on<SetThemeSource>(_onSetThemeSource);
|
|
on<SetSelectedColor>(_onSetSelectedColor);
|
|
on<SetDownloadFolder>(_onSetDownloadFolder);
|
|
on<SetDownloadSchema>(_onSetDownloadSchema);
|
|
on<SetCostumSend2EreaderEnabled>(_onSetSend2EreaderEnabled);
|
|
on<SetCostumSend2EreaderUrl>(_onSetSend2EreaderUrl);
|
|
on<SetDownloaderEnabled>(_onSetDownloaderEnabled);
|
|
on<SetDownloaderUrl>(_onSetDownloaderUrl);
|
|
on<SetDownloaderCredentials>(_onSetDownloaderCredentials);
|
|
on<SubmitFeedback>(_onSubmitFeedback);
|
|
on<SetLanguage>(_onSetLanguage);
|
|
on<SetShowReadNowButton>(_onSetShowReadNowButton);
|
|
on<SetStoreReadNowAndSendToEReaderOnDevice>(
|
|
_onSetStoreReadNowAndSendToEReaderOnDevice,
|
|
);
|
|
on<BuyMeACoffee>(_onBuyMeACoffee);
|
|
on<SetWebDavSyncEnabled>(_onSetWebDavSyncEnabled);
|
|
on<SetWebDavUrl>(_onSetWebDavUrl);
|
|
on<SetWebDavCredentials>(_onSetWebDavCredentials);
|
|
on<TestDownloaderConnection>(_onTestDownloaderConnection);
|
|
on<TestWebDavConnection>(_onTestWebDavConnection);
|
|
on<ResetConnectionTestStatus>(_onResetConnectionTestStatus);
|
|
on<SetShowSendToEReaderButton>(_onSetShowSendToEReaderButton);
|
|
on<SetEInkMode>(_onSetEInkMode);
|
|
on<SetTextScale>(_onSetTextScale);
|
|
on<SetBookActionsOrder>(_onSetBookActionsOrder);
|
|
on<SetBookActionEnabled>(_onSetBookActionEnabled);
|
|
on<ResetBookActionsCustomization>(_onResetBookActionsCustomization);
|
|
on<SetBookDetailsSectionsOrder>(_onSetBookDetailsSectionsOrder);
|
|
on<SetBookDetailsSectionEnabled>(_onSetBookDetailsSectionEnabled);
|
|
on<ResetBookDetailsSectionsCustomization>(
|
|
_onResetBookDetailsSectionsCustomization,
|
|
);
|
|
on<SetDiscoverMainSectionsOrder>(_onSetDiscoverMainSectionsOrder);
|
|
on<SetDiscoverMainSectionEnabled>(_onSetDiscoverMainSectionEnabled);
|
|
on<SetDiscoverItemsOrder>(_onSetDiscoverItemsOrder);
|
|
on<SetDiscoverItemEnabled>(_onSetDiscoverItemEnabled);
|
|
on<SetCategoryItemsOrder>(_onSetCategoryItemsOrder);
|
|
on<SetCategoryItemEnabled>(_onSetCategoryItemEnabled);
|
|
on<ResetDiscoverCustomization>(_onResetDiscoverCustomization);
|
|
}
|
|
|
|
Future<void> _onLoadSettings(
|
|
LoadSettings event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
emit(state.copyWith(status: SettingsStatus.loading));
|
|
|
|
try {
|
|
final settings = await repository.getSettings();
|
|
final packageInfo = await PackageInfo.fromPlatform();
|
|
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.loaded,
|
|
themeMode: settings.themeMode,
|
|
themeSource: settings.themeSource,
|
|
selectedColorKey: settings.selectedColorKey,
|
|
isDownloaderEnabled: settings.isDownloaderEnabled,
|
|
downloaderUrl: settings.downloaderUrl,
|
|
downloaderUsername: settings.downloaderUsername,
|
|
downloaderPassword: settings.downloaderPassword,
|
|
isSend2ereaderEnabled: settings.isSend2ereaderEnabled,
|
|
send2ereaderUrl: settings.send2ereaderUrl,
|
|
defaultDownloadPath: settings.defaultDownloadPath,
|
|
downloadSchema: settings.downloadSchema,
|
|
showReadNowButton: settings.showReadNowButton,
|
|
showSendToEReaderButton: settings.showSendToEReaderButton,
|
|
appVersion: packageInfo.version,
|
|
buildNumber: packageInfo.buildNumber,
|
|
languageCode: settings.languageCode,
|
|
storeReadNowAndSendToEReaderOnDevice:
|
|
settings.storeReadNowAndSendToEReaderOnDevice,
|
|
webDavUrl: settings.webDavUrl,
|
|
webDavUsername: settings.webDavUsername,
|
|
webDavPassword: settings.webDavPassword,
|
|
isWebDavSyncEnabled: settings.isWebDavSyncEnabled,
|
|
isEInkMode: settings.isEInkMode,
|
|
textScale: settings.textScale,
|
|
bookActionsOrder: settings.bookActionsOrder,
|
|
enabledBookActions: settings.enabledBookActions,
|
|
bookDetailsSectionsOrder: settings.bookDetailsSectionsOrder,
|
|
enabledBookDetailsSections: settings.enabledBookDetailsSections,
|
|
discoverMainSectionsOrder: settings.discoverMainSectionsOrder,
|
|
enabledDiscoverMainSections: settings.enabledDiscoverMainSections,
|
|
discoverItemsOrder: settings.discoverItemsOrder,
|
|
enabledDiscoverItems: settings.enabledDiscoverItems,
|
|
categoryItemsOrder: settings.categoryItemsOrder,
|
|
enabledCategoryItems: settings.enabledCategoryItems,
|
|
),
|
|
);
|
|
|
|
// Keep the home-screen widgets themed to match the app.
|
|
await widgetService.pushThemeColors();
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetThemeMode(
|
|
SetThemeMode event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setThemeMode(event.themeMode);
|
|
emit(state.copyWith(themeMode: event.themeMode));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetThemeSource(
|
|
SetThemeSource event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setThemeSource(event.themeSource);
|
|
emit(state.copyWith(themeSource: event.themeSource));
|
|
await widgetService.pushThemeColors();
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetSelectedColor(
|
|
SetSelectedColor event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setSelectedColor(event.colorKey);
|
|
emit(state.copyWith(selectedColorKey: event.colorKey));
|
|
await widgetService.pushThemeColors();
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDownloadFolder(
|
|
SetDownloadFolder event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setDefaultDownloadPath(event.downloadFolder);
|
|
emit(state.copyWith(defaultDownloadPath: event.downloadFolder));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDownloadSchema(
|
|
SetDownloadSchema event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setDownloadSchema(event.downloadSchema);
|
|
emit(state.copyWith(downloadSchema: event.downloadSchema));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetSend2EreaderEnabled(
|
|
SetCostumSend2EreaderEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setSend2ereaderEnabled(event.enabled);
|
|
emit(state.copyWith(isSend2ereaderEnabled: event.enabled));
|
|
if (!event.enabled) {
|
|
await repository.setSend2ereaderUrl('https://send.djazz.se');
|
|
emit(state.copyWith(send2ereaderUrl: 'https://send.djazz.se'));
|
|
}
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetSend2EreaderUrl(
|
|
SetCostumSend2EreaderUrl event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setSend2ereaderUrl(event.url);
|
|
emit(state.copyWith(send2ereaderUrl: event.url));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDownloaderEnabled(
|
|
SetDownloaderEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setDownloaderEnabled(event.enabled);
|
|
emit(state.copyWith(isDownloaderEnabled: event.enabled));
|
|
await widgetService.pushQuickActions();
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDownloaderUrl(
|
|
SetDownloaderUrl event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setDownloaderUrl(event.url);
|
|
emit(state.copyWith(downloaderUrl: event.url));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDownloaderCredentials(
|
|
SetDownloaderCredentials event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setDownloaderCredentials(event.username, event.password);
|
|
emit(
|
|
state.copyWith(
|
|
downloaderUsername: event.username,
|
|
downloaderPassword: event.password,
|
|
),
|
|
);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSubmitFeedback(
|
|
SubmitFeedback event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
emit(state.copyWith(feedbackStatus: SettingsFeedbackStatus.loading));
|
|
|
|
try {
|
|
await repository.submitFeedback(
|
|
event.title ?? '',
|
|
event.description ?? '',
|
|
);
|
|
emit(state.copyWith(status: SettingsStatus.loaded));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
feedbackStatus: SettingsFeedbackStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetLanguage(
|
|
SetLanguage event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setLanguage(event.languageCode);
|
|
emit(state.copyWith(languageCode: event.languageCode));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetShowReadNowButton(
|
|
SetShowReadNowButton event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setShowReadNowButton(event.enabled);
|
|
emit(state.copyWith(showReadNowButton: event.enabled));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetStoreReadNowAndSendToEReaderOnDevice(
|
|
SetStoreReadNowAndSendToEReaderOnDevice event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setStoreReadNowAndSendToEReaderOnDevice(event.enabled);
|
|
emit(state.copyWith(storeReadNowAndSendToEReaderOnDevice: event.enabled));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onBuyMeACoffee(
|
|
BuyMeACoffee event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.buyMeACoffee();
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetWebDavSyncEnabled(
|
|
SetWebDavSyncEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setWebDavSyncEnabled(event.enabled);
|
|
|
|
emit(state.copyWith(isWebDavSyncEnabled: event.enabled));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetWebDavUrl(
|
|
SetWebDavUrl event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setWebDavUrl(event.url);
|
|
|
|
emit(state.copyWith(webDavUrl: event.url));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetWebDavCredentials(
|
|
SetWebDavCredentials event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setWebDavCredentials(event.username, event.password);
|
|
|
|
emit(
|
|
state.copyWith(
|
|
webDavUsername: event.username,
|
|
webDavPassword: event.password,
|
|
),
|
|
);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onTestDownloaderConnection(
|
|
TestDownloaderConnection event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
emit(state.copyWith(downloaderTestStatus: ConnectionTestStatus.loading));
|
|
try {
|
|
final success = await repository.testDownloaderConnection(
|
|
event.url,
|
|
event.username,
|
|
event.password,
|
|
);
|
|
|
|
if (success) {
|
|
emit(
|
|
state.copyWith(downloaderTestStatus: ConnectionTestStatus.success),
|
|
);
|
|
} else {
|
|
emit(
|
|
state.copyWith(
|
|
downloaderTestStatus: ConnectionTestStatus.error,
|
|
testErrorMessage: "Login failed (Invalid credentials or URL)",
|
|
),
|
|
);
|
|
}
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
downloaderTestStatus: ConnectionTestStatus.error,
|
|
testErrorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onTestWebDavConnection(
|
|
TestWebDavConnection event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
emit(state.copyWith(webDavTestStatus: ConnectionTestStatus.loading));
|
|
try {
|
|
await repository.testWebDavConnection(
|
|
event.url,
|
|
event.username,
|
|
event.password,
|
|
);
|
|
emit(state.copyWith(webDavTestStatus: ConnectionTestStatus.success));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
webDavTestStatus: ConnectionTestStatus.error,
|
|
testErrorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
void _onResetConnectionTestStatus(
|
|
ResetConnectionTestStatus event,
|
|
Emitter<SettingsState> emit,
|
|
) {
|
|
emit(
|
|
state.copyWith(
|
|
downloaderTestStatus: ConnectionTestStatus.initial,
|
|
webDavTestStatus: ConnectionTestStatus.initial,
|
|
testErrorMessage: null,
|
|
),
|
|
);
|
|
}
|
|
|
|
Future<void> _onSetShowSendToEReaderButton(
|
|
SetShowSendToEReaderButton event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setShowSendToEReaderButton(event.enabled);
|
|
emit(state.copyWith(showSendToEReaderButton: event.enabled));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetTextScale(
|
|
SetTextScale event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setTextScale(event.scale);
|
|
emit(state.copyWith(textScale: event.scale));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetEInkMode(
|
|
SetEInkMode event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
await repository.setEInkMode(event.enabled);
|
|
emit(state.copyWith(isEInkMode: event.enabled));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetBookActionsOrder(
|
|
SetBookActionsOrder event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final normalizedOrder = BookDetailsActionConfig.normalizeOrder(
|
|
event.actionKeys,
|
|
);
|
|
emit(state.copyWith(bookActionsOrder: normalizedOrder));
|
|
|
|
try {
|
|
await repository.setBookActionsOrder(normalizedOrder);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetBookActionEnabled(
|
|
SetBookActionEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
final updated = List<String>.from(state.enabledBookActions);
|
|
if (event.enabled) {
|
|
if (!updated.contains(event.actionKey)) {
|
|
updated.add(event.actionKey);
|
|
}
|
|
} else {
|
|
updated.remove(event.actionKey);
|
|
}
|
|
|
|
final normalized = BookDetailsActionConfig.normalizeEnabled(updated);
|
|
await repository.setEnabledBookActions(normalized);
|
|
emit(state.copyWith(enabledBookActions: normalized));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onResetBookActionsCustomization(
|
|
ResetBookActionsCustomization event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final defaults = List<String>.from(BookDetailsActionConfig.defaultOrder);
|
|
emit(
|
|
state.copyWith(bookActionsOrder: defaults, enabledBookActions: defaults),
|
|
);
|
|
|
|
try {
|
|
await Future.wait([
|
|
repository.setBookActionsOrder(defaults),
|
|
repository.setEnabledBookActions(defaults),
|
|
]);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetBookDetailsSectionsOrder(
|
|
SetBookDetailsSectionsOrder event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final normalizedOrder = BookDetailsSectionConfig.normalizeOrder(
|
|
event.sectionKeys,
|
|
);
|
|
emit(state.copyWith(bookDetailsSectionsOrder: normalizedOrder));
|
|
|
|
try {
|
|
await repository.setBookDetailsSectionsOrder(normalizedOrder);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetBookDetailsSectionEnabled(
|
|
SetBookDetailsSectionEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
final updated = List<String>.from(state.enabledBookDetailsSections);
|
|
if (event.enabled) {
|
|
if (!updated.contains(event.sectionKey)) {
|
|
updated.add(event.sectionKey);
|
|
}
|
|
} else {
|
|
updated.remove(event.sectionKey);
|
|
}
|
|
|
|
final normalized = BookDetailsSectionConfig.normalizeEnabled(updated);
|
|
await repository.setEnabledBookDetailsSections(normalized);
|
|
emit(state.copyWith(enabledBookDetailsSections: normalized));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onResetBookDetailsSectionsCustomization(
|
|
ResetBookDetailsSectionsCustomization event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final defaults = List<String>.from(BookDetailsSectionConfig.defaultOrder);
|
|
emit(
|
|
state.copyWith(
|
|
bookDetailsSectionsOrder: defaults,
|
|
enabledBookDetailsSections: defaults,
|
|
),
|
|
);
|
|
|
|
try {
|
|
await Future.wait([
|
|
repository.setBookDetailsSectionsOrder(defaults),
|
|
repository.setEnabledBookDetailsSections(defaults),
|
|
]);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDiscoverMainSectionsOrder(
|
|
SetDiscoverMainSectionsOrder event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final normalizedOrder = DiscoverLayoutConfig.normalizeMainSectionsOrder(
|
|
event.sectionKeys,
|
|
);
|
|
emit(state.copyWith(discoverMainSectionsOrder: normalizedOrder));
|
|
|
|
try {
|
|
await repository.setDiscoverMainSectionsOrder(normalizedOrder);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDiscoverMainSectionEnabled(
|
|
SetDiscoverMainSectionEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
final updated = List<String>.from(state.enabledDiscoverMainSections);
|
|
if (event.enabled) {
|
|
if (!updated.contains(event.sectionKey)) {
|
|
updated.add(event.sectionKey);
|
|
}
|
|
} else {
|
|
updated.remove(event.sectionKey);
|
|
}
|
|
|
|
final normalized = DiscoverLayoutConfig.normalizeEnabledMainSections(
|
|
updated,
|
|
);
|
|
await repository.setEnabledDiscoverMainSections(normalized);
|
|
emit(state.copyWith(enabledDiscoverMainSections: normalized));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDiscoverItemsOrder(
|
|
SetDiscoverItemsOrder event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final normalizedOrder = DiscoverLayoutConfig.normalizeDiscoverItemsOrder(
|
|
event.itemKeys,
|
|
);
|
|
emit(state.copyWith(discoverItemsOrder: normalizedOrder));
|
|
|
|
try {
|
|
await repository.setDiscoverItemsOrder(normalizedOrder);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetDiscoverItemEnabled(
|
|
SetDiscoverItemEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
final updated = List<String>.from(state.enabledDiscoverItems);
|
|
if (event.enabled) {
|
|
if (!updated.contains(event.itemKey)) {
|
|
updated.add(event.itemKey);
|
|
}
|
|
} else {
|
|
updated.remove(event.itemKey);
|
|
}
|
|
|
|
final normalized = DiscoverLayoutConfig.normalizeEnabledDiscoverItems(
|
|
updated,
|
|
);
|
|
await repository.setEnabledDiscoverItems(normalized);
|
|
emit(state.copyWith(enabledDiscoverItems: normalized));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetCategoryItemsOrder(
|
|
SetCategoryItemsOrder event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final normalizedOrder = DiscoverLayoutConfig.normalizeCategoryItemsOrder(
|
|
event.itemKeys,
|
|
);
|
|
emit(state.copyWith(categoryItemsOrder: normalizedOrder));
|
|
|
|
try {
|
|
await repository.setCategoryItemsOrder(normalizedOrder);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onSetCategoryItemEnabled(
|
|
SetCategoryItemEnabled event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
try {
|
|
final updated = List<String>.from(state.enabledCategoryItems);
|
|
if (event.enabled) {
|
|
if (!updated.contains(event.itemKey)) {
|
|
updated.add(event.itemKey);
|
|
}
|
|
} else {
|
|
updated.remove(event.itemKey);
|
|
}
|
|
|
|
final normalized = DiscoverLayoutConfig.normalizeEnabledCategoryItems(
|
|
updated,
|
|
);
|
|
await repository.setEnabledCategoryItems(normalized);
|
|
emit(state.copyWith(enabledCategoryItems: normalized));
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _onResetDiscoverCustomization(
|
|
ResetDiscoverCustomization event,
|
|
Emitter<SettingsState> emit,
|
|
) async {
|
|
final mainDefaults = List<String>.from(
|
|
DiscoverLayoutConfig.defaultMainSectionsOrder,
|
|
);
|
|
final discoverDefaults = List<String>.from(
|
|
DiscoverLayoutConfig.defaultDiscoverItemsOrder,
|
|
);
|
|
final categoryDefaults = List<String>.from(
|
|
DiscoverLayoutConfig.defaultCategoryItemsOrder,
|
|
);
|
|
|
|
emit(
|
|
state.copyWith(
|
|
discoverMainSectionsOrder: mainDefaults,
|
|
enabledDiscoverMainSections: mainDefaults,
|
|
discoverItemsOrder: discoverDefaults,
|
|
enabledDiscoverItems: discoverDefaults,
|
|
categoryItemsOrder: categoryDefaults,
|
|
enabledCategoryItems: categoryDefaults,
|
|
),
|
|
);
|
|
|
|
try {
|
|
await Future.wait([
|
|
repository.setDiscoverMainSectionsOrder(mainDefaults),
|
|
repository.setEnabledDiscoverMainSections(mainDefaults),
|
|
repository.setDiscoverItemsOrder(discoverDefaults),
|
|
repository.setEnabledDiscoverItems(discoverDefaults),
|
|
repository.setCategoryItemsOrder(categoryDefaults),
|
|
repository.setEnabledCategoryItems(categoryDefaults),
|
|
]);
|
|
} catch (e) {
|
|
emit(
|
|
state.copyWith(
|
|
status: SettingsStatus.error,
|
|
errorMessage: e.toString(),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
}
|