Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow selecting BMS package without drag-and-drop on mobile devices #711

Closed
dtinth opened this issue Oct 20, 2021 · 9 comments · Fixed by #714
Closed

Allow selecting BMS package without drag-and-drop on mobile devices #711

dtinth opened this issue Oct 20, 2021 · 9 comments · Fixed by #714
Assignees

Comments

@dtinth
Copy link
Member

dtinth commented Oct 20, 2021

Background

Users on mobile devices (Android) cannot drag BMS packages into Bemuse window, so we should allow users to pick a file on their machine.

Requested by

Task

  • Your PR should change these files, CustomBMS.jsx, CustomBMS.scss and CustomSongsIO.js.

  • Add an option to select a file to the Load Custom BMS modal.

    💁‍♂️ How to reach this modal: Launch Bemuse > Enter Game > Keyboard Mode. Click on Play Custom BMS at the bottom left (desktop) or in the hamburger menu at the top left (mobile)

  • Upon clicking the option, the user will be asked to pick a zip, rar or 7z file. Once a file is selected, it should act as if the file has been dropped into the drop zone.

    💁‍♂️ If you need a zip file for testing, try this one. https://www.dropbox.com/s/hwxjo1l5ibj8bef/BMS_Shuin-422.zip

  • All automated checks should pass.

  • Your solution should work on iOS and Android.

  • Please include a screenshot in your PR to confirm that it is working.

Hacktoberfest

If you would like to work on this task, please write a comment stating your intent. We will then assign the issue to you. To ensure continuity, the issue will be unassigned after 3 days of inactivity — so please keep us updated.

@aj-ya
Copy link
Contributor

aj-ya commented Oct 20, 2021

Hey! I would like to work on this issue.

@dtinth
Copy link
Member Author

dtinth commented Oct 20, 2021

@aj-ya Thank you for taking on this issue 🙏. It is yours now.

@aj-ya
Copy link
Contributor

aj-ya commented Oct 20, 2021

Hey! I seem to have hit a dead end while trying to solve this without changing the existing code.
I tried to add an input:file element inside the dropzone div that triggers the handleDrop function when a file is uploaded,
the handleDrop itself has function calls that need the event to be a dragEvent and have a dataTransfer object. I've been trying to create an event with a dataTransfer object to send the data but after some stumbling, I feel I have found some conclusive evidence that it won't work.
source

It is not possible to create a useful DataTransfer object from script, since DataTransfer objects have a processing and security model that is coordinated by the browser during drag-and-drops.
Therefore synthetic objects wont work because of safety constraints.
Screenshot (43)

@dtinth
Copy link
Member Author

dtinth commented Oct 20, 2021

@aj-ya Hello, thank you, you are right! Seems like the CustomSongsIO code has been hard-coded to only accept drop events. This has been a mistake in my assumption, my apologies for the confusion.

What I would recommend trying:

  1. Create a new function in CustomSongsIO.js based on handleCustomSongFolderDrop.

    • Maybe name it handleCustomSongFileSelect.
    • Then use it in CustomBMS.jsx.
  2. Instead of a new DndResources(event), create an instance of new CustomSongResources(…) directly, e.g.

    new CustomSongResources({
      getFiles: async () => [{ name: file.name, file }]
    })

You can also change CustomBMS.scss.

@aj-ya
Copy link
Contributor

aj-ya commented Oct 20, 2021

Thanks for the suggestions,will work on that.

@aj-ya
Copy link
Contributor

aj-ya commented Oct 21, 2021

Hey! I've been working according to your suggestion,but I cant seem to figure out why my createIO async function doesn't fulfill.
code looks like this.

export function handleCustomSongFileSelect(selectedfile) {
console.log('before')
return createIO(async ({ store, customSongLoader }) => {
console.log('async')
const resources = new CustomSongResources({
getFiles: async () => [ { name: selectedfile.name, file: selectedfile } ],
})
console.log('after')
const initialLog = ['Examining selected items...']
return loadCustomSong(resources, initialLog, { store, customSongLoader })
})
}`

the console prints out only the 'before' .
Screenshot (46).
I tried checking the impure docs, but I'm out of ideas. any suggestions?

@dtinth
Copy link
Member Author

dtinth commented Oct 21, 2021

@aj-ya Sure, happy to help! You cannot call a function directly — its body won’t run. To make it run, you will have to “connect” it to the UI using connectIO here:

connectIO({
onFileDrop: () => (event) =>
CustomSongsIO.handleCustomSongFolderDrop(event),
onPaste: () => (e) => CustomSongsIO.handleClipboardPaste(e),
loadFromURL: () => (url) => CustomSongsIO.handleCustomSongURLLoad(url),
})

Add this:

    onFileSelect: () => (event) =>
      CustomSongsIO.handleCustomSongFileSelect(event),

Then in the component code, call this.props.onFileSelect and the IO function inside should be run. Let me know if you need any further help. Thanks again!

@aj-ya
Copy link
Contributor

aj-ya commented Oct 22, 2021

Hey! I think I've successfully fixed the issue, please take a look at the PR and the code too.
Also thanks for all the suggestions.

@dtinth
Copy link
Member Author

dtinth commented Oct 22, 2021

@aj-ya Thanks, I will review and test by tonight!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

2 participants