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/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/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"> 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/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/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/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} 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