Skip to content
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

UI redesign part 4 #883

Open
wants to merge 40 commits into
base: UI-redesign-part3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4ab610b
Migrate WalletConnectSessionRequestModal
mvaivre Oct 11, 2024
b02a778
Add handy paste button to Input component
mvaivre Oct 11, 2024
12d5e7f
Replace header canvas gradient by expo linear gradient
mvaivre Oct 11, 2024
ce751ae
Replace footer gradient with expo linear gradient
mvaivre Oct 11, 2024
7462668
Android Navigation: workaround to avoid glitch
mvaivre Oct 14, 2024
ba58ce9
Fix RoundedCard look
mvaivre Oct 14, 2024
ec52509
Improve header / footer margins on Android
mvaivre Oct 15, 2024
96528b5
Add padding bottom to BottomModal on Android
mvaivre Oct 15, 2024
fff2d49
Fix ActivityScreen's scroll end behaviour
mvaivre Oct 15, 2024
d0f26b0
Fix bottom modal scroll (Android) + avoid clash on iOS
mvaivre Oct 16, 2024
690aa7b
DRY things up with BottomModalBase
mvaivre Oct 16, 2024
7fdfa69
Dynamically mount modal's children according to their "scrollability"
mvaivre Oct 16, 2024
55eb0f5
Extract BottomModalHeader
mvaivre Oct 16, 2024
d355c71
Fix BottomModal types
mvaivre Oct 16, 2024
b790895
Improve Transaction modal
mvaivre Oct 16, 2024
c1d81bb
Fixes in new contact modal / screen
mvaivre Oct 16, 2024
d3c078e
Remove callbacks renames
mvaivre Oct 21, 2024
edc2b33
Wrap Screens with KeyboardAvoidingView by default
mvaivre Oct 21, 2024
e79ea23
Use flashListRenderer in BottomModalFlashList
mvaivre Oct 31, 2024
33c142e
Update modals titles
mvaivre Oct 31, 2024
7ee0f08
flashListRenderer -> flashListRender
mvaivre Oct 31, 2024
86333c9
Redesign / simplify rows
mvaivre Nov 1, 2024
dc67ec7
Layout tweaks
mvaivre Nov 1, 2024
0b44911
BoxSurface -> Surface
mvaivre Nov 1, 2024
2d6d313
Redesign NftModal attribute list, simplify Row and Input components
mvaivre Nov 1, 2024
0598baa
Fix BottomModalBase inner container
mvaivre Nov 2, 2024
ed21fc6
Stop using progress header in Send flow, add gradient to BottomButtons
mvaivre Nov 2, 2024
9b049fd
Input tweaks
mvaivre Nov 2, 2024
dfa571b
Nit fixes
mvaivre Nov 5, 2024
1604e49
Fix Input copy text useEffect
mvaivre Nov 5, 2024
85ed15c
Use walletConnectClient from context in WalletConnectSessionRequestModal
mvaivre Nov 5, 2024
5013d84
Lint
mvaivre Nov 5, 2024
842f5fa
Send navigation header tweaks
mvaivre Nov 5, 2024
4c6d4d5
Use FlashList for address selection screen
mvaivre Nov 5, 2024
da2baa6
Add bottomButtonsRender props to ScrollScreen and FlashListScreen
mvaivre Nov 5, 2024
f3b4bcb
Add bottom button to verify screen
mvaivre Nov 5, 2024
d6ebad8
Use proper way to set custom header, but needs refinements
mvaivre Nov 5, 2024
3fe8b5f
Fix modal scrollable content flex
mvaivre Nov 6, 2024
ac36054
Use new layout in receive flow + allow address FlashList item rerende…
mvaivre Nov 6, 2024
e2aa938
handleClose -> onClose
mvaivre Nov 6, 2024
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
3 changes: 1 addition & 2 deletions apps/mobile-wallet/src/components/AddressesTokensList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,7 @@ const AddressesTokensList = ({ addressHash, isRefreshing, style }: AddressesToke
}

export default styled(AddressesTokensList)`
padding-top: 5px;
padding-bottom: 10px;
padding: 10px 0;
`

const LoadingRow = styled.View`
Expand Down
57 changes: 0 additions & 57 deletions apps/mobile-wallet/src/components/BlurredCard.tsx

This file was deleted.

3 changes: 2 additions & 1 deletion apps/mobile-wallet/src/components/NFTsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const NFTsGrid = forwardRef(
{...props}
data={data}
ref={ref}
overScrollMode="auto"
keyExtractor={(item) => item.id}
renderItem={({ item: nft }) => (
<NFTThumbnailContainer key={nft.id}>
Expand All @@ -70,7 +71,7 @@ const NFTsGrid = forwardRef(
)}
contentContainerStyle={{ paddingHorizontal: containerHorizontalPadding, paddingBottom: 70 }}
numColumns={columns}
estimatedItemSize={64}
estimatedItemSize={props.estimatedItemSize || 64}
scrollEnabled={scrollEnabled}
ListEmptyComponent={
<NoNFTsMessage>
Expand Down
37 changes: 37 additions & 0 deletions apps/mobile-wallet/src/components/RoundedCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
Copyright 2018 - 2024 The Alephium Authors
This file is part of the alephium project.
The library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with the library. If not, see <http://www.gnu.org/licenses/>.
*/
import { ReactNode } from 'react'
import { StyleProp, ViewStyle } from 'react-native'
import styled from 'styled-components/native'

interface RoundedCardProps {
children: ReactNode
style?: StyleProp<ViewStyle>
}

const RoundedCard = ({ children, style }: RoundedCardProps) => (
<RoundedCardContainer style={style}>{children}</RoundedCardContainer>
)

export default RoundedCard

const RoundedCardContainer = styled.View`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern we've used so far is RoundedCardStyled for this sort of components

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

border-radius: 38px;
overflow: hidden;
background-color: ${({ theme }) => theme.bg.primary};
`
46 changes: 24 additions & 22 deletions apps/mobile-wallet/src/components/footers/FooterMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
*/

import { BottomTabBarProps } from '@react-navigation/bottom-tabs'
import { Canvas, LinearGradient, Rect, vec } from '@shopify/react-native-skia'
import { colord } from 'colord'
import { LinearGradient } from 'expo-linear-gradient'
import { useState } from 'react'
import { LayoutChangeEvent, StyleProp, useWindowDimensions, View, ViewStyle } from 'react-native'
import { LayoutChangeEvent, Platform, StyleProp, View, ViewStyle } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import styled, { css, useTheme } from 'styled-components/native'

Expand All @@ -30,13 +30,14 @@ interface FooterMenuProps extends BottomTabBarProps {
style?: StyleProp<ViewStyle>
}

const isIos = Platform.OS === 'ios'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: we have this in other places too. Let's extract it to a util somewhere or just use Platform.OS === 'ios' which is short enough imo

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


const FooterMenu = ({ state, descriptors, navigation, style }: FooterMenuProps) => {
const insets = useSafeAreaInsets()
const { width: screenWidth } = useWindowDimensions()
const theme = useTheme()
const [footerHeight, setFooterHeight] = useState(120)

const gradientHeight = footerHeight + 30
const gradientHeight = footerHeight + 50

const footerContent = (
<>
Expand All @@ -54,25 +55,26 @@ const FooterMenu = ({ state, descriptors, navigation, style }: FooterMenuProps)
)

const handleFooterLayout = (e: LayoutChangeEvent) => {
setFooterHeight(e.nativeEvent.layout.height + insets.bottom)
setFooterHeight(e.nativeEvent.layout.height)
}

return (
<View style={style} onLayout={handleFooterLayout}>
<FooterGradientCanvas pointerEvents="none" height={gradientHeight}>
<Rect x={0} y={0} width={screenWidth} height={gradientHeight}>
<LinearGradient
start={vec(0, gradientHeight / 1.9)}
end={vec(0, 0)}
colors={
theme.name === 'dark'
? [theme.bg.back2, colord(theme.bg.back2).alpha(0).toHex()]
: [theme.bg.highlight, colord(theme.bg.highlight).alpha(0).toHex()]
}
/>
</Rect>
</FooterGradientCanvas>
<FooterMenuContent style={{ paddingBottom: insets.bottom }}>{footerContent}</FooterMenuContent>
<FooterGradient
start={{ x: 0.5, y: 1 }}
end={{ x: 0.5, y: 0 }}
locations={[0.45, 1]}
colors={
theme.name === 'dark'
? [theme.bg.back2, colord(theme.bg.back2).alpha(0).toHex()]
: [theme.bg.highlight, colord(theme.bg.highlight).alpha(0).toHex()]
}
style={{ height: gradientHeight }}
pointerEvents="none"
/>
<FooterMenuContent style={{ paddingBottom: isIos ? insets.bottom : insets.bottom + 18 }}>
{footerContent}
</FooterMenuContent>
</View>
)
}
Expand All @@ -97,10 +99,10 @@ const FooterMenuContent = styled.View`
${footerMenuStyles}
`

const FooterGradientCanvas = styled(Canvas)<{ height: number }>`
// Bottom value is to avoid glitch on Android
const FooterGradient = styled(LinearGradient)`
position: absolute;
bottom: 0;
bottom: -1px;
left: 0;
right: 0;
height: ${({ height }) => height}px;
`
36 changes: 18 additions & 18 deletions apps/mobile-wallet/src/components/headers/BaseHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ along with the library. If not, see <http://www.gnu.org/licenses/>.
*/

import { StackHeaderProps } from '@react-navigation/stack'
import { Canvas, LinearGradient, Rect, vec } from '@shopify/react-native-skia'
import { colord } from 'colord'
import { LinearGradient } from 'expo-linear-gradient'
import { ReactNode, RefObject, useState } from 'react'
import { LayoutChangeEvent, Platform, useWindowDimensions, View, ViewProps } from 'react-native'
import Animated, {
Expand Down Expand Up @@ -50,6 +50,8 @@ export interface BaseHeaderProps extends ViewProps {

const isIos = Platform.OS === 'ios'

const AnimatedHeaderGradient = Animated.createAnimatedComponent(LinearGradient)

const BaseHeader = ({
options: { headerRight, headerLeft, headerTitle, headerTitleRight },
headerRef,
Expand All @@ -64,9 +66,9 @@ const BaseHeader = ({
const { width: screenWidth } = useWindowDimensions()
const [headerHeight, setHeaderHeight] = useState(80)

const gradientHeight = headerHeight + 30
const gradientHeight = headerHeight + 42
const defaultScrollRange = [0 + scrollEffectOffset, 80 + scrollEffectOffset]
const paddingTop = isIos ? insets.top : insets.top + 7
const paddingTop = isIos ? insets.top : insets.top + 18

const HeaderRight = (headerRight && headerRight({})) || <HeaderSidePlaceholder />
const HeaderLeft = (headerLeft && headerLeft({})) || <HeaderSidePlaceholder />
Expand Down Expand Up @@ -97,19 +99,18 @@ const BaseHeader = ({
return (
<BaseHeaderStyled ref={headerRef} onLayout={handleHeaderLayout} {...props}>
<View pointerEvents="none">
<HeaderGradientCanvas height={gradientHeight} pointerEvents="none">
<Rect x={0} y={0} width={screenWidth} height={gradientHeight} opacity={animatedOpacity}>
<LinearGradient
start={vec(0, gradientHeight / 1.5)}
end={vec(0, gradientHeight)}
colors={
theme.name === 'dark'
? [theme.bg.back2, colord(theme.bg.back2).alpha(0).toHex()]
: [theme.bg.highlight, colord(theme.bg.highlight).alpha(0).toHex()]
}
/>
</Rect>
</HeaderGradientCanvas>
<HeaderGradient
pointerEvents="none"
style={{ opacity: animatedOpacity, width: screenWidth, height: gradientHeight }}
start={{ x: 0.5, y: 0 }}
end={{ x: 0.5, y: 1 }}
locations={[0.6, 1]}
colors={
theme.name === 'dark'
? [theme.bg.back2, colord(theme.bg.back2).alpha(0).toHex()]
: [theme.bg.highlight, colord(theme.bg.highlight).alpha(0).toHex()]
}
/>
</View>
<HeaderContainer>
<Header style={{ paddingTop }}>
Expand Down Expand Up @@ -147,12 +148,11 @@ const BaseHeaderStyled = styled(Animated.View)`
position: absolute;
`

const HeaderGradientCanvas = styled(Canvas)<{ height: number }>`
const HeaderGradient = styled(AnimatedHeaderGradient)`
position: absolute;
top: 0;
left: 0;
right: 0;
height: ${({ height }) => height}px;
`

const HeaderContainer = styled(Animated.View)`
Expand Down
52 changes: 52 additions & 0 deletions apps/mobile-wallet/src/components/inputs/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ You should have received a copy of the GNU Lesser General Public License
along with the library. If not, see <http://www.gnu.org/licenses/>.
*/

import { colord } from 'colord'
import { getStringAsync } from 'expo-clipboard'
import { LinearGradient } from 'expo-linear-gradient'
import { ReactNode, RefObject, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import {
NativeSyntheticEvent,
StyleProp,
Expand All @@ -31,6 +35,7 @@ import styled, { css, useTheme } from 'styled-components/native'

import { fastSpringConfiguration } from '~/animations/reanimated/reanimatedAnimations'
import AppText from '~/components/AppText'
import Button from '~/components/buttons/Button'
import Row from '~/components/Row'
import { BORDER_RADIUS } from '~/style/globalStyle'

Expand All @@ -44,6 +49,7 @@ export interface InputProps<T extends InputValue> extends Omit<TextInputProps, '
resetDisabledColor?: boolean
RightContent?: ReactNode
renderValue?: RenderValueFunc<T>
showPasteButton?: boolean
error?: string
style?: StyleProp<ViewStyle>
layout?: AnimatedProps<ViewProps>['layout']
Expand All @@ -60,13 +66,16 @@ const Input = <T extends InputValue>({
resetDisabledColor,
RightContent,
renderValue,
showPasteButton,
error,
layout,
inputRef,
...props
}: InputProps<T>) => {
const { t } = useTranslation()
const theme = useTheme()
const [isActive, setIsActive] = useState(false)
const [copiedText, setCopiedText] = useState('')
const localInputRef = useRef<TextInput>(null)
const usedInputRef = inputRef || localInputRef

Expand All @@ -81,6 +90,15 @@ const Input = <T extends InputValue>({
fontSize: withSpring(!isActive ? 15 : 11, fastSpringConfiguration)
}))

useEffect(() => {
const fetchCopiedText = async () => {
const text = await getStringAsync()
setCopiedText(text)
}

fetchCopiedText()
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependency array is missing.

Also, I started preferring this pattern, WDYT?

Suggested change
useEffect(() => {
const fetchCopiedText = async () => {
const text = await getStringAsync()
setCopiedText(text)
}
fetchCopiedText()
})
useEffect(() => {
getStringAsync().then(setCopiedText)
}, [])

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also like it better I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to the pattern you proposed


useEffect(() => {
if (renderedValue) {
setIsActive(true)
Expand All @@ -97,6 +115,10 @@ const Input = <T extends InputValue>({
onBlur && onBlur(e)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing dependency array

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code has been removed


const handlePasteButtonPress = () => {
usedInputRef.current?.setNativeProps({ text: copiedText })
}

return (
<Row
onPress={onPress}
Expand Down Expand Up @@ -129,6 +151,19 @@ const Input = <T extends InputValue>({
hide={showCustomValueRendering}
{...props}
/>
{copiedText && showPasteButton && (
<PasteButtonContainer>
<PasteButtonContainerBackground
colors={[colord(theme.bg.highlight).alpha(0.1).toHex(), theme.bg.highlight]}
start={{ x: 0, y: 0.5 }}
end={{ x: 1, y: 0.5 }}
locations={[0, 0.2]}
/>
<Button compact onPress={handlePasteButtonPress}>
<AppText>{t('Paste')}</AppText>
</Button>
</PasteButtonContainer>
)}
</InputContainer>
{RightContent}
{error && (
Expand Down Expand Up @@ -205,3 +240,20 @@ const Error = styled(AppText)`
font-size: 11px;
`

const PasteButtonContainer = styled.View`
position: absolute;
right: 0;
top: 0;
bottom: 0;
align-items: center;
justify-content: center;
`

const PasteButtonContainerBackground = styled(LinearGradient)`
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 0;
`
Loading
Loading