diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 5c7050ba..9d017fb8 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -204,6 +204,8 @@ dependencies {
// Drive: "Scannen" (Google's document scanner and text recognition, both through Play services: no models in the APK)
implementation(libs.mlkit.document.scanner)
implementation(libs.mlkit.text.recognition)
+ // Drive: work photos apart — image labeling on the phone (Play services, no model in the APK, no picture leaves the phone)
+ implementation(libs.mlkit.image.labeling)
// Vault: end-to-end encryption (README "Kryptoformat" of gatecontrol-vault) and the recovery key's QR
implementation(libs.bouncycastle.prov)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2a66e4ae..08238547 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -70,10 +70,11 @@
android:theme="@style/Theme.GateControl"
tools:replace="android:theme">
-
+
+ android:value="ocr,ica" />
+
+
+
post(path: String, body: JsonObject, parse: (JsonObject) -> T?) =
call(request = { pluginPost(DRIVE_PLUGIN, path, body, lang()) }, parse = parse)
+ private suspend fun put(path: String, body: JsonObject, parse: (JsonObject) -> T?) =
+ call(request = { pluginPut(DRIVE_PLUGIN, path, body, lang()) }, parse = parse)
+
private suspend fun patch(path: String, body: JsonObject, parse: (JsonObject) -> T?) =
call(request = { pluginPatch(DRIVE_PLUGIN, path, body, lang()) }, parse = parse)
@@ -247,11 +252,37 @@ class DriveApi @Inject constructor(
* Photos and videos, newest first; [before] is the cursor of the page before. Without [area]: all I can read.
* [camera]: only the camera uploads (Drive 1.10, feature `photosFolder`).
*/
- suspend fun photos(area: String? = null, before: String? = null, limit: Int = 120, camera: Boolean = false): DResult =
- get("photos", DriveJson.photosQuery(area, before, limit, camera) ?: return bad()) { o -> DriveJson.photos(o)?.let { it.copy(items = DriveLogic.withoutVaults(it.items)) } }
+ suspend fun photos(area: String? = null, before: String? = null, limit: Int = 120, camera: Boolean = false, cls: String? = null): DResult =
+ get("photos", DriveJson.photosQuery(area, before, limit, camera, cls = cls) ?: return bad()) { o -> DriveJson.photos(o)?.let { it.copy(items = DriveLogic.withoutVaults(it.items)) } }
+
+ suspend fun photoMonths(area: String? = null, camera: Boolean = false, cls: String? = null): DResult> =
+ get("photos/months", DriveJson.photosQuery(area, camera = camera, cls = cls) ?: return bad(), DriveJson::months)
+
+ // ─── work photos (Drive 1.13, feature `photoClasses`) ───────────
+
+ /** Where my work photos go, for every device and the portal. */
+ suspend fun photoSettings(): DResult = get("photos/settings", parse = DriveJson::photoSettings)
+
+ /** Changes only what is given; [clearFolder]: no work folder any more. */
+ suspend fun putPhotoSettings(workFolder: Long? = null, clearFolder: Boolean = false, workSubfolders: Boolean? = null, workInMemories: Boolean? = null): DResult =
+ put("photos/settings", DriveJson.photoSettingsBody(workFolder, clearFolder, workSubfolders, workInMemories), DriveJson::photoSettings)
+
+ /** Sets or clears the review mark of [ids] (at most 500 a call, so in parts); [hint] the AI's "work" in percent. */
+ suspend fun photoReview(ids: List, review: Boolean, hint: Int? = null): DResult