From 98d2b455191364f1a24a3e664fd51ada6dc85ce9 Mon Sep 17 00:00:00 2001 From: Prem Kumar Sharma Date: Tue, 24 Dec 2024 19:11:24 +0530 Subject: [PATCH 1/3] feat: Add Force Update Implemented a Force Update feature to ensure users are always on the latest version of the app. This helps provide access to the newest features and fixes by guiding users to update when a new version is available. --- .gitignore | 1 + App.js | 18 +++--- src/Components/ForceUpdate/index.js | 88 +++++++++++++++++++++++++++++ src/Components/Func/getReleases.js | 23 ++++++++ src/Components/UIComp/MarkDown.js | 34 ++++++++--- src/Redux/Controller/Interceptor.js | 3 - src/Screens/Update/index.js | 37 +++++------- 7 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 src/Components/ForceUpdate/index.js create mode 100644 src/Components/Func/getReleases.js diff --git a/.gitignore b/.gitignore index 7df07c8..5b9ae4d 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,7 @@ global.jks **/LocalComic/index.js **/Actions/Download.js **/OfflineComic/index.js +**/ForceUpdate/Func.js #ignore app.json file app.json diff --git a/App.js b/App.js index f81daf5..530aab8 100644 --- a/App.js +++ b/App.js @@ -1,11 +1,12 @@ -import {Provider} from 'react-redux'; -import {PersistGate} from 'redux-persist/integration/react'; -import {persistor, store} from './src/Redux/Store'; -import {GestureHandlerRootView} from 'react-native-gesture-handler'; -import {RootNavigation} from './src/Navigation'; +import { Provider } from 'react-redux'; +import { PersistGate } from 'redux-persist/integration/react'; +import { persistor, store } from './src/Redux/Store'; +import { GestureHandlerRootView } from 'react-native-gesture-handler'; +import { RootNavigation } from './src/Navigation'; import Loading from './src/Components/UIComp/Loading'; import Toast from 'react-native-toast-message'; -import {PaperProvider} from 'react-native-paper'; +import { PaperProvider } from 'react-native-paper'; +import ForceUpdate from './src/Components/ForceUpdate'; /** * The main App component that sets up the root of the application. @@ -16,13 +17,16 @@ import {PaperProvider} from 'react-native-paper'; * @returns {JSX.Element} The root component of the application. */ const App = () => { + + return ( - + } persistor={persistor}> + diff --git a/src/Components/ForceUpdate/index.js b/src/Components/ForceUpdate/index.js new file mode 100644 index 0000000..788af89 --- /dev/null +++ b/src/Components/ForceUpdate/index.js @@ -0,0 +1,88 @@ +import React, { useEffect, useState } from 'react'; +import { + View, + Text, + StyleSheet, + TouchableOpacity, + Image, + Modal, + Linking +} from 'react-native'; +import { checkUpdate } from './Func'; + +const ForceUpdate = () => { + const [isForceUpdate, setIsForceUpdate] = useState(false); + useEffect(() => { + checkUpdate(setIsForceUpdate, handleUpdate) + }, []); + + const handleUpdate = () => { + Linking.openURL('https://p2devs.github.io/InkNest/'); + } + + return ( + + + + Update Required + + A newer version of the app is available. Please update to continue using the app. + + + Update Now + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + padding: 30, + backgroundColor: 'rgba(0, 0, 0, 0.8)', + }, + image: { + width: 200, + height: 200, + marginBottom: 20, + borderRadius: 20, + resizeMode: 'contain', + }, + title: { + fontSize: 24, + fontWeight: 'bold', + color: '#FFFFFF', + marginBottom: 10, + }, + message: { + fontSize: 16, + color: '#FFFFFF', + textAlign: 'center', + marginBottom: 20, + lineHeight: 24, + }, + updateButton: { + backgroundColor: '#007BFF', + paddingVertical: 12, + paddingHorizontal: 24, + borderRadius: 8, + shadowColor: '#000', + shadowOffset: { width: 0, height: 2 }, + shadowOpacity: 0.2, + shadowRadius: 3, + elevation: 3, + }, + updateButtonText: { + color: '#FFFFFF', + fontSize: 16, + fontWeight: 'bold', + }, +}); + +export default ForceUpdate; \ No newline at end of file diff --git a/src/Components/Func/getReleases.js b/src/Components/Func/getReleases.js new file mode 100644 index 0000000..ceda2f1 --- /dev/null +++ b/src/Components/Func/getReleases.js @@ -0,0 +1,23 @@ +import axios from "axios"; +import APICaller from "../../Redux/Controller/Interceptor"; +import { Alert, Linking, Modal, View } from "react-native"; +import DeviceInfo from "react-native-device-info"; + +export const getReleases = async (setLogs = null, navigation = null) => { + try { + let response = await APICaller.get('https://api.github.com/repos/p2devs/InkNest/releases') + + if (setLogs) { + setLogs(response?.data); + } + + return response?.data + } catch (error) { + + if (navigation) { + navigation.goBack(); + } + + return null; + } +} diff --git a/src/Components/UIComp/MarkDown.js b/src/Components/UIComp/MarkDown.js index e90b3d2..7baba41 100644 --- a/src/Components/UIComp/MarkDown.js +++ b/src/Components/UIComp/MarkDown.js @@ -12,10 +12,16 @@ const parseMarkdown = (text) => { return {line.substring(3)}; } else if (line.startsWith('### ')) { return {line.substring(4)}; + } else if (line.startsWith('**') && line.includes('**')) { + return {line.replaceAll('**', '')}; } else if (line.startsWith('* ')) { return {'\u2022'} {line.substring(2)}; } else if (line.startsWith('- ')) { return {'\u2022'} {line.substring(2)}; + } else if (line.startsWith(' - ')) { + return {'\u2219'} {line.substring(4)}; + } else if (line.startsWith(' - ')) { + return {'\u2023'} {line.substring(7)}; } else if (line.startsWith('> ')) { return {line.substring(2)}; } else if (line.startsWith('```')) { @@ -26,8 +32,7 @@ const parseMarkdown = (text) => { const url = line.substring(endIndex + 2, line.length - 1); return Linking.openURL(url)}> {text}; } else { - return {line}; + return {line}; } }); @@ -50,30 +55,43 @@ const styles = StyleSheet.create({ color: "white", fontSize: 28, fontWeight: 'bold', - marginBottom: 10, }, h2: { color: "white", fontSize: 24, fontWeight: 'bold', - marginBottom: 10, }, h3: { color: "white", fontSize: 18, fontWeight: 'bold', - marginBottom: 10, }, paragraph: { color: "white", fontSize: 16, - marginBottom: 10, + }, + bold: { + fontWeight: 'bold', + color: "white", + fontSize: 16, }, listItem: { color: "white", fontSize: 16, marginBottom: 5, - paddingLeft: 20, + paddingLeft: 15, + }, + subListItem: { + color: "white", + fontSize: 16, + marginBottom: 5, + paddingLeft: 30, + }, + subSubListItem: { + color: "white", + fontSize: 16, + marginBottom: 5, + paddingLeft: 50, }, blockquote: { color: "white", @@ -82,7 +100,6 @@ const styles = StyleSheet.create({ borderLeftWidth: 4, borderLeftColor: '#ddd', paddingLeft: 10, - marginBottom: 10, }, codeBlock: { color: "white", @@ -90,7 +107,6 @@ const styles = StyleSheet.create({ backgroundColor: '#f4f4f4', padding: 10, borderRadius: 5, - marginBottom: 10, }, link: { color: 'steelblue', diff --git a/src/Redux/Controller/Interceptor.js b/src/Redux/Controller/Interceptor.js index 273cccd..5261690 100644 --- a/src/Redux/Controller/Interceptor.js +++ b/src/Redux/Controller/Interceptor.js @@ -28,10 +28,7 @@ APICaller.interceptors.response.use( async response => { // Stop the trace when the response is received const {httpMetric} = response.config.metadata; - - console.log(response, 'response', httpMetric); - httpMetric.setHttpResponseCode(response.status); httpMetric.setResponseContentType(response.headers['content-type']); diff --git a/src/Screens/Update/index.js b/src/Screens/Update/index.js index d4957e8..305bd09 100644 --- a/src/Screens/Update/index.js +++ b/src/Screens/Update/index.js @@ -1,30 +1,23 @@ -import axios from 'axios'; -import React, {useLayoutEffect, useState} from 'react'; -import {View, Text, TouchableOpacity, ScrollView, Alert} from 'react-native'; -import {heightPercentageToDP as hp} from 'react-native-responsive-screen'; +import React, { useLayoutEffect, useState } from 'react'; +import { View, Text, TouchableOpacity, ScrollView, Alert } from 'react-native'; +import { heightPercentageToDP as hp } from 'react-native-responsive-screen'; -import {SafeAreaView} from 'react-native-safe-area-context'; +import { SafeAreaView } from 'react-native-safe-area-context'; import Ionicons from 'react-native-vector-icons/Ionicons'; import Markdown from '../../Components/UIComp/MarkDown'; import Header from '../../Components/UIComp/Header'; +import { getReleases } from '../../Components/Func/getReleases'; -const UpdateScreen = ({navigation}) => { - const [updateLogs, setUpdateLogs] = useState([]); +const UpdateScreen = ({ navigation }) => { + const [updateLogs, setLogs] = useState([]); const [selected, setSelected] = useState(-1); + useLayoutEffect(() => { - axios - .get('https://api.github.com/repos/p2devs/InkNest/releases') - .then(response => { - setUpdateLogs(response.data); - }) - .catch(error => { - Alert.alert('Error', 'Failed to fetch update logs'); - navigation.goBack(); - console.log(error); - }); + getReleases(setLogs, navigation); }, []); + return ( - +
{ name="chevron-back" size={hp('3%')} color="#fff" - style={{marginRight: 10}} + style={{ marginRight: 10 }} /> { {updateLogs.map((log, index) => { return ( - + { if (selected == index) { @@ -99,9 +92,9 @@ const UpdateScreen = ({navigation}) => { } }} style={[ - {fontSize: hp('2%'), color: '#FFF', fontWeight: 'bold'}, + { fontSize: hp('2%'), color: '#FFF', fontWeight: 'bold' }, selected == index - ? {fontSize: hp('3%'), color: 'gold'} + ? { fontSize: hp('3%'), color: 'gold' } : null, ]}> {log.name} From 4fd73d3116b742259a343bee894d2a8a4fd22734 Mon Sep 17 00:00:00 2001 From: Pushpender Singh Date: Fri, 27 Dec 2024 00:00:15 +0530 Subject: [PATCH 2/3] feat: enable GWP ASan mode in AndroidManifest.xml --- android/app/src/main/AndroidManifest.xml | 3 ++- ios/InkNest.xcodeproj/project.pbxproj | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ff5c950..2e90278 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -10,7 +10,8 @@ android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" - android:supportsRtl="true"> + android:supportsRtl="true" + android:gwpAsanMode="always"> Date: Fri, 27 Dec 2024 19:25:36 +0530 Subject: [PATCH 3/3] feat: add Firebase In-App Messaging support --- android/app/build.gradle | 3 ++- firebase.json | 3 ++- ios/Podfile.lock | 20 ++++++++++++++++++++ package.json | 1 + src/Navigation/index.js | 14 ++++++++++++++ yarn.lock | 11 +++++++++++ 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 9b7b6bd..acba19f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -124,9 +124,10 @@ dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - implementation platform('com.google.firebase:firebase-bom:33.1.0') // Add firebase bom + implementation(platform("com.google.firebase:firebase-bom:33.7.0")) // Import the BoM for the Firebase platform implementation 'com.google.firebase:firebase-analytics' // Add firebase analytics implementation("com.google.firebase:firebase-crashlytics") // Add firebase crashlytics + implementation("com.google.firebase:firebase-inappmessaging-display") // Add firebase inapp messaging implementation ('com.facebook.soloader:soloader:0.12.1+') diff --git a/firebase.json b/firebase.json index 53321b9..c8a18e2 100644 --- a/firebase.json +++ b/firebase.json @@ -13,6 +13,7 @@ "messaging_auto_init_enabled": true, "messaging_android_notification_channel_id": "high-priority", "perf_auto_collection_enabled": false, - "google_analytics_automatic_screen_reporting_enabled": true + "google_analytics_automatic_screen_reporting_enabled": true, + "in_app_messaging_auto_collection_enabled": true } } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index c7ff8e1..0a071e6 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -61,6 +61,9 @@ PODS: - Firebase/Crashlytics (11.4.0): - Firebase/CoreOnly - FirebaseCrashlytics (~> 11.4.0) + - Firebase/InAppMessaging (11.4.0): + - Firebase/CoreOnly + - FirebaseInAppMessaging (~> 11.4.0-beta) - Firebase/Messaging (11.4.0): - Firebase/CoreOnly - FirebaseMessaging (~> 11.4.0) @@ -104,6 +107,13 @@ PODS: - GoogleUtilities/Environment (~> 8.0) - nanopb (~> 3.30910.0) - PromisesObjC (~> 2.4) + - FirebaseInAppMessaging (11.4.0-beta): + - FirebaseABTesting (~> 11.0) + - FirebaseCore (~> 11.0) + - FirebaseInstallations (~> 11.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - nanopb (~> 3.30910.0) - FirebaseInstallations (11.4.0): - FirebaseCore (~> 11.0) - GoogleUtilities/Environment (~> 8.0) @@ -1926,6 +1936,10 @@ PODS: - FirebaseCoreExtension (<= 11.4.0) - React-Core - RNFBApp + - RNFBInAppMessaging (21.6.1): + - Firebase/InAppMessaging (= 11.4.0) + - React-Core + - RNFBApp - RNFBMessaging (21.4.0): - Firebase/Messaging (<= 11.4.0) - FirebaseCoreExtension (<= 11.4.0) @@ -2256,6 +2270,7 @@ DEPENDENCIES: - "RNFBAnalytics (from `../node_modules/@react-native-firebase/analytics`)" - "RNFBApp (from `../node_modules/@react-native-firebase/app`)" - "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)" + - "RNFBInAppMessaging (from `../node_modules/@react-native-firebase/in-app-messaging`)" - "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)" - "RNFBPerf (from `../node_modules/@react-native-firebase/perf`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) @@ -2275,6 +2290,7 @@ SPEC REPOS: - FirebaseCoreExtension - FirebaseCoreInternal - FirebaseCrashlytics + - FirebaseInAppMessaging - FirebaseInstallations - FirebaseMessaging - FirebasePerformance @@ -2445,6 +2461,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-firebase/app" RNFBCrashlytics: :path: "../node_modules/@react-native-firebase/crashlytics" + RNFBInAppMessaging: + :path: "../node_modules/@react-native-firebase/in-app-messaging" RNFBMessaging: :path: "../node_modules/@react-native-firebase/messaging" RNFBPerf: @@ -2478,6 +2496,7 @@ SPEC CHECKSUMS: FirebaseCoreExtension: 4445e4cd877e0790c4af33bedca61eaef27b7513 FirebaseCoreInternal: f47dd28ae7782e6a4738aad3106071a8fe0af604 FirebaseCrashlytics: 41bbdd2b514a8523cede0c217aee6ef7ecf38401 + FirebaseInAppMessaging: 711d4357e9e6cfab5123f67ce1ea1f63bbb6442d FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414 FirebaseMessaging: f8a160d99c2c2e5babbbcc90c4a3e15db036aee2 FirebasePerformance: 89f9e52ea9d86d1819cde923a7ca397743df8593 @@ -2563,6 +2582,7 @@ SPEC CHECKSUMS: RNFBAnalytics: e4b4e0d20810d12309e5522432fbf4c0f2b2c2e1 RNFBApp: 21cbda2e7d2657cd3c92f490c050f5f0905d2ff0 RNFBCrashlytics: 1f0f79d23fc26cebc5325edf685f69bb5b9493e2 + RNFBInAppMessaging: 1500674838d6f688f8dac648b16b9cad3898505d RNFBMessaging: 5bc9395c4d411f0411e6ea939dd61fd5247a3db8 RNFBPerf: 816ff369b041978ab7a10dcbdafff0e88dc6b39c RNGestureHandler: 1e33ee267aaf61bbab6089d32df3b38c3024e3dd diff --git a/package.json b/package.json index 67ad06a..5b3b5d9 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@react-native-firebase/analytics": "^21.4.0", "@react-native-firebase/app": "^21.4.0", "@react-native-firebase/crashlytics": "^21.4.0", + "@react-native-firebase/in-app-messaging": "^21.6.1", "@react-native-firebase/messaging": "^21.4.0", "@react-native-firebase/perf": "^21.4.0", "@react-native-picker/picker": "^2.9.0", diff --git a/src/Navigation/index.js b/src/Navigation/index.js index 7a148bc..4265b02 100644 --- a/src/Navigation/index.js +++ b/src/Navigation/index.js @@ -10,6 +10,8 @@ import messaging from '@react-native-firebase/messaging'; import {firebase} from '@react-native-firebase/perf'; import crashlytics from '@react-native-firebase/crashlytics'; import {firebase as fire} from '@react-native-firebase/analytics'; +import inAppMessaging from '@react-native-firebase/in-app-messaging'; + import { check, request, @@ -83,6 +85,17 @@ export function RootNavigation() { console.log('Adapter Statuses ->', adapterStatuses); } + /** + * Enables the reception of in-app messages by disabling message display suppression. + * + * @async + * @function allowToReceiveInAppMessages + * @returns {Promise} Resolves when in-app messages can be received. + */ + async function allowToReceiveInAppMessages() { + await inAppMessaging().setMessagesDisplaySuppressed(false); + } + /** * Enables analytics collection for the application. * @@ -123,6 +136,7 @@ export function RootNavigation() { } useEffect(() => { + allowToReceiveInAppMessages(); requestUserPermission(); requestAppTrackingPermission(); if (!__DEV__) { diff --git a/yarn.lock b/yarn.lock index 4c861ba..f0da9a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3035,6 +3035,16 @@ __metadata: languageName: node linkType: hard +"@react-native-firebase/in-app-messaging@npm:^21.6.1": + version: 21.6.1 + resolution: "@react-native-firebase/in-app-messaging@npm:21.6.1" + peerDependencies: + "@react-native-firebase/analytics": 21.6.1 + "@react-native-firebase/app": 21.6.1 + checksum: e086fb9319ab79c8300a2a3461c5af2db7e881f49a71790feb0a16d1a77420a5dc43f29ed74078e56b040c1058782b80b927511736190bd52e25f3d4513fdc90 + languageName: node + linkType: hard + "@react-native-firebase/messaging@npm:^21.4.0": version: 21.4.0 resolution: "@react-native-firebase/messaging@npm:21.4.0" @@ -4002,6 +4012,7 @@ __metadata: "@react-native-firebase/analytics": ^21.4.0 "@react-native-firebase/app": ^21.4.0 "@react-native-firebase/crashlytics": ^21.4.0 + "@react-native-firebase/in-app-messaging": ^21.6.1 "@react-native-firebase/messaging": ^21.4.0 "@react-native-firebase/perf": ^21.4.0 "@react-native-picker/picker": ^2.9.0