fix: images resize with window, blend toolbar into content
Images sized themselves once at restyle time and never got re-measured on a pure window/pane resize (no text change, no image fingerprint change) - so they'd stay whatever width they were last styled at. The engine already had the fix for exactly this shape of problem for wide tables (a stamped .scrollableBlockFullRange attribute triggers a targeted restyle on width change), and the shared image-rendering helper already had a restyleOnWidthChange flag to opt into it - just never passed at the image call sites. Wired it on for both ![]() and ![[embed]] rendering. Also makes the titlebar/toolbar strip blend into the sidebar's background instead of reading as a separate bar, matching Mail/Notes/ Finder - titlebarAppearsTransparent + fullSizeContentView via a small NSViewRepresentable, same "reach into NSWindow directly" pattern applyMacAppearance() already uses since SwiftUI's WindowGroup has no direct API for either.
This commit is contained in:
@@ -34,6 +34,7 @@ struct OutpostApp: App {
|
||||
.onAppear { applyMacAppearance() }
|
||||
.onChange(of: appearance) { _, _ in applyMacAppearance() }
|
||||
.logoutConfirmationDialog(isPresented: $isShowingLogoutConfirmation, session: session)
|
||||
.background(TransparentTitlebarWindowAccessor())
|
||||
#endif
|
||||
}
|
||||
#if os(macOS)
|
||||
@@ -101,3 +102,27 @@ struct OutpostApp: App {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
/// Makes the titlebar/toolbar strip blend into the sidebar's own background
|
||||
/// instead of reading as a separate bar — same look as Mail/Notes/Finder.
|
||||
/// SwiftUI's `WindowGroup` exposes no direct hook for this, so this reaches
|
||||
/// into the underlying `NSWindow` the way `applyMacAppearance()` above
|
||||
/// reaches into `NSApp` for the same reason (no SwiftUI-level API exists).
|
||||
/// A `View` (not the window itself) is what actually needs to extend under
|
||||
/// the now-transparent titlebar — `.fullSizeContentView` just makes room;
|
||||
/// the sidebar's `.background` already does the rest with no other change.
|
||||
private struct TransparentTitlebarWindowAccessor: NSViewRepresentable {
|
||||
func makeNSView(context: Context) -> NSView {
|
||||
let view = NSView()
|
||||
DispatchQueue.main.async {
|
||||
guard let window = view.window else { return }
|
||||
window.titlebarAppearsTransparent = true
|
||||
window.styleMask.insert(.fullSizeContentView)
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
func updateNSView(_ nsView: NSView, context: Context) {}
|
||||
}
|
||||
#endif
|
||||
|
||||
+4
@@ -75,6 +75,7 @@ extension MarkdownStyler {
|
||||
paragraphSpacing: imageEmbedConfig.paragraphSpacing,
|
||||
alignment: .left,
|
||||
mode: .visibleSource(imageGap: imageEmbedConfig.imageGap),
|
||||
restyleOnWidthChange: true,
|
||||
ctx: ctx,
|
||||
attrs: &attrs
|
||||
)
|
||||
@@ -88,6 +89,7 @@ extension MarkdownStyler {
|
||||
paragraphSpacing: imageEmbedConfig.paragraphSpacing,
|
||||
alignment: .left,
|
||||
mode: .collapsedSource(markerTexts: ["![", "]", "(", ")"]),
|
||||
restyleOnWidthChange: true,
|
||||
ctx: ctx,
|
||||
attrs: &attrs
|
||||
)
|
||||
@@ -166,6 +168,7 @@ extension MarkdownStyler {
|
||||
paragraphSpacing: imageEmbedConfig.paragraphSpacing,
|
||||
alignment: .left,
|
||||
mode: .visibleSource(imageGap: imageEmbedConfig.imageGap),
|
||||
restyleOnWidthChange: true,
|
||||
ctx: ctx,
|
||||
attrs: &attrs
|
||||
)
|
||||
@@ -179,6 +182,7 @@ extension MarkdownStyler {
|
||||
paragraphSpacing: imageEmbedConfig.paragraphSpacing,
|
||||
alignment: .left,
|
||||
mode: .collapsedSource(markerTexts: ["![[", "]]"]),
|
||||
restyleOnWidthChange: true,
|
||||
ctx: ctx,
|
||||
attrs: &attrs
|
||||
)
|
||||
|
||||
+9
-5
@@ -269,21 +269,25 @@ extension NativeTextView {
|
||||
|
||||
recalcOverscroll(for: scrollView, targetWidth: newSize.width, debugTag: "setFrameSize")
|
||||
|
||||
// Width change → only rendered table paragraphs need restyling. Their image
|
||||
// width can change, and an initially narrow table can become scrollable.
|
||||
// Width change → only paragraphs tagged `.scrollableBlockFullRange`
|
||||
// (rendered tables and standalone images — see appendRenderedStandaloneBlock's
|
||||
// `restyleOnWidthChange`) need restyling. Their display size is measured
|
||||
// off the container width, and an initially narrow table can become
|
||||
// scrollable.
|
||||
if widthChanged {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
if self.configuration.readingWidth == nil {
|
||||
self.restyleTableParagraphsForWidthChange()
|
||||
self.restyleWidthDependentParagraphsForWidthChange()
|
||||
}
|
||||
self.updateWideTableOverlays()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Restyle only table paragraphs via stamped anchor ranges; avoids re-tokenizing the doc.
|
||||
private func restyleTableParagraphsForWidthChange() {
|
||||
/// Restyle only width-dependent paragraphs (tables, standalone images) via
|
||||
/// stamped anchor ranges; avoids re-tokenizing the doc.
|
||||
private func restyleWidthDependentParagraphsForWidthChange() {
|
||||
guard let storage = textStorage,
|
||||
let coord = delegate as? NativeTextViewCoordinator else { return }
|
||||
var ranges: [NSRange] = []
|
||||
|
||||
Reference in New Issue
Block a user