Removed unnecessary call to SwitchDesktop when setting thread to input desktop.
Renamed ClipboardTransfer to TextTransfer and reused it for sending virtual keyboard input.
There's no risk of API incompatibility here. The enum is the same number, and the data model didn't change, so outdated agents will still handle the message.
Moved the showing of "file transfer complete" modal out of the RPC call, which was blocking subsequent SignalR messages (e.g. input).
Changed the input processing thread from STA to MTA.
I could have sworn some of the APIs (clipboard or input) required STA, which is why I was explicitly using it.
I'm not sure if something changed, but it apparently needs to be MTA now in order for it to switch desktops.
Changed the virtual keyboard hidden input from textarea to input.
I was previously doing some hacky things to determine if enter or backspace was being pressed on the virtual keyboard on mobile.
While building ControlR, I discovered that it would pick up on keydown event for only these two keys. All other keys have "unidentified" as the key in the event.
But having these two keys identified in keydown allowed me to do things in a much less hacky way.
It also allows pasting from the virtual keyboard and having it transfer.
The virtual keyboard button is now a toggle. It will stay open while it's toggled on and can't be passively dismissed.
Fixed an issue with a weird "Paste" button constantly popping up in Firefox.
This was because they locked down the clipboard API in a recent update.
In Firefox and Safari, it now requires transient user activation for the call to await clipboard.readText succeed.
But instead of returning the clipboard content immediately, it pops up the Paste button. If the user clicks it, then the function returns the text. If not, it throws.
This behavior can be detected by querying the state of clipboard-read permission.
If the call throws, that means it requires transient user activation, and there will never be an option for the user to allow background access.
In this case, we warn them about it once with a modal, write to the console with more info, and put a value in localStorage that lets us know not to prompt again.
Added async/await to a bunch of SignalR calls that should have been that way to begin with.
Changes:
SwitchDesktop
when setting thread to input desktop.ClipboardTransfer
toTextTransfer
and reused it for sending virtual keyboard input.keydown
event for only these two keys. All other keys have "unidentified" as the key in the event.await clipboard.readText
succeed.clipboard-read
permission.localStorage
that lets us know not to prompt again.