feat: download and share buttons + handling that#20
Conversation
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
| const client = new (window as any).WebTorrent(); | ||
|
|
||
| // Seed the file | ||
| // @ts-expect-error | ||
| client.seed(file, (torrent) => { | ||
| const magnetURI = torrent.magnetURI; | ||
| console.log("Seeding WACZ file via WebTorrent:", magnetURI); | ||
|
|
||
| // Optionally display/share this magnet link | ||
| alert(`Magnet Link Ready:\n${magnetURI}`); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Suggestion: The WebTorrent client is created but never destroyed, which can lead to memory leaks and continued seeding even after the user navigates away. Store the client instance as a class property and implement proper cleanup when the component is disconnected or when sharing is complete. [possible issue, importance: 8]
| const client = new (window as any).WebTorrent(); | |
| // Seed the file | |
| // @ts-expect-error | |
| client.seed(file, (torrent) => { | |
| const magnetURI = torrent.magnetURI; | |
| console.log("Seeding WACZ file via WebTorrent:", magnetURI); | |
| // Optionally display/share this magnet link | |
| alert(`Magnet Link Ready:\n${magnetURI}`); | |
| }); | |
| } | |
| // Create a WebTorrent client if not already available | |
| const client = new (window as any).WebTorrent(); | |
| this.torrentClient = client; | |
| // Seed the file | |
| // @ts-expect-error | |
| client.seed(file, (torrent) => { | |
| const magnetURI = torrent.magnetURI; | |
| console.log("Seeding WACZ file via WebTorrent:", magnetURI); | |
| // Optionally display/share this magnet link | |
| alert(`Magnet Link Ready:\n${magnetURI}`); | |
| }); |
| const response = await downloader.download(); | ||
| if (!(response instanceof Response)) { | ||
| console.error("Download failed:", response); | ||
| alert("Failed to download archive."); | ||
| return; | ||
| } | ||
|
|
||
| const opfsRoot = await navigator.storage.getDirectory(); | ||
| const waczFileHandle = await opfsRoot.getFileHandle(filename, { | ||
| create: true, | ||
| }); | ||
| const writable = await waczFileHandle.createWritable(); | ||
|
|
||
| const reader = response.body!.getReader(); | ||
| while (true) { | ||
| const { done, value } = await reader.read(); | ||
| if (done) break; | ||
| await writable.write(value); | ||
| } | ||
|
|
||
| await writable.close(); |
There was a problem hiding this comment.
Suggestion: The code doesn't handle errors during file writing operations. If any error occurs during reading from the response or writing to OPFS, the writable stream might remain open, causing resource leaks. Add proper error handling with try/catch and ensure the writable is closed even if an error occurs. [possible issue, importance: 7]
| const response = await downloader.download(); | |
| if (!(response instanceof Response)) { | |
| console.error("Download failed:", response); | |
| alert("Failed to download archive."); | |
| return; | |
| } | |
| const opfsRoot = await navigator.storage.getDirectory(); | |
| const waczFileHandle = await opfsRoot.getFileHandle(filename, { | |
| create: true, | |
| }); | |
| const writable = await waczFileHandle.createWritable(); | |
| const reader = response.body!.getReader(); | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| await writable.write(value); | |
| } | |
| await writable.close(); | |
| const response = await downloader.download(); | |
| if (!(response instanceof Response)) { | |
| console.error("Download failed:", response); | |
| alert("Failed to download archive."); | |
| return; | |
| } | |
| const opfsRoot = await navigator.storage.getDirectory(); | |
| const waczFileHandle = await opfsRoot.getFileHandle(filename, { | |
| create: true, | |
| }); | |
| const writable = await waczFileHandle.createWritable(); | |
| try { | |
| const reader = response.body!.getReader(); | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| await writable.write(value); | |
| } | |
| } catch (error) { | |
| console.error("Error writing file to OPFS:", error); | |
| alert("Failed to save archive."); | |
| await writable.close(); | |
| return; | |
| } | |
| await writable.close(); |
|
The magnet link is now copied to the user's clipboard automatically |
|
Looks great! Maybe later we could display the magnet link copied as a toast or disappearing tooltip? |


User description
This PR addresses #18.
It adds two new buttons to the UI:
We will need to work more on the UX aspect of this but the core functionality is there.
PR Type
Enhancement
Description
Added download functionality for WACZ archives
Implemented WebTorrent sharing capability
Added UI controls for selecting pages
Integrated with OPFS for file storage
Changes walkthrough 📝
3 files
Implement download and share functionalityAdd page selection functionalityAdd WebTorrent script and archive list ID4 files
Add WebTorrent module type definitionsAdd WebTorrent global type definitionsConfigure WebTorrent dependenciesUpdate TypeScript configuration2 files
Add WebTorrent and related dependenciesAdd WebTorrent client library