Skip to content

Commit 8580f3a

Browse files
Make minute selecting working + white text when selected or nearly selected
1 parent a5ccc4f commit 8580f3a

File tree

10 files changed

+361
-86
lines changed

10 files changed

+361
-86
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
"<rootDir>/lib/"
8484
]
8585
},
86-
8786
"commitlint": {
8887
"extends": [
8988
"@commitlint/config-conventional"
File renamed without changes.

src/Date/DatePickerModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Calendar, {
99
SingleChange,
1010
} from './Calendar'
1111

12-
import AnimatedCrossView from '../AnimatedCrossView'
12+
import AnimatedCrossView from './AnimatedCrossView'
1313

1414
import DatePickerModalHeader, { HeaderPickProps } from './DatePickerModalHeader'
1515
import CalendarEdit from './CalendarEdit'

src/Time/AnalogClock.tsx

Lines changed: 81 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
clockTypes,
1212
getAngle,
1313
getHours,
14+
getMinutes,
1415
isPM,
1516
PossibleClockTypes,
1617
} from './timeUtils'
@@ -19,55 +20,82 @@ import { useCallback } from 'react'
1920
import { useLatest } from '../utils'
2021
import AnalogClockHours from './AnalogClockHours'
2122

23+
import AnimatedClockSwitcher from './AnimatedClockSwitcher'
24+
import AnalogClockMinutes from './AnalogClockMinutes'
25+
2226
export const circleSize = 215
2327

24-
export default function AnalogClock({
28+
function AnalogClock({
2529
hours,
2630
minutes,
2731
focused,
2832
is24Hour,
33+
onChange,
2934
}: {
3035
hours: number
3136
minutes: number
3237
focused: PossibleClockTypes
3338
is24Hour: boolean
39+
onChange: ({
40+
hours,
41+
minutes,
42+
focused,
43+
}: {
44+
hours: number
45+
minutes: number
46+
focused?: undefined | PossibleClockTypes
47+
}) => any
3448
}) {
3549
const theme = useTheme()
36-
const pointerNumber = focused === clockTypes.hours ? hours : minutes
50+
3751
const clockRef = React.useRef<View | null>(null)
3852
const elementX = React.useRef<number>(0)
3953
const elementY = React.useRef<number>(0)
4054

41-
// We need the latest values
55+
// Hooks are nice, sometimes :-)..
56+
// We need the latest values, since the onPointerMove uses a closure to the function
4257
const hoursRef = useLatest(hours)
58+
const onChangeRef = useLatest(onChange)
59+
const minutesRef = useLatest(minutes)
4360
const focusedRef = useLatest(focused)
4461
const is24HourRef = useLatest(is24Hour)
62+
4563
const onPointerMove = React.useCallback(
46-
(e: GestureResponderEvent) => {
64+
(e: GestureResponderEvent, final: boolean) => {
4765
let x = e.nativeEvent.pageX - elementX.current
4866
let y = e.nativeEvent.pageY - elementY.current
4967

5068
let angle = getAngle(x, y, circleSize)
5169
if (focusedRef.current === clockTypes.hours) {
5270
let pickedHours = getHours(angle)
53-
5471
if (is24HourRef.current && isPM(x, y, circleSize)) {
5572
pickedHours += 12
5673
}
57-
if (hoursRef.current !== pickedHours) {
58-
// TODO: add onChange
59-
// setHours(pickedHours)
74+
if (hoursRef.current !== pickedHours || final) {
75+
onChangeRef.current({
76+
hours: pickedHours,
77+
minutes: minutesRef.current,
78+
focused: final ? clockTypes.minutes : undefined,
79+
})
80+
}
81+
} else if (focusedRef.current === clockTypes.minutes) {
82+
let pickedMinutes = getMinutes(angle)
83+
if (minutesRef.current !== pickedMinutes) {
84+
onChangeRef.current({
85+
hours: hoursRef.current,
86+
minutes: pickedMinutes,
87+
})
6088
}
6189
}
6290
},
63-
[hoursRef, focusedRef, is24HourRef]
91+
[focusedRef, is24HourRef, hoursRef, onChangeRef, minutesRef]
6492
)
6593

6694
const panResponder = React.useRef(
6795
PanResponder.create({
68-
onPanResponderGrant: onPointerMove,
69-
onPanResponderMove: onPointerMove,
70-
onPanResponderRelease: onPointerMove,
96+
onPanResponderGrant: (e) => onPointerMove(e, false),
97+
onPanResponderMove: (e) => onPointerMove(e, false),
98+
onPanResponderRelease: (e) => onPointerMove(e, true),
7199

72100
onStartShouldSetPanResponder: returnTrue,
73101
onStartShouldSetPanResponderCapture: returnTrue,
@@ -91,6 +119,11 @@ export default function AnalogClock({
91119
},
92120
[elementX, elementY]
93121
)
122+
123+
// used to make pointer shorter if hours are selected and above 12
124+
const dynamicSize = focused === clockTypes.hours && hours > 12 ? 33 : 0
125+
const pointerNumber = focused === clockTypes.hours ? hours : minutes
126+
const degreesPerNumber = focused === clockTypes.hours ? 30 : 6
94127
return (
95128
<View
96129
ref={clockRef}
@@ -108,30 +141,23 @@ export default function AnalogClock({
108141
cursor={'pointer'}
109142
>
110143
<View
111-
style={{
112-
position: 'absolute',
113-
width: circleSize / 2 - 4 - (hours > 12 ? 33 : 0),
114-
marginBottom: -1,
115-
height: 2,
116-
borderRadius: 4,
117-
backgroundColor: theme.colors.primary,
118-
transform: [
119-
{ rotate: -90 + pointerNumber * 30 + 'deg' },
120-
{ translateX: circleSize / 4 - 4 - (hours > 12 ? 33 / 2 : 0) },
121-
],
122-
}}
144+
style={[
145+
styles.line,
146+
{
147+
backgroundColor: theme.colors.primary,
148+
transform: [
149+
{ rotate: -90 + pointerNumber * degreesPerNumber + 'deg' },
150+
{
151+
translateX: circleSize / 4 - 4 - dynamicSize / 2,
152+
},
153+
],
154+
width: circleSize / 2 - 4 - dynamicSize,
155+
},
156+
]}
123157
pointerEvents="none"
124158
>
125159
<View
126-
style={{
127-
borderRadius: 15,
128-
height: 30,
129-
width: 30,
130-
position: 'absolute',
131-
backgroundColor: theme.colors.primary,
132-
right: 0,
133-
bottom: -14,
134-
}}
160+
style={[styles.endPoint, { backgroundColor: theme.colors.primary }]}
135161
/>
136162
</View>
137163
<View
@@ -147,7 +173,11 @@ export default function AnalogClock({
147173
]}
148174
/>
149175
</View>
150-
<AnalogClockHours is24Hour={is24Hour} hours={hours} />
176+
<AnimatedClockSwitcher
177+
focused={focused}
178+
hours={<AnalogClockHours is24Hour={is24Hour} hours={hours} />}
179+
minutes={<AnalogClockMinutes minutes={minutes} />}
180+
/>
151181
</View>
152182
)
153183
}
@@ -167,8 +197,25 @@ const styles = StyleSheet.create({
167197
width: 8,
168198
},
169199
center: { justifyContent: 'center', alignItems: 'center' },
200+
endPoint: {
201+
borderRadius: 15,
202+
height: 30,
203+
width: 30,
204+
position: 'absolute',
205+
right: 0,
206+
bottom: -14,
207+
},
208+
line: {
209+
position: 'absolute',
210+
211+
marginBottom: -1,
212+
height: 2,
213+
borderRadius: 4,
214+
},
170215
})
171216

172217
function returnTrue() {
173218
return true
174219
}
220+
221+
export default React.memo(AnalogClock)

src/Time/AnalogClockHours.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import * as React from 'react'
22
import { View, StyleSheet } from 'react-native'
33
import { Text } from 'react-native-paper'
4-
import { getNumbers } from './timeUtils'
54
import { circleSize } from './AnalogClock'
65

7-
const outerRange = getNumbers(false, circleSize, 12)
8-
const innerRange = getNumbers(true, circleSize, 12)
9-
10-
export default function AnalogClockHours({
6+
function AnalogClockHours({
117
is24Hour,
128
hours,
13-
}: {
9+
}: // onChange,
10+
{
1411
is24Hour: boolean
1512
hours: number
13+
// onChange: (hour: number) => any
1614
}) {
15+
const outerRange = getHourNumbers(false, circleSize, 12)
16+
const innerRange = getHourNumbers(true, circleSize, 12)
1717
return (
1818
<>
1919
{outerRange.map((a, i) => (
@@ -23,14 +23,14 @@ export default function AnalogClockHours({
2323
style={[
2424
styles.outerHourRoot,
2525
{
26-
top: a[1],
27-
left: a[0],
26+
top: a[1] || 0,
27+
left: a[0] || 0,
2828
},
2929
]}
3030
>
3131
<View style={styles.outerHourInner}>
3232
<Text
33-
style={hours === i + 1 ? { color: '#fff' } : null}
33+
style={hours === i + 1 ? styles.textWhite : null}
3434
selectable={false}
3535
>
3636
{i + 1}
@@ -46,17 +46,17 @@ export default function AnalogClockHours({
4646
style={[
4747
styles.innerHourRoot,
4848
{
49-
top: a[1],
50-
left: a[0],
49+
top: a[1] || 0,
50+
left: a[0] || 0,
5151
},
5252
]}
5353
>
5454
<View style={styles.innerHourInner}>
5555
<Text
5656
selectable={false}
5757
style={[
58-
{ fontSize: 13 },
59-
i + 13 === hours ? { color: '#fff' } : null,
58+
styles.innerHourText,
59+
i + 13 === hours ? styles.textWhite : null,
6060
]}
6161
>
6262
{i + 13 === 24 ? '00' : i + 13}
@@ -95,4 +95,25 @@ const styles = StyleSheet.create({
9595
borderRadius: 20,
9696
},
9797
innerHourInner: { borderRadius: 20 },
98+
innerHourText: { fontSize: 13 },
99+
textWhite: { color: '#fff' },
98100
})
101+
102+
function getHourNumbers(is24Hour: boolean, size: number, count: number) {
103+
let angle = 0
104+
let step = (2 * Math.PI) / count
105+
let radius = size / (is24Hour ? 4 : 2.5)
106+
107+
angle = (-90 * Math.PI) / 180 + Math.PI / 6
108+
109+
return Array(12)
110+
.fill(true)
111+
.map(() => {
112+
let x = Math.round(size / 2 + radius * Math.cos(angle))
113+
let y = Math.round(size / 2 + radius * Math.sin(angle))
114+
angle += step
115+
return [x, y]
116+
})
117+
}
118+
119+
export default React.memo(AnalogClockHours)

0 commit comments

Comments
 (0)