Merge pull request 'amalia/28-jul-25' (#6) from amalia/28-jul-25 into join

Reviewed-on: bip/mobile-darmasaba#6
This commit is contained in:
2025-07-28 17:57:40 +08:00
20 changed files with 1349 additions and 428 deletions

View File

@@ -14,7 +14,8 @@
"bundleIdentifier": "mobiledarmasaba.app", "bundleIdentifier": "mobiledarmasaba.app",
"infoPlist": { "infoPlist": {
"ITSAppUsesNonExemptEncryption": false "ITSAppUsesNonExemptEncryption": false
} },
"googleServicesFile": "./ios/mobiledarmasaba/GoogleService-Info.plist"
}, },
"android": { "android": {
"package": "mobiledarmasaba.app", "package": "mobiledarmasaba.app",
@@ -41,7 +42,15 @@
} }
], ],
"expo-font", "expo-font",
"expo-web-browser" "expo-web-browser",
[
"@react-native-firebase/app",
{
"ios": {
"googleServicesFile": "./ios/mobiledarmasaba/GoogleService-Info.plist"
}
}
]
], ],
"experiments": { "experiments": {
"typedRoutes": true "typedRoutes": true

View File

@@ -6,17 +6,21 @@ import HeaderRightGroupList from "@/components/group/headerGroupList";
import HeaderMemberList from "@/components/member/headerMemberList"; import HeaderMemberList from "@/components/member/headerMemberList";
import HeaderRightPositionList from "@/components/position/headerRightPositionList"; import HeaderRightPositionList from "@/components/position/headerRightPositionList";
import HeaderRightProjectList from "@/components/project/headerProjectList"; import HeaderRightProjectList from "@/components/project/headerProjectList";
import Text from "@/components/Text";
import ToastCustom from "@/components/toastCustom";
import { Headers } from "@/constants/Headers"; import { Headers } from "@/constants/Headers";
import Styles from "@/constants/Styles";
import { apiReadOneNotification } from "@/lib/api"; import { apiReadOneNotification } from "@/lib/api";
import { pushToPage } from "@/lib/pushToPage"; import { pushToPage } from "@/lib/pushToPage";
import store from "@/lib/store"; import store from "@/lib/store";
import { useAuthSession } from "@/providers/AuthProvider"; import { useAuthSession } from "@/providers/AuthProvider";
import messaging from "@react-native-firebase/messaging"; import firebase from '@react-native-firebase/app';
import { Redirect, router, Stack } from "expo-router"; import { Redirect, router, Stack } from "expo-router";
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { useEffect } from "react"; import { useEffect } from "react";
import { Text } from "react-native"; import { View } from "react-native";
import { Easing, Notifier } from 'react-native-notifier'; import { Easing, Notifier } from 'react-native-notifier';
import Toast from "react-native-toast-message";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
export default function RootLayout() { export default function RootLayout() {
@@ -33,7 +37,7 @@ export default function RootLayout() {
} }
useEffect(() => { useEffect(() => {
const unsubscribe = messaging().onMessage(async remoteMessage => { const unsubscribe = firebase.app().messaging().onMessage(async remoteMessage => {
const id = remoteMessage?.data?.id; const id = remoteMessage?.data?.id;
const category = remoteMessage?.data?.category; const category = remoteMessage?.data?.category;
const content = remoteMessage?.data?.content; const content = remoteMessage?.data?.content;
@@ -122,6 +126,7 @@ export default function RootLayout() {
/> />
</Stack> </Stack>
<StatusBar style="light" translucent={false} backgroundColor="black" /> <StatusBar style="light" translucent={false} backgroundColor="black" />
<ToastCustom />
</Provider> </Provider>
) )
} }

View File

@@ -1,11 +1,11 @@
import ViewLogin from "@/components/auth/viewLogin"; import ViewLogin from "@/components/auth/viewLogin";
import ViewVerification from "@/components/auth/viewVerification"; import ViewVerification from "@/components/auth/viewVerification";
import Text from '@/components/Text';
import ToastCustom from "@/components/toastCustom";
import { requestPermission } from "@/lib/useNotification"; import { requestPermission } from "@/lib/useNotification";
import { useAuthSession } from "@/providers/AuthProvider"; import { useAuthSession } from "@/providers/AuthProvider";
import { Redirect } from "expo-router"; import { Redirect } from "expo-router";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { View } from "react-native";
import Text from '@/components/Text';
export default function Index() { export default function Index() {
const [isValid, setValid] = useState(false) const [isValid, setValid] = useState(false)

BIN
bun.lockb

Binary file not shown.

View File

@@ -2,10 +2,13 @@ import Styles from "@/constants/Styles"
import { apiCheckPhoneLogin, apiSendOtp } from "@/lib/api" import { apiCheckPhoneLogin, apiSendOtp } from "@/lib/api"
import AsyncStorage from "@react-native-async-storage/async-storage" import AsyncStorage from "@react-native-async-storage/async-storage"
import { useState } from "react" import { useState } from "react"
import { Image, SafeAreaView, Text, ToastAndroid, View } from "react-native" import { Image, SafeAreaView, View } from "react-native"
import Toast from "react-native-toast-message"
import { ButtonForm } from "../buttonForm" import { ButtonForm } from "../buttonForm"
import { InputForm } from "../inputForm" import { InputForm } from "../inputForm"
import ModalLoading from "../modalLoading" import ModalLoading from "../modalLoading"
import Text from "../Text"
import ToastCustom from "../toastCustom"
type Props = { type Props = {
@@ -30,10 +33,9 @@ export default function ViewLogin({ onValidate }: Props) {
return onValidate({ phone: `62${phone}`, otp }) return onValidate({ phone: `62${phone}`, otp })
} }
} }
return ToastAndroid.show(response.message, ToastAndroid.SHORT) return Toast.show({ type: 'small', text1: response.message, })
} catch (error) { } catch (error) {
console.error('Error fetching data:', error); return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', })
return ToastAndroid.show(`Terjadi kesalahan ${error}`, ToastAndroid.SHORT)
} finally { } finally {
setLoadingLogin(false) setLoadingLogin(false)
} }
@@ -41,6 +43,7 @@ export default function ViewLogin({ onValidate }: Props) {
return ( return (
<SafeAreaView> <SafeAreaView>
<ToastCustom />
<View style={Styles.p20}> <View style={Styles.p20}>
<View style={{ alignItems: "center", marginVertical: 50 }}> <View style={{ alignItems: "center", marginVertical: 50 }}>
<Image <Image

View File

@@ -3,9 +3,12 @@ import { apiSendOtp } from "@/lib/api";
import { useAuthSession } from "@/providers/AuthProvider"; import { useAuthSession } from "@/providers/AuthProvider";
import AsyncStorage from "@react-native-async-storage/async-storage"; import AsyncStorage from "@react-native-async-storage/async-storage";
import { useState } from "react"; import { useState } from "react";
import { Image, Text, ToastAndroid, View } from "react-native"; import { Image, View } from "react-native";
import { OtpInput } from "react-native-otp-entry"; import { OtpInput } from "react-native-otp-entry";
import Toast from 'react-native-toast-message';
import { ButtonForm } from "../buttonForm"; import { ButtonForm } from "../buttonForm";
import Text from "../Text";
import ToastCustom from "../toastCustom";
type Props = { type Props = {
phone: string phone: string
@@ -24,7 +27,7 @@ export default function ViewVerification({ phone, otp }: Props) {
const encrypted = await encryptToken(valueUser); const encrypted = await encryptToken(valueUser);
signIn(encrypted); signIn(encrypted);
} else { } else {
return ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT) return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', })
} }
} }
@@ -32,7 +35,7 @@ export default function ViewVerification({ phone, otp }: Props) {
if (value === otpFix.toString()) { if (value === otpFix.toString()) {
login() login()
} else { } else {
return ToastAndroid.show('Kode OTP tidak sesuai', ToastAndroid.SHORT) return Toast.show({ type: 'error', text1: 'Kode OTP tidak sesuai' });
} }
} }
@@ -42,17 +45,18 @@ export default function ViewVerification({ phone, otp }: Props) {
setOtpFix(otpNew) setOtpFix(otpNew)
const responseOtp = await apiSendOtp({ phone, otp: otpNew }) const responseOtp = await apiSendOtp({ phone, otp: otpNew })
if (responseOtp == 200) { if (responseOtp == 200) {
return ToastAndroid.show('Kode OTP berhasil dikirim ulang', ToastAndroid.SHORT) return Toast.show({ type: 'small', text1: 'Kode OTP berhasil dikirim ulang', })
} }
return ToastAndroid.show('Terjadi kesalahan dalam mengirim kode OTP', ToastAndroid.SHORT) return Toast.show({ type: 'small', text1: 'Terjadi kesalahan dalam mengirim kode OTP', })
} catch (error) { } catch (error) {
console.error('Error fetching data:', error); console.error('Error fetching data:', error);
return ToastAndroid.show('Terjadi kesalahan', ToastAndroid.SHORT) return Toast.show({ type: 'small', text1: 'Terjadi kesalahan', })
} }
} }
return ( return (
<> <>
<ToastCustom />
<View style={Styles.wrapLogin} > <View style={Styles.wrapLogin} >
<View style={{ alignItems: "center", marginVertical: 50 }}> <View style={{ alignItems: "center", marginVertical: 50 }}>
<Image <Image
@@ -77,6 +81,7 @@ export default function ViewVerification({ phone, otp }: Props) {
alignSelf: 'center' alignSelf: 'center'
}, },
pinCodeContainerStyle: Styles.verificationCell, pinCodeContainerStyle: Styles.verificationCell,
pinCodeTextStyle: { color: 'black' }
}} }}
/> />
<ButtonForm <ButtonForm

View File

@@ -0,0 +1,16 @@
import Styles from "@/constants/Styles";
import { View } from "react-native";
import Toast from "react-native-toast-message";
import Text from "./Text";
export default function ToastCustom() {
return (
<Toast autoHide onPress={() => Toast.hide()} visibilityTime={1500} position="bottom" config={{
small: ({ text1 }) => (
<View style={[Styles.toastContainer]}>
<Text style={{ fontSize: 12 }}>{text1}</Text>
</View>
)
}} />
)
}

View File

@@ -550,6 +550,14 @@ const Styles = StyleSheet.create({
top: 18, top: 18,
left: 20, left: 20,
position: 'absolute' position: 'absolute'
},
toastContainer: {
backgroundColor: 'white',
borderRadius: 10,
padding: 10,
width: '90%',
borderWidth: 1,
borderColor: '#d6d8f6',
} }
}) })

View File

@@ -1,40 +1,69 @@
require_relative '../node_modules/react-native/scripts/react_native_pods' require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
platform :ios, '15.1' require 'json'
install! 'cocoapods', :deterministic_uuids => false podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
# Add Expo modules autolinking ENV['RCT_NEW_ARCH_ENABLED'] = '0' if podfile_properties['newArchEnabled'] == 'false'
expo_autolinking_script = File.join(File.dirname(%x(node --print "require.resolve('expo/package.json')").strip), "scripts/autolinking") ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
require expo_autolinking_script if File.exist?(expo_autolinking_script)
platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
install! 'cocoapods',
:deterministic_uuids => false
prepare_react_native_project!
target 'mobiledarmasaba' do target 'mobiledarmasaba' do
# Use Expo modules with guard use_expo_modules!
use_expo_modules! if respond_to?(:use_expo_modules!)
if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
config = { config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"];
:reactNativePath => "../node_modules/react-native" else
} config_command = [
'npx',
'expo-modules-autolinking',
'react-native-config',
'--json',
'--platform',
'ios'
]
pod 'FirebaseDatabase', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
pod 'FirebaseAppCheckInterop', :modular_headers => true
pod 'leveldb-library', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
end
config = use_native_modules!(config_command)
use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
use_react_native!( use_react_native!(
:path => config[:reactNativePath], :path => config[:reactNativePath],
:hermes_enabled => true :hermes_enabled => podfile_properties['expo.jsEngine'] == nil || podfile_properties['expo.jsEngine'] == 'hermes',
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/..",
:privacy_file_aggregation_enabled => podfile_properties['apple.privacyManifestAggregationEnabled'] != 'false',
) )
# Post Install processing
post_install do |installer| post_install do |installer|
# Call react_native_post_install without parameters react_native_post_install(
react_native_post_install(installer) installer,
config[:reactNativePath],
# Set C++20 standard for all targets :mac_catalyst_enabled => false,
installer.pods_project.targets.each do |target| :ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
target.build_configurations.each do |config| )
config.build_settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++20'
config.build_settings['CLANG_CXX_LIBRARY'] = 'libc++' # This is necessary for Xcode 14, because it signs resource bundles by default
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1' # when building for devices.
installer.target_installation_results.pod_target_installation_results
# Enable C++ modules .each do |pod_name, target_installation_result|
config.build_settings['CLANG_ENABLE_MODULES'] = 'YES' target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
config.build_settings['GCC_C_LANGUAGE_STANDARD'] = 'gnu11' resource_bundle_target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end end
end end
end end

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,48 +1,74 @@
import UIKit import Expo
import ExpoModulesCore import FirebaseCore
import React import React
import ReactAppDependencyProvider
@main @UIApplicationMain
class AppDelegate: ExpoAppDelegate { public class AppDelegate: ExpoAppDelegate {
override func application( var window: UIWindow?
var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
var reactNativeFactory: RCTReactNativeFactory?
public override func application(
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool { ) -> Bool {
// Make sure the expo modules provider is set up let delegate = ReactNativeDelegate()
let reactNativeWindow = (window as? UIWindow) ?? UIWindow() let factory = ExpoReactNativeFactory(delegate: delegate)
delegate.dependencyProvider = RCTAppDependencyProvider()
if #available(iOS 13.0, *) {
reactNativeWindow.overrideUserInterfaceStyle = .light reactNativeDelegate = delegate
} reactNativeFactory = factory
bindReactNativeFactory(factory)
// Initialize the Expo modules provider
let reactAppDelegate = ReactAppDelegateWrapper(moduleProvider: { #if os(iOS) || os(tvOS)
return [ window = UIWindow(frame: UIScreen.main.bounds)
// Add any custom modules here if needed // @generated begin @react-native-firebase/app-didFinishLaunchingWithOptions - expo prebuild (DO NOT MODIFY) sync-10e8520570672fd76b2403b7e1e27f5198a6349a
] FirebaseApp.configure()
}) // @generated end @react-native-firebase/app-didFinishLaunchingWithOptions
factory.startReactNative(
// Call the parent's implementation withModuleName: "main",
let result = super.application(application, didFinishLaunchingWithOptions: launchOptions) in: window,
launchOptions: launchOptions)
// Set up the React Native root view #endif
if let rootView = self.window?.rootViewController?.view as? RCTRootView {
rootView.backgroundColor = .white return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
return result
} }
// MARK: - UISceneSession Lifecycle // Linking API
public override func application(
override func application( _ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options)
}
// Universal Links
public override func application(
_ application: UIApplication, _ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession, continue userActivity: NSUserActivity,
options: UIScene.ConnectionOptions restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> UISceneConfiguration { ) -> Bool {
return UISceneConfiguration( let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
name: "Default Configuration", return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
sessionRole: connectingSceneSession.role }
) }
class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
// Extension point for config-plugins
override func sourceURL(for bridge: RCTBridge) -> URL? {
// needed to return the correct URL for expo-dev-client.
bridge.bundleURL ?? bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
#else
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
} }
} }

View File

@@ -1,70 +0,0 @@
import Expo
import React
import ReactAppDependencyProvider
@UIApplicationMain
public class AppDelegate: ExpoAppDelegate {
var window: UIWindow?
var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
var reactNativeFactory: RCTReactNativeFactory?
public override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
let delegate = ReactNativeDelegate()
let factory = ExpoReactNativeFactory(delegate: delegate)
delegate.dependencyProvider = RCTAppDependencyProvider()
reactNativeDelegate = delegate
reactNativeFactory = factory
bindReactNativeFactory(factory)
#if os(iOS) || os(tvOS)
window = UIWindow(frame: UIScreen.main.bounds)
factory.startReactNative(
withModuleName: "main",
in: window,
launchOptions: launchOptions)
#endif
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// Linking API
public override func application(
_ app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
return super.application(app, open: url, options: options) || RCTLinkingManager.application(app, open: url, options: options)
}
// Universal Links
public override func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
let result = RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
return super.application(application, continue: userActivity, restorationHandler: restorationHandler) || result
}
}
class ReactNativeDelegate: ExpoReactNativeFactoryDelegate {
// Extension point for config-plugins
override func sourceURL(for bridge: RCTBridge) -> URL? {
// needed to return the correct URL for expo-dev-client.
bridge.bundleURL ?? bundleURL()
}
override func bundleURL() -> URL? {
#if DEBUG
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: ".expo/.virtual-metro-entry")
#else
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
#endif
}
}

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>AIzaSyBq_C4lMw-zIevHMpajQPzOQ4HRpUBBLHQ</string>
<key>GCM_SENDER_ID</key>
<string>867439221179</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>mobiledarmasaba.app</string>
<key>PROJECT_ID</key>
<string>mobile-darmasaba</string>
<key>STORAGE_BUCKET</key>
<string>mobile-darmasaba.firebasestorage.app</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:867439221179:ios:aedc34b89ff4919e9b0c9e</string>
<key>DATABASE_URL</key>
<string>https://mobile-darmasaba-default-rtdb.asia-southeast1.firebasedatabase.app</string>
</dict>
</plist>

View File

@@ -53,14 +53,6 @@
<key>NSAllowsLocalNetworking</key> <key>NSAllowsLocalNetworking</key>
<true/> <true/>
</dict> </dict>
<key>NSCameraUsageDescription</key>
<string>Allow $(PRODUCT_NAME) to access your camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>Allow $(PRODUCT_NAME) to access your microphone</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Allow $(PRODUCT_NAME) to save photos</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Allow $(PRODUCT_NAME) to access your photos</string>
<key>NSUserActivityTypes</key> <key>NSUserActivityTypes</key>
<array> <array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route</string>

View File

@@ -37,8 +37,8 @@
<string>NSPrivacyAccessedAPICategoryDiskSpace</string> <string>NSPrivacyAccessedAPICategoryDiskSpace</string>
<key>NSPrivacyAccessedAPITypeReasons</key> <key>NSPrivacyAccessedAPITypeReasons</key>
<array> <array>
<string>85F4.1</string>
<string>E174.1</string> <string>E174.1</string>
<string>85F4.1</string>
</array> </array>
</dict> </dict>
</array> </array>

View File

@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict/>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist> </plist>

View File

@@ -1,8 +1,7 @@
import { getApp, getApps, initializeApp } from '@react-native-firebase/app'; import { getApp, getApps, initializeApp } from '@react-native-firebase/app';
import { getMessaging } from '@react-native-firebase/messaging'; import messaging, { getMessaging } from '@react-native-firebase/messaging';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { PermissionsAndroid } from 'react-native'; import { PermissionsAndroid, Platform } from 'react-native';
import { pushToPage } from './pushToPage';
// Your Firebase project configuration // Your Firebase project configuration
const RNfirebaseConfig = { const RNfirebaseConfig = {
@@ -21,6 +20,8 @@ const initializeFirebase = async () => {
const app = getApps().length ? getApp() : initializeApp(RNfirebaseConfig); const app = getApps().length ? getApp() : initializeApp(RNfirebaseConfig);
const mess = getMessaging(app); const mess = getMessaging(app);
await messaging().registerDeviceForRemoteMessages();
// Set auto initialization and background message handler // Set auto initialization and background message handler
mess.setAutoInitEnabled(true); mess.setAutoInitEnabled(true);
mess.setBackgroundMessageHandler(async remoteMessage => { mess.setBackgroundMessageHandler(async remoteMessage => {
@@ -36,15 +37,17 @@ const initializeFirebase = async () => {
export const requestPermission = async () => { export const requestPermission = async () => {
try { try {
const cek = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS) if (Platform.OS === 'android') {
if (!cek) { const cek = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS)
const granted = await PermissionsAndroid.request( if (!cek) {
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS const granted = await PermissionsAndroid.request(
); PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
if (granted === PermissionsAndroid.RESULTS.GRANTED) { );
return true if (granted === PermissionsAndroid.RESULTS.GRANTED) {
return true
}
return false
} }
return false
} }
return true return true
} catch (err) { } catch (err) {
@@ -54,8 +57,8 @@ export const requestPermission = async () => {
export const getToken = async () => { export const getToken = async () => {
try { try {
const mess = await initializeFirebase(); await initializeFirebase();
const token = await mess?.getToken(); const token = await messaging().getToken();
return token; return token;
} catch (error) { } catch (error) {
console.error("Error getting token:", error); console.error("Error getting token:", error);

View File

@@ -82,6 +82,7 @@
"react-native-safe-area-context": "5.4.0", "react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1", "react-native-screens": "~4.11.1",
"react-native-svg": "15.11.2", "react-native-svg": "15.11.2",
"react-native-toast-message": "^2.3.3",
"react-native-ui-datepicker": "^3.0.5", "react-native-ui-datepicker": "^3.0.5",
"react-native-web": "^0.20.0", "react-native-web": "^0.20.0",
"react-native-webview": "13.13.5", "react-native-webview": "13.13.5",

View File

@@ -4,6 +4,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
import CryptoES from "crypto-es"; import CryptoES from "crypto-es";
import { router } from "expo-router"; import { router } from "expo-router";
import { createContext, MutableRefObject, ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react'; import { createContext, MutableRefObject, ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react';
import { Platform } from 'react-native';
const AuthContext = createContext<{ const AuthContext = createContext<{
signIn: (arg0: string) => void; signIn: (arg0: string) => void;
@@ -76,7 +77,9 @@ export default function AuthProvider({ children }: { children: ReactNode }): Rea
try { try {
const hasil = await decryptToken(String(tokenRef.current)) const hasil = await decryptToken(String(tokenRef.current))
const token = await getToken() const token = await getToken()
const response = await apiUnregisteredToken({ user: hasil, token: String(token) }) if (Platform.OS === 'android'){
const response = await apiUnregisteredToken({ user: hasil, token: String(token) })
}
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} finally { } finally {