Skip to content

Commit e020d19

Browse files
committed
WIP
1 parent 136a3d4 commit e020d19

File tree

43 files changed

+1523
-906
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1523
-906
lines changed

__tests__/todos.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import {
2121
transferClosingChannelTodo,
2222
supportTodo,
2323
inviteTodo,
24-
// fastpayTodo,
24+
quickpayTodo,
2525
// discountTodo,
2626
} from '../src/store/shapes/todos';
2727
import { createNewWallet } from '../src/utils/startup';
@@ -51,7 +51,7 @@ describe('Todos selector', () => {
5151
buyBitcoinTodo,
5252
supportTodo,
5353
inviteTodo,
54-
// fastpayTodo,
54+
quickpayTodo,
5555
slashtagsProfileTodo,
5656
// discountTodo,
5757
]);

ios/Podfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ PODS:
3434
- MMKV (1.3.7):
3535
- MMKVCore (~> 1.3.7)
3636
- MMKVCore (1.3.7)
37-
- OpenSSL-Universal (3.3.2000)
37+
- OpenSSL-Universal (3.1.5007)
3838
- RCT-Folly (2024.01.01.00):
3939
- boost
4040
- DoubleConversion
@@ -2218,7 +2218,7 @@ SPEC CHECKSUMS:
22182218
lottie-react-native: 31197e5c65aa7cb59e6affcefaf901588bb708c4
22192219
MMKV: 36a22a9ec84c9bb960613a089ddf6f48be9312b0
22202220
MMKVCore: 158e61c8516401a9fac730288acb29e6fc19bbf9
2221-
OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4
2221+
OpenSSL-Universal: 2d916d735a0196be6a14b959ce976c564d392861
22222222
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
22232223
RCTDeprecation: 34cbf122b623037ea9facad2e92e53434c5c7422
22242224
RCTRequired: 24c446d7bcd0f517d516b6265d8df04dc3eb1219
@@ -2308,7 +2308,7 @@ SPEC CHECKSUMS:
23082308
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
23092309
sodium-react-native-direct: 8feb9a6d0d88ce65efa305d6cc774c11c62d9a15
23102310
SSZipArchive: c69881e8ac5521f0e622291387add5f60f30f3c4
2311-
Yoga: 2a45d7e59592db061217551fd3bbe2dd993817ae
2311+
Yoga: a1d7895431387402a674fd0d1c04ec85e87909b8
23122312
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
23132313

23142314
PODFILE CHECKSUM: cb153cb4a39e6c92c8b869eafab65a4bba7b869f

ios/bitkit.xcodeproj/project.pbxproj

Lines changed: 52 additions & 52 deletions
Large diffs are not rendered by default.
373 KB
Loading
469 KB
Loading

src/components/HourglassSpinner.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { ReactElement } from 'react';
2-
import { View, StyleSheet, StyleProp, ViewStyle, Image } from 'react-native';
2+
import { View, StyleSheet, StyleProp, ViewStyle, Image, ImageSourcePropType } from 'react-native';
33
import { Easing, withRepeat, withTiming } from 'react-native-reanimated';
44

55
import { AnimatedView } from '../styles/components';
@@ -8,9 +8,11 @@ import { __E2E__ } from '../constants/env';
88
const imageSrc = require('../assets/illustrations/hourglass.png');
99

1010
const HourglassSpinner = ({
11+
image = imageSrc,
1112
imageSize = 256,
1213
style,
1314
}: {
15+
image?: ImageSourcePropType;
1416
imageSize?: number;
1517
style?: StyleProp<ViewStyle>;
1618
}): ReactElement => {
@@ -47,7 +49,7 @@ const HourglassSpinner = ({
4749
color="transparent"
4850
testID="HourglassSpinner">
4951
<View style={[styles.imageContainer, { width: imageSize }]}>
50-
<Image style={styles.image} source={imageSrc} />
52+
<Image style={styles.image} source={image} />
5153
</View>
5254
</AnimatedView>
5355
);

src/components/LightningSyncing.tsx

Lines changed: 3 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import React, { ReactElement, useEffect, useState } from 'react';
22
import { Image, StyleProp, StyleSheet, View, ViewStyle } from 'react-native';
3-
import Animated, {
3+
import {
44
Easing,
55
cancelAnimation,
66
runOnJS,
77
useSharedValue,
8-
withDelay,
98
withRepeat,
10-
withSequence,
119
withTiming,
1210
} from 'react-native-reanimated';
1311
import { useTranslation } from 'react-i18next';
@@ -17,13 +15,12 @@ import { AnimatedView } from '../styles/components';
1715
import SafeAreaInset from './SafeAreaInset';
1816
import BottomSheetNavigationHeader from './BottomSheetNavigationHeader';
1917
import GradientView from './GradientView';
18+
import SyncSpinner from './SyncSpinner';
2019
import { useAppSelector } from '../hooks/redux';
2120
import { isLDKReadySelector } from '../store/reselect/ui';
2221
import { __E2E__ } from '../constants/env';
2322

2423
const imageSrc = require('../assets/illustrations/lightning.png');
25-
const imageSyncSmall = require('../assets/illustrations/ln-sync-small.png');
26-
const imageSyncLarge = require('../assets/illustrations/ln-sync-large.png');
2724

2825
const LightningSyncing = ({
2926
title,
@@ -69,62 +66,6 @@ const LightningSyncing = ({
6966
return <></>;
7067
}
7168

72-
const animationLarge = (): { initialValues: {}; animations: {} } => {
73-
'worklet';
74-
const initialValues = { transform: [{ rotate: '0deg' }] };
75-
const animations = {
76-
transform: [
77-
{
78-
rotate: withRepeat(
79-
withSequence(
80-
withTiming('-180deg', {
81-
duration: 1500,
82-
easing: Easing.inOut(Easing.ease),
83-
}),
84-
withDelay(
85-
100,
86-
withTiming('-360deg', {
87-
duration: 1500,
88-
easing: Easing.inOut(Easing.ease),
89-
}),
90-
),
91-
),
92-
-1,
93-
),
94-
},
95-
],
96-
};
97-
return { initialValues, animations };
98-
};
99-
100-
const animationSmall = (): { initialValues: {}; animations: {} } => {
101-
'worklet';
102-
const initialValues = { transform: [{ rotate: '0deg' }] };
103-
const animations = {
104-
transform: [
105-
{
106-
rotate: withRepeat(
107-
withSequence(
108-
withTiming('180deg', {
109-
duration: 1500,
110-
easing: Easing.inOut(Easing.ease),
111-
}),
112-
withDelay(
113-
100,
114-
withTiming('360deg', {
115-
duration: 1500,
116-
easing: Easing.inOut(Easing.ease),
117-
}),
118-
),
119-
),
120-
-1,
121-
),
122-
},
123-
],
124-
};
125-
return { initialValues, animations };
126-
};
127-
12869
return (
12970
<AnimatedView
13071
style={[style, { opacity: rootOpacity }]}
@@ -135,18 +76,7 @@ const LightningSyncing = ({
13576
<BodyM color="secondary">{t('wait_text_top')}</BodyM>
13677

13778
<View style={styles.imageContainer}>
138-
<View style={styles.animation}>
139-
<Animated.Image
140-
style={styles.circleSmall}
141-
source={imageSyncSmall}
142-
entering={__E2E__ ? undefined : animationSmall}
143-
/>
144-
<Animated.Image
145-
style={styles.circleLarge}
146-
source={imageSyncLarge}
147-
entering={__E2E__ ? undefined : animationLarge}
148-
/>
149-
</View>
79+
<SyncSpinner />
15080
<Image style={styles.image} source={imageSrc} />
15181
</View>
15282

@@ -182,28 +112,6 @@ const styles = StyleSheet.create({
182112
flex: 1,
183113
resizeMode: 'contain',
184114
},
185-
animation: {
186-
justifyContent: 'center',
187-
alignItems: 'center',
188-
alignSelf: 'center',
189-
position: 'absolute',
190-
width: 311,
191-
aspectRatio: 1,
192-
},
193-
circleSmall: {
194-
flex: 1,
195-
position: 'absolute',
196-
resizeMode: 'contain',
197-
width: 207,
198-
aspectRatio: 1,
199-
},
200-
circleLarge: {
201-
flex: 1,
202-
position: 'absolute',
203-
resizeMode: 'contain',
204-
width: 311,
205-
aspectRatio: 1,
206-
},
207115
bottom: {
208116
textAlign: 'center',
209117
marginTop: 'auto',

src/components/Slider.tsx

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
import React, { ReactElement, useEffect, useState } from 'react';
2+
import { View, StyleSheet } from 'react-native';
3+
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
4+
import Animated, {
5+
useSharedValue,
6+
useAnimatedStyle,
7+
withSpring,
8+
clamp,
9+
interpolate,
10+
runOnJS,
11+
} from 'react-native-reanimated';
12+
13+
import { Text13UP } from '../styles/text';
14+
import { View as ThemedView } from '../styles/components';
15+
import useColors from '../hooks/colors';
16+
17+
const KNOB_SIZE = 32;
18+
19+
const Slider = ({
20+
steps,
21+
value,
22+
onValueChange,
23+
}: {
24+
steps: number[];
25+
value: number;
26+
onValueChange: (value: number) => void;
27+
}): ReactElement => {
28+
const colors = useColors();
29+
const [sliderWidth, setSliderWidth] = useState(0);
30+
const panX = useSharedValue(0);
31+
const prevPanX = useSharedValue(0);
32+
33+
// Convert steps to evenly spaced positions on the slider
34+
const stepPositions = steps.map((_, index) => {
35+
const numSteps = steps.length - 1;
36+
// Calculate position based on index, using full width
37+
return (index / numSteps) * sliderWidth;
38+
});
39+
40+
// Set initial position when slider width changes or value changes
41+
useEffect(() => {
42+
if (sliderWidth === 0) {
43+
return;
44+
}
45+
46+
// Find index of current value in steps array
47+
const valueIndex = steps.indexOf(value);
48+
panX.value = stepPositions[valueIndex];
49+
50+
// eslint-disable-next-line react-hooks/exhaustive-deps
51+
}, [sliderWidth, value, steps]);
52+
53+
const gesture = Gesture.Pan()
54+
.onStart(() => {
55+
prevPanX.value = panX.value;
56+
})
57+
.onUpdate((event) => {
58+
panX.value = clamp(prevPanX.value + event.translationX, 0, sliderWidth);
59+
})
60+
.onEnd(() => {
61+
const findClosestStep = (currentPosition: number): number => {
62+
return stepPositions.reduce((prev, curr) => {
63+
return Math.abs(curr - currentPosition) <
64+
Math.abs(prev - currentPosition)
65+
? curr
66+
: prev;
67+
});
68+
};
69+
70+
const closestStep = findClosestStep(panX.value);
71+
panX.value = withSpring(closestStep);
72+
73+
if (onValueChange) {
74+
const stepIndex = stepPositions.indexOf(closestStep);
75+
runOnJS(onValueChange)(steps[stepIndex]);
76+
}
77+
});
78+
79+
const animatedStyle = useAnimatedStyle(() => ({
80+
transform: [{ translateX: panX.value - KNOB_SIZE / 2 }],
81+
}));
82+
83+
const trailStyle = useAnimatedStyle(() => ({
84+
width: interpolate(panX.value, [0, sliderWidth], [0, sliderWidth]),
85+
backgroundColor: colors.green,
86+
}));
87+
88+
return (
89+
<View
90+
style={styles.container}
91+
onLayout={(e): void => setSliderWidth(e.nativeEvent.layout.width)}>
92+
<View style={styles.sliderContainer}>
93+
<ThemedView style={styles.track} color="green32" />
94+
<Animated.View style={[styles.track, trailStyle]} />
95+
{stepPositions.map((pos, index) => (
96+
<View
97+
key={`step-${index}`}
98+
style={[styles.stepContainer, { left: pos - 2 }]}>
99+
<ThemedView style={styles.stepMarker} color="white" />
100+
<Text13UP style={styles.stepLabel} numberOfLines={1}>
101+
${steps[index]}
102+
</Text13UP>
103+
</View>
104+
))}
105+
<GestureDetector gesture={gesture}>
106+
<Animated.View style={[styles.knob, animatedStyle]}>
107+
<ThemedView color="green" style={styles.knobOuter}>
108+
<ThemedView color="white" style={styles.knobInner} />
109+
</ThemedView>
110+
</Animated.View>
111+
</GestureDetector>
112+
</View>
113+
</View>
114+
);
115+
};
116+
117+
const styles = StyleSheet.create({
118+
container: {
119+
marginTop: 16,
120+
flex: 1,
121+
},
122+
sliderContainer: {
123+
height: KNOB_SIZE,
124+
flexDirection: 'row',
125+
position: 'relative',
126+
alignItems: 'center',
127+
justifyContent: 'center',
128+
},
129+
track: {
130+
borderRadius: 3,
131+
height: 8,
132+
width: '100%',
133+
position: 'absolute',
134+
left: 0,
135+
},
136+
stepContainer: {
137+
position: 'absolute',
138+
alignItems: 'center',
139+
height: '100%',
140+
justifyContent: 'center',
141+
},
142+
stepMarker: {
143+
width: 4,
144+
height: 16,
145+
borderRadius: 5,
146+
},
147+
stepLabel: {
148+
position: 'absolute',
149+
top: '100%',
150+
marginTop: 4,
151+
width: 30,
152+
textAlign: 'center',
153+
},
154+
knob: {
155+
width: KNOB_SIZE,
156+
height: KNOB_SIZE,
157+
borderRadius: KNOB_SIZE / 2,
158+
position: 'absolute',
159+
left: 0,
160+
},
161+
knobOuter: {
162+
borderRadius: KNOB_SIZE,
163+
height: KNOB_SIZE,
164+
width: KNOB_SIZE,
165+
alignItems: 'center',
166+
justifyContent: 'center',
167+
},
168+
knobInner: {
169+
borderRadius: 16,
170+
height: 16,
171+
width: 16,
172+
},
173+
});
174+
175+
export default Slider;

0 commit comments

Comments
 (0)