Move clear cache db out of the hidden dev settings

This commit is contained in:
Ming Ming 2022-12-31 15:52:22 +08:00
parent 7b1a70d1d1
commit 346ad2a028
7 changed files with 348 additions and 28 deletions

View file

@ -0,0 +1,79 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:copy_with/copy_with.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/sqlite_table_extension.dart' as sql;
import 'package:np_codegen/np_codegen.dart';
import 'package:to_string/to_string.dart';
part 'expert.g.dart';
@autoCopyWith
@toString
class ExpertSettingsState {
const ExpertSettingsState({
this.lastSuccessful,
});
@override
String toString() => _$toString();
final ExpertSettingsEvent? lastSuccessful;
}
abstract class ExpertSettingsEvent {
const ExpertSettingsEvent();
}
@toString
class ExpertSettingsClearCacheDatabase extends ExpertSettingsEvent {
ExpertSettingsClearCacheDatabase();
@override
String toString() => _$toString();
}
class ExpertSettingsError {
const ExpertSettingsError(this.ev, [this.error, this.stackTrace]);
final ExpertSettingsEvent ev;
final Object? error;
final StackTrace? stackTrace;
}
@npLog
class ExpertSettingsBloc
extends Bloc<ExpertSettingsEvent, ExpertSettingsState> {
ExpertSettingsBloc(DiContainer c)
: _c = c,
super(const ExpertSettingsState()) {
on<ExpertSettingsClearCacheDatabase>(_onClearCacheDatabase);
}
static bool require(DiContainer c) =>
DiContainer.has(c, DiType.pref) && DiContainer.has(c, DiType.sqliteDb);
Stream<ExpertSettingsError> errorStream() => _errorStream.stream;
Future<void> _onClearCacheDatabase(ExpertSettingsClearCacheDatabase ev,
Emitter<ExpertSettingsState> emit) async {
try {
await _c.sqliteDb.use((db) async {
await db.truncate();
final accounts = _c.pref.getAccounts3Or([]);
for (final a in accounts) {
await db.insertAccountOf(a);
}
});
emit(state.copyWith(lastSuccessful: Nullable(ev)));
} catch (e, stackTrace) {
_log.shout("[_onClearCacheDatabase] Uncaught exception", e, stackTrace);
_errorStream.add(ExpertSettingsError(ev, e, stackTrace));
}
}
final DiContainer _c;
final _errorStream = StreamController<ExpertSettingsError>.broadcast();
}

View file

@ -0,0 +1,50 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'expert.dart';
// **************************************************************************
// CopyWithGenerator
// **************************************************************************
extension $ExpertSettingsStateCopyWith on ExpertSettingsState {
ExpertSettingsState copyWith(
{Nullable<ExpertSettingsEvent>? lastSuccessful}) =>
_$copyWith(lastSuccessful: lastSuccessful);
ExpertSettingsState _$copyWith(
{Nullable<ExpertSettingsEvent>? lastSuccessful}) {
return ExpertSettingsState(
lastSuccessful:
lastSuccessful != null ? lastSuccessful.obj : this.lastSuccessful);
}
}
// **************************************************************************
// NpLogGenerator
// **************************************************************************
extension _$ExpertSettingsBlocNpLog on ExpertSettingsBloc {
// ignore: unused_element
Logger get _log => log;
static final log = Logger("bloc.settings.expert.ExpertSettingsBloc");
}
// **************************************************************************
// ToStringGenerator
// **************************************************************************
extension _$ExpertSettingsStateToString on ExpertSettingsState {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "ExpertSettingsState {lastSuccessful: $lastSuccessful}";
}
}
extension _$ExpertSettingsClearCacheDatabaseToString
on ExpertSettingsClearCacheDatabase {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "ExpertSettingsClearCacheDatabase {}";
}
}

View file

@ -453,6 +453,14 @@
},
"settingsExperimentalTitle": "Experimental",
"settingsExperimentalDescription": "Features that are not ready for everyday use",
"settingsExpertTitle": "Advanced",
"@settingsExpertTitle": {
"description": "Settings that must be tweaked with caution"
},
"settingsExpertWarningText": "Please make sure you fully understand what each option does before proceeding",
"settingsClearCacheDatabaseTitle": "Clear file database",
"settingsClearCacheDatabaseDescription": "Clear cached file info and trigger a complete resync with the server",
"settingsClearCacheDatabaseSuccessNotification": "Database cleared successfully. You are suggested to restart the app",
"settingsAboutSectionTitle": "About",
"@settingsAboutSectionTitle": {
"description": "Title of the about section in settings widget"
@ -1501,7 +1509,6 @@
"@loopTooltip": {
"description": "Enable or disable loop in the video player"
},
"errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues",
"@errorUnauthenticated": {
"description": "Error message when server responds with HTTP401"

View file

@ -40,6 +40,11 @@
"settingsPhotosTabSortByNameTitle",
"settingsExperimentalTitle",
"settingsExperimentalDescription",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"rootPickerSkipConfirmationDialogContent2",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
@ -226,6 +231,11 @@
"settingsPhotosTabSortByNameTitle",
"settingsExperimentalTitle",
"settingsExperimentalDescription",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"rootPickerSkipConfirmationDialogContent2",
"timeSecondInputHint",
"sortOptionFilenameAscendingLabel",
@ -405,6 +415,11 @@
"settingsSeedColorDescription",
"settingsSeedColorPickerTitle",
"settingsDoubleTapExitTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"slideshowSetupDialogReverseTitle",
"shareMethodPreviewTitle",
"shareMethodPreviewDescription",
@ -474,6 +489,11 @@
"es": [
"connectingToServerInstruction",
"settingsEnhanceMaxResolutionTitle2",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"initialSyncMessage",
"loopTooltip"
],
@ -485,6 +505,11 @@
"settingsSeedColorTitle",
"settingsSeedColorDescription",
"settingsSeedColorPickerTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"initialSyncMessage",
"loopTooltip"
],
@ -515,6 +540,11 @@
"settingsMiscellaneousTitle",
"settingsDoubleTapExitTitle",
"settingsPhotosTabSortByNameTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
"helpTooltip",
@ -622,6 +652,11 @@
"settingsMiscellaneousTitle",
"settingsDoubleTapExitTitle",
"settingsPhotosTabSortByNameTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
"slideshowSetupDialogReverseTitle",
@ -747,6 +782,11 @@
"settingsMiscellaneousTitle",
"settingsDoubleTapExitTitle",
"settingsPhotosTabSortByNameTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
"slideshowSetupDialogReverseTitle",
@ -851,6 +891,11 @@
"settingsMiscellaneousTitle",
"settingsDoubleTapExitTitle",
"settingsPhotosTabSortByNameTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
"slideshowSetupDialogReverseTitle",
@ -955,6 +1000,11 @@
"settingsMiscellaneousTitle",
"settingsDoubleTapExitTitle",
"settingsPhotosTabSortByNameTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
"slideshowSetupDialogReverseTitle",
@ -1059,6 +1109,11 @@
"settingsMiscellaneousTitle",
"settingsDoubleTapExitTitle",
"settingsPhotosTabSortByNameTitle",
"settingsExpertTitle",
"settingsExpertWarningText",
"settingsClearCacheDatabaseTitle",
"settingsClearCacheDatabaseDescription",
"settingsClearCacheDatabaseSuccessNotification",
"sortOptionFilenameAscendingLabel",
"sortOptionFilenameDescendingLabel",
"slideshowSetupDialogReverseTitle",

View file

@ -27,6 +27,7 @@ import 'package:nc_photos/widget/gps_map.dart';
import 'package:nc_photos/widget/home.dart';
import 'package:nc_photos/widget/list_tile_center_leading.dart';
import 'package:nc_photos/widget/root_picker.dart';
import 'package:nc_photos/widget/settings/expert_settings.dart';
import 'package:nc_photos/widget/settings/theme_settings.dart';
import 'package:nc_photos/widget/share_folder_picker.dart';
import 'package:nc_photos/widget/simple_input_dialog.dart';
@ -185,6 +186,12 @@ class _SettingsState extends State<Settings> {
description: L10n.global().settingsExperimentalDescription,
builder: () => _ExperimentalSettings(),
),
_buildSubSettings(
context,
leading: const Icon(Icons.warning_amber),
label: L10n.global().settingsExpertTitle,
builder: () => const ExpertSettings(),
),
if (_isShowDevSettings)
_buildSubSettings(
context,
@ -1642,10 +1649,6 @@ class _DevSettingsState extends State<_DevSettings> {
SliverList(
delegate: SliverChildListDelegate(
[
ListTile(
title: const Text("Clear cache database"),
onTap: () => _clearCacheDb(),
),
ListTile(
title: const Text("SQL:VACUUM"),
onTap: () => _runSqlVacuum(),
@ -1657,29 +1660,6 @@ class _DevSettingsState extends State<_DevSettings> {
);
}
Future<void> _clearCacheDb() async {
try {
final c = KiwiContainer().resolve<DiContainer>();
await c.sqliteDb.use((db) async {
await db.truncate();
final accounts = Pref().getAccounts3Or([]);
for (final a in accounts) {
await db.insertAccountOf(a);
}
});
SnackBarManager().showSnackBar(const SnackBar(
content: Text("Database cleared"),
duration: k.snackBarDurationShort,
));
} catch (e, stackTrace) {
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(e)),
duration: k.snackBarDurationNormal,
));
_log.shout("[_clearCacheDb] Uncaught exception", e, stackTrace);
}
}
Future<void> _runSqlVacuum() async {
try {
final c = KiwiContainer().resolve<DiContainer>();

View file

@ -0,0 +1,134 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/app_localizations.dart';
import 'package:nc_photos/bloc/settings/expert.dart';
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/exception_util.dart' as exception_util;
import 'package:nc_photos/k.dart' as k;
import 'package:nc_photos/snack_bar_manager.dart';
import 'package:np_codegen/np_codegen.dart';
part 'expert_settings.g.dart';
class ExpertSettings extends StatelessWidget {
const ExpertSettings({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => ExpertSettingsBloc(KiwiContainer().resolve<DiContainer>()),
child: const _WrappedExpertSettings(),
);
}
}
class _WrappedExpertSettings extends StatefulWidget {
const _WrappedExpertSettings();
@override
State<StatefulWidget> createState() => _WrappedExpertSettingsState();
}
@npLog
class _WrappedExpertSettingsState extends State<_WrappedExpertSettings> {
@override
void initState() {
super.initState();
_errorSubscription =
context.read<ExpertSettingsBloc>().errorStream().listen((error) {
if (error.ev is ExpertSettingsClearCacheDatabase) {
SnackBarManager().showSnackBar(SnackBar(
content: Text(exception_util.toUserString(error.error)),
duration: k.snackBarDurationNormal,
));
}
});
}
@override
void dispose() {
_errorSubscription.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (context) =>
BlocListener<ExpertSettingsBloc, ExpertSettingsState>(
listenWhen: (previous, current) =>
!identical(previous.lastSuccessful, current.lastSuccessful),
listener: (context, state) {
if (state.lastSuccessful is ExpertSettingsClearCacheDatabase) {
showDialog(
context: context,
builder: (_) => AlertDialog(
content: Text(L10n.global()
.settingsClearCacheDatabaseSuccessNotification),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
MaterialLocalizations.of(context).closeButtonLabel),
),
],
),
);
}
},
child: CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text(L10n.global().settingsExpertTitle),
),
SliverPadding(
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
sliver: SliverToBoxAdapter(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Icons.warning_amber,
color: Theme.of(context).colorScheme.error,
),
const SizedBox(height: 8),
Text(L10n.global().settingsExpertWarningText),
],
),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
ListTile(
title:
Text(L10n.global().settingsClearCacheDatabaseTitle),
subtitle: Text(
L10n.global().settingsClearCacheDatabaseDescription),
onTap: () {
context
.read<ExpertSettingsBloc>()
.add(ExpertSettingsClearCacheDatabase());
},
),
],
),
),
],
),
),
),
);
}
late final StreamSubscription _errorSubscription;
}

View file

@ -0,0 +1,15 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'expert_settings.dart';
// **************************************************************************
// NpLogGenerator
// **************************************************************************
extension _$_WrappedExpertSettingsStateNpLog on _WrappedExpertSettingsState {
// ignore: unused_element
Logger get _log => log;
static final log =
Logger("widget.settings.expert_settings._WrappedExpertSettingsState");
}