Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions com.stakwork.sphinx.desktop/Helpers/ChatHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ class ChatHelper {
return viewsHeight
}

public static func getTextHeightFor(
@MainActor public static func getTextHeightFor(
text: String,
width: CGFloat,
font: NSFont? = nil,
Expand All @@ -761,7 +761,19 @@ class ChatHelper {
let attributedString: NSAttributedString

if useMarkdown {
attributedString = ChatHelper.markdownRenderer.render(text)
let rendered = NSMutableAttributedString(
attributedString: ChatHelper.markdownRenderer.render(text)
)
// Strip .link so boundingRect applies the same slash-boundary word-breaking
// used by the displayed string. Intentionally uses bulk removeAttribute
// rather than MessageTextField.stripLinkAttributes — measurement only needs
// removal; .sphinxURL substitution is not needed here and coupling ChatHelper
// to MessageTextField for a 1-line operation adds unnecessary overhead.
// If stripLinkAttributes is ever changed (e.g. conditional skip logic or a
// different replacement attribute), audit this site to keep the two paths
// in sync.
rendered.removeAttribute(.link, range: NSRange(location: 0, length: rendered.length))
attributedString = rendered
} else {
let attrs = [NSAttributedString.Key.font: font ?? Constants.kMessageFont]
let mutable = NSMutableAttributedString(string: text, attributes: attrs)
Expand Down Expand Up @@ -827,6 +839,10 @@ class ChatHelper {
}
}

// Strip .link before boundingRect — the display path removes .link from URL
// runs, and leaving it here causes the same undercount as the useMarkdown: true
// path. See comment in the useMarkdown: true branch above for rationale.
mutable.removeAttribute(.link, range: NSRange(location: 0, length: mutable.length))
attributedString = mutable
}

Expand Down
31 changes: 31 additions & 0 deletions com.stakwork.sphinx.desktopTests/ChatHelperHeightTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// ChatHelperHeightTests.swift
// com.stakwork.sphinx.desktopTests
//

import XCTest
@testable import sphinx

final class ChatHelperHeightTests: XCTestCase {

@MainActor
func testGetTextHeightForMatchesBoundingRectAfterLinkStrip() {
let text = "Check this out https://hive.sphinx.chat/w/graphmindset/plan/cmt1iwce9000hjt04m755nqc5"
let width: CGFloat = 500

// Manually reproduce what the fixed getTextHeightFor does internally
let rendered = NSMutableAttributedString(
attributedString: ChatHelper.markdownRenderer.render(text)
)
rendered.removeAttribute(.link, range: NSRange(location: 0, length: rendered.length))
let expected = rendered.boundingRect(
with: CGSize(width: width, height: .greatestFiniteMagnitude),
options: [.usesLineFragmentOrigin, .usesFontLeading]
).height

let actual = ChatHelper.getTextHeightFor(text: text, width: width, useMarkdown: true)

XCTAssertEqual(actual, expected, accuracy: 1.0,
"getTextHeightFor must match boundingRect on a .link-stripped string")
}
}
2 changes: 2 additions & 0 deletions com.stakwork.sphinx.desktopTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>ATSApplicationFontsPath</key>
<string>Fonts</string>
</dict>
</plist>
6 changes: 6 additions & 0 deletions sphinx.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,8 @@
PTFT00100000000001PTFT001 /* PaddedTextFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = PTFT00000000000001PTFT000 /* PaddedTextFieldTests.swift */; };
SOMCT0020000000001SOMCT02 /* SphinxOnionManagerConnectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = SOMCT0010000000001SOMCT01 /* SphinxOnionManagerConnectionTests.swift */; };
SOMSG0020000000001SOMSG02 /* SphinxOnionManagerSeedGenerationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = SOMSG0010000000001SOMSG01 /* SphinxOnionManagerSeedGenerationTests.swift */; };
CHHT0020000000001CHHT002 /* ChatHelperHeightTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CHHT0010000000001CHHT001 /* ChatHelperHeightTests.swift */; };
CHHT0030000000001CHHT003 /* Roboto-Light.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4703F05B2481C61B00282186 /* Roboto-Light.ttf */; };
TRTTS0020000000001TRTTS02 /* TribeTimestampTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = TRTTS0010000000001TRTTS01 /* TribeTimestampTests.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -1845,6 +1847,7 @@
PTFT00000000000001PTFT000 /* PaddedTextFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaddedTextFieldTests.swift; sourceTree = "<group>"; };
SOMCT0010000000001SOMCT01 /* SphinxOnionManagerConnectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SphinxOnionManagerConnectionTests.swift; sourceTree = "<group>"; };
SOMSG0010000000001SOMSG01 /* SphinxOnionManagerSeedGenerationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SphinxOnionManagerSeedGenerationTests.swift; sourceTree = "<group>"; };
CHHT0010000000001CHHT001 /* ChatHelperHeightTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatHelperHeightTests.swift; sourceTree = "<group>"; };
TRTTS0010000000001TRTTS01 /* TribeTimestampTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TribeTimestampTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -2262,6 +2265,7 @@
TRTTS0010000000001TRTTS01 /* TribeTimestampTests.swift */,
SOMSG0010000000001SOMSG01 /* SphinxOnionManagerSeedGenerationTests.swift */,
SOMCT0010000000001SOMCT01 /* SphinxOnionManagerConnectionTests.swift */,
CHHT0010000000001CHHT001 /* ChatHelperHeightTests.swift */,
4734D3AD2417E3D500D6957E /* Info.plist */,
);
path = com.stakwork.sphinx.desktopTests;
Expand Down Expand Up @@ -4489,6 +4493,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CHHT0030000000001CHHT003 /* Roboto-Light.ttf in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -5130,6 +5135,7 @@
TRTTS0020000000001TRTTS02 /* TribeTimestampTests.swift in Sources */,
SOMSG0020000000001SOMSG02 /* SphinxOnionManagerSeedGenerationTests.swift in Sources */,
SOMCT0020000000001SOMCT02 /* SphinxOnionManagerConnectionTests.swift in Sources */,
CHHT0020000000001CHHT002 /* ChatHelperHeightTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down