Compare commits

..

5 Commits

Author SHA1 Message Date
Shadowfacts 2e2279ba8c Bump build number and update changelog 2024-07-22 21:56:44 -07:00
Shadowfacts 60dadf599c Fix status meta indicators overlapping thread links
This isn't great, but there's nowhere else for either to go and the
difference between the large/default scales wasn't doing much before.

Closes #449
2024-07-22 21:48:43 -07:00
Shadowfacts 90537f9d12 Fix not being able to resolve remote Mastodon posts
Closes #515
2024-07-22 21:40:19 -07:00
Shadowfacts 8b0c2f80b6 Fix preserving conversation expand all not working for ancestors
Closes #516
2024-07-22 21:28:42 -07:00
Shadowfacts 42423f36db Fix Dynamic Type not applying to status content 2024-07-21 19:46:17 -07:00
13 changed files with 54 additions and 12 deletions

View File

@ -1,5 +1,23 @@
# Changelog # Changelog
## 2024.3 (129)
Bugfixes:
- Fix excessive network traffic on profile pages
- Fix attachment gallery controls visibility not being synced between pages
- Fix video attachments not restarting when play pressed while at ends
- Fix profile field text being misaligned
- Fix at sign in timeline statuses usernames sometimes clipping
- Fix add hashtag/instance to Pinned Timelines sheets dismissing immediately when opened
- Fix for display name being replaced with incorrect user in certain circumstances
- Fix profile moved overlay view appearing behind avatar/header
- Fix profile moved view accessibility with VoiceOver
- Fix mention/status push notifications not showing content warning
- Fix sensitive attachment thumbnails being shown in push notifications
- Fix Dynamic Type not applying to status content
- Fix expand all option in Conversation not transferring when opening ancestors
- Fix not being able to resolve remote Mastodon status links in Conversation screen
- Fix status indicator icons overlapping thread links when Dynamic Type is enabled
## 2024.3 (128) ## 2024.3 (128)
Bugfixes: Bugfixes:
- Fix selecting poll option playing too much haptic feedback - Fix selecting poll option playing too much haptic feedback

View File

@ -3260,7 +3260,7 @@
repositoryURL = "https://git.shadowfacts.net/shadowfacts/HTMLStreamer.git"; repositoryURL = "https://git.shadowfacts.net/shadowfacts/HTMLStreamer.git";
requirement = { requirement = {
kind = exactVersion; kind = exactVersion;
version = 0.2.5; version = 0.3.0;
}; };
}; };
D63CC700290EC0B8000E19DE /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = { D63CC700290EC0B8000E19DE /* XCRemoteSwiftPackageReference "sentry-cocoa" */ = {

View File

@ -25,8 +25,14 @@ class HTMLConverter {
private let converter: AttributedStringConverter<Callbacks> private let converter: AttributedStringConverter<Callbacks>
init(font: UIFont, monospaceFont: UIFont, color: UIColor, paragraphStyle: NSParagraphStyle) { init(font: UIFont, monospaceFont: UIFont, fontMetrics: UIFontMetrics, color: UIColor, paragraphStyle: NSParagraphStyle) {
let config = AttributedStringConverterConfiguration(font: font, monospaceFont: monospaceFont, color: color, paragraphStyle: paragraphStyle) let config = AttributedStringConverterConfiguration(
font: font,
monospaceFont: monospaceFont,
fontMetrics: fontMetrics,
color: color,
paragraphStyle: paragraphStyle
)
self.converter = AttributedStringConverter(configuration: config) self.converter = AttributedStringConverter(configuration: config)
} }

View File

@ -364,7 +364,9 @@ extension ConversationCollectionViewController: UICollectionViewDelegate {
conv.showStatusesAutomatically = showStatusesAutomatically conv.showStatusesAutomatically = showStatusesAutomatically
show(conv) show(conv)
} else { } else {
selected(status: id, state: state.copy()) let conv = ConversationViewController(for: id, state: state.copy(), mastodonController: mastodonController)
conv.showStatusesAutomatically = showStatusesAutomatically
show(conv)
} }
case .expandThread(childThreads: let childThreads, inline: _): case .expandThread(childThreads: let childThreads, inline: _):
let indexPathBeforeExpandThread = IndexPath(row: indexPath.row - 1, section: indexPath.section) let indexPathBeforeExpandThread = IndexPath(row: indexPath.row - 1, section: indexPath.section)

View File

@ -221,10 +221,16 @@ class ConversationViewController: UIViewController {
completionHandler(nil) completionHandler(nil)
} }
} }
if isLikelyMastodonRemoteStatus(url: url), if isLikelyMastodonRemoteStatus(url: url) {
let (_, response) = try? await URLSession.appDefault.data(from: url, delegate: RedirectBlocker()), var request = URLRequest(url: url)
let location = (response as? HTTPURLResponse)?.value(forHTTPHeaderField: "location") { // Mastodon uses an intermediate redirect page for browsers which requires user input that we don't want.
effectiveURL = location request.addValue("application/activity+json", forHTTPHeaderField: "accept")
if let (_, response) = try? await URLSession.appDefault.data(for: request, delegate: RedirectBlocker()),
let location = (response as? HTTPURLResponse)?.value(forHTTPHeaderField: "location") {
effectiveURL = location
} else {
effectiveURL = WebURL(url)!.serialized(excludingFragment: true)
}
} else { } else {
effectiveURL = WebURL(url)!.serialized(excludingFragment: true) effectiveURL = WebURL(url)!.serialized(excludingFragment: true)
} }
@ -232,9 +238,14 @@ class ConversationViewController: UIViewController {
let request = Client.search(query: effectiveURL, types: [.statuses], resolve: true) let request = Client.search(query: effectiveURL, types: [.statuses], resolve: true)
do { do {
let (results, _) = try await mastodonController.run(request) let (results, _) = try await mastodonController.run(request)
guard let status = results.statuses.compactMap(\.value).first(where: { $0.url?.serialized() == effectiveURL }) else { let statuses = results.statuses.compactMap(\.value)
// Don't try to exactly match effective URL because the URL form Mastodon
// uses for the ActivityPub redirect doesn't match what's returned by the API.
// Instead we just assume that, if only one status was returned, it worked.
guard statuses.count == 1 else {
throw UnableToResolveError() throw UnableToResolveError()
} }
let status = statuses[0]
_ = mastodonController.persistentContainer.addOrUpdateOnViewContext(status: status) _ = mastodonController.persistentContainer.addOrUpdateOnViewContext(status: status)
mode = .localID(status.id) mode = .localID(status.id)
return status.id return status.id

View File

@ -12,6 +12,7 @@ import SwiftUI
private var converter = HTMLConverter( private var converter = HTMLConverter(
font: .preferredFont(forTextStyle: .body), font: .preferredFont(forTextStyle: .body),
monospaceFont: UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)), monospaceFont: UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)),
fontMetrics: .default,
color: .label, color: .label,
paragraphStyle: .default paragraphStyle: .default
) )

View File

@ -13,6 +13,7 @@ class ConfirmReblogStatusPreviewView: UIView {
private static let htmlConverter = HTMLConverter( private static let htmlConverter = HTMLConverter(
font: .preferredFont(forTextStyle: .caption2), font: .preferredFont(forTextStyle: .caption2),
monospaceFont: UIFontMetrics(forTextStyle: .caption2).scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)), monospaceFont: UIFontMetrics(forTextStyle: .caption2).scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)),
fontMetrics: UIFontMetrics(forTextStyle: .caption2),
color: .label, color: .label,
paragraphStyle: .default paragraphStyle: .default
) )

View File

@ -25,6 +25,7 @@ class ContentTextView: LinkTextView, BaseEmojiLabel {
private static let defaultBodyHTMLConverter = HTMLConverter( private static let defaultBodyHTMLConverter = HTMLConverter(
font: .preferredFont(forTextStyle: .body), font: .preferredFont(forTextStyle: .body),
monospaceFont: UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)), monospaceFont: UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)),
fontMetrics: .default,
color: .label, color: .label,
paragraphStyle: .default paragraphStyle: .default
) )

View File

@ -21,6 +21,7 @@ class ProfileFieldValueView: UIView {
private static let converter = HTMLConverter( private static let converter = HTMLConverter(
font: .preferredFont(forTextStyle: .body), font: .preferredFont(forTextStyle: .body),
monospaceFont: UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)), monospaceFont: UIFontMetrics.default.scaledFont(for: .monospacedSystemFont(ofSize: 17, weight: .regular)),
fontMetrics: .default,
color: .label, color: .label,
paragraphStyle: .default paragraphStyle: .default
) )

View File

@ -20,6 +20,7 @@ class ConversationMainStatusCollectionViewCell: UICollectionViewListCell, Status
private static let htmlConverter = HTMLConverter( private static let htmlConverter = HTMLConverter(
font: ConversationMainStatusCollectionViewCell.contentFont, font: ConversationMainStatusCollectionViewCell.contentFont,
monospaceFont: ConversationMainStatusCollectionViewCell.monospaceFont, monospaceFont: ConversationMainStatusCollectionViewCell.monospaceFont,
fontMetrics: .default,
color: .label, color: .label,
paragraphStyle: ConversationMainStatusCollectionViewCell.contentParagraphStyle paragraphStyle: ConversationMainStatusCollectionViewCell.contentParagraphStyle
) )

View File

@ -70,8 +70,7 @@ class StatusMetaIndicatorsView: UIView {
private func configureImageView(_ imageView: UIImageView) { private func configureImageView(_ imageView: UIImageView) {
let weight: UIImage.SymbolWeight = UIAccessibility.isBoldTextEnabled ? .regular : traitCollection.preferredContentSizeCategory > .large ? .light : .thin let weight: UIImage.SymbolWeight = UIAccessibility.isBoldTextEnabled ? .regular : traitCollection.preferredContentSizeCategory > .large ? .light : .thin
let scale: UIImage.SymbolScale = traitCollection.preferredContentSizeCategory > .extraLarge ? .large : .default imageView.preferredSymbolConfiguration = .init(pointSize: 0, weight: weight, scale: .default)
imageView.preferredSymbolConfiguration = .init(pointSize: 0, weight: weight, scale: scale)
} }
func updateUI(status: StatusMO) { func updateUI(status: StatusMO) {

View File

@ -23,6 +23,7 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
static let htmlConverter = HTMLConverter( static let htmlConverter = HTMLConverter(
font: TimelineStatusCollectionViewCell.contentFont, font: TimelineStatusCollectionViewCell.contentFont,
monospaceFont: TimelineStatusCollectionViewCell.monospaceFont, monospaceFont: TimelineStatusCollectionViewCell.monospaceFont,
fontMetrics: .default,
color: .label, color: .label,
paragraphStyle: TimelineStatusCollectionViewCell.contentParagraphStyle paragraphStyle: TimelineStatusCollectionViewCell.contentParagraphStyle
) )

View File

@ -10,7 +10,7 @@
// https://help.apple.com/xcode/#/dev745c5c974 // https://help.apple.com/xcode/#/dev745c5c974
MARKETING_VERSION = 2024.3 MARKETING_VERSION = 2024.3
CURRENT_PROJECT_VERSION = 128 CURRENT_PROJECT_VERSION = 129
CURRENT_PROJECT_VERSION = $(inherited)$(CURRENT_PROJECT_VERSION_BUILD_SUFFIX_$(CONFIGURATION)) CURRENT_PROJECT_VERSION = $(inherited)$(CURRENT_PROJECT_VERSION_BUILD_SUFFIX_$(CONFIGURATION))
CURRENT_PROJECT_VERSION_BUILD_SUFFIX_Debug=-dev CURRENT_PROJECT_VERSION_BUILD_SUFFIX_Debug=-dev