[mob][photos] ML user developer options
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
103
mobile/lib/ui/settings/ml/ml_user_dev_screen.dart
Normal file
103
mobile/lib/ui/settings/ml/ml_user_dev_screen.dart
Normal 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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user