From f85f955a419a186b03f640a1a1cf482fbb1d3a27 Mon Sep 17 00:00:00 2001 From: Georg Bauer Date: Fri, 31 Jul 2026 11:39:50 +0200 Subject: [PATCH] Fix horizontal source scrolling --- ios/Sources/DetailScreens.swift | 60 +++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/ios/Sources/DetailScreens.swift b/ios/Sources/DetailScreens.swift index cec5fc4..5c6ec49 100644 --- a/ios/Sources/DetailScreens.swift +++ b/ios/Sources/DetailScreens.swift @@ -343,6 +343,7 @@ final class RepositoryFileViewController: UIViewController, QLPreviewControllerD private let spinner = UIActivityIndicatorView(style: .medium) private var loadingTask: Task? private var previewURL: URL? + private weak var sourceTextView: UITextView? init(context: AppContext, owner: String, repository: String, path: String) { self.context = context @@ -379,6 +380,11 @@ final class RepositoryFileViewController: UIViewController, QLPreviewControllerD } } + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + updateSourceContentSize() + } + private func isMediaFile(_ path: String) -> Bool { guard let type = UTType(filenameExtension: (path as NSString).pathExtension) else { return false @@ -403,33 +409,59 @@ final class RepositoryFileViewController: UIViewController, QLPreviewControllerD } private func showSource(_ source: String) { + let highlighter = Highlighter() + highlighter?.setTheme( + traitCollection.userInterfaceStyle == .dark ? "atom-one-dark" : "atom-one-light" + ) + highlighter?.theme.setCodeFont(.monospacedSystemFont(ofSize: 13, weight: .regular)) + let highlighted = highlighter?.highlight(source, as: sourceLanguage(path)) + ?? NSAttributedString(string: source, attributes: [ + .font: UIFont.monospacedSystemFont(ofSize: 13, weight: .regular), + .foregroundColor: UIColor.label, + ]) + let text = NSMutableAttributedString(attributedString: highlighted) + let paragraph = NSMutableParagraphStyle() + paragraph.lineBreakMode = .byClipping + text.addAttribute(.paragraphStyle, value: paragraph, range: NSRange(location: 0, length: text.length)) + let textView = UITextView(frame: view.bounds) + textView.textContainer.size = CGSize( + width: CGFloat.greatestFiniteMagnitude, + height: CGFloat.greatestFiniteMagnitude + ) + textView.textContainer.lineBreakMode = .byClipping + textView.textContainer.widthTracksTextView = false + textView.textStorage.setAttributedString(text) textView.autoresizingMask = [.flexibleWidth, .flexibleHeight] textView.isEditable = false textView.isSelectable = true textView.alwaysBounceHorizontal = true textView.isDirectionalLockEnabled = true textView.showsHorizontalScrollIndicator = true + sourceTextView = textView + view.addSubview(textView) + updateSourceContentSize() + } + + private func updateSourceContentSize() { + guard let textView = sourceTextView else { return } textView.textContainer.widthTracksTextView = false textView.textContainer.size = CGSize( width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude ) - let highlighter = Highlighter() - highlighter?.setTheme( - traitCollection.userInterfaceStyle == .dark ? "atom-one-dark" : "atom-one-light" - ) - highlighter?.theme.setCodeFont(.monospacedSystemFont(ofSize: 13, weight: .regular)) - textView.attributedText = highlighter?.highlight(source, as: sourceLanguage(path)) - ?? NSAttributedString(string: source, attributes: [ - .font: UIFont.monospacedSystemFont(ofSize: 13, weight: .regular), - .foregroundColor: UIColor.label, - ]) textView.layoutManager.ensureLayout(for: textView.textContainer) - textView.contentSize.width = textView.layoutManager.usedRect(for: textView.textContainer).width - + textView.textContainerInset.left - + textView.textContainerInset.right - view.addSubview(textView) + let textSize = textView.layoutManager.usedRect(for: textView.textContainer).size + textView.contentSize = CGSize( + width: max( + textView.bounds.width, + ceil(textSize.width + textView.textContainerInset.left + textView.textContainerInset.right) + ), + height: max( + textView.bounds.height, + ceil(textSize.height + textView.textContainerInset.top + textView.textContainerInset.bottom) + ) + ) } private func showQuickLook(_ data: Data) throws {