Skip to content

Bottom sheets #1335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
May 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
18f8bc0
Create working example with bottom sheets library
nop33 May 14, 2025
4244d3b
Migrate simple modals
nop33 May 14, 2025
2bbce63
Fix dashboard box and address discovery scrolling
nop33 Apr 24, 2025
28fb811
Customize handle
nop33 May 14, 2025
c5ea204
Give bottom spacing to handle
nop33 May 15, 2025
e812722
Migrate scrollable view modals
nop33 May 15, 2025
33862fb
Migrate address details modal flash list
nop33 May 15, 2025
64e2071
Extract NFTs grid flash list props to hook
nop33 May 15, 2025
a808253
Migrate NFTs grids
nop33 May 15, 2025
a4a256e
Migrate remaining flash list modals
nop33 May 15, 2025
24a9fd2
Migrate some modals with input fields
nop33 May 15, 2025
33ed8ba
Fix contact creation
nop33 May 15, 2025
b6d145a
Migrate remaining modals
nop33 May 15, 2025
8b5fe8f
Migrate token amount modal
nop33 May 15, 2025
7ce49c2
Fix modal dismissals
nop33 May 15, 2025
f8147d8
Add stacking behavior to Redux action
nop33 May 15, 2025
52b0360
Convert modal id to string
nop33 May 15, 2025
8887a1e
Use id in dismiss
nop33 May 15, 2025
3ccaa81
Fix address details modal dismissal
nop33 May 16, 2025
04931c6
Fix display of hidden tokens button in dashboard
nop33 May 16, 2025
20d4d7b
Fix modal dismissals
nop33 May 16, 2025
7b6124b
Update eslint packages
nop33 May 16, 2025
4fde471
Fix eslint
nop33 May 16, 2025
534990b
Rename file
nop33 May 16, 2025
09639ae
Remove ModalContent from modals
nop33 May 16, 2025
6d3e23a
Fix position of refresh control
nop33 May 16, 2025
339a07e
Fix navigation reset
nop33 May 16, 2025
98fa315
Delete prices slice
nop33 May 16, 2025
5d66ea0
Start scanning when navigation to discovery screen
nop33 May 16, 2025
06e2578
Fix spinner modal
nop33 May 16, 2025
455bcdb
Fix missing addresses on wallet import
nop33 May 16, 2025
345aff0
Fix backdrop in Android
nop33 May 16, 2025
27678b9
Remove purple bottom modal handle
nop33 May 26, 2025
dbb4acc
Fix spacing
nop33 May 26, 2025
f3e6ff7
Fix lint
nop33 May 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/mobile-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@dev-plugins/react-query": "^0.2.0",
"@expo/vector-icons": "^14.0.4",
"@fugashu/alphland-api-client": "^1.0.4",
"@gorhom/bottom-sheet": "^5",
"@json-rpc-tools/utils": "^1.7.6",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-community/netinfo": "^11.4.1",
Expand Down
19 changes: 11 additions & 8 deletions apps/mobile-wallet/src/components/BiometricsWarningModal.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { useBottomSheetModal } from '@gorhom/bottom-sheet'
import { useTranslation } from 'react-i18next'

import AppText from '~/components/AppText'
import BottomButtons from '~/components/buttons/BottomButtons'
import Button from '~/components/buttons/Button'
import { ScreenSection } from '~/components/layout/Screen'
import BottomModal from '~/features/modals/BottomModal'
import { closeModal } from '~/features/modals/modalActions'
import BottomModal2 from '~/features/modals/BottomModal2'
import withModal from '~/features/modals/withModal'
import { useAppDispatch } from '~/hooks/redux'
import { VERTICAL_GAP } from '~/style/globalStyle'

interface BiometricsWarningModalProps {
Expand All @@ -17,27 +16,31 @@ interface BiometricsWarningModalProps {

const BiometricsWarningModal = withModal<BiometricsWarningModalProps>(({ id, onConfirm, confirmText }) => {
const { t } = useTranslation()
const dispatch = useAppDispatch()
const { dismiss } = useBottomSheetModal()

const handleConfirm = () => {
onConfirm()
dispatch(closeModal({ id }))
dismiss(id)
}

const handleCancel = () => {
dismiss(id)
}

return (
<BottomModal modalId={id} title={`⚠️ ${t('Are you sure?')}`} noPadding>
<BottomModal2 notScrollable modalId={id} title={`⚠️ ${t('Are you sure?')}`} noPadding>
<ScreenSection verticalGap>
<AppText color="secondary" size={18} style={{ textAlign: 'center', paddingTop: VERTICAL_GAP }}>
{t(
"If you don't turn on biometrics, anyone who gains access to your device can open the app and steal your funds."
)}
</AppText>
<BottomButtons fullWidth backgroundColor="back1" bottomInset>
<Button title={t('Cancel')} onPress={() => dispatch(closeModal({ id }))} flex />
<Button title={t('Cancel')} onPress={handleCancel} flex />
<Button title={confirmText ?? t('Disable')} onPress={handleConfirm} variant="alert" flex />
</BottomButtons>
</ScreenSection>
</BottomModal>
</BottomModal2>
)
})

Expand Down
64 changes: 32 additions & 32 deletions apps/mobile-wallet/src/components/ConsolidationModal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useBottomSheetModal } from '@gorhom/bottom-sheet'
import { useTranslation } from 'react-i18next'
import { View } from 'react-native'
import styled from 'styled-components/native'
Expand All @@ -7,11 +8,8 @@ import AppText from '~/components/AppText'
import Button from '~/components/buttons/Button'
import ButtonsRow from '~/components/buttons/ButtonsRow'
import { ModalScreenTitle, ScreenSection } from '~/components/layout/Screen'
import BottomModal from '~/features/modals/BottomModal'
import { closeModal } from '~/features/modals/modalActions'
import { ModalContent } from '~/features/modals/ModalContent'
import BottomModal2 from '~/features/modals/BottomModal2'
import withModal from '~/features/modals/withModal'
import { useAppDispatch } from '~/hooks/redux'

interface ConsolidationModalProps {
onConsolidate: () => void
Expand All @@ -20,40 +18,42 @@ interface ConsolidationModalProps {

const ConsolidationModal = withModal<ConsolidationModalProps>(({ id, onConsolidate, fees }) => {
const { t } = useTranslation()
const dispatch = useAppDispatch()
const { dismiss } = useBottomSheetModal()

const handleConsolidate = () => {
onConsolidate()
dispatch(closeModal({ id }))
dismiss(id)
}

const handleCancel = () => {
dismiss(id)
}

return (
<BottomModal modalId={id}>
<ModalContent verticalGap>
<ScreenSection>
<ModalScreenTitle>{t('Consolidation required')}</ModalScreenTitle>
</ScreenSection>
<ScreenSection>
<View>
<AppText>
{t(
'It appears that the address you use to send funds from has too many UTXOs! Would you like to consolidate them? This will cost as small fee.'
)}
</AppText>
<Fee>
<AppText>{t('Fee')}:</AppText>
<Amount value={fees} fullPrecision bold />
</Fee>
</View>
</ScreenSection>
<ScreenSection centered>
<ButtonsRow>
<Button title={t('Cancel')} onPress={() => dispatch(closeModal({ id }))} flex variant="accent" short />
<Button title={t('Consolidate')} onPress={handleConsolidate} variant="highlight" flex short />
</ButtonsRow>
</ScreenSection>
</ModalContent>
</BottomModal>
<BottomModal2 notScrollable modalId={id}>
<ScreenSection>
<ModalScreenTitle>{t('Consolidation required')}</ModalScreenTitle>
</ScreenSection>
<ScreenSection>
<View>
<AppText>
{t(
'It appears that the address you use to send funds from has too many UTXOs! Would you like to consolidate them? This will cost as small fee.'
)}
</AppText>
<Fee>
<AppText>{t('Fee')}:</AppText>
<Amount value={fees} fullPrecision bold />
</Fee>
</View>
</ScreenSection>
<ScreenSection centered>
<ButtonsRow>
<Button title={t('Cancel')} onPress={handleCancel} flex variant="accent" short />
<Button title={t('Consolidate')} onPress={handleConsolidate} variant="highlight" flex short />
</ButtonsRow>
</ScreenSection>
</BottomModal2>
)
})

Expand Down
4 changes: 1 addition & 3 deletions apps/mobile-wallet/src/components/NFTWebView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ const NFTWebView = ({ imageUri, size = '100%' }: NFTWebViewProps) => (
borderRadius: BORDER_RADIUS_SMALL,
backgroundColor: 'transparent'
}}
injectedJavaScript={
"const meta = document.createElement('meta'); meta.setAttribute('content', 'width=width, initial-scale=1, maximum-scale=1, user-scalable=1'); meta.setAttribute('name', 'viewport'); document.getElementsByTagName('head')[0].appendChild(meta); "
}
injectedJavaScript="const meta = document.createElement('meta'); meta.setAttribute('content', 'width=width, initial-scale=1, maximum-scale=1, user-scalable=1'); meta.setAttribute('name', 'viewport'); document.getElementsByTagName('head')[0].appendChild(meta); "
javaScriptEnabled={false}
startInLoadingState={true}
javaScriptCanOpenWindowsAutomatically={false}
Expand Down
94 changes: 0 additions & 94 deletions apps/mobile-wallet/src/components/NFTsGrid.tsx

This file was deleted.

21 changes: 18 additions & 3 deletions apps/mobile-wallet/src/components/SearchInput.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { BottomSheetTextInput } from '@gorhom/bottom-sheet'
import { useTranslation } from 'react-i18next'
import { TextInput, TextInputProps } from 'react-native'
import styled, { css, useTheme } from 'styled-components/native'

import Button from '~/components/buttons/Button'

const SearchInput = (props: TextInputProps) => {
interface SearchInputProps extends TextInputProps {
isInModal?: boolean
}

const SearchInput = ({ isInModal, ...props }: SearchInputProps) => {
const { t } = useTranslation()
const theme = useTheme()

const handleClearPress = () => {
props.onChangeText?.('')
}

const InputComponent = isInModal ? BottomSheetInputStyled : TextInputStyled

return (
<SearchInputStyled>
<TextInputStyled placeholder={t('Search')} placeholderTextColor={theme.font.tertiary} {...props} />
<InputComponent placeholder={t('Search')} placeholderTextColor={theme.font.tertiary} {...props} />

{props.value && (
<ClearButtonContainer>
Expand All @@ -41,7 +48,7 @@ const ClearButtonContainer = styled.View`
justify-content: center;
`

const TextInputStyled = styled(TextInput)`
const InputStyles = css<{ value?: string }>`
width: 100%;
background-color: ${({ theme }) => theme.bg.highlight};
padding: 12px 14px;
Expand All @@ -54,3 +61,11 @@ const TextInputStyled = styled(TextInput)`
padding-right: 52px;
`};
`

const TextInputStyled = styled(TextInput)`
${InputStyles}
`

const BottomSheetInputStyled = styled(BottomSheetTextInput)`
${InputStyles}
`
26 changes: 22 additions & 4 deletions apps/mobile-wallet/src/components/inputs/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { BottomSheetTextInput } from '@gorhom/bottom-sheet'
import * as Clipboard from 'expo-clipboard'
import { ReactNode, RefObject, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleProp, TextInput, TextInputProps, ViewProps, ViewStyle } from 'react-native'
import { StyleProp, TextInputProps, ViewProps, ViewStyle } from 'react-native'
import { TextInput } from 'react-native-gesture-handler'
import Animated, { AnimatedProps, FadeIn, FadeOut } from 'react-native-reanimated'
import styled, { css, useTheme } from 'styled-components/native'

Expand All @@ -25,6 +27,7 @@ export interface InputProps<T extends InputValue> extends Omit<TextInputProps, '
style?: StyleProp<ViewStyle>
layout?: AnimatedProps<ViewProps>['layout']
inputRef?: RefObject<TextInput>
isInModal?: boolean
}

const Input = <T extends InputValue>({
Expand All @@ -43,6 +46,7 @@ const Input = <T extends InputValue>({
layout,
inputRef,
onChangeText,
isInModal,
...props
}: InputProps<T>) => {
const { t } = useTranslation()
Expand All @@ -68,19 +72,19 @@ const Input = <T extends InputValue>({
}

const isShowingPasteButton = copiedText && showPasteButton
const TextInputComponent = isInModal ? BottomSheetTextInputStyled : TextInputStyled

return (
<InputStyled onPress={onPress} style={style} short={short}>
<InputContainer>
{showCustomValueRendering && <CustomRenderedValue>{renderedValue}</CustomRenderedValue>}
<TextInputStyled
<TextInputComponent
selectionColor={theme.global.accent}
value={renderedValue?.toString()}
onFocus={onFocus}
onBlur={onBlur}
ref={usedInputRef}
placeholder={label}
forwardedAs={TextInput}
placeholderTextColor={theme.font.tertiary}
style={resetDisabledColor && !props.editable ? { color: theme.font.primary } : undefined}
hide={showCustomValueRendering}
Expand Down Expand Up @@ -119,11 +123,25 @@ const InputContainer = styled.View`
gap: 5px;
`

const TextInputStyled = styled.TextInput<{ hide?: boolean }>`
const InputStyles = css`
flex: 1;
height: 100%;
color: ${({ theme }) => theme.font.primary};
font-size: 15px;
`

const TextInputStyled = styled.TextInput<{ hide?: boolean }>`
${InputStyles};

${({ hide }) =>
hide &&
css`
opacity: 0;
`}
`

const BottomSheetTextInputStyled = styled(BottomSheetTextInput)<{ hide?: boolean }>`
${InputStyles};

${({ hide }) =>
hide &&
Expand Down
1 change: 1 addition & 0 deletions apps/mobile-wallet/src/components/layout/Screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export const ScreenSection = styled.View<ScreenSectionProps>`
export const ModalScreenTitle = styled(AppText)`
font-weight: 600;
font-size: 28px;
margin-top: 10px;
`

export const ScreenSectionTitle = styled(AppText)`
Expand Down
Loading
Loading