mirror of
https://github.com/priyanshujain/margin.git
synced 2026-10-03 19:47:03 +00:00
81 lines
4.7 KiB
Markdown
81 lines
4.7 KiB
Markdown
# Platform
|
|
|
|
Facts that cost a day each to find and are not derivable from the repo or the crate docs.
|
|
|
|
## macOS notifications need UN and a bundle signature
|
|
|
|
Verified on 2026-09-05 with throwaway Swift probes. On macOS 26, `NSUserNotificationCenter`, which is
|
|
what `tauri-plugin-notification`, `notify-rust` and `mac-notification-sys` all post through, reports
|
|
successful delivery and shows nothing. It never registers the app in Notification Center and never
|
|
prompts. The failure is completely silent: the plugin returns `Ok` and the system log says nothing.
|
|
|
|
`UNUserNotificationCenter` prompts and shows, but only when the process is a real `NSApplication` in
|
|
a bundle that carries a bundle signature. Ad-hoc is enough, `codesign -s -` works. The linker
|
|
signature a plain `tauri build` leaves behind is not, and produces "Notifications are not allowed
|
|
for this application".
|
|
|
|
That same error text also appears when the user dismissed the permission banner, so the message
|
|
alone does not tell you which of the two happened.
|
|
|
|
A banner that reads "Margin Mail" over the single word "Notification" is not the app posting that
|
|
word. It is the system hiding the content, and on this machine the cause was the global Show
|
|
previews setting being Never, at the bottom of System Settings > Notifications, which every app on
|
|
"Default" inherits. To read that without prompting anybody, build a throwaway bundle that only calls
|
|
`getNotificationSettings` and writes `showPreviewsSetting.rawValue` to a file: 0 always, 1 when
|
|
unlocked, 2 never. Do not trust `content_visibility` in `com.apple.ncprefs`, which read 1 while the
|
|
API said never.
|
|
|
|
Margin Mail posts through `src-tauri/src/notify/macos.rs` and its `just build` sources the signing
|
|
env file.
|
|
|
|
One correction to what was previously written down here: the other three apps do not have this bug,
|
|
because they do not post notifications at all. Checked on 2026-09-06, neither
|
|
`tauri-plugin-notification` nor `@tauri-apps/plugin-notification` appears in Margin's, Margin
|
|
Calendar's or Margin Docs' manifests, and Margin Calendar's `notify` at `App.tsx:27` is a toast
|
|
helper with nothing to do with the system. The point still stands for the day one of them wants
|
|
notifications, because the plugin is what anyone would reach for and it silently does nothing.
|
|
|
|
## Reading the installed app's state
|
|
|
|
A Tauri app's `localStorage` lives under
|
|
`~/Library/WebKit/<bundle-id>/WebsiteData/Default/*/*/LocalStorage/localstorage.sqlite3`. Copy that
|
|
file and its `-wal` sibling to `/tmp` first, then read it with
|
|
`sqlite3 ... "select key, hex(value) from ItemTable"`. Values are UTF-16LE.
|
|
|
|
The dev server origin has a separate store under `~/Library/WebKit/<package-name>/`, so a dev run
|
|
does not reproduce what the installed app shows. When a screenshot of the installed app disagrees
|
|
with what the code should draw, read the real state before theorising. Reading is fine. Never edit
|
|
that file.
|
|
|
|
## Mobile
|
|
|
|
Margin has an initialised iOS target (`src-tauri/gen/apple`, not gitignored) that builds and runs in
|
|
the simulator; typst, harper and reqwest all cross-compile. Android is not set up and needs the SDK,
|
|
NDK and JDK 17.
|
|
|
|
`isDesktop` in `src/ipc.ts` really means "is Tauri", so it is true on mobile. Anything genuinely
|
|
desktop-only has to be gated on something else.
|
|
|
|
WKWebView CSS problems that do not reproduce in a desktop browser, all fixed in Margin and worth
|
|
copying into any app that goes mobile: text auto-inflation of wide blocks needs
|
|
`html { -webkit-text-size-adjust: 100% }`; zoom on input focus needs `maximum-scale=1.0,
|
|
user-scalable=no` in the viewport; the keyboard scrolling the whole page and pushing the title bar
|
|
under the notch needs `body { position: fixed; inset: 0; overflow: hidden }` with the scrolling
|
|
confined to one pane; a caret drawn below its text needs a line-height at or above the face's natural
|
|
metrics, 1.4 rather than 1.16 for Literata.
|
|
|
|
Programmatic `.focus()` on iOS does not show the caret or keyboard without a real gesture, so those
|
|
states cannot be verified with `simctl` screenshots. A human has to tap.
|
|
|
|
Mobile OAuth cannot use a loopback listener. That is why Margin Calendar and Margin Mail both
|
|
register `tauri-plugin-deep-link` and take the answer back through a custom URI scheme, on desktop
|
|
too, so both flows are one code path with one difference in it.
|
|
|
|
## Responsive layout
|
|
|
|
The compact breakpoint is `(max-width: 899px)`, read through `useCompact()` in `src/useMedia.ts`. The
|
|
root element carries `data-compact` and the pane state. Desktop collapses the sidebar to width zero
|
|
and lets the main pane reclaim it. Compact turns the side panes into fixed slide-in drawers over a
|
|
full-width main pane, one at a time, behind a scrim, with extra title bar actions folded into an
|
|
overflow menu. Safe-area insets and a `--titlebar-h` token handle the notch.
|