Skip to content

Add page details panel#18

Merged
Chefski merged 4 commits into
devfrom
codex/docmostly-details-panel
Jul 6, 2026
Merged

Add page details panel#18
Chefski merged 4 commits into
devfrom
codex/docmostly-details-panel

Conversation

@Chefski

@Chefski Chefski commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add a native Docmost-style Details panel for page readers, including creator/updater metadata, stats, backlink counts/list drill-in, labels, and label editing entry points.
  • Wire Details into the shared page reader panel system: iOS/iPadOS opens a large sheet and macOS uses the inspector/sidebar.
  • Include all currently uncommitted local changes as requested, including the unrelated login, page browser, workspace icon/title, table editor, and script updates already present in the worktree.

Verification

  • Manually tested in iPhone 17 Simulator on the Jumpseat workspace: opened Localisation Contributors, opened page actions, selected Show Details, verified metadata/stats/backlinks/labels loaded, and opened Incoming links to the loaded empty state.
  • mcp__xcodebuildmcp.test_sim on iPhone 17: 603 passed, 0 failed.
  • xcodebuild test -quiet -project docmostly.xcodeproj -scheme docmostly -destination platform=iOS Simulator,name=iPad Pro 13-inch (M5): result bundle Passed, 603 total, 0 failed.
  • xcodebuild test -quiet -project docmostly.xcodeproj -scheme DocmostlyMac -destination platform=macOS: 9 passed.
  • swiftlint lint --strict --no-cache on modified Details files: 0 violations.
  • git diff --cached --check before commit and git diff --check after commit: clean.

Notes

  • This PR intentionally includes unrelated local changes because the requested scope was all uncommitted changes, including unrelated work.

@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a native page details panel and folds in several related app updates. The main changes are:

  • Page metadata, stats, backlinks, and labels in the reader details UI.
  • Reader panel wiring for iOS sheets and the macOS inspector.
  • Backlink and favorite-ID networking updates.
  • Login, page browser, workspace icon, editor table, and script updates.

Confidence Score: 4/5

This is close, but the workspace icon cookie handling should be fixed before merging.

  • Backlink loading is now scoped by page and direction.
  • Favorite ID decoding now covers both response formats.
  • Workspace icon requests can still attach stored cookies to unrestricted absolute logo URLs.

docmostly/Features/Spaces/WorkspaceIconView.swift and docmostly/Networking/SpaceLogoURL.swift

Security Review

Workspace icon loading can still send stored cookies to unrestricted absolute logo URLs when the URL matches the app cookie rules.

Important Files Changed

Filename Overview
docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift Adds page-scoped backlink loading state and guards stale backlink responses.
docmostly/Features/Spaces/WorkspaceIconView.swift Adds a manual workspace icon fetch path that still attaches cookies to unrestricted absolute logo URLs.
docmostly/Networking/FavoriteIDListResponse.swift Adds favorite-ID decoding for both paginated and flat response shapes.

Reviews (3): Last reviewed commit: "fix: address page details review finding..." | Re-trigger Greptile

Comment thread docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift
Comment thread docmostly/Features/Spaces/WorkspaceIconView.swift
Comment thread docmostly/App/AppState+Engagement.swift Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 issues found across 48 files

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

Comment thread docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift Outdated
Comment thread docmostlyTests/Networking/PageDetailsDecodingTests.swift Outdated
Comment thread docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1ab095010

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +288 to +289
rowCount: rowCount,
columnCount: columnCount

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Remove unsupported selection-stroke arguments

This call now passes rowCount and columnCount into NativeEditorTableSelectionStroke, but that view only declares selection, rowIndex, and columnIndex, so any target that compiles NativeEditorTableGridView will fail at this initializer instead of building the app.

Useful? React with 👍 / 👎.

Comment on lines +11 to +12
if reset == false, backlinkPagesByDirection[direction]?.isEmpty == false {
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Allow backlink pagination after the first page

When the first backlink request returns items and hasNextPage == true, tapping “Load more” calls loadBacklinks(reset: false), but this guard immediately returns because the direction already has a non-empty page array. That means the saved cursor is never used and users can never fetch page 2+ for backlink lists that already displayed results.

Useful? React with 👍 / 👎.


static func stats(in document: NativeEditorDocument) -> Self {
let text = document.blocks
.map { String($0.text.characters).trimmingCharacters(in: .whitespacesAndNewlines) }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Count table cell text in page stats

For pages that contain tables, this stats builder only reads block.text, but table blocks store their actual content in NativeEditorTableCell.plainText while block.text is just the preview string such as the row/column count. The Details panel will therefore undercount or count the table dimensions instead of the user's words, making the displayed word and character counts wrong for table-heavy pages.

Useful? React with 👍 / 👎.

.foregroundStyle(.primary)
.font(cell.map(NativeEditorTableLayout.font) ?? .callout)
.foregroundStyle(cell?.isHeader == true ? .primary : NativeEditorTableLayout.bodyForeground)
.lineLimit(6)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't truncate read-only table cells

When viewing a page that has a table cell with more than six lines, this new limit silently hides the rest of the cell's content in the reader/preview state, and read-only users have no way to reveal it. Tables previously rendered the full displayText, so long documentation content can now disappear from normal page reading.

Useful? React with 👍 / 👎.

.padding()
.frame(maxWidth: .infinity, alignment: .leading)
}
.task(id: direction) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reload backlink lists when the page changes

If the user changes pages while an incoming/outgoing backlink list is still presented, such as from the split-view sidebar, the engagement snapshot for the new page clears the backlink arrays but this task is keyed only by direction, so it does not fetch links for the new pageID. The list can stay empty or stale until it is dismissed and reopened; include the page id in the task identity.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 6 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread docmostly/Features/Editor/NativeEditorTableGridView.swift
Comment on lines +70 to +72
let cookies = await appState.activeSessionCookies(for: url)
if cookies.isEmpty == false {
request.setValue(cookieHeader(from: cookies), forHTTPHeaderField: "Cookie")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 security Cookies Still Escape
SpaceLogoURL.url(...) still returns absolute http and https logo strings unchanged, and this path then builds a manual Cookie header for that returned URL. httpShouldHandleCookies = false only disables the system cookie jar; it does not stop activeSessionCookies(for:) from adding stored cookies that match the absolute URL's domain and path. If a workspace logo is set to a same-site arbitrary URL, or to a subdomain covered by a domain-scoped session cookie, the icon request can still send authenticated cookies outside the intended workspace attachment endpoint. Please only attach cookies after confirming the URL is the expected same-origin workspace-icon attachment URL, or reject absolute workspace icon URLs before fetching.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 10 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift">

<violation number="1" location="docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift:35">
P2: A failed backlinks request from the previous page can still show an error on the newly opened page. The success path now guards `backlinkPageID == pageID`, but the `catch` path should apply the same stale-request check before assigning `backlinkErrorMessage`.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

do {
let cursor = loadNextPage ? backlinkNextCursorByDirection[direction] ?? nil : nil
let response = try await appState.loadPageBacklinks(pageId: pageID, direction: direction, cursor: cursor)
guard backlinkPageID == pageID else { return }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: A failed backlinks request from the previous page can still show an error on the newly opened page. The success path now guards backlinkPageID == pageID, but the catch path should apply the same stale-request check before assigning backlinkErrorMessage.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docmostly/Features/PageReader/PageReaderViewModel+Backlinks.swift, line 35:

<comment>A failed backlinks request from the previous page can still show an error on the newly opened page. The success path now guards `backlinkPageID == pageID`, but the `catch` path should apply the same stale-request check before assigning `backlinkErrorMessage`.</comment>

<file context>
@@ -5,21 +5,36 @@ extension PageReaderViewModel {
+            let cursor = loadNextPage ? backlinkNextCursorByDirection[direction] ?? nil : nil
             let response = try await appState.loadPageBacklinks(pageId: pageID, direction: direction, cursor: cursor)
-            if reset {
+            guard backlinkPageID == pageID else { return }
+
+            if reset || loadNextPage == false {
</file context>

@Chefski Chefski merged commit 0ecc4d2 into dev Jul 6, 2026
8 checks passed
@Chefski Chefski deleted the codex/docmostly-details-panel branch July 6, 2026 22:48
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.

1 participant