Skip to content

Align initial Platform implementation with spec - #132

Open
dolanske wants to merge 16 commits into
prototypefrom
36-align-the-platform-contract-with-the-spec-port-table
Open

Align initial Platform implementation with spec#132
dolanske wants to merge 16 commits into
prototypefrom
36-align-the-platform-contract-with-the-spec-port-table

Conversation

@dolanske

@dolanske dolanske commented Jul 30, 2026

Copy link
Copy Markdown
Member

This PR implements the web platform controller based on #36

It intentionally leaves out history and desktop implementation - the idea is to have it aligned with the spec as much as possible to get the ball moving, without getting too much into the weeds. At least that's how I understood it.


This PR also adds support for tray on the web. After some thought, I realized that tray does pretty much the same thing in all environments.

  • Adds a badge with a number to the icon
  • Adds a red alert circle (without a number) to the icon
  • Sets the application title

Side effect of this was that I had to upload a favicon and I also removed some random HTML jank. Hopefully this does not stray much from the task's core.


Additionally, it adds a mock platform implementation and tests against it. Improves a couple types and adds simple comments explaining what platforms are these methods available on.

@dolanske
dolanske changed the base branch from main to prototype July 30, 2026 09:30
@dolanske
dolanske marked this pull request as ready for review August 3, 2026 07:48
@dolanske dolanske changed the title Implement initial version of web platform Align initial Platform implementation with spec Aug 3, 2026
@dolanske
dolanske requested a review from zealsprince August 4, 2026 09:51
@dolanske dolanske self-assigned this Aug 4, 2026
@dolanske
dolanske requested a review from Jokler August 4, 2026 09:52

@zealsprince zealsprince left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tray reframing is the best part of this PR. Awesome! Once you say it out loud, badge count plus alert dot plus title really is the same contract on every target, and the spec's own capability table at 06-platform.md line 56 already describes exactly this for web (document.title badge count, favicon overlay). It's the interface snippet a few lines up that says tray: TrayPort | null.

So your change is more consistent with the spec than the spec is with itself, and I'll get orbit-spec updated to match unless you'd rather fold it in. The @targets doc comments are also exactly what #36 wanted.

Three things I'd want fixed before this merges:

  • I want to confirm the badge actually draws red :)
  • The mock's notify constructs a real Notification, which throws ReferenceError in a DOM-less env. That's the one thing #36 explicitly asked the mock not to do.
  • OrbitApp.vue has "Did you know that" as the loading copy.

Two open questions:

  • historyCache was listed as out of scope on #36, with #10 owning it. This PR lands the full HistoryCachePort interface, the mock stubs, and a createIndexedDbCachePort TODO. I'm not against claiming the shape early, but it means #10 inherits a contract it didn't write, and the mock returning empty arrays from seed means anything wired to it shows no history with no error. Would you rather strip it back out and let #10 define it or keep it? Also createIndexedDbCachePort builds a whole mock platform just to pull one port off it, which a createMockHistoryCache export from mock.ts would tidy up.

  • createDesktopPlatform returning the mock is the one I keep coming back to. #36 was about making null mean something, and this makes desktop claim every capability while doing nothing. Silent noops on a target nobody's testing yet feels like the failure mode we were trying to design out.

Comment thread apps/web/index.html Outdated
Comment thread packages/app/src/OrbitApp.vue Outdated
fileTransfer: null,
dns: null,
}
return createMockPlatform("desktop")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want desktop returning the mock? #36's whole framing was making null mean "this target can't do this", and now desktop reports every port as present when it actually does nothing. A tray badge that never shows up with no error is a lot harder to chase than a null check I think. Could createDesktopPlatform keep returning null per port (or throw) until the Tauri side lands, so the gap stays visible?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change would have to make all platforms fields nullable though. Which would affect the web platform implementation, since we'd have to check for fields, which in the future we'll 100% have available on all platforms.

It feels like the correct response is to completely nuke the desktop folder, because platform is wired right into orbit initialization function (see createOrbitApp)

Obviously "let's ignore the leaking toilet until we have to use it" approach does not feel right, but I don't really know what's the simplest way to fix that. Any ideas?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to touch nullability for this. Desktop runs in a webview, so we could spread createWebPlatform() and just override target: "desktop". Title, mediaDevices and the anchor download all should genuinely work in a Tauri window, the notification port already degrades to false when Notification isn't around, and deepLinks / dns stay null since those are the two that need Rust. That keeps the "null means can't do this" reading from #36 without the web adapter having to guard fields it'll always have. The spec's own line for new targets is "reuse an existing adapter and override only what differs", which is pretty much this. The one port that would misbehave is the favicon overlay, since there's no tab to draw on, so I'd leave a TODO on it as the first thing the Tauri ticket overrides. I'd rather not nuke apps/desktop either. It's the shell the Tauri work lands in, and desktop implementations are already their own ticket per #36

Comment thread packages/platform/src/mock.ts Outdated
Comment thread packages/platform/src/types.ts Outdated
Comment thread packages/platform/src/web.ts Outdated
Comment thread packages/platform/src/web.ts Outdated
Comment thread packages/platform/test/mock.test.ts Outdated
it("Should contain nullable fields on desktop", () => {
const mocked = createMockPlatform("desktop")
expect(mocked.deepLinks).toBeDefined()
expect(mocked.deepLinks.onOpen).toBeDefined()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth knowing the reason line 40 doesn't error on a DeepLinkPort | null is that tsconfig.app.json only includes src/**/*.ts, so vue-tsc -b never sees the test files at all.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anything I can do to improve the situation here? I might be having trouble understanding this. I get that TS might not be evaluating test files right now, but after adding .test.ts into the settings, nothing changed in my IDE

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that it's including src/**/*.ts but never packages/**/*.ts. Also, I don't think your rule works because it's just checking for .test.ts files. If anything, it would have to be **/*.test.ts to match all test files.

Comment thread packages/platform/test/web.test.ts
@Jokler
Jokler removed their request for review August 28, 2026 23:54
@dolanske
dolanske requested a review from zealsprince September 2, 2026 16:26

@zealsprince zealsprince left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! I'm preemptively approving to not block. I think we should double check the test thing though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants