From 3cf932f5bee217799bf8a7889b71748b4b124bf0 Mon Sep 17 00:00:00 2001
From: Tasker <26747046+tmgrask@users.noreply.github.com>
Date: Mon, 7 Oct 2024 12:10:22 -0400
Subject: [PATCH] Fix duplicate splash screen warning from Play console (#15)
* fix all tsserver diagnostics in project
* move dots into their own component; undo metro config change
* fix duplicate splash screen warning in play console
---
android/app/src/main/res/values/styles.xml | 4 +-
babel.config.js | 2 +-
src/app/(app)/onboarding.tsx | 181 ++++++++++++---------
src/app/index.tsx | 6 +-
src/components/GitHash.tsx | 2 +-
src/components/canvas/Phone.tsx | 2 +-
src/i18n/fake-translation.js | 4 +-
src/i18n/i18n.test.ts | 3 +-
src/i18n/pseudo.js | 18 +-
9 files changed, 125 insertions(+), 97 deletions(-)
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index 912e38b..32c1447 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -13,5 +13,7 @@
-
\ No newline at end of file
+
diff --git a/babel.config.js b/babel.config.js
index 9d89e13..68405ea 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,4 +1,4 @@
-module.exports = function (api) {
+export default function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
diff --git a/src/app/(app)/onboarding.tsx b/src/app/(app)/onboarding.tsx
index 2dbc29c..6a133d3 100644
--- a/src/app/(app)/onboarding.tsx
+++ b/src/app/(app)/onboarding.tsx
@@ -27,6 +27,7 @@ import {
GestureHandlerRootView,
} from "react-native-gesture-handler";
import Animated, {
+ SharedValue,
runOnJS,
useDerivedValue,
useSharedValue,
@@ -216,19 +217,6 @@ export default function OnboardingScreen() {
.build();
});
- const dot0Fill = useDerivedValue(() => {
- return currentView.value >= 0 ? palette.blueTint2 : palette.transparent;
- });
- const dot1Fill = useDerivedValue(() => {
- return currentView.value >= 1 ? palette.blueTint2 : palette.transparent;
- });
- const dot2Fill = useDerivedValue(() => {
- return currentView.value >= 2 ? palette.blueTint2 : palette.transparent;
- });
- const dot3Fill = useDerivedValue(() => {
- return currentView.value >= 3 ? palette.blueTint2 : palette.transparent;
- });
-
const buttonP = useDerivedValue(() => {
buttonTextChanged.value;
if (!fontMgr) {
@@ -258,10 +246,12 @@ export default function OnboardingScreen() {
const backListener = BackHandler.addEventListener(
"hardwareBackPress",
() => {
+ // when this callback returns false, the hardware back is
+ // actuated, when it returns true the hardware back is ignored.
if (currentView.value === 0) {
return false; // allow hardware back from first view only
} else {
- return true; // disable hardware back, we'll handle the gesture
+ return true;
}
},
);
@@ -271,30 +261,32 @@ export default function OnboardingScreen() {
};
}, []);
+ function replaceOrGoBack() {
+ // this will be called in an animation callback using runOnJS, need to
+ // encapsulate so we can consume the output of a synchronous function.
+ if (router.canGoBack()) {
+ router.back();
+ } else {
+ router.replace("/(app)/");
+ }
+ }
+
async function goToNext() {
if (currentView.value < views.length - 1) {
+ // continue onboarding
const beforeNext = views[currentView.value].beforeNext;
if (beforeNext) {
await beforeNext();
}
currentView.value += 1;
} else {
- runOnJS(goToMainApp)();
- }
- }
- function replaceOrGoBack() {
- if (router.canGoBack()) {
- router.back();
- } else {
- router.replace("/(app)/");
+ // onboarding done, record completion and fade to main view
+ await AsyncStorage.setItem("hasOnboarded", "true");
+ everythingOpacity.value = withTiming(0, { duration: 500 }, () => {
+ runOnJS(replaceOrGoBack)();
+ });
}
}
- async function goToMainApp() {
- everythingOpacity.value = withTiming(0, { duration: 500 }, () => {
- runOnJS(replaceOrGoBack)();
- });
- await AsyncStorage.setItem("hasOnboarded", "true");
- }
const buttonGesture = Gesture.Tap().onEnd(goToNext).runOnJS(true);
@@ -397,57 +389,9 @@ export default function OnboardingScreen() {
/>
-
-
-
-
-
-
-
-
@@ -503,3 +447,82 @@ export default function OnboardingScreen() {
);
}
+
+function ProgressDots({
+ dotWidth,
+ currentView,
+}: {
+ dotWidth: number;
+ currentView: SharedValue;
+}) {
+ // Couldn't figure out a way to avoid hardcoding these
+ const dot0Fill = useDerivedValue(() => {
+ return currentView.value >= 0 ? palette.blueTint2 : palette.transparent;
+ });
+ const dot1Fill = useDerivedValue(() => {
+ return currentView.value >= 1 ? palette.blueTint2 : palette.transparent;
+ });
+ const dot2Fill = useDerivedValue(() => {
+ return currentView.value >= 2 ? palette.blueTint2 : palette.transparent;
+ });
+ const dot3Fill = useDerivedValue(() => {
+ return currentView.value >= 3 ? palette.blueTint2 : palette.transparent;
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/index.tsx b/src/app/index.tsx
index 48fa640..e0b5382 100644
--- a/src/app/index.tsx
+++ b/src/app/index.tsx
@@ -1,5 +1,7 @@
+import AsyncStorage from "@react-native-async-storage/async-storage";
import { Canvas } from "@shopify/react-native-skia";
import { router } from "expo-router";
+import * as SplashScreen from "expo-splash-screen";
import React from "react";
import { View, useWindowDimensions } from "react-native";
import { runOnJS, useSharedValue, withTiming } from "react-native-reanimated";
@@ -9,7 +11,8 @@ import { timedLog } from "@/src/common/utils";
import { SafeAreaView } from "@/src/components/SafeAreaView";
import { PsiphonConduitLoading } from "@/src/components/canvas/PsiphonConduitLoading";
import { sharedStyles as ss } from "@/src/styles";
-import AsyncStorage from "@react-native-async-storage/async-storage";
+
+SplashScreen.preventAutoHideAsync();
export default function Index() {
const { signIn } = useAuthContext();
@@ -20,6 +23,7 @@ export default function Index() {
const opacity = useSharedValue(0);
async function doSignIn() {
+ await SplashScreen.hideAsync();
timedLog("Starting signIn");
const signInResult = await signIn();
if (signInResult instanceof Error) {
diff --git a/src/components/GitHash.tsx b/src/components/GitHash.tsx
index 60c8f9a..0ae53fe 100644
--- a/src/components/GitHash.tsx
+++ b/src/components/GitHash.tsx
@@ -31,7 +31,7 @@ export function GitHash() {
ss.bodyFont,
]}
>
- v.{GIT_HASH.substr(0, 12)}
+ v.{GIT_HASH.substring(0, 12)}
);
diff --git a/src/components/canvas/Phone.tsx b/src/components/canvas/Phone.tsx
index a5a5a11..a9700ea 100644
--- a/src/components/canvas/Phone.tsx
+++ b/src/components/canvas/Phone.tsx
@@ -16,6 +16,7 @@ import {
import React from "react";
import {
Easing,
+ SharedValue,
cancelAnimation,
useAnimatedReaction,
useSharedValue,
@@ -23,7 +24,6 @@ import {
withRepeat,
withTiming,
} from "react-native-reanimated";
-import { SharedValue } from "react-native-reanimated/lib/typescript/Animated";
import { ConduitConnectionLight } from "@/src/components/canvas/ConduitConnectionLight";
diff --git a/src/i18n/fake-translation.js b/src/i18n/fake-translation.js
index 0589c24..ac4d7af 100644
--- a/src/i18n/fake-translation.js
+++ b/src/i18n/fake-translation.js
@@ -1,6 +1,6 @@
"use strict";
-const fs = require("fs").promises;
+import { promises as fs } from "fs";
const path = require("path");
const pseudo = require("./pseudo").PSEUDO;
@@ -14,7 +14,7 @@ let englishLines,
async function getEnglishLines() {
const data = await fs.readFile(
path.resolve(__dirname, "locales/en/translation.json"),
- (err, data) => {
+ (err, _) => {
if (err) throw err;
},
);
diff --git a/src/i18n/i18n.test.ts b/src/i18n/i18n.test.ts
index 772650c..e42e2e1 100644
--- a/src/i18n/i18n.test.ts
+++ b/src/i18n/i18n.test.ts
@@ -1,11 +1,10 @@
import * as fs from "fs";
import i18n from "i18next";
+import path from "path";
import { findBestLanguageTag } from "react-native-localize";
import i18nService from "./i18n";
-const path = require("path");
-
jest.mock("react-native-localize", () => ({
findBestLanguageTag: jest.fn(() => ({ languageTag: "fr" })),
}));
diff --git a/src/i18n/pseudo.js b/src/i18n/pseudo.js
index 0d2a658..f3d3b38 100644
--- a/src/i18n/pseudo.js
+++ b/src/i18n/pseudo.js
@@ -67,17 +67,17 @@ function mapContent(fn, val) {
return modified.join("");
}
-function Pseudo(id, name, charMap, modFn) {
- this.id = id;
- this.translate = mapContent.bind(null, function (val) {
- return replaceChars(charMap, modFn(val));
- });
- this.name = this.translate(name);
+class Pseudo {
+ constructor(id, name, charMap, modFn) {
+ this.id = id;
+ this.translate = mapContent.bind(null, function (val) {
+ return replaceChars(charMap, modFn(val));
+ });
+ this.name = this.translate(name);
+ }
}
-var PSEUDO = {
+export const PSEUDO = {
xa: new Pseudo("xa", "Packaged Accented", ACCENTED_MAP, makeLonger),
xb: new Pseudo("xb", "Packaged Mirrored", FLIPPED_MAP, makeRTL),
};
-
-exports.PSEUDO = PSEUDO;