-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ (core) [DSDK-504]: Listen to known devices (WebHID for now) & displ…
…ay them in sample app (#392)
- Loading branch information
Showing
28 changed files
with
1,171 additions
and
262 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@ledgerhq/device-management-kit": patch | ||
"@ledgerhq/device-sdk-sample": patch | ||
--- | ||
|
||
New use case listenToKnownDevices |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, { useCallback, useState } from "react"; | ||
import { DiscoveredDevice } from "@ledgerhq/device-management-kit"; | ||
import { Flex, Icons, Text } from "@ledgerhq/react-ui"; | ||
import styled from "styled-components"; | ||
|
||
import { AvailableDevice } from "@/components/Device"; | ||
import { useAvailableDevices } from "@/hooks/useAvailableDevices"; | ||
import { useSdk } from "@/providers/DeviceSdkProvider"; | ||
import { useDeviceSessionsContext } from "@/providers/DeviceSessionsProvider"; | ||
|
||
const Title = styled(Text)<{ disabled: boolean }>` | ||
:hover { | ||
user-select: none; | ||
text-decoration: ${(p) => (p.disabled ? "none" : "underline")}; | ||
cursor: ${(p) => (p.disabled ? "default" : "pointer")}; | ||
} | ||
`; | ||
|
||
export const AvailableDevices: React.FC<Record<never, unknown>> = () => { | ||
const discoveredDevices = useAvailableDevices(); | ||
const noDevice = discoveredDevices.length === 0; | ||
|
||
const [unfolded, setUnfolded] = useState(false); | ||
|
||
const toggleUnfolded = useCallback(() => { | ||
setUnfolded((prev) => !prev); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<Flex | ||
flexDirection="row" | ||
onClick={noDevice ? undefined : toggleUnfolded} | ||
alignItems="center" | ||
mt={1} | ||
> | ||
<Title variant="tiny" disabled={noDevice}> | ||
Available devices ({discoveredDevices.length}) | ||
</Title> | ||
<Flex style={{ visibility: noDevice ? "hidden" : "visible" }}> | ||
{unfolded ? ( | ||
<Icons.ChevronUp size={"XS"} /> | ||
) : ( | ||
<Icons.ChevronDown size={"XS"} /> | ||
)} | ||
</Flex> | ||
</Flex> | ||
<Flex | ||
flexDirection="column" | ||
rowGap={4} | ||
alignSelf="stretch" | ||
mt={unfolded ? 5 : 0} | ||
mb={4} | ||
> | ||
{unfolded | ||
? discoveredDevices.map((device) => ( | ||
<KnownDevice key={device.id} {...device} /> | ||
)) | ||
: null} | ||
</Flex> | ||
</> | ||
); | ||
}; | ||
|
||
const KnownDevice: React.FC<DiscoveredDevice & { connected: boolean }> = ( | ||
device, | ||
) => { | ||
const { deviceModel, connected } = device; | ||
const sdk = useSdk(); | ||
const { dispatch } = useDeviceSessionsContext(); | ||
const connectToDevice = useCallback(() => { | ||
sdk.connect({ device }).then((sessionId) => { | ||
dispatch({ | ||
type: "add_session", | ||
payload: { | ||
sessionId, | ||
connectedDevice: sdk.getConnectedDevice({ sessionId }), | ||
}, | ||
}); | ||
}); | ||
}, [sdk, device, dispatch]); | ||
|
||
return ( | ||
<Flex flexDirection="row" alignItems="center"> | ||
<AvailableDevice | ||
name={deviceModel.name} | ||
model={deviceModel.model} | ||
type={"USB"} | ||
connected={connected} | ||
onConnect={connectToDevice} | ||
/> | ||
</Flex> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,6 @@ export const MainView: React.FC = () => { | |
} | ||
}; | ||
}, [connectionError]); | ||
|
||
return ( | ||
<Root> | ||
<NanoLogo | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { useEffect, useMemo, useRef, useState } from "react"; | ||
import { DiscoveredDevice } from "@ledgerhq/device-management-kit"; | ||
import { Subscription } from "rxjs"; | ||
|
||
import { useSdk } from "@/providers/DeviceSdkProvider"; | ||
import { useDeviceSessionsContext } from "@/providers/DeviceSessionsProvider"; | ||
|
||
type AvailableDevice = DiscoveredDevice & { connected: boolean }; | ||
|
||
export function useAvailableDevices(): AvailableDevice[] { | ||
const sdk = useSdk(); | ||
const [discoveredDevices, setDiscoveredDevices] = useState< | ||
DiscoveredDevice[] | ||
>([]); | ||
const { state: deviceSessionsState } = useDeviceSessionsContext(); | ||
|
||
const subscription = useRef<Subscription | null>(null); | ||
useEffect(() => { | ||
if (!subscription.current) { | ||
subscription.current = sdk.listenToKnownDevices().subscribe((devices) => { | ||
setDiscoveredDevices(devices); | ||
}); | ||
} | ||
return () => { | ||
if (subscription.current) { | ||
setDiscoveredDevices([]); | ||
subscription.current.unsubscribe(); | ||
subscription.current = null; | ||
} | ||
}; | ||
}, [sdk]); | ||
|
||
const result = useMemo( | ||
() => | ||
discoveredDevices.map((device) => ({ | ||
...device, | ||
connected: Object.values(deviceSessionsState.deviceById).some( | ||
(connectedDevice) => connectedDevice.id === device.id, | ||
), | ||
})), | ||
[discoveredDevices, deviceSessionsState], | ||
); | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { useRef } from "react"; | ||
|
||
/** | ||
* A custom hook that returns whether the value has changed since the last render. | ||
* @param value The value to compare against the previous render. | ||
* @returns A boolean indicating whether the value has changed since the last render. | ||
*/ | ||
export function useHasChanged<T>(value: T): boolean { | ||
const ref = useRef<T>(value); | ||
const hasChanged = ref.current !== value; | ||
ref.current = value; | ||
return hasChanged; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,13 @@ | ||
import { useEffect, useRef } from "react"; | ||
import { useRef } from "react"; | ||
|
||
/** | ||
* A custom hook that returns the previous value of the provided value. | ||
* @param value The value to compare against the previous render. | ||
* @returns The previous value of the provided value. | ||
*/ | ||
export function usePrevious<T>(value: T) { | ||
const ref = useRef<T>(); | ||
useEffect(() => { | ||
ref.current = value; //assign the value of ref to the argument | ||
}, [value]); //this code will run when the value of 'value' changes | ||
return ref.current; //in the end, return the current ref value. | ||
const previousValue = ref.current; | ||
ref.current = value; | ||
return previousValue; | ||
} |
Oops, something went wrong.