Conversation
ErikSin
left a comment
There was a problem hiding this comment.
There are a few event emitters/listeners needed.
- The ui is designed to constantly be listening in the background and notify the user when a map has been shared. So there needs to be some listener function that invalidates the
useManyMapSharesfunction when a map get shared that lives at the top of the app - Similar to invites, the person receiving the map needs to also listen in the background for when the person sending the map has cancelled sending the map. This has to be listener because it can happen at any time during the process.
- As mentioned in the comments, if we want to show progress of the map being downloaded, the map sharing function needs to be an event emitter. As it is now, there is no way to show the progress in the ui as it an async function that will just return one object when resolved at the end.
cimigree
left a comment
There was a problem hiding this comment.
I agree with what Erik said. Thanks for the thorough review, Erik. I added a few things that I noticed as well.
|
Hi, @gmaclennan
|
I can update this branch to export those hooks!
Yes this is branch is based off of main, which includes the changes from #141 . You no longer need to use that hook as it's done automatically when setting up the api client provider.
Can fix this for you.
|
|
I will try and re-visit this API tomorrow now that I've got further into the implementation. We will actually need two similar APIs I think for managing the map shares from the sender side and from the receiver side. They are subtly different and I think this current API design maybe conflates the two. It could be possible to make this current API design work for both I guess - I'll look into this. |
|
@cimigree & @ErikSin : So after implementing this, I realize there is a slight confusion with this API with the distinction between sent map shares and received map shares, which I imagine you have encountered when you are implementing this? For the API we have a couple of options:
Which do you think would be preferable to work with? I am thinking (2) is better because you there would never be a use-case for reading both sent and received map shares at the same time, and it would complicate the effects (e.g. showing the share offer screen) when the value updates. |
* main: chore: update deps and actions (#148)
achou11
left a comment
There was a problem hiding this comment.
A few valid issues in CI that need to be fixed but overall the changes and their tests read well!
The PR title should be updated to categorize this as a breaking change.
| export function useMapStyleUrl({ | ||
| refreshToken, | ||
| }: { | ||
| refreshToken?: string | ||
| } = {}) { |
There was a problem hiding this comment.
probably should update the PR title to reflect the existence of a breaking change
| @@ -1,4 +1,4 @@ | |||
| export { ClientApiProvider } from './contexts/ClientApi.js' | |||
There was a problem hiding this comment.
Yeah definitely worth marking this PR as a breaking change.
|
@gmaclennan Is it to be expected that the new maps you added come in as default.smp? With no name? Just checking... |
Clean up test utils
achou11
left a comment
There was a problem hiding this comment.
Couple of non-blocking suggestions. Otherwise implementation generally looks sound! Relying on @cimigree to give some feedback as to whether it fulfills app-usage needs.
Also please update the PR title to indicate a breaking change.
| } | ||
|
|
||
| async function monitor(mapShareId: string, path: string) { | ||
| // TODO: add a timeout in case the download stalls and never completes |
There was a problem hiding this comment.
just checking - is it okay for this to be added as a follow-up?
| .json<{ downloadId: string }>() | ||
| .then(({ downloadId }) => downloadId) |
There was a problem hiding this comment.
maybe too much of an edge case, but would feel better if an explicit runtime check for downloadId was done instead of trusting the provided type here.
it'd be helpful to surface if the map server API payload was incorrect before blindly using it.
| .post('mapShares', { | ||
| json: { receiverDeviceId, mapId }, | ||
| }) | ||
| .json<ServerMapShareState>() |
There was a problem hiding this comment.
similar comment about maybe introducing a runtime validation check here. given how verbose a full check could be, maybe at least check that shareId exists since it's used explicitly in lines afterwards?
There was a problem hiding this comment.
I wonder if validations here are necessary because this is being deployed together with the map server on the same device and we have the end to end tests for this. When map server to map server communication happens, where versions could differ and types could change, there is validation.
There was a problem hiding this comment.
Yeah I guess I'm wondering if the map server dep here is updated and the payload changes, where does that misalignment get surfaced?
Again, pretty edge case since we control that dep but I think it's still technically possible that something like that could happen at runtime.
There was a problem hiding this comment.
I guess the assumption is that the type used for the payload in the server and the type used here are the same, which I guess is safe enough in the context of these things being deployed together as you mentioned.
Not adamant about introducing something, just wanted to inquire out of caution!
cimigree
left a comment
There was a problem hiding this comment.
All tested great on my devices running from the frontend. I still get this error when adding and removing maps. I don't think it has anything to do with your code. And I can dismiss it and all works fine... Just noting here:
This was with the 213 MB map file, openfreemap-z5.smp
ERROR Mapbox [error] RNMBXMapView | Map load failed: {type=source, message=Source mapboxUserLocation is not in style, begin=180950462069}
Map Sharing Hooks
Adds React hooks for sharing maps between devices. The API separates receiver and sender functionality.
Receiver Hooks
useManyReceivedMapShares()- List all received map shares. Updates when shares arrive or status changes (but not during download progress updates).useSingleReceivedMapShare({ shareId })- Get a specific received share with real-time updates including download progress.useDownloadReceivedMapShare()- Accept and start downloading a share. Resolves when download starts, not when complete.useDeclineReceivedMapShare()- Decline a pending share. Notifies the sender.useAbortReceivedMapShareDownload()- Cancel an in-progress download.Sender Hooks
useSendMapShare({ projectId })- Send a map to another device. Resolves immediately with the share object (doesn't wait for recipient response).useSingleSentMapShare({ shareId })- Track a sent share's status in real-time (pending, downloading, declined, canceled).useCancelSentMapShare()- Cancel a sent share before the recipient completes the download.Example Usage