summaryrefslogtreecommitdiff
path: root/app/(tabs)
diff options
context:
space:
mode:
authorJustZvan <justzvan@justzvan.xyz>2026-04-06 15:32:51 +0200
committerJustZvan <justzvan@justzvan.xyz>2026-04-06 15:32:51 +0200
commit3273e7a0fbbce82f4ce6cacbcdb7b6d6848f6c1b (patch)
tree7662ab528c950e5b3605d3f134dc89f399417c8d /app/(tabs)
parent7eb8ccae48b0cc18a9dcaa9c3626a02df8e6d919 (diff)
feat: gallery scanning preferences
Diffstat (limited to 'app/(tabs)')
-rw-r--r--app/(tabs)/controls.tsx90
1 files changed, 81 insertions, 9 deletions
diff --git a/app/(tabs)/controls.tsx b/app/(tabs)/controls.tsx
index ac44f1b..3e41b6a 100644
--- a/app/(tabs)/controls.tsx
+++ b/app/(tabs)/controls.tsx
@@ -1,6 +1,11 @@
import { useEffect, useState } from "react";
import { Pressable, Switch, View } from "react-native";
-import { ControlsData, getControlsData, updateSafetyControl } from "../../api";
+import {
+ ControlsData,
+ SafetyControlValue,
+ getControlsData,
+ updateSafetyControl,
+} from "../../api";
import { useDevice } from "../../lib/device";
import { t } from "../../lib/locales";
import { colors } from "../../lib/theme";
@@ -18,14 +23,16 @@ import {
export default function ControlsScreen() {
const [data, setData] = useState<ControlsData | null>(null);
- const [state, setState] = useState<Record<string, boolean>>({});
+ const [state, setState] = useState<Record<string, SafetyControlValue>>({});
const [communication, setCommunication] = useState<"scan" | "block">("scan");
const [communicationModalVisible, setCommunicationModalVisible] =
useState(false);
+ const [galleryScanningMode, setGalleryScanningMode] = useState<
+ "delete" | "notify" | "none"
+ >("none");
+ const [galleryScanningModalVisible, setGalleryScanningModalVisible] =
+ useState(false);
const [confirmModalVisible, setConfirmModalVisible] = useState(false);
- const [pendingSelection, setPendingSelection] = useState<
- "scan" | "block" | null
- >(null);
const {
devices,
@@ -34,6 +41,16 @@ export default function ControlsScreen() {
isLoading: isDeviceLoading,
} = useDevice();
+ const normalizeGalleryScanningMode = (
+ value: SafetyControlValue | undefined,
+ ): "delete" | "notify" | "none" => {
+ if (value === "delete" || value === "notify" || value === "none") {
+ return value;
+ }
+
+ return "none";
+ };
+
useEffect(() => {
if (selectedDevice) {
getControlsData().then((d) => {
@@ -47,15 +64,34 @@ export default function ControlsScreen() {
(c) => c.key === "block_strangers",
)?.defaultValue;
setCommunication(blockDefault ? "block" : "scan");
+ const galleryDefault = d.safetyControls.find(
+ (c) => c.key === "gallery_scanning_mode",
+ )?.defaultValue;
+ setGalleryScanningMode(normalizeGalleryScanningMode(galleryDefault));
});
}
}, [selectedDevice]);
- const handleToggle = (key: string, value: boolean) => {
+ const handleToggle = (key: string, value: SafetyControlValue) => {
setState((prev) => ({ ...prev, [key]: value }));
updateSafetyControl(key, value);
};
+ const handleGalleryScanningModeChange = (
+ value: "delete" | "notify" | "none",
+ ) => {
+ setGalleryScanningMode(value);
+ handleToggle("gallery_scanning_mode", value);
+ setGalleryScanningModalVisible(false);
+ };
+
+ const galleryScanningLabel =
+ galleryScanningMode === "delete"
+ ? t("galleryScanningDelete")
+ : galleryScanningMode === "notify"
+ ? t("galleryScanningNotify")
+ : t("galleryScanningNone");
+
const openCommunicationOptions = () => {
setCommunicationModalVisible(true);
};
@@ -67,7 +103,6 @@ export default function ControlsScreen() {
setCommunicationModalVisible(false);
} else {
// block chosen - show confirmation
- setPendingSelection("block");
setConfirmModalVisible(true);
setCommunicationModalVisible(false);
}
@@ -77,12 +112,10 @@ export default function ControlsScreen() {
setCommunication("block");
handleToggle("block_strangers", true);
setConfirmModalVisible(false);
- setPendingSelection(null);
};
const cancelConfirm = () => {
setConfirmModalVisible(false);
- setPendingSelection(null);
};
if (!selectedDevice && !isDeviceLoading)
@@ -265,6 +298,45 @@ export default function ControlsScreen() {
}
/>
</Card>
+
+ <Card>
+ <H2>{t("galleryScanning")}</H2>
+ <Divider />
+ <Row
+ left={
+ <View style={{ gap: 4 }}>
+ <H2>{t("galleryScanning")}</H2>
+ <Muted>{t("scanGalleryForInappropriateImages")}</Muted>
+ </View>
+ }
+ right={
+ <Pressable onPress={() => setGalleryScanningModalVisible(true)}>
+ <Muted>{galleryScanningLabel}</Muted>
+ </Pressable>
+ }
+ />
+
+ <SelectDialog
+ visible={galleryScanningModalVisible}
+ title={t("galleryScanningTitle")}
+ options={[
+ {
+ label: t("galleryScanningNone"),
+ onPress: () => handleGalleryScanningModeChange("none"),
+ },
+ {
+ label: t("galleryScanningNotify"),
+ onPress: () => handleGalleryScanningModeChange("notify"),
+ },
+ {
+ label: t("galleryScanningDelete"),
+ onPress: () => handleGalleryScanningModeChange("delete"),
+ destructive: true,
+ },
+ ]}
+ onClose={() => setGalleryScanningModalVisible(false)}
+ />
+ </Card>
</Screen>
);
}