From e6971366fe49a7ed569d72c5d986cc6dbb47886d Mon Sep 17 00:00:00 2001 From: Tasker <26747046+tmgrask@users.noreply.github.com> Date: Tue, 10 Dec 2024 22:23:45 -0500 Subject: [PATCH 1/6] android 1.3.0-RC.25 (#80) --- android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index bec951d..8aafdbb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -119,8 +119,8 @@ android { applicationId 'ca.psiphon.conduit' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 24 - versionName "1.3.0-RC.24" + versionCode 25 + versionName "1.3.0-RC.25" } signingConfigs { config { From 0397a1a4f5a36f93f5269776058c2fb355731c76 Mon Sep 17 00:00:00 2001 From: Tasker <26747046+tmgrask@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:11:24 -0500 Subject: [PATCH 2/6] fix index layout (#81) Includes a workaround for this useWindowDimensions() bug: https://github.com/facebook/react-native/issues/47080 --- src/app/(app)/index.tsx | 33 ++++++---- src/app/(app)/onboarding.tsx | 108 ++++++++++++++++++------------- src/components/ConduitStatus.tsx | 1 - 3 files changed, 85 insertions(+), 57 deletions(-) diff --git a/src/app/(app)/index.tsx b/src/app/(app)/index.tsx index 16971aa..ec206da 100644 --- a/src/app/(app)/index.tsx +++ b/src/app/(app)/index.tsx @@ -18,8 +18,9 @@ */ import React from "react"; -import { useWindowDimensions } from "react-native"; +import { LayoutChangeEvent, useWindowDimensions, View } from "react-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; import { ConduitOrbToggle } from "@/src/components/ConduitOrbToggle"; import { ConduitSettings } from "@/src/components/ConduitSettings"; @@ -28,34 +29,44 @@ import { GitHash } from "@/src/components/GitHash"; import { KeepAwakeOnIOS } from "@/src/components/KeepAwake"; import { LogoWordmark } from "@/src/components/LogoWordmark"; import { SafeAreaView } from "@/src/components/SafeAreaView"; +import { sharedStyles as ss } from "@/src/styles"; export default function HomeScreen() { const win = useWindowDimensions(); + const insets = useSafeAreaInsets(); + + // Derive usable dimensions from an absolutely positioned View + // https://github.com/facebook/react-native/issues/47080 + const [totalUsableWidth, setTotalUsableWidth] = React.useState(win.width); + const [totalUsableHeight, setTotalUsableHeight] = React.useState( + win.height, + ); + + function onScreenLayout(event: LayoutChangeEvent) { + setTotalUsableWidth(event.nativeEvent.layout.width); + setTotalUsableHeight(event.nativeEvent.layout.height - insets.top); + } // NOTE this assumes a portrait layout. - const totalUsableHeight = win.height; - const totalUsableWidth = win.width; - const logoWordmarkHeight = totalUsableHeight * 0.1; - const conduitOrbToggleHeight = totalUsableHeight * 0.6; - const conduitStatusHeight = totalUsableHeight * 0.3; return ( + {/* Header takes up 10% of vertical space */} - {/* Orb takes up the middle 60% of the vertical space */} + {/* Orb takes up the middle 55% of the vertical space */} - {/* Status taking up bottom 30% of the vertical space */} + {/* Status taking up bottom 35% of the vertical space */} {/* Settings icon is absolutely positioned bottom right */} diff --git a/src/app/(app)/onboarding.tsx b/src/app/(app)/onboarding.tsx index edc45b5..bab7923 100644 --- a/src/app/(app)/onboarding.tsx +++ b/src/app/(app)/onboarding.tsx @@ -39,7 +39,12 @@ import * as Notifications from "expo-notifications"; import { useRouter } from "expo-router"; import React from "react"; import { useTranslation } from "react-i18next"; -import { BackHandler, useWindowDimensions } from "react-native"; +import { + BackHandler, + LayoutChangeEvent, + View, + useWindowDimensions, +} from "react-native"; import { Gesture, GestureDetector, @@ -86,8 +91,17 @@ export default function OnboardingScreen() { } }, [notificationPermissions]); - const usableWidth = win.width - (insets.left + insets.right); - const usableHeight = win.height - (insets.top + insets.bottom); + // Derive usable dimensions from an absolutely positioned View + // https://github.com/facebook/react-native/issues/47080 + const [totalUsableWidth, setTotalUsableWidth] = React.useState(win.width); + const [totalUsableHeight, setTotalUsableHeight] = React.useState( + win.height, + ); + + function onScreenLayout(event: LayoutChangeEvent) { + setTotalUsableWidth(event.nativeEvent.layout.width); + setTotalUsableHeight(event.nativeEvent.layout.height - insets.top); + } const views = [ { @@ -156,47 +170,50 @@ export default function OnboardingScreen() { // header takes up the first 12% of usableHeight const headerTransform = [ - { translateY: usableHeight * 0.05 }, - { translateX: usableWidth * 0.02 }, + { translateY: totalUsableHeight * 0.05 }, + { translateX: totalUsableWidth * 0.02 }, ]; const headerSize = { - width: usableWidth * 0.96, + width: totalUsableWidth * 0.96, }; // image takes up the next 28% of usableHeight (40% total) const sceneTransform = [ - { translateY: usableHeight * 0.12 }, + { translateY: totalUsableHeight * 0.12 }, //{ translateX: usableWidth * 0.18 }, ]; const sceneSize = { - width: usableWidth, - height: usableHeight * 0.25, + width: totalUsableWidth, + height: totalUsableHeight * 0.25, }; // body takes up the next 36% of usableHeight (76% total) const bodyTransform = [ - { translateY: usableHeight * 0.4 }, - { translateX: usableWidth * 0.06 }, + { translateY: totalUsableHeight * 0.4 }, + { translateX: totalUsableWidth * 0.06 }, ]; const bodySize = { - width: usableWidth * 0.88, - height: usableHeight * 0.36, + width: totalUsableWidth * 0.88, + height: totalUsableHeight * 0.36, }; // indicator dots take up the next 3% of usableHeight (79% total) const dotWidth = 24; const dotsTransform = [ - { translateY: usableHeight * 0.79 }, - { translateX: usableWidth * 0.5 - (dotWidth * (views.length - 1)) / 2 }, + { translateY: totalUsableHeight * 0.79 }, + { + translateX: + totalUsableWidth * 0.5 - (dotWidth * (views.length - 1)) / 2, + }, ]; // button claims the next 8% of usableHeight (90% total) const buttonTransform = [ - { translateY: usableHeight * 0.82 }, - { translateX: usableWidth * 0.06 }, + { translateY: totalUsableHeight * 0.82 }, + { translateX: totalUsableWidth * 0.06 }, ]; const buttonSize = { - width: usableWidth * 0.88, - height: usableHeight * 0.08, + width: totalUsableWidth * 0.88, + height: totalUsableHeight * 0.08, }; const buttonBorderRadius = 15; - const privacyPolicyHeight = usableHeight * 0.05; + const privacyPolicyHeight = totalUsableHeight * 0.05; // 10% of usable height is left for the Privacy Policy link to appear in const fontMgr = useFonts({ @@ -329,10 +346,10 @@ export default function OnboardingScreen() { const anywhereGesture = Gesture.Pan() .onEnd(async (event) => { - if (event.translationX < -usableWidth * 0.1) { + if (event.translationX < -totalUsableWidth * 0.1) { // when user swipes over 10% to the right, move view forward goToNext(); - } else if (event.translationX > usableWidth * 0.1) { + } else if (event.translationX > totalUsableWidth * 0.1) { // when user swipes over 10% to the left, move view backwards if (currentView.value > 0) { currentView.value -= 1; @@ -345,7 +362,7 @@ export default function OnboardingScreen() { const everythingOpacityMatrix = useDerivedValue(() => { // prettier-ignore return [ - //R, G, B, A, Bias + //R, G, B, A, Bias 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, @@ -357,7 +374,7 @@ export default function OnboardingScreen() { const contentOpacityMatrix = useDerivedValue(() => { // prettier-ignore return [ - //R, G, B, A, Bias + //R, G, B, A, Bias 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, @@ -370,8 +387,9 @@ export default function OnboardingScreen() { }, []); return ( - - + + + @@ -460,8 +478,8 @@ export default function OnboardingScreen() { aria-valuetext={bodyText} style={{ position: "absolute", - width: usableWidth, - height: usableHeight, + width: totalUsableWidth, + height: totalUsableHeight, }} /> @@ -479,24 +497,24 @@ export default function OnboardingScreen() { }} /> - - - - + + + + - - - - + + + + - - + + ); } diff --git a/src/components/ConduitStatus.tsx b/src/components/ConduitStatus.tsx index bd72e85..9113335 100644 --- a/src/components/ConduitStatus.tsx +++ b/src/components/ConduitStatus.tsx @@ -200,7 +200,6 @@ export function ConduitStatus({ Date: Wed, 11 Dec 2024 11:14:48 -0500 Subject: [PATCH 3/6] android 1.3.0-RC.26 (#82) --- android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 8aafdbb..cbccf71 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -119,8 +119,8 @@ android { applicationId 'ca.psiphon.conduit' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 25 - versionName "1.3.0-RC.25" + versionCode 26 + versionName "1.3.0-RC.26" } signingConfigs { config { From 72c21520aa50e1ba6c7729b85b591c2f7714bba1 Mon Sep 17 00:00:00 2001 From: Tasker <26747046+tmgrask@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:58:46 -0500 Subject: [PATCH 4/6] revert root view based layout fix (#83) * deriving layout from root view doesn't work when keyboard can be opened, as this re-renders everything below the root view * leave 3% blank to avoid overlapping elements --- src/app/(app)/index.tsx | 24 +++++++++--------------- src/components/ConduitStatus.tsx | 2 ++ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/app/(app)/index.tsx b/src/app/(app)/index.tsx index ec206da..6d5c87d 100644 --- a/src/app/(app)/index.tsx +++ b/src/app/(app)/index.tsx @@ -18,7 +18,7 @@ */ import React from "react"; -import { LayoutChangeEvent, useWindowDimensions, View } from "react-native"; +import { useWindowDimensions } from "react-native"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import { useSafeAreaInsets } from "react-native-safe-area-context"; @@ -29,39 +29,33 @@ import { GitHash } from "@/src/components/GitHash"; import { KeepAwakeOnIOS } from "@/src/components/KeepAwake"; import { LogoWordmark } from "@/src/components/LogoWordmark"; import { SafeAreaView } from "@/src/components/SafeAreaView"; -import { sharedStyles as ss } from "@/src/styles"; export default function HomeScreen() { const win = useWindowDimensions(); const insets = useSafeAreaInsets(); - // Derive usable dimensions from an absolutely positioned View + // This layout is slightly imprecise due to a bug in Android/React Native // https://github.com/facebook/react-native/issues/47080 - const [totalUsableWidth, setTotalUsableWidth] = React.useState(win.width); - const [totalUsableHeight, setTotalUsableHeight] = React.useState( - win.height, - ); - - function onScreenLayout(event: LayoutChangeEvent) { - setTotalUsableWidth(event.nativeEvent.layout.width); - setTotalUsableHeight(event.nativeEvent.layout.height - insets.top); - } + // For now, ConduitStatus is absolutely positioned and pinned to bottom to + // compensate for the slightly inaccurate totalUsableHeight value, and we + // leave 3% "blank" to hopefully avoid overlapping elements + const totalUsableHeight = win.height - insets.top * 1.5; + const totalUsableWidth = win.width; // NOTE this assumes a portrait layout. return ( - {/* Header takes up 10% of vertical space */} - {/* Orb takes up the middle 55% of the vertical space */} + {/* Orb takes up the middle 52% of the vertical space */} {/* Status taking up bottom 35% of the vertical space */} Date: Wed, 11 Dec 2024 16:00:56 -0500 Subject: [PATCH 5/6] android 1.3.0-RC.27 (#84) --- android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index cbccf71..5bb57cd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -119,8 +119,8 @@ android { applicationId 'ca.psiphon.conduit' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 26 - versionName "1.3.0-RC.26" + versionCode 27 + versionName "1.3.0-RC.27" } signingConfigs { config { From 0c5aa9f3a5dc68c285ebee33924638dde29f0987 Mon Sep 17 00:00:00 2001 From: Tasker <26747046+tmgrask@users.noreply.github.com> Date: Wed, 11 Dec 2024 22:57:48 -0500 Subject: [PATCH 6/6] android 1.3.0 (#85) --- android/app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 5bb57cd..a1d3c9d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -119,8 +119,8 @@ android { applicationId 'ca.psiphon.conduit' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 27 - versionName "1.3.0-RC.27" + versionCode 28 + versionName "1.3.0" } signingConfigs { config {