Add Downloads Monitor with opt-in auto scanning - #29
Open
andrei-chernikov wants to merge 6 commits into
Open
andrei-chernikov wants to merge 6 commits into
andrei-chernikov wants to merge 6 commits into
Conversation
Scanning a large file blocked the main actor while it was hashed, could not be stopped once started, and .app bundles could not be picked at all because the file importers were limited to UTType.data. - FileHasher reads the file in 4 MB chunks off the main actor and honours Task cancellation, so the UI stays responsive on large files instead of loading the whole file into memory with Data(contentsOf:). - FilePreparation zips .app bundles into a temporary archive before upload and cleans the archive up afterwards. - FileAnalysisCancellationToken carries an Alamofire request through upload and polling, so "cancel" actually stops the in-flight request instead of leaving it running in the background. - ScanPolicy holds the upload limits, endpoint choice, and polling budget that were previously duplicated across the view models. - Error.isCancellation distinguishes a user cancellation from a failure, and Error.displayMessageWithCode surfaces the domain and code so a failed scan can actually be diagnosed. - The file importers accept UTType.item, so .app bundles can be selected. Adds a VirusTotalTests unit test target covering the hasher, the file preparation, the scan policy, and batch cancellation. Czech and Simplified Chinese strings are machine translations and are marked as such in the catalog.
Contributor
Author
|
This branch does not contain #25 or #26 — it was rebuilt on top of #28 alone, with the language-picker helper replaced by plain It does touch some of the same files, so whichever merges second needs a small conflict fix — both sides add adjacent lines, so keep both:
Only hard requirement is #28 first. Ping me when something conflicts and I'll rebase same day. |
A file VirusTotal had never seen could be uploaded and then never reported
on. After the upload the app slept for exactly 20 seconds and asked for
/files/{sha256} once. The report does not exist until the queued analysis
finishes, so that single request answered 404, the status fell back to
"upload", and nothing scheduled another attempt. The scan sat silent while
VirusTotal was still working, and only the website showed any progress.
- uploadFile now keeps the analysis id VirusTotal returns for the upload.
- The upload path polls /analyses/{id}, the endpoint the API documents for
this, until the status is "completed", instead of guessing a delay.
- ScanPolicy.analysisPollDecision decides finished / keep waiting / timed
out, reusing the existing 28-attempt budget. An unknown or missing status
counts as still running.
- A 404 from /files/{sha256} after a successful upload now enters the retry
loop rather than ending the scan, so the report cannot be lost even if the
analysis outlives the polling budget.
Four tests cover the decision function, including the timeout boundary.
Adds a Downloads Monitor service that watches a folder the user picks and scans new files as they arrive. - Folder access goes through a security-scoped bookmark, so the choice survives a relaunch without re-prompting. The sandbox now asks for read-only access to user-selected files and to Downloads instead of read-write, since nothing is written back. - Auto Scan is off by default and cannot be turned on without an explicit confirmation, because an unknown file gets uploaded to VirusTotal and spends API quota. Scanning the files already in the folder is a separate, separately confirmed action. - Which file categories are watched is configurable; archives and applications are watched by default. - Partial downloads (.download, .crdownload, .part, ...) are skipped until the download finishes. - Background Monitoring keeps the app running from the menu bar with no Dock icon, so monitoring survives closing the window. - Notifications carry the scanned file, so clicking one selects that file in the monitor. Czech and Simplified Chinese strings are machine translations and are marked as such in the catalog. Built on the scan-core branch, which supplies the hashing, file preparation and cancellation types this monitor reuses.
The status item's first entry opens the existing main window, or restores it if it was closed, so "New Window" described an action the app does not perform. It now reads "Open VirusTotal" in every language.
Four pieces of Downloads Monitor UI were written as English literals, so the catalog entries that already carried translations for them were never looked up and the text stayed English in every language: the Scan Existing confirmation button and its message, the empty-state description, and the "Preparing" status. - The three existing keys are now used at the call sites. - Adds downloadsmonitor.status.preparing, which had no key at all. - The file-extension examples are Text(verbatim:), since punctuation around a value has nothing to translate.
Hiding the window title through AppKit patched a layout problem that belongs to the navigation structure, not to the Downloads Monitor: the sidebar and the detail column both drive navigation, so the title is squeezed into the sidebar titlebar area and clipped. Papering over it here made this branch carry an unrelated fix and hid the real issue. The title is visible again, exactly as it is on main. The underlying layout problem is reported separately.
andrei-chernikov
force-pushed
the
feat/downloads-monitor-standalone
branch
from
August 21, 2026 16:29
2264155 to
deed662
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on the scan core PR #28 — this branch is built on it. Please merge that one first.
Adds a Downloads Monitor that watches a folder the user picks and scans new files as they arrive.
15 tests. Czech and Simplified Chinese strings are machine translations and are marked as such in the catalog.