Skip to content

Commit d613468

Browse files
committed
Refactor Device component to use relative time format and add self logout option
1 parent 1413ad0 commit d613468

File tree

6 files changed

+64
-32
lines changed

6 files changed

+64
-32
lines changed

src/screens/Settings/Devices/Device.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import React, { useEffect, useMemo } from 'react'
1010
import { Alert, ToastAndroid, View } from 'react-native'
1111
import type { Device } from './types'
1212
import { getDate, getDeviceIcon, getOSIcon } from './utils'
13+
import { getRelativeTime } from '@utils/timeFormat'
14+
import { Medium, F } from '@utils/fonts'
1315

1416
type ParamList = {
1517
Device: DeviceParamList
@@ -21,12 +23,18 @@ export type DeviceParamList = {
2123

2224
export default function Device({ navigation, route }: { navigation: StackNav; route: RouteProp<ParamList, 'Device'> }) {
2325
const device = route.params.device
26+
27+
useEffect(() => {
28+
console.log(route.params.device?.isSelf)
29+
}, [route.params.device?.isSelf])
30+
2431
// const client = getClient()
2532
const { mutate, isPending, data } = useMutation({
2633
mutationKey: ['removeDevice', device?.id],
2734
mutationFn: async () =>
2835
await (await client.api.devices.delete.$post({ form: { device: device?.id || '' } })).json(),
2936
})
37+
const relativeTime = useMemo(() => getRelativeTime(device?.time), [device?.time])
3038

3139
const DeviceIcon = useMemo(() => getDeviceIcon(device?.os, device?.name), [device?.os, device?.name])
3240
const OsIcon = useMemo(() => getOSIcon(device?.os), [device?.os])
@@ -49,6 +57,7 @@ export default function Device({ navigation, route }: { navigation: StackNav; ro
4957
}, [data])
5058

5159
function handelRemove() {
60+
if (route.params.device?.isSelf) return navigation.navigate('Logout')
5261
Alert.alert('Remove Device', 'Are you sure you want to remove this device?', [
5362
{ text: 'Cancel', style: 'cancel' },
5463
{ text: 'Remove', onPress: () => mutate(), style: 'destructive' },
@@ -64,18 +73,19 @@ export default function Device({ navigation, route }: { navigation: StackNav; ro
6473
</View> */}
6574
<SettWrapper title={device?.name || 'Unknown Device'} navigation={navigation}>
6675
<Gap gap={15}>
67-
<SettText className='mt-3'>
68-
If you see a device that you don't recognize, you can remove it from the list. Just click on the 'Remove
69-
Device' button.
70-
</SettText>
76+
<SettText className='mt-3'>If you cannot identify this device, you can remove it from the list.</SettText>
7177
<SettGroup title='Device' className='pb-4'>
7278
<SettOption title={device?.name || 'Unknown'} Icon={DeviceIcon}></SettOption>
7379
</SettGroup>
7480
<SettGroup title='Operating System' className='pb-4'>
7581
<SettOption title={device?.os || 'Unknown'} Icon={OsIcon}></SettOption>
7682
</SettGroup>
7783
<SettGroup title='Logged In'>
78-
<SettOption title={getDate(device?.time)}></SettOption>
84+
<SettOption title={relativeTime}>
85+
<Medium className='text-zinc-600 dark:text-zinc-400' style={F.F10_5} numberOfLines={1}>
86+
{getDate(device?.time)}
87+
</Medium>
88+
</SettOption>
7989
</SettGroup>
8090
<SettGroup title='Device ID'>
8191
<SettOption title={device?.id || 'Unknown'}></SettOption>
@@ -84,7 +94,7 @@ export default function Device({ navigation, route }: { navigation: StackNav; ro
8494
Removing a device will log you out from the device. You will need to log in again to use the app on that
8595
device.
8696
</SettText>
87-
<View className='px-5'>
97+
<View className='px-6'>
8898
<Btn
8999
title={isPending ? 'Removing Device...' : 'Remove Device'}
90100
onPress={handelRemove}

src/screens/Settings/Devices/Devices.tsx

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
1-
import {
2-
AndroidSolidIcon,
3-
AppleSolidIcon,
4-
ChromeSolidIcon,
5-
WavingHand02SolidIcon,
6-
WindowsOldSolidIcon,
7-
} from '@assets/icons/icons'
1+
import { WavingHand02SolidIcon } from '@assets/icons/icons'
82
import { Gap12 } from '@components/Gap'
93
import RoundedIcon from '@components/RoundedIcon'
104
import { SettGroup, SettOption, SettText, SettWrapper } from '@components/Settings'
115
import { useMutation, useQuery } from '@tanstack/react-query'
126
import { client } from '@utils/client'
137
import { Colors } from '@utils/colors'
148
import { F, Medium } from '@utils/fonts'
15-
import type { NavProp, NU, StackNav } from '@utils/types'
9+
import { getRelativeTime } from '@utils/timeFormat'
10+
import type { NavProp, StackNav } from '@utils/types'
1611
import React, { useEffect, useMemo } from 'react'
1712
import { ActivityIndicator, Alert, ToastAndroid } from 'react-native'
1813
import type { Device } from './types'
19-
import { getDate, getDeviceIcon } from './utils'
20-
import { getRelativeTime } from '@utils/timeFormat'
14+
import { getDeviceIcon } from './utils'
2115

2216
export default function Devices({ navigation }: NavProp) {
2317
const { data, isPending } = useQuery({
@@ -50,12 +44,10 @@ export default function Devices({ navigation }: NavProp) {
5044
return (
5145
<SettWrapper title='Devices' navigation={navigation}>
5246
<Gap12>
53-
<SettText className='mt-3'>
54-
You can manage your devices here. You can remove unwanted devices from the list.
55-
</SettText>
47+
<SettText className='mt-3'>You can remove unwanted devices from the list.</SettText>
5648
<SettGroup title='This Device'>
5749
{isPending && <ActivityIndicator size='large' color={Colors.accent} className='mb-10 mt-5' />}
58-
{data && data.data && <Device navigation={navigation} device={data.data.currentDevice} />}
50+
{data && data.data && <Device navigation={navigation} device={data.data.currentDevice} isSelf={true} />}
5951
</SettGroup>
6052
{data && data.data && data.data.devices.length > 0 && (
6153
<SettGroup>
@@ -72,7 +64,7 @@ export default function Devices({ navigation }: NavProp) {
7264
{data && data.data && data.data.devices.length > 0 && (
7365
<SettGroup title='Other Devices'>
7466
{data.data.devices.map((device, i) => (
75-
<Device key={i} navigation={navigation} device={device} arrow />
67+
<Device key={i} navigation={navigation} device={device} isSelf />
7668
))}
7769
</SettGroup>
7870
)}
@@ -84,21 +76,33 @@ export default function Devices({ navigation }: NavProp) {
8476
)
8577
}
8678

87-
function Device({ navigation, device, arrow }: { navigation: StackNav; device: Device; arrow?: boolean }) {
79+
function Device({ navigation, device, isSelf }: { navigation: StackNav; device: Device; isSelf: boolean }) {
8880
const Icon = useMemo(() => getDeviceIcon(device?.os, device?.name), [device?.os, device?.name])
8981
const { id, time, os, name } = device || {}
90-
// const relativeTime = useMemo(() => getRelativeTime(time), [time])
82+
83+
const relativeTime = useMemo(() => getRelativeTime(time), [time])
9184
return (
9285
<SettOption
93-
onPress={() => arrow && navigation.navigate('Device', { device })}
86+
onPress={() =>
87+
navigation.navigate('Device', {
88+
device: {
89+
id: id || 'Unknown',
90+
time: time || 0,
91+
os,
92+
name,
93+
isSelf,
94+
},
95+
})
96+
}
9497
title={name || 'Unknown'}
9598
numberOfLines={1}
9699
key={id}
97100
Icon={Icon}
98-
arrow={arrow}
101+
arrow
99102
>
100103
<Medium className='text-zinc-600 dark:text-zinc-400' style={F.F10_5} numberOfLines={1}>
101-
{os || 'Unknown'}{getDate(time)}
104+
{/* {os || 'Unknown'} • {getDate(time)} */}
105+
{os || 'Unknown'}{relativeTime}
102106
</Medium>
103107
</SettOption>
104108
)

src/screens/Settings/Devices/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export type Device = {
55
time: number
66
name: string | NU
77
os: string | NU
8+
isSelf?: boolean
89
} | null

src/screens/Settings/Devices/utils.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ export function getDeviceIcon(os: string | NU, name: string | NU) {
2626
else if (name?.includes('Opera')) return <RoundedIcon Icon={OperaIcon} className='bg-rose-600' />
2727
else if (name?.includes('Firefox')) return <RoundedIcon Icon={FirefoxIcon} className='bg-orange-500' />
2828
else if (name?.includes('Safari')) return <RoundedIcon Icon={SafariIcon} className='bg-blue-500' />
29-
else if (os?.startsWith('Windows')) return <RoundedIcon Icon={WindowsOldSolidIcon} className='bg-blue-500' />
30-
else if (os?.startsWith('Linux')) return <RoundedIcon Icon={LinuxIcon} className='bg-black' />
29+
else if (os?.includes('Windows')) return <RoundedIcon Icon={WindowsOldSolidIcon} className='bg-blue-500' />
30+
else if (os?.includes('Linux')) return <RoundedIcon Icon={LinuxIcon} className='bg-black' />
3131
else return <RoundedIcon Icon={DeviceAccessSolidIcon} className='bg-rose-500' />
3232
}
3333

src/screens/Settings/Settings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ function AdminSettings({ navigation }: NavProp) {
273273

274274
return (
275275
<Gap12>
276-
<SettGroup title='Admin Settings'>
276+
<SettGroup title='Admin Settings' className='pb-3.5'>
277277
<SettOption
278278
title='All users'
279279
Icon={<RoundedIcon Icon={UserSolidIcon} className='bg-green-500' />}

src/utils/timeFormat.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const f = new Intl.RelativeTimeFormat('en-us', { numeric: 'auto', style: 'long' })
1+
// const f = new Intl.RelativeTimeFormat('en-us', { numeric: 'auto', style: 'long' })
22

33
const MIN = 60
44
const HOUR = MIN * 60
@@ -15,14 +15,31 @@ const units: { unit: Intl.RelativeTimeFormatUnit; value: number }[] = [
1515
{ unit: 'second', value: 1 },
1616
]
1717

18+
// export function getRelativeTime(date1: number | undefined, date2: number = new Date().getTime()) {
19+
// if (!date1) return 'Unknown Time'
20+
// const diffInSeconds = (date1 - date2) / 1000
21+
// for (const { unit, value } of units) {
22+
// const relativeValue = diffInSeconds / value
23+
// if (Math.abs(relativeValue) >= 1) {
24+
// return f.format(Math.round(relativeValue), unit)
25+
// }
26+
// }
27+
// return f.format(0, 'second')
28+
// }
29+
1830
export function getRelativeTime(date1: number | undefined, date2: number = new Date().getTime()) {
1931
if (!date1) return 'Unknown Time'
2032
const diffInSeconds = (date1 - date2) / 1000
2133
for (const { unit, value } of units) {
2234
const relativeValue = diffInSeconds / value
2335
if (Math.abs(relativeValue) >= 1) {
24-
return f.format(Math.round(relativeValue), unit)
36+
const roundedValue = Math.round(relativeValue)
37+
if (relativeValue > 0) {
38+
return `in ${roundedValue} ${unit}${roundedValue > 1 ? 's' : ''}`
39+
} else {
40+
return `${Math.abs(roundedValue)} ${unit}${Math.abs(roundedValue) > 1 ? 's' : ''} ago`
41+
}
2542
}
2643
}
27-
return f.format(0, 'second')
44+
return 'just now'
2845
}

0 commit comments

Comments
 (0)