[mob][photos] ML user developer options

This commit is contained in:
laurenspriem
2024-08-28 13:46:58 +02:00
parent db8e203c36
commit ac5d9d99f1
3 changed files with 146 additions and 2 deletions

View File

@@ -668,6 +668,22 @@ class MLDataDB {
return maps.first['count'] as int;
}
Future<Set<int>> getErroredFileIDs() async {
final db = await instance.asyncDB;
final List<Map<String, dynamic>> maps = await db.getAll(
'SELECT DISTINCT $fileIDColumn FROM $facesTable WHERE $faceScore < 0',
);
return maps.map((e) => e[fileIDColumn] as int).toSet();
}
Future<void> deleteFaceIndexForFiles(List<int> fileIDs) async {
final db = await instance.asyncDB;
final String sql = '''
DELETE FROM $facesTable WHERE $fileIDColumn IN (${fileIDs.join(", ")})
''';
await db.execute(sql);
}
Future<int> getClusteredOrFacelessFileCount() async {
final db = await instance.asyncDB;
final List<Map<String, dynamic>> clustered = await db.getAll(

View File

@@ -26,6 +26,7 @@ import "package:photos/ui/components/title_bar_title_widget.dart";
import "package:photos/ui/components/title_bar_widget.dart";
import "package:photos/ui/components/toggle_switch_widget.dart";
import "package:photos/ui/settings/ml/enable_ml_consent.dart";
import "package:photos/ui/settings/ml/ml_user_dev_screen.dart";
import "package:photos/utils/ml_util.dart";
import "package:photos/utils/network_util.dart";
import "package:photos/utils/wakelock_util.dart";
@@ -42,6 +43,8 @@ class _MachineLearningSettingsPageState
extends State<MachineLearningSettingsPage> {
final EnteWakeLock _wakeLock = EnteWakeLock();
Timer? _timer;
int _titleTapCount = 0;
Timer? _advancedOptionsTimer;
@override
void initState() {
@@ -55,6 +58,9 @@ class _MachineLearningSettingsPageState
}
});
}
_advancedOptionsTimer = Timer.periodic(const Duration(seconds: 7), (timer) {
_titleTapCount = 0;
});
}
@override
@@ -63,6 +69,7 @@ class _MachineLearningSettingsPageState
_wakeLock.disable();
MachineLearningController.instance.forceOverrideML(turnOn: false);
_timer?.cancel();
_advancedOptionsTimer?.cancel();
}
@override
@@ -73,8 +80,26 @@ class _MachineLearningSettingsPageState
primary: false,
slivers: <Widget>[
TitleBarWidget(
flexibleSpaceTitle: TitleBarTitleWidget(
title: S.of(context).machineLearning,
flexibleSpaceTitle: GestureDetector(
child: TitleBarTitleWidget(
title: S.of(context).machineLearning,
),
onTap: () {
setState(() {
_titleTapCount++;
if (_titleTapCount >= 7) {
_titleTapCount = 0;
// showShortToast(context, "Advanced options enabled");
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const MLUserDeveloperOptions();
},
),
).ignore();
}
});
},
),
actionIcons: [
IconButtonWidget(

View File

@@ -0,0 +1,103 @@
import "package:flutter/material.dart";
import "package:photos/core/event_bus.dart";
import "package:photos/db/ml/clip_db.dart";
import "package:photos/db/ml/db.dart";
import "package:photos/events/people_changed_event.dart";
import "package:photos/services/machine_learning/semantic_search/semantic_search_service.dart";
import "package:photos/theme/ente_theme.dart";
import "package:photos/ui/components/buttons/button_widget.dart";
import "package:photos/ui/components/models/button_type.dart";
import "package:photos/ui/components/title_bar_title_widget.dart";
import "package:photos/ui/components/title_bar_widget.dart";
import "package:photos/utils/dialog_util.dart";
import "package:photos/utils/toast_util.dart";
class MLUserDeveloperOptions extends StatelessWidget {
const MLUserDeveloperOptions({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
primary: false,
slivers: <Widget>[
const TitleBarWidget(
flexibleSpaceTitle: TitleBarTitleWidget(
title: "ML debug options",
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(delegateBuildContext, index) => Padding(
padding: const EdgeInsets.only(left: 16, right: 16),
child: Column(
children: [
Text(
"Only use if you know what you're doing",
textAlign: TextAlign.left,
style: getEnteTextTheme(context).body.copyWith(
color: getEnteColorScheme(context).textMuted,
),
),
const SizedBox(height: 48),
ButtonWidget(
buttonType: ButtonType.neutral,
labelText: "Purge empty indices",
onTap: () async {
await deleteEmptyIndices(context);
},
),
const SizedBox(height: 24),
ButtonWidget(
buttonType: ButtonType.neutral,
labelText: "Reset all local ML",
onTap: () async {
await deleteAllLocalML(context);
},
),
const SafeArea(
child: SizedBox(
height: 12,
),
),
],
),
),
childCount: 1,
),
),
],
),
);
}
Future<void> deleteEmptyIndices(BuildContext context) async {
try {
final Set<int> emptyFileIDs = await MLDataDB.instance.getErroredFileIDs();
await MLDataDB.instance.deleteFaceIndexForFiles(emptyFileIDs.toList());
await MLDataDB.instance.deleteEmbeddings(emptyFileIDs.toList());
showShortToast(context, "Deleted ${emptyFileIDs.length} entries");
} catch (e) {
// ignore: unawaited_futures
showGenericErrorDialog(
context: context,
error: e,
);
}
}
Future<void> deleteAllLocalML(BuildContext context) async {
try {
await MLDataDB.instance.dropClustersAndPersonTable(faces: true);
await SemanticSearchService.instance.clearIndexes();
Bus.instance.fire(PeopleChangedEvent());
showShortToast(context, "All local ML cleared");
} catch (e) {
// ignore: unawaited_futures
showGenericErrorDialog(
context: context,
error: e,
);
}
}
}