feat(sentry): integrate Sentry for error tracking and monitoring
- Added Sentry for error reporting in the mobile application. - Updated the app configuration to initialize Sentry with the necessary DSN and settings. - Replaced Firebase Crashlytics with Sentry for error capturing in the ErrorBoundary component. - Updated various workflows to include Sentry authentication token. - Adjusted dependencies to use React Native version 0.79.6 and updated related packages. This integration enhances the application's ability to track and manage errors effectively. Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
a350950672
commit
866abbef20
|
|
@ -55,6 +55,7 @@ jobs:
|
|||
working-directory: apps/mobile
|
||||
run: eas build --platform ios --profile development --non-interactive --local --output=./build.ipa
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.RN_SENTRY_AUTH_TOKEN }}
|
||||
CI: true
|
||||
|
||||
# Optional: Upload artifact
|
||||
|
|
@ -105,7 +106,7 @@ jobs:
|
|||
run: eas build --platform ios --profile development --non-interactive --local --output=./build.ipa
|
||||
env:
|
||||
CI: true
|
||||
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.RN_SENTRY_AUTH_TOKEN }}
|
||||
# Optional: Upload artifact
|
||||
- name: 📤 Upload IPA
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
@ -149,7 +150,7 @@ jobs:
|
|||
run: eas build --platform ios --profile ios-simulator --non-interactive --local --output=./build-simulator.ipa
|
||||
env:
|
||||
CI: true
|
||||
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.RN_SENTRY_AUTH_TOKEN }}
|
||||
# Optional: Upload artifact
|
||||
- name: 📤 Upload IPA
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ jobs:
|
|||
working-directory: apps/mobile
|
||||
run: eas build --platform ios --profile ${{ github.event.inputs.profile || 'preview' }} --non-interactive --local --output=./build.ipa
|
||||
env:
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.RN_SENTRY_AUTH_TOKEN }}
|
||||
CI: true
|
||||
|
||||
# Optional: Upload artifact
|
||||
|
|
@ -117,7 +118,7 @@ jobs:
|
|||
run: eas build --platform ios --profile ${{ github.event.inputs.profile || 'preview' }} --non-interactive --local --output=./build.ipa
|
||||
env:
|
||||
CI: true
|
||||
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.RN_SENTRY_AUTH_TOKEN }}
|
||||
# Optional: Upload artifact
|
||||
- name: 📤 Upload IPA
|
||||
uses: actions/upload-artifact@v4
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
EXPO_PUBLIC_APP_CHECK_DEBUG_TOKEN=
|
||||
SENTRY_AUTH_TOKEN=
|
||||
|
|
|
|||
|
|
@ -45,3 +45,5 @@ android
|
|||
Podfile.lock
|
||||
|
||||
buildServer.json
|
||||
|
||||
.env.local
|
||||
|
|
|
|||
|
|
@ -137,7 +137,14 @@ export default ({ config }: ConfigContext): ExpoConfig => {
|
|||
require("./plugins/with-android-manifest-plugin.js"),
|
||||
"expo-secure-store",
|
||||
"@react-native-firebase/app",
|
||||
"@react-native-firebase/crashlytics",
|
||||
[
|
||||
"@sentry/react-native/expo",
|
||||
{
|
||||
url: "https://sentry.io/",
|
||||
project: "react-native",
|
||||
organization: "follow-rg",
|
||||
},
|
||||
],
|
||||
[
|
||||
"expo-image-picker",
|
||||
{
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@
|
|||
800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
|
||||
6E4ADCBDA5B760296BAE78FA /* [CP] Embed Pods Frameworks */,
|
||||
8F2D99FDEA6998C9D98BD7E0 /* [CP-User] [RNFB] Core Configuration */,
|
||||
8DF9409D54556D15DD94C0B5 /* [CP-User] [RNFB] Crashlytics Configuration */,
|
||||
3B0B406257C84B7586048134 /* Upload Debug Symbols to Sentry */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n";
|
||||
shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n/bin/sh `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode.sh'\"` `\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n";
|
||||
};
|
||||
08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
|
|
@ -267,6 +267,20 @@
|
|||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B0B406257C84B7586048134 /* Upload Debug Symbols to Sentry */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Upload Debug Symbols to Sentry";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh ../../../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh\n";
|
||||
};
|
||||
6E4ADCBDA5B760296BAE78FA /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -306,7 +320,6 @@
|
|||
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCore/FirebaseCore_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreExtension/FirebaseCoreExtension_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCoreInternal/FirebaseCoreInternal_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseCrashlytics/FirebaseCrashlytics_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseInstallations/FirebaseInstallations_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/FirebaseMessaging/FirebaseMessaging_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/FollowNative/js.bundle",
|
||||
|
|
@ -315,7 +328,6 @@
|
|||
"${PODS_CONFIGURATION_BUILD_DIR}/GoogleUtilities/GoogleUtilities_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/Mute/Mute.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/PromisesObjC/FBLPromises_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/PromisesSwift/Promises_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RCT-Folly/RCT-Folly_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNDeviceInfo/RNDeviceInfoPrivacyInfo.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/RNSVG/RNSVGFilters.bundle",
|
||||
|
|
@ -323,6 +335,7 @@
|
|||
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/React-Core_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/React-cxxreact/React-cxxreact_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/Sentry/Sentry.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/SnapKit/SnapKit_Privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/boost/boost_privacy.bundle",
|
||||
"${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle",
|
||||
|
|
@ -346,7 +359,6 @@
|
|||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCore_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCoreExtension_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCoreInternal_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseCrashlytics_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseInstallations_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FirebaseMessaging_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/js.bundle",
|
||||
|
|
@ -355,7 +367,6 @@
|
|||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleUtilities_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Mute.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FBLPromises_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Promises_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RCT-Folly_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNDeviceInfoPrivacyInfo.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/RNSVGFilters.bundle",
|
||||
|
|
@ -363,6 +374,7 @@
|
|||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-Core_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/React-cxxreact_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SDWebImage.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Sentry.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SnapKit_Privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/boost_privacy.bundle",
|
||||
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle",
|
||||
|
|
@ -375,22 +387,6 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Folo/Pods-Folo-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
8DF9409D54556D15DD94C0B5 /* [CP-User] [RNFB] Crashlytics Configuration */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}",
|
||||
"$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)",
|
||||
);
|
||||
name = "[CP-User] [RNFB] Crashlytics Configuration";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "#!/usr/bin/env bash\n#\n# Copyright (c) 2016-present Invertase Limited & Contributors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this library except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\nset -e\n\nif [[ ${PODS_ROOT} ]]; then\n echo \"info: Exec FirebaseCrashlytics Run from Pods\"\n \"${PODS_ROOT}/FirebaseCrashlytics/run\"\nelse\n echo \"info: Exec FirebaseCrashlytics Run from framework\"\n \"${PROJECT_DIR}/FirebaseCrashlytics.framework/run\"\nfi\n";
|
||||
};
|
||||
8F2D99FDEA6998C9D98BD7E0 /* [CP-User] [RNFB] Core Configuration */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
defaults.url=https://sentry.io/
|
||||
defaults.org=follow-rg
|
||||
defaults.project=react-native
|
||||
# Using SENTRY_AUTH_TOKEN environment variable
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
const { getDefaultConfig } = require("expo/metro-config")
|
||||
const { withNativeWind } = require("nativewind/metro")
|
||||
const path = require("pathe")
|
||||
const { wrapWithReanimatedMetroConfig } = require("react-native-reanimated/metro-config")
|
||||
const { getSentryExpoConfig } = require("@sentry/react-native/metro")
|
||||
|
||||
const config = getDefaultConfig(__dirname, { isCSSEnabled: true })
|
||||
const config = getSentryExpoConfig(__dirname, { isCSSEnabled: true })
|
||||
config.resolver.sourceExts.push("sql")
|
||||
|
||||
config.transformer.getTransformOptions = async () => ({
|
||||
|
|
|
|||
|
|
@ -38,11 +38,11 @@
|
|||
"@react-native-firebase/analytics": "22.2.1",
|
||||
"@react-native-firebase/app": "22.2.1",
|
||||
"@react-native-firebase/app-check": "22.2.1",
|
||||
"@react-native-firebase/crashlytics": "22.2.1",
|
||||
"@react-native-firebase/messaging": "22.2.1",
|
||||
"@react-native-masked-view/masked-view": "0.3.2",
|
||||
"@react-native-menu/menu": "1.2.3",
|
||||
"@react-native-picker/picker": "2.11.2",
|
||||
"@sentry/react-native": "6.20.0",
|
||||
"@shopify/flash-list": "2.0.3",
|
||||
"@tanstack/query-sync-storage-persister": "5.89.0",
|
||||
"@tanstack/react-query": "5.89.0",
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
"react-error-boundary": "6.0.0",
|
||||
"react-hook-form": "7.62.0",
|
||||
"react-i18next": "15.7.3",
|
||||
"react-native": "0.79.1",
|
||||
"react-native": "0.79.6",
|
||||
"react-native-awesome-slider": "2.9.0",
|
||||
"react-native-bouncy-checkbox": "4.1.2",
|
||||
"react-native-color-matrix-image-filters": "7.0.2",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { useTypeScriptHappyCallback } from "@follow/hooks"
|
||||
import { getCrashlytics, recordError } from "@react-native-firebase/crashlytics"
|
||||
import { captureException } from "@sentry/react-native"
|
||||
import type { FC } from "react"
|
||||
import { createElement, useEffect } from "react"
|
||||
import { ErrorBoundary as ReactErrorBoundary } from "react-error-boundary"
|
||||
|
|
@ -51,7 +51,7 @@ const defaultFallbackRender = ({ error }: { error: Error }) => {
|
|||
}
|
||||
const ErrorReport = ({ error }: { error: Error }) => {
|
||||
useEffect(() => {
|
||||
recordError(getCrashlytics(), error)
|
||||
captureException(error)
|
||||
console.error(error)
|
||||
}, [error])
|
||||
return null
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
import { whoami } from "@follow/store/user/getters"
|
||||
import { getCrashlytics, setAttributes, setUserId } from "@react-native-firebase/crashlytics"
|
||||
|
||||
export const initCrashlytics = async () => {
|
||||
const crashlytics = getCrashlytics()
|
||||
const user = whoami()
|
||||
if (user) {
|
||||
await Promise.all([
|
||||
setUserId(crashlytics, user.id),
|
||||
setAttributes(crashlytics, {
|
||||
email: user.email ?? "",
|
||||
name: user.name ?? "",
|
||||
handle: user.handle ?? "",
|
||||
}),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
|
@ -7,12 +7,12 @@ import { settingSyncQueue } from "../modules/settings/sync-queue"
|
|||
import { initAnalytics } from "./analytics"
|
||||
import { initializeAppCheck } from "./app-check"
|
||||
import { initBackgroundTask } from "./background"
|
||||
import { initCrashlytics } from "./crashlytics"
|
||||
import { initializeDayjs } from "./dayjs"
|
||||
import { initDeviceType } from "./device"
|
||||
import { hydrateQueryClient, hydrateSettings } from "./hydrate"
|
||||
import { migrateDatabase } from "./migration"
|
||||
import { initializePlayer } from "./player"
|
||||
import { initializeSentry } from "./sentry"
|
||||
|
||||
/* eslint-disable no-console */
|
||||
export const initializeApp = async () => {
|
||||
|
|
@ -20,6 +20,8 @@ export const initializeApp = async () => {
|
|||
|
||||
const now = Date.now()
|
||||
|
||||
initializeSentry()
|
||||
|
||||
await initDeviceType()
|
||||
await initializeDB()
|
||||
|
||||
|
|
@ -57,7 +59,7 @@ export const initializeApp = async () => {
|
|||
electron: false,
|
||||
using_indexed_db: true,
|
||||
})
|
||||
initCrashlytics()
|
||||
|
||||
initBackgroundTask()
|
||||
console.log(`Initialize done,`, `${loadingTime}ms`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import * as Sentry from "@sentry/react-native"
|
||||
|
||||
export const initializeSentry = () => {
|
||||
// Unlike Sentry on other platforms, you do not need to import anything to use tracing on React Native
|
||||
Sentry.init({
|
||||
dsn: "https://cbfecd786e09a9481676655a4da88a7e@o4507542488023040.ingest.us.sentry.io/4509926421102593",
|
||||
// We recommend adjusting this value in production, or using tracesSampler
|
||||
// for finer control
|
||||
tracesSampleRate: 1,
|
||||
})
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import "./global.css"
|
|||
import "./polyfill"
|
||||
|
||||
import { apiContext, authClientContext, queryClientContext } from "@follow/store/context"
|
||||
import * as Sentry from "@sentry/react-native"
|
||||
import { registerRootComponent } from "expo"
|
||||
import { Image } from "expo-image"
|
||||
import { LinearGradient } from "expo-linear-gradient"
|
||||
|
|
@ -27,7 +28,6 @@ import { DiscoverTabScreen } from "./screens/(stack)/(tabs)/discover"
|
|||
import { SettingsTabScreen } from "./screens/(stack)/(tabs)/settings"
|
||||
import { SubscriptionsTabScreen } from "./screens/(stack)/(tabs)/subscriptions"
|
||||
import { registerSitemap } from "./sitemap"
|
||||
|
||||
// @ts-expect-error
|
||||
global.APP_NAME = "Folo"
|
||||
// @ts-expect-error
|
||||
|
|
@ -45,7 +45,7 @@ enableFreeze(true)
|
|||
initializeApp()
|
||||
registerSitemap()
|
||||
initializeI18n()
|
||||
registerRootComponent(RootComponent)
|
||||
registerRootComponent(Sentry.wrap(RootComponent))
|
||||
|
||||
function RootComponent() {
|
||||
const { t } = useTranslation()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
import { View } from "react-native"
|
||||
|
||||
import { SafeNavigationScrollView } from "@/src/components/layouts/views/SafeNavigationScrollView"
|
||||
import { Search3CuteFiIcon } from "@/src/icons/search_3_cute_fi"
|
||||
import { Search3CuteReIcon } from "@/src/icons/search_3_cute_re"
|
||||
import type { TabScreenComponent } from "@/src/lib/navigation/bottom-tab/types"
|
||||
import Content from "@/src/modules/discover/Content"
|
||||
import {
|
||||
|
|
@ -30,9 +28,5 @@ export default function Discover() {
|
|||
}
|
||||
|
||||
export const DiscoverTabScreen: TabScreenComponent = Discover
|
||||
DiscoverTabScreen.tabBarIcon = ({ focused, color }) => {
|
||||
const Icon = !focused ? Search3CuteReIcon : Search3CuteFiIcon
|
||||
return <Icon color={color} width={24} height={24} />
|
||||
}
|
||||
|
||||
DiscoverTabScreen.lazy = true
|
||||
|
|
|
|||
|
|
@ -1,17 +1,11 @@
|
|||
import { useResetTabOpacityWhenFocused } from "@/src/components/layouts/tabbar/hooks"
|
||||
import { usePrepareEntryRenderWebView } from "@/src/components/native/webview/hooks"
|
||||
import { Home5CuteFiIcon } from "@/src/icons/home_5_cute_fi"
|
||||
import { Home5CuteReIcon } from "@/src/icons/home_5_cute_re"
|
||||
import type { TabScreenComponent } from "@/src/lib/navigation/bottom-tab/types"
|
||||
import { EntryList } from "@/src/modules/entry-list"
|
||||
|
||||
export const IndexTabScreen: TabScreenComponent = () => {
|
||||
usePrepareEntryRenderWebView()
|
||||
useResetTabOpacityWhenFocused()
|
||||
|
||||
return <EntryList />
|
||||
}
|
||||
|
||||
IndexTabScreen.tabBarIcon = ({ focused, color }) => {
|
||||
const Icon = !focused ? Home5CuteReIcon : Home5CuteFiIcon
|
||||
return <Icon color={color} width={24} height={24} />
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ import { useRegisterNavigationScrollView } from "@/src/components/layouts/tabbar
|
|||
import { getDefaultHeaderHeight } from "@/src/components/layouts/utils"
|
||||
import { SafeNavigationScrollView } from "@/src/components/layouts/views/SafeNavigationScrollView"
|
||||
import { Text } from "@/src/components/ui/typography/Text"
|
||||
import { Settings1CuteFiIcon } from "@/src/icons/settings_1_cute_fi"
|
||||
import { Settings1CuteReIcon } from "@/src/icons/settings_1_cute_re"
|
||||
import type { TabScreenComponent } from "@/src/lib/navigation/bottom-tab/types"
|
||||
import { useNavigation } from "@/src/lib/navigation/hooks"
|
||||
import { ScreenItemContext } from "@/src/lib/navigation/ScreenItemContext"
|
||||
|
|
@ -97,7 +95,3 @@ const EditProfileButton = () => {
|
|||
)
|
||||
}
|
||||
export const SettingsTabScreen: TabScreenComponent = Settings
|
||||
SettingsTabScreen.tabBarIcon = ({ focused, color }) => {
|
||||
const Icon = !focused ? Settings1CuteReIcon : Settings1CuteFiIcon
|
||||
return <Icon color={color} width={24} height={24} />
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import { ErrorBoundary } from "@/src/components/common/ErrorBoundary"
|
|||
import { NoLoginInfo } from "@/src/components/common/NoLoginInfo"
|
||||
import { ListErrorView } from "@/src/components/errors/ListErrorView"
|
||||
import { useResetTabOpacityWhenFocused } from "@/src/components/layouts/tabbar/hooks"
|
||||
import { BlackBoard2CuteFiIcon } from "@/src/icons/black_board_2_cute_fi"
|
||||
import { BlackBoard2CuteReIcon } from "@/src/icons/black_board_2_cute_re"
|
||||
import type { TabScreenComponent } from "@/src/lib/navigation/bottom-tab/types"
|
||||
import { EntryListContext } from "@/src/modules/screen/atoms"
|
||||
import { PagerList } from "@/src/modules/screen/PagerList"
|
||||
|
|
@ -37,10 +35,6 @@ export default function Subscriptions() {
|
|||
}
|
||||
|
||||
export const SubscriptionsTabScreen: TabScreenComponent = Subscriptions
|
||||
SubscriptionsTabScreen.tabBarIcon = ({ focused, color }) => {
|
||||
const Icon = !focused ? BlackBoard2CuteReIcon : BlackBoard2CuteFiIcon
|
||||
return <Icon color={color} width={24} height={24} />
|
||||
}
|
||||
|
||||
const renderItem = (view: FeedViewType, active: boolean) => (
|
||||
<ErrorBoundary fallbackRender={ListErrorView} key={view}>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": ">=0.74.0"
|
||||
"react-native": ">=0.79.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@follow/shared": "workspace:*",
|
||||
|
|
@ -46,6 +46,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@follow/configs": "workspace:*",
|
||||
"react-native": "0.79.6",
|
||||
"vite-tsconfig-paths": "5.1.4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1523
pnpm-lock.yaml
1523
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue