index.tsx 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import { useEffect, useRef, useState } from "react";
  2. import { BackHandler, Platform, StyleSheet, View } from "react-native";
  3. import { LogLevel, OneSignal } from 'react-native-onesignal';
  4. import { WebView, WebViewNavigation } from "react-native-webview";
  5. import BottomTabs from "../components/bottom-tabs";
  6. import Header from "../components/header";
  7. import WebViewContainer from "../components/web-view";
  8. import { ONESIGNAL_APP_ID } from "../constants/settings";
  9. import { WebViewHandlers } from "../types/webview-handlers-type";
  10. import { requestAndroidPermissions } from "../utils/android-permissins-request";
  11. export default function App() {
  12. const webViewRef = useRef<WebView>(null);
  13. const [loggedin, setLoggedIn] = useState(false);
  14. const [title, setTitle] = useState("");
  15. const [loading, setLoadingState] = useState(false);
  16. const [canGoBack, setCanGoBack] = useState(false);
  17. const [data, setData] = useState<any>(null);
  18. const [backButtonEnabled, setBackButtonEnabled] = useState(true);
  19. // android permissions request
  20. useEffect(() => {
  21. requestAndroidPermissions();
  22. }, []);
  23. // OneSignal initialization
  24. useEffect(() => {
  25. OneSignal.Debug.setLogLevel(LogLevel.Verbose);
  26. OneSignal.setConsentRequired(true);
  27. OneSignal.initialize(ONESIGNAL_APP_ID);
  28. OneSignal.Notifications.addEventListener('click', (event:any) => {
  29. console.log('OneSignal: notification clicked:', event);
  30. const url = event.notification?.additionalData?.url;
  31. if (url && webViewRef.current) {
  32. webViewRef.current.injectJavaScript(`window.location = '${url}';`);
  33. }
  34. });
  35. }, []);
  36. // Android hardware back button
  37. useEffect(() => {
  38. let backHandler: any;
  39. if (Platform.OS === "android") {
  40. backHandler = BackHandler.addEventListener("hardwareBackPress", () => {
  41. if (backButtonEnabled && webViewRef.current) {
  42. webViewRef.current.goBack();
  43. return true;
  44. }
  45. return false;
  46. });
  47. }
  48. // cleanup
  49. return () => {
  50. if (Platform.OS === "android" && backHandler) {
  51. backHandler.remove();
  52. }
  53. };
  54. }, [backButtonEnabled]);
  55. // Handle navigation changes
  56. const handleNavChange = (nav: WebViewNavigation) => {
  57. setCanGoBack(nav.canGoBack);
  58. setTitle(nav.title || ""); // replaced with 'handleTitleChange'
  59. };
  60. // All WebViewHandlers
  61. const webViewHandlers: WebViewHandlers = {
  62. setLoading: (b:boolean) => {
  63. setLoadingState(b);
  64. },
  65. setData,
  66. setLoggedIn,
  67. onVideoCallStart: (uri, audio) => {
  68. console.log("Video call start:", uri, audio);
  69. // Add your actual video call logic here
  70. },
  71. endVideoCall: () => {
  72. console.log("Video call stop");
  73. },
  74. onRequestPurchase: (payload) => {
  75. console.log("Purchase request:", payload);
  76. },
  77. onRequestSubscription: (payload) => {
  78. console.log("Subscription request:", payload);
  79. },
  80. onHomeMenu: () => {
  81. console.log("Goto home");
  82. webViewRef.current?.reload(); // Example: reload home page
  83. },
  84. reload: () => {
  85. webViewRef.current?.reload();
  86. },
  87. onStateChange: handleNavChange,
  88. onLoadProgress: (progress) => setLoadingState(progress < 1),
  89. //onTitleChange: (newTitle) => setTitle(newTitle),
  90. };
  91. return (
  92. <View style={styles.container}>
  93. <Header
  94. title={title}
  95. loading={loading}
  96. canGoBack={canGoBack}
  97. onBack={() => webViewRef.current?.goBack()}
  98. />
  99. <WebViewContainer
  100. ref={webViewRef}
  101. {...webViewHandlers}
  102. />
  103. {loggedin === true && (
  104. <BottomTabs webViewRef={webViewRef} data={data} />
  105. )}
  106. </View>
  107. );
  108. }
  109. const styles = StyleSheet.create({
  110. container: { flex: 1 },
  111. });
  112. /*
  113. import { Image } from 'expo-image';
  114. import { Platform, StyleSheet } from 'react-native';
  115. import { HelloWave } from '@/components/hello-wave';
  116. import ParallaxScrollView from '@/components/parallax-scroll-view';
  117. import { ThemedText } from '@/components/themed-text';
  118. import { ThemedView } from '@/components/themed-view';
  119. import { Link } from 'expo-router';
  120. export default function HomeScreen() {
  121. return (
  122. <ParallaxScrollView
  123. headerBackgroundColor={{ light: '#A1CEDC', dark: '#1D3D47' }}
  124. headerImage={
  125. <Image
  126. source={require('@/assets/images/partial-react-logo.png')}
  127. style={styles.reactLogo}
  128. />
  129. }>
  130. <ThemedView style={styles.titleContainer}>
  131. <ThemedText type="title">Welcome!</ThemedText>
  132. <HelloWave />
  133. </ThemedView>
  134. <ThemedView style={styles.stepContainer}>
  135. <ThemedText type="subtitle">Step 1: Try it</ThemedText>
  136. <ThemedText>
  137. Edit <ThemedText type="defaultSemiBold">app/(tabs)/index.tsx</ThemedText> to see changes.
  138. Press{' '}
  139. <ThemedText type="defaultSemiBold">
  140. {Platform.select({
  141. ios: 'cmd + d',
  142. android: 'cmd + m',
  143. web: 'F12',
  144. })}
  145. </ThemedText>{' '}
  146. to open developer tools.
  147. </ThemedText>
  148. </ThemedView>
  149. <ThemedView style={styles.stepContainer}>
  150. <Link href="/modal">
  151. <Link.Trigger>
  152. <ThemedText type="subtitle">Step 2: Explore</ThemedText>
  153. </Link.Trigger>
  154. <Link.Preview />
  155. <Link.Menu>
  156. <Link.MenuAction title="Action" icon="cube" onPress={() => alert('Action pressed')} />
  157. <Link.MenuAction
  158. title="Share"
  159. icon="square.and.arrow.up"
  160. onPress={() => alert('Share pressed')}
  161. />
  162. <Link.Menu title="More" icon="ellipsis">
  163. <Link.MenuAction
  164. title="Delete"
  165. icon="trash"
  166. destructive
  167. onPress={() => alert('Delete pressed')}
  168. />
  169. </Link.Menu>
  170. </Link.Menu>
  171. </Link>
  172. <ThemedText>
  173. {`Tap the Explore tab to learn more about what's included in this starter app.`}
  174. </ThemedText>
  175. </ThemedView>
  176. <ThemedView style={styles.stepContainer}>
  177. <ThemedText type="subtitle">Step 3: Get a fresh start</ThemedText>
  178. <ThemedText>
  179. {`When you're ready, run `}
  180. <ThemedText type="defaultSemiBold">npm run reset-project</ThemedText> to get a fresh{' '}
  181. <ThemedText type="defaultSemiBold">app</ThemedText> directory. This will move the current{' '}
  182. <ThemedText type="defaultSemiBold">app</ThemedText> to{' '}
  183. <ThemedText type="defaultSemiBold">app-example</ThemedText>.
  184. </ThemedText>
  185. </ThemedView>
  186. </ParallaxScrollView>
  187. );
  188. }
  189. const styles = StyleSheet.create({
  190. titleContainer: {
  191. flexDirection: 'row',
  192. alignItems: 'center',
  193. gap: 8,
  194. },
  195. stepContainer: {
  196. gap: 8,
  197. marginBottom: 8,
  198. },
  199. reactLogo: {
  200. height: 178,
  201. width: 290,
  202. bottom: 0,
  203. left: 0,
  204. position: 'absolute',
  205. },
  206. });
  207. */