Skip to content

Commit

Permalink
Sync with fedibtc/fedi f2dd70deb07d5562846a88fc8e084bbebf7558b4 (#14)
Browse files Browse the repository at this point in the history
Co-authored-by: Fedi CI <ci@fedi.xyz>
  • Loading branch information
fedigord and Fedi CI authored Feb 22, 2025
1 parent d9f1e9c commit d78a88a
Show file tree
Hide file tree
Showing 29 changed files with 576 additions and 2,417 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/upload-android-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ jobs:
- name: Create draft GitHub release with APK
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.prep-apk.outputs.APK_VERSION }}
name: 'v${{ steps.prep-apk.outputs.APK_VERSION }}'
tag_name: ${{ steps.prep-apk.outputs.APK_VERSION }}
name: '${{ steps.prep-apk.outputs.APK_VERSION }}'
body: 'Built from commit: ${{ github.sha }}'
draft: true
append_body: true
Expand Down
12 changes: 8 additions & 4 deletions ui/common/hooks/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function usePublishNotificationToken(
appName: string,
permissionGranted: boolean,
secondaryPublish: (token: string, dispatch: CommonDispatch) => void,
secondaryPermissionGranted: boolean,
currentToken: string | null,
) {
const dispatch = useCommonDispatch()
Expand Down Expand Up @@ -97,10 +98,12 @@ export function usePublishNotificationToken(
})

// Zendesk
secondaryPublish(newToken, dispatch)
log.debug(
'Successfully updated secondary publish push notification token',
)
if (secondaryPermissionGranted) {
secondaryPublish(newToken, dispatch)
log.debug(
'Successfully updated secondary publish push notification token',
)
}
}

publishToken()
Expand All @@ -112,6 +115,7 @@ export function usePublishNotificationToken(
permissionGranted,
currentToken,
secondaryPublish,
secondaryPermissionGranted,
])

return null
Expand Down
13 changes: 13 additions & 0 deletions ui/common/redux/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const initialState = {
supportPermissionGranted: false,
zendeskPushNotificationToken: null as string | null,
zendeskInitialized: false,
zendeskUnreadMessageCount: 0,
}

export type SupportState = typeof initialState
Expand All @@ -28,6 +29,9 @@ export const supportSlice = createSlice({
setZendeskInitialized(state, action: PayloadAction<boolean>) {
state.zendeskInitialized = action.payload
},
setZendeskUnreadMessageCount(state, action: PayloadAction<number>) {
state.zendeskUnreadMessageCount = action.payload
},
},
extraReducers: builder => {
builder.addCase(loadFromStorage.fulfilled, (state, action) => {
Expand All @@ -50,6 +54,7 @@ export const {
setSupportPermission,
setZendeskPushNotificationToken,
setZendeskInitialized,
setZendeskUnreadMessageCount,
} = supportSlice.actions

/*** Selectors ***/
Expand All @@ -63,6 +68,9 @@ export const selectZendeskPushNotificationToken = (s: CommonState) =>
export const selectZendeskInitialized = (s: CommonState) =>
s.support.zendeskInitialized

export const selectZendeskUnreadMessageCount = (s: CommonState) =>
s.support.zendeskUnreadMessageCount

/*** Synchronous wrapper actions ***/

export const grantSupportPermission = () => (dispatch: Dispatch) => {
Expand All @@ -73,3 +81,8 @@ export const saveZendeskPushNotificationToken =
(token: string) => (dispatch: Dispatch) => {
dispatch(setZendeskPushNotificationToken(token))
}

export const updateZendeskUnreadMessageCount =
(count: number) => (dispatch: Dispatch) => {
dispatch(setZendeskUnreadMessageCount(count))
}
2 changes: 1 addition & 1 deletion ui/native/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 240051929
versionName "25.2.3"
versionName "25.2.5"
}

packagingOptions {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 3 additions & 36 deletions ui/native/components/feature/settings/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,13 @@ import { requestNotifications } from 'react-native-permissions'

import { EULA_URL } from '@fedi/common/constants/tos'
import { useNuxStep } from '@fedi/common/hooks/nux'
import { ToastHandler, useToast } from '@fedi/common/hooks/toast'
import { selectDeveloperMode } from '@fedi/common/redux/environment'

import { usePinContext } from '../../../state/contexts/PinContext'
import { useAppSelector } from '../../../state/hooks'
import { NavigationHook } from '../../../types/navigation'
import { useNotificationsPermission } from '../../../utils/hooks'
import {
useNpub,
useSupportPermission,
useZendeskInitialization,
} from '../../../utils/hooks/support'
import {
useDisplayName,
zendeskInitialize,
zendeskOpenMessagingView,
} from '../../../utils/support'
import { useLaunchZendesk } from '../../../utils/hooks/support'
import SettingsItem from './SettingsItem'

export const GeneralSettings = () => {
Expand All @@ -33,13 +23,7 @@ export const GeneralSettings = () => {
const navigation = useNavigation<NavigationHook>()
const { notificationsPermission } = useNotificationsPermission()

const { supportPermissionGranted } = useSupportPermission()
const displayName = useDisplayName()
const nostrPublic = useNpub()
const toast = useToast()
const nostrNpub = nostrPublic ?? null
const { zendeskInitialized, handleZendeskInitialization } =
useZendeskInitialization()
const { launchZendesk } = useLaunchZendesk()

const developerMode = useAppSelector(selectDeveloperMode)
const [hasPerformedPersonalBackup] = useNuxStep(
Expand All @@ -59,23 +43,6 @@ export const GeneralSettings = () => {
}
}

const handleSupportPress = () => {
if (!zendeskInitialized) {
zendeskInitialize(
nostrNpub,
displayName,
handleZendeskInitialization,
toast as unknown as ToastHandler,
t,
)
}
if (supportPermissionGranted && zendeskInitialized) {
zendeskOpenMessagingView()
} else {
navigation.navigate('HelpCentre')
}
}

const handleNotificationSettings = useCallback(async () => {
// If not granted, ask for permission
if (notificationsPermission !== 'granted') {
Expand Down Expand Up @@ -153,7 +120,7 @@ export const GeneralSettings = () => {
<SettingsItem
icon="SmileMessage"
label={t('feature.support.title')}
onPress={handleSupportPress}
onPress={() => launchZendesk()}
/>
<SettingsItem
icon="SpeakerPhone"
Expand Down
133 changes: 17 additions & 116 deletions ui/native/components/feature/support/SupportChat.tsx
Original file line number Diff line number Diff line change
@@ -1,127 +1,36 @@
import { useFocusEffect } from '@react-navigation/native'
import { useNavigation } from '@react-navigation/native'
import { Button, useTheme, Theme, Text } from '@rneui/themed'
import React, { useCallback, useEffect } from 'react'
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, View, Linking } from 'react-native'
import * as Zendesk from 'react-native-zendesk-messaging'

import { usePushNotificationToken } from '@fedi/common/hooks/matrix'
import { ToastHandler, useToast } from '@fedi/common/hooks/toast'
import { makeLog } from '@fedi/common/utils/log'
import { grantSupportPermission } from '@fedi/common/redux/support'
import SvgImage from '@fedi/native/components/ui/SvgImage'

import { HELP_URL, PRIVACY_POLICY_URL } from '../../../constants'
import { useSupportPermission, useNpub } from '../../../utils/hooks/support'
import { zendeskInitialize, useDisplayName } from '../../../utils/support'
import { useAppDispatch } from '../../../state/hooks'
import { useLaunchZendesk } from '../../../utils/hooks/support'
import HoloGuidance from '../../ui/HoloGuidance'

const log = makeLog('SupportChat')

type SupportChatProps = {
zendeskInitialized: boolean
setZendeskInitialized: (value: boolean) => void
}

const SupportChat: React.FC<SupportChatProps> = ({
zendeskInitialized,
setZendeskInitialized,
}) => {
const SupportChat: React.FC = () => {
const { theme } = useTheme()
const { t } = useTranslation()
const toast = useToast()

const navigation = useNavigation()
const style = styles(theme)
const dispatch = useAppDispatch()

const {
supportPermissionGranted,
grantPermission,
zendeskPushNotificationToken,
savePushNotificationToken,
} = useSupportPermission()
const pushNotificationToken = usePushNotificationToken()
const nostrPublic = useNpub()
const nostrNpub = nostrPublic ?? null
const displayName = useDisplayName()

useEffect(() => {
if (nostrNpub && displayName && !zendeskInitialized) {
zendeskInitialize(
nostrNpub,
displayName,
setZendeskInitialized,
toast as unknown as ToastHandler,
t,
)
}
}, [
nostrNpub,
displayName,
setZendeskInitialized,
zendeskInitialized,
toast,
t,
])

useFocusEffect(
useCallback(() => {
if (zendeskInitialized && supportPermissionGranted) {
Zendesk.openMessagingView()
.then(() =>
log.debug('Zendesk messaging shown successfully'),
)
.catch(error => {
log.error('Zendesk messaging failed to show', error)
toast.error(
t,
error,
'feature.support.zendesk-initialization-failed',
)
})
}
}, [zendeskInitialized, supportPermissionGranted, toast, t]),
)

useEffect(() => {
if (
supportPermissionGranted &&
pushNotificationToken &&
pushNotificationToken !== zendeskPushNotificationToken
) {
Zendesk.updatePushNotificationToken(pushNotificationToken)
savePushNotificationToken(pushNotificationToken)
log.debug(
'Zendesk push notification token updated: ' +
pushNotificationToken,
)
}
}, [
supportPermissionGranted,
pushNotificationToken,
zendeskPushNotificationToken,
savePushNotificationToken,
])
const { launchZendesk } = useLaunchZendesk()

const handlePrivacyPolicyPress = () => {
Linking.openURL(PRIVACY_POLICY_URL)
}

const grantSupportPermission = () => {
if (!supportPermissionGranted) {
grantPermission()
}
}

const handleZendeskPress = () => {
if (!supportPermissionGranted) {
grantPermission()
} else {
Zendesk.openMessagingView()
.then(() => log.debug('Zendesk messaging shown successfully'))
.catch(error =>
log.error('Zendesk messaging failed to show', error),
)
}
}
const grantPermission = useCallback(() => {
dispatch(grantSupportPermission())
launchZendesk(true)
// Close the Permission screen while the modal opens
navigation.goBack()
}, [dispatch, launchZendesk, navigation])

const handleHelpCenterPress = () => {
Linking.openURL(HELP_URL)
Expand Down Expand Up @@ -164,16 +73,8 @@ const SupportChat: React.FC<SupportChatProps> = ({
<View style={style.overlayButtonsContainer}>
<Button
fullWidth
onPress={
supportPermissionGranted
? handleZendeskPress
: grantSupportPermission
}
title={
supportPermissionGranted
? t('feature.support.open-chat')
: t('phrases.i-understand')
}
onPress={grantPermission}
title={t('phrases.i-understand')}
/>
</View>
</View>
Expand Down
47 changes: 47 additions & 0 deletions ui/native/components/feature/support/ZendeskBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { useTheme, Theme, Text } from '@rneui/themed'
import React from 'react'
import { View, StyleSheet } from 'react-native'

import { selectZendeskUnreadMessageCount } from '@fedi/common/redux/support'

import { useAppSelector } from '../../../state/hooks'

const ZendeskBadge: React.FC<{ title: string }> = ({ title }) => {
const { theme } = useTheme()
const unreadCount = useAppSelector(selectZendeskUnreadMessageCount)
const style = styles(theme)

// Show badge ONLY if title is "Ask Fedi" and count is > 0
if (title.toLowerCase() !== 'ask fedi' || unreadCount === 0) {
return null
}

return (
<View style={style.badge}>
<Text style={style.badgeText}>{unreadCount}</Text>
</View>
)
}

const styles = (theme: Theme) =>
StyleSheet.create({
badge: {
position: 'absolute',
zIndex: 1000,
top: -3,
right: 32,
backgroundColor: theme.colors.red,
borderRadius: 10,
width: 20,
height: 20,
justifyContent: 'center',
alignItems: 'center',
},
badgeText: {
color: theme.colors.white,
fontSize: 12,
fontWeight: 'bold',
},
})

export default ZendeskBadge
Loading

0 comments on commit d78a88a

Please sign in to comment.