fivecar / react-native-background-downloader-queue

A wifi-aware background downloader that maintains a queue of files
MIT License
8 stars 0 forks source link

useDownloader hook #24

Closed gorbypark closed 1 week ago

gorbypark commented 1 year ago

Feature Request

Just thought I'd throw it out there that it would be cool to have a hook that could be consumed in any component. How I imagine it would work is that you'd create a new DownloadQueue() and run .init() at the top level of the app somewhere. Then in any component, you could do something like below:

 import {useDownloader} from 'react-native-background-downloader-queue';

const MyComponent = () => {
  const downloader = useDownloader();
  const [downloadProgress, setDownloadProgress] = useState()

  useEffect(() => {
    const myDownloadId = downloader.addUrl('http://example.com/lala.mp3'); // Returns a unique id?
    setDownloadProgress(downloader.progress(myDownloadId)); // should be able to call downloader.progress() and get entire queue, or download.progress(id) to get only specific progress for the id
  }, [downloader])

  return <View><Text>{downloadProgress}% downloaded</Text></View>
}

I didn't fully think through how the API would look, but something like the above. The main feature would be able to add and get the progress of all downloads or specific downloads from any component. I'm sure we'd want to be able to pause/cancel/resume and all the other niceties, too.

fivecar commented 1 year ago

I think some hooks would be great -- certainly for the way that many people will likely want to use this library.

How should we handle the various options available at init? I wonder if it'd be easiest to provide a React.Context around this, to encapsulate all the various inits. So it'd look something like this:

import {DownloadQueueContextProvider} from 'react-native-background-downloader-queue';

export default function App() {
  return (
    <DownloadQueueContextProvider
      domain='someUserId'
      urlToPath={url => new URL(url).pathname}
      netInfoAddEventListener={NetInfo.addEventListener}
      activeNetworkTypes={["wifi", "ethernet"]}
    >
      <MyComponent />
    </DownloadQueueContextProvider>
  );
}

function MyComponent() {
  const myFavUrl = 'https://boo.com/8675309.mp3';
  const downloader = useDownloader();  // This gets the DownloadQueue instance from the provider
  const [percent, bytesWritten, total] = useDownloadProgress(myFavUrl);
  const finished = useDownloadDone(myFavUrl);

  // finished === true iff percent === 1.0 && bytesWritten === total

  async function onPressPause() {
    // You can call all DownloadQueue functions, as usual.
    const statuses = await downloader.getQueueStatus();

    downloader.pauseAll();
  }
}

The idea would be to get all setup done via DownloadQueueContextProvider, which gives you a chance to set domain and a few other init() options. Notably, I'm proposing (for your feedback) that you can't pass handlers directly via the context provider, but that there are instead hooks for all those handlers that each take a url.

Thoughts on this approach?

fivecar commented 1 week ago

Closing due to lack of activity/interest.