Merge branch 'mobile_face' into fix_face_thumbnail
This commit is contained in:
commit
58cd9350c0
|
@ -348,6 +348,18 @@ class FaceMLDataDB {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int?> getClusterIDForFaceID(String faceID) async {
|
||||||
|
final db = await instance.sqliteAsyncDB;
|
||||||
|
final List<Map<String, dynamic>> maps = await db.getAll(
|
||||||
|
'SELECT $fcClusterID FROM $faceClustersTable WHERE $fcFaceId = ?',
|
||||||
|
[faceID],
|
||||||
|
);
|
||||||
|
if (maps.isEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return maps.first[fcClusterID] as int;
|
||||||
|
}
|
||||||
|
|
||||||
Future<Map<int, Iterable<String>>> getAllClusterIdToFaceIDs() async {
|
Future<Map<int, Iterable<String>>> getAllClusterIdToFaceIDs() async {
|
||||||
final db = await instance.sqliteAsyncDB;
|
final db = await instance.sqliteAsyncDB;
|
||||||
final Map<int, List<String>> result = {};
|
final Map<int, List<String>> result = {};
|
||||||
|
@ -420,8 +432,8 @@ class FaceMLDataDB {
|
||||||
Future<Map<String, int?>> getFaceIdsToClusterIds(
|
Future<Map<String, int?>> getFaceIdsToClusterIds(
|
||||||
Iterable<String> faceIds,
|
Iterable<String> faceIds,
|
||||||
) async {
|
) async {
|
||||||
final db = await instance.sqliteAsyncDB;
|
final db = await instance.database;
|
||||||
final List<Map<String, dynamic>> maps = await db.getAll(
|
final List<Map<String, dynamic>> maps = await db.rawQuery(
|
||||||
'SELECT $fcFaceId, $fcClusterID FROM $faceClustersTable where $fcFaceId IN (${faceIds.map((id) => "'$id'").join(",")})',
|
'SELECT $fcFaceId, $fcClusterID FROM $faceClustersTable where $fcFaceId IN (${faceIds.map((id) => "'$id'").join(",")})',
|
||||||
);
|
);
|
||||||
final Map<String, int?> result = {};
|
final Map<String, int?> result = {};
|
||||||
|
@ -433,8 +445,8 @@ class FaceMLDataDB {
|
||||||
|
|
||||||
Future<Map<int, Set<int>>> getFileIdToClusterIds() async {
|
Future<Map<int, Set<int>>> getFileIdToClusterIds() async {
|
||||||
final Map<int, Set<int>> result = {};
|
final Map<int, Set<int>> result = {};
|
||||||
final db = await instance.sqliteAsyncDB;
|
final db = await instance.database;
|
||||||
final List<Map<String, dynamic>> maps = await db.getAll(
|
final List<Map<String, dynamic>> maps = await db.rawQuery(
|
||||||
'SELECT $fcClusterID, $fcFaceId FROM $faceClustersTable',
|
'SELECT $fcClusterID, $fcFaceId FROM $faceClustersTable',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -966,7 +966,12 @@ class FaceMlService {
|
||||||
switch (typeOfData) {
|
switch (typeOfData) {
|
||||||
case FileDataForML.fileData:
|
case FileDataForML.fileData:
|
||||||
final stopwatch = Stopwatch()..start();
|
final stopwatch = Stopwatch()..start();
|
||||||
final File? file = await getFile(enteFile, isOrigin: true);
|
File? file;
|
||||||
|
if (enteFile.fileType == FileType.video) {
|
||||||
|
file = await getThumbnailForUploadedFile(enteFile);
|
||||||
|
} else {
|
||||||
|
file = await getFile(enteFile, isOrigin: true);
|
||||||
|
}
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
_logger.warning("Could not get file for $enteFile");
|
_logger.warning("Could not get file for $enteFile");
|
||||||
imagePath = null;
|
imagePath = null;
|
||||||
|
@ -1294,10 +1299,6 @@ class FaceMlService {
|
||||||
if (!enteFile.isUploaded || enteFile.isOwner == false) {
|
if (!enteFile.isUploaded || enteFile.isOwner == false) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Skip if the file is a video
|
|
||||||
if (enteFile.fileType == FileType.video) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// I don't know how motionPhotos and livePhotos work, so I'm also just skipping them for now
|
// I don't know how motionPhotos and livePhotos work, so I'm also just skipping them for now
|
||||||
if (enteFile.fileType == FileType.other) {
|
if (enteFile.fileType == FileType.other) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import "dart:typed_data";
|
||||||
import "package:flutter/cupertino.dart";
|
import "package:flutter/cupertino.dart";
|
||||||
import "package:flutter/foundation.dart" show kDebugMode;
|
import "package:flutter/foundation.dart" show kDebugMode;
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
import "package:photos/extensions/stop_watch.dart";
|
||||||
import "package:photos/face/db.dart";
|
import "package:photos/face/db.dart";
|
||||||
import "package:photos/face/model/face.dart";
|
import "package:photos/face/model/face.dart";
|
||||||
import "package:photos/face/model/person.dart";
|
import "package:photos/face/model/person.dart";
|
||||||
|
@ -65,7 +66,50 @@ class _FaceWidgetState extends State<FaceWidget> {
|
||||||
name: "FaceWidget",
|
name: "FaceWidget",
|
||||||
);
|
);
|
||||||
if (widget.person == null && widget.clusterID == null) {
|
if (widget.person == null && widget.clusterID == null) {
|
||||||
return;
|
// Get faceID and double check that it doesn't belong to an existing clusterID. If it does, push that cluster page
|
||||||
|
final w = (kDebugMode ? EnteWatch('FaceWidget') : null)
|
||||||
|
?..start();
|
||||||
|
final existingClusterID = await FaceMLDataDB.instance
|
||||||
|
.getClusterIDForFaceID(widget.face.faceID);
|
||||||
|
w?.log('getting existing clusterID for faceID');
|
||||||
|
if (existingClusterID != null) {
|
||||||
|
final fileIdsToClusterIds =
|
||||||
|
await FaceMLDataDB.instance.getFileIdToClusterIds();
|
||||||
|
final files = await SearchService.instance.getAllFiles();
|
||||||
|
final clusterFiles = files
|
||||||
|
.where(
|
||||||
|
(file) =>
|
||||||
|
fileIdsToClusterIds[file.uploadedFileID]
|
||||||
|
?.contains(existingClusterID) ??
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ClusterPage(
|
||||||
|
clusterFiles,
|
||||||
|
clusterID: existingClusterID,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new clusterID for the faceID and update DB to assign the faceID to the new clusterID
|
||||||
|
final int newClusterID =
|
||||||
|
DateTime.now().microsecondsSinceEpoch;
|
||||||
|
await FaceMLDataDB.instance.updateFaceIdToClusterId(
|
||||||
|
{widget.face.faceID: newClusterID},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Push page for the new cluster
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ClusterPage(
|
||||||
|
[widget.file],
|
||||||
|
clusterID: newClusterID,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (widget.person != null) {
|
if (widget.person != null) {
|
||||||
await Navigator.of(context).push(
|
await Navigator.of(context).push(
|
||||||
|
@ -230,7 +274,49 @@ class _FaceWidgetState extends State<FaceWidget> {
|
||||||
name: "FaceWidget",
|
name: "FaceWidget",
|
||||||
);
|
);
|
||||||
if (widget.person == null && widget.clusterID == null) {
|
if (widget.person == null && widget.clusterID == null) {
|
||||||
return;
|
// Get faceID and double check that it doesn't belong to an existing clusterID. If it does, push that cluster page
|
||||||
|
final w = (kDebugMode ? EnteWatch('FaceWidget') : null)
|
||||||
|
?..start();
|
||||||
|
final existingClusterID = await FaceMLDataDB.instance
|
||||||
|
.getClusterIDForFaceID(widget.face.faceID);
|
||||||
|
w?.log('getting existing clusterID for faceID');
|
||||||
|
if (existingClusterID != null) {
|
||||||
|
final fileIdsToClusterIds =
|
||||||
|
await FaceMLDataDB.instance.getFileIdToClusterIds();
|
||||||
|
final files = await SearchService.instance.getAllFiles();
|
||||||
|
final clusterFiles = files
|
||||||
|
.where(
|
||||||
|
(file) =>
|
||||||
|
fileIdsToClusterIds[file.uploadedFileID]
|
||||||
|
?.contains(existingClusterID) ??
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ClusterPage(
|
||||||
|
clusterFiles,
|
||||||
|
clusterID: existingClusterID,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new clusterID for the faceID and update DB to assign the faceID to the new clusterID
|
||||||
|
final int newClusterID = DateTime.now().microsecondsSinceEpoch;
|
||||||
|
await FaceMLDataDB.instance.updateFaceIdToClusterId(
|
||||||
|
{widget.face.faceID: newClusterID},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Push page for the new cluster
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => ClusterPage(
|
||||||
|
[widget.file],
|
||||||
|
clusterID: newClusterID,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (widget.person != null) {
|
if (widget.person != null) {
|
||||||
await Navigator.of(context).push(
|
await Navigator.of(context).push(
|
||||||
|
|
|
@ -4,8 +4,10 @@ import "dart:io" show File;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import "package:photos/face/model/face.dart";
|
import "package:photos/face/model/face.dart";
|
||||||
import "package:photos/models/file/file.dart";
|
import "package:photos/models/file/file.dart";
|
||||||
|
import "package:photos/models/file/file_type.dart";
|
||||||
import "package:photos/ui/viewer/file/thumbnail_widget.dart";
|
import "package:photos/ui/viewer/file/thumbnail_widget.dart";
|
||||||
import "package:photos/utils/file_util.dart";
|
import "package:photos/utils/file_util.dart";
|
||||||
|
import "package:photos/utils/thumbnail_util.dart";
|
||||||
|
|
||||||
class CroppedFaceInfo {
|
class CroppedFaceInfo {
|
||||||
final Image image;
|
final Image image;
|
||||||
|
@ -103,7 +105,12 @@ class CroppedFaceImageView extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Image?> getImage() async {
|
Future<Image?> getImage() async {
|
||||||
final File? ioFile = await getFile(enteFile);
|
final File? ioFile;
|
||||||
|
if (enteFile.fileType == FileType.video) {
|
||||||
|
ioFile = await getThumbnailForUploadedFile(enteFile);
|
||||||
|
} else {
|
||||||
|
ioFile = await getFile(enteFile);
|
||||||
|
}
|
||||||
if (ioFile == null) {
|
if (ioFile == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue