Add a Plugins tab with import and Documents-backed storage#21
Merged
Conversation
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.
Makes plugins a first-class, user-manageable part of the app: a top-level tab, import from a file,
and on-disk storage in Documents that bundled plugins are installed into on first launch.
Follows #20, which added the GATT characteristic plugins this manages.
Storage
Every plugin — bundled or imported — now lives at
Documents/Plugins/<plugin-id>/, holding itsmanifest and module. One location means one load path and one place a user can actually look.
refreshes them.
handled, so it is not resurrected on the next launch.
and
sha256are all checked before anything lands on disk, so a bad import cannot leave abroken plugin behind.
If Documents is unavailable the manager falls back to loading read-only from the app bundle, so
parsing keeps working even when management does not.
UI
Plugins is now a top-level tab rather than a row buried in Settings (the now-redundant Settings link
is removed). The screen gains an Import button, swipe-to-delete, and inline reporting of import and
load errors.
Tests
44 pass, up from 37. The seven new ones cover the storage logic directly: first-launch install,
that installed plugins load and verify against their own hashes, idempotence on a second launch,
that a deleted bundled plugin is not resurrected, that a valid import copies and loads, that an
import with a tampered hash fails and writes nothing, and identifier-to-folder-name sanitising.
They run against temporary directories, never the real Documents folder — worth noting because
PluginDirectory.default()resolves to~/Documentson a macOS test host, so a careless test herewould write plugins into the developer's own home directory.
Reviewer notes
.fileImporterand security-scoped resource access are gatedbehind
#if !os(Android)/#if canImport(Darwin). Android compiles but has no import buttonyet; the storage layer itself is portable.
private @State, soPluginsView's state properties are internalwith a comment saying why — otherwise the build fails with "cannot be bridged to Android".
still cannot resolve. Pre-existing and unrelated — see
Documentation/DependencyState.mdonfeature/skip-dependency-updates.