diff --git a/.detoxrc.js b/.detoxrc.js index 2652b4c..96cdb42 100644 --- a/.detoxrc.js +++ b/.detoxrc.js @@ -1,5 +1,5 @@ const basicLaunchArgs = { - disableAnimations: true, + testingEnvironment: true, }; function createDetoxURLBlacklistRegex(patterns) { diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b7ea9a1..66401a0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -172,7 +172,7 @@ jobs: android-test: name: "Android Detox (test)" runs-on: ubuntu-latest - timeout-minutes: 20 + timeout-minutes: 30 needs: android-build strategy: matrix: diff --git a/App.tsx b/App.tsx index f5533c2..386e182 100644 --- a/App.tsx +++ b/App.tsx @@ -24,6 +24,7 @@ import { SCHEME } from "utils/constants"; import SwitchServerScreen from "screens/SwitchServerScreen"; import EditServerScreen from "screens/EditServerScreen"; import { KeyboardProvider } from "react-native-keyboard-controller"; +import QRCodeCameraScreen from "screens/QRCodeCameraScreen"; if (!global.btoa) { global.btoa = encode; @@ -68,6 +69,10 @@ function SwitchServerStack() { name="AddServer" component={AddServerScreen} /> + ); } @@ -128,6 +133,11 @@ function AppNavigator() { component={AddServerScreen} options={sheetOpts} /> + )} diff --git a/app.config.ts b/app.config.ts index d8c2351..c098947 100644 --- a/app.config.ts +++ b/app.config.ts @@ -73,6 +73,12 @@ export default ({ config }: ConfigContext) => }, }, ], + [ + "expo-camera", + { + recordAudioAndroid: false, + }, + ], [ "expo-font", { diff --git a/components/Header.tsx b/components/Header.tsx index c9515d0..3e995c7 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -6,12 +6,26 @@ import IconBack from "@material-symbols/svg-400/rounded/arrow_back_ios_new.svg"; export function CloseIcon() { const theme = useTheme(); - return ; + return ( + + ); } export function BackIcon() { const theme = useTheme(); - return ; + return ( + + ); } interface HeaderProps { diff --git a/components/ScanQRCodeButton.tsx b/components/ScanQRCodeButton.tsx new file mode 100644 index 0000000..40f66ad --- /dev/null +++ b/components/ScanQRCodeButton.tsx @@ -0,0 +1,45 @@ +import { Button } from "@ui-kitten/components"; +import { useTranslation } from "react-i18next"; +import { useCameraPermissions } from "expo-camera"; +import { Linking } from "react-native"; +import { useNavigation } from "@react-navigation/native"; +import { testingEnvironment } from "helper/launchArguments"; + +interface ScanQRCodeButtonProps { + shown: "Onboarding" | "Addserverform"; +} + +export default function ScanQRCodeButton({ shown }: ScanQRCodeButtonProps) { + const { t } = useTranslation(); + const navigation = useNavigation(); + const [permission, requestPermission] = useCameraPermissions(); + + if (!permission) { + return null; + } + + return ( + + ); +} diff --git a/components/ServerForm.tsx b/components/ServerForm.tsx index 49a00a5..741658b 100644 --- a/components/ServerForm.tsx +++ b/components/ServerForm.tsx @@ -5,6 +5,7 @@ import LoadingIndicator from "./animations/LoadingIndicator"; import { useTranslation } from "react-i18next"; import { BasicAuth, Server } from "types"; import { useAppContext } from "./AppContext"; +import ScanQRCodeButton from "./ScanQRCodeButton"; interface ServerFormProps { server: Server | undefined; @@ -182,6 +183,8 @@ export default function ServerForm({ )} + {mode === "create" && } + + ) : ( + { + try { + const qrcodeUrl = new URL(r.data); + + const title = qrcodeUrl.searchParams.get("title") ?? ""; + const url = qrcodeUrl.searchParams.get("url") ?? ""; + const username = + qrcodeUrl.searchParams.get("username") ?? ""; + const password = + qrcodeUrl.searchParams.get("password") ?? ""; + + if ( + qrcodeUrl.protocol === "evcc:" && + qrcodeUrl.hostname === "server" && + title && + url + ) { + showStatus( + t("servers.manually.qrcode.recognized"), + "success", + ); + + serverDetected({ + title, + url, + username, + password, + required: !!username || !!password, + }); + } else { + showStatus( + t("servers.manually.qrcode.invalid"), + "error", + ); + } + } catch (e) { + console.log("Error parsing qr code data: ", e); + showStatus(t("servers.manually.qrcode.invalid"), "error"); + } + } + : undefined + } + /> + )} + + + {statusMessage ? ( + + {statusMessage} + + ) : ( + + + + {t("servers.manually.qrcode.scanning")} + + + )} + + + + ); +} diff --git a/types.ts b/types.ts index b8f7bef..c4fc3b1 100644 --- a/types.ts +++ b/types.ts @@ -27,9 +27,11 @@ export type SwitchServerStackParamList = { serverIndex: number; }; AddServer?: AddServerParams; + QRCodeCamera: undefined; }; export type RootStackParamList = { + QRCodeCamera: undefined; Main: undefined; Onboarding: undefined; SwitchServerModal?: NavigatorScreenParams;