Clean up instance type/feature detection

Add akkoma detection
This commit is contained in:
Shadowfacts 2022-11-14 21:17:08 -05:00
parent 603e989879
commit 99a1c76cb1
5 changed files with 94 additions and 49 deletions

View File

@ -11,15 +11,18 @@ import Pachyderm
struct InstanceFeatures {
private static let pleromaVersionRegex = try! NSRegularExpression(pattern: "\\(compatible; pleroma (.*)\\)", options: .caseInsensitive)
private static let akkomaVersionRegex = try! NSRegularExpression(pattern: "\\(compatible; akkoma (.*)\\)", options: .caseInsensitive)
private(set) var instanceType = InstanceType.mastodon
private(set) var version: Version?
private(set) var pleromaVersion: Version?
private(set) var hometownVersion: Version?
private var instanceType: InstanceType = .mastodon(.vanilla, nil)
private(set) var maxStatusChars = 500
var localOnlyPosts: Bool {
instanceType == .hometown || instanceType == .glitch
switch instanceType {
case .mastodon(.hometown(_), _), .mastodon(.glitch, _):
return true
default:
return false
}
}
var mastodonAttachmentRestrictions: Bool {
@ -27,15 +30,20 @@ struct InstanceFeatures {
}
var pollsAndAttachments: Bool {
instanceType == .pleroma
instanceType.isPleroma
}
var boostToOriginalAudience: Bool {
instanceType == .pleroma || instanceType.isMastodon
instanceType.isPleroma || instanceType.isMastodon
}
var profilePinnedStatuses: Bool {
instanceType != .pixelfed
switch instanceType {
case .pixelfed:
return false
default:
return true
}
}
var trends: Bool {
@ -48,45 +56,65 @@ struct InstanceFeatures {
var reblogVisibility: Bool {
(instanceType.isMastodon && hasVersion(2, 8, 0))
|| (instanceType == .pleroma && hasPleromaVersion(2, 0, 0))
|| (instanceType.isPleroma && hasPleromaVersion(2, 0, 0))
}
var probablySupportsMarkdown: Bool {
instanceType == .pleroma || instanceType == .glitch || instanceType == .hometown
switch instanceType {
case .pleroma(_), .mastodon(.glitch, _), .mastodon(.hometown(_), _):
return true
default:
return false
}
}
var needsLocalOnlyEmojiHack: Bool {
if case .mastodon(.glitch, _) = instanceType {
return true
} else {
return false
}
}
mutating func update(instance: Instance, nodeInfo: NodeInfo?) {
var version: Version?
let ver = instance.version.lowercased()
if ver.contains("glitch") {
instanceType = .glitch
instanceType = .mastodon(.glitch, Version(string: ver))
} else if nodeInfo?.software.name == "hometown" {
instanceType = .hometown
var mastoVersion: Version?
var hometownVersion: Version?
// like "1.0.6+3.5.2"
let parts = ver.split(separator: "+")
if parts.count == 2 {
version = Version(string: String(parts[1]))
mastoVersion = Version(string: String(parts[1]))
hometownVersion = Version(string: String(parts[0]))
} else {
mastoVersion = Version(string: ver)
}
instanceType = .mastodon(.hometown(hometownVersion), mastoVersion)
} else if ver.contains("pleroma") {
instanceType = .pleroma
var pleromaVersion: Version?
if let match = InstanceFeatures.pleromaVersionRegex.firstMatch(in: ver, range: NSRange(location: 0, length: ver.utf16.count)) {
pleromaVersion = Version(string: (ver as NSString).substring(with: match.range(at: 1)))
}
instanceType = .pleroma(.vanilla(pleromaVersion))
} else if ver.contains("akkoma") {
var akkomaVersion: Version?
if let match = InstanceFeatures.akkomaVersionRegex.firstMatch(in: ver, range: NSRange(location: 0, length: ver.utf16.count)) {
akkomaVersion = Version(string: (ver as NSString).substring(with: match.range(at: 1)))
}
instanceType = .pleroma(.akkoma(akkomaVersion))
} else if ver.contains("pixelfed") {
instanceType = .pixelfed
} else {
instanceType = .mastodon
instanceType = .mastodon(.vanilla, Version(string: ver))
}
self.version = version ?? Version(string: ver)
maxStatusChars = instance.maxStatusCharacters ?? 500
}
func hasVersion(_ major: Int, _ minor: Int, _ patch: Int) -> Bool {
if let version {
if case .mastodon(_, .some(let version)) = instanceType {
return version >= Version(major, minor, patch)
} else {
return false
@ -94,30 +122,47 @@ struct InstanceFeatures {
}
func hasPleromaVersion(_ major: Int, _ minor: Int, _ patch: Int) -> Bool {
if let pleromaVersion {
return pleromaVersion >= Version(major, minor, patch)
} else {
switch instanceType {
case .pleroma(.vanilla(.some(let version))), .pleroma(.akkoma(.some(let version))):
return version >= Version(major, minor, patch)
default:
return false
}
}
}
extension InstanceFeatures {
enum InstanceType: Equatable {
case mastodon // vanilla
case pleroma
case hometown
case glitch
enum InstanceType {
case mastodon(MastodonType, Version?)
case pleroma(PleromaType)
case pixelfed
var isMastodon: Bool {
switch self {
case .mastodon, .hometown, .glitch:
if case .mastodon(_, _) = self {
return true
default:
} else {
return false
}
}
var isPleroma: Bool {
if case .pleroma(_) = self {
return true
} else {
return false
}
}
}
enum MastodonType {
case vanilla
case hometown(Version?)
case glitch
}
enum PleromaType {
case vanilla(Version?)
case akkoma(Version?)
}
}

View File

@ -39,7 +39,7 @@ class PostService: ObservableObject {
let sensitive = contentWarning != nil
let request = Client.createStatus(
text: draft.textForPosting(on: mastodonController.instanceFeatures),
text: textForPosting(),
contentType: Preferences.shared.statusContentType,
inReplyTo: draft.inReplyToID,
media: uploadedAttachments,
@ -104,6 +104,19 @@ class PostService: ObservableObject {
return try await mastodonController.run(req).0
}
private func textForPosting() -> String {
var text = draft.text
// when using dictation, iOS sometimes leaves a U+FFFC OBJECT REPLACEMENT CHARACTER behind in the text,
// which we want to strip out before actually posting the status
text = text.replacingOccurrences(of: "\u{fffc}", with: "")
if draft.localOnly && mastodonController.instanceFeatures.needsLocalOnlyEmojiHack {
text += " 👁"
}
return text
}
enum Error: Swift.Error, LocalizedError {
case attachmentData(index: Int, cause: CompositionAttachmentData.Error)
case attachmentUpload(index: Int, cause: Client.Error)

View File

@ -86,19 +86,6 @@ class Draft: Codable, ObservableObject {
try container.encode(initialText, forKey: .initialText)
}
func textForPosting(on instance: InstanceFeatures) -> String {
var text = self.text
// when using dictation, iOS sometimes leaves a U+FFFC OBJECT REPLACEMENT CHARACTER behind in the text,
// which we want to strip out before actually posting the status
text = text.replacingOccurrences(of: "\u{fffc}", with: "")
if localOnly && instance.instanceType == .glitch {
text += " 👁"
}
return text
}
}
extension Draft: Equatable {

View File

@ -141,7 +141,7 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections(Section.allCases.filter { $0 != .discover })
snapshot.appendItems([.bookmarks], toSection: .bookmarks)
if mastodonController.instanceFeatures.instanceType.isMastodon,
if mastodonController.instanceFeatures.trends,
!Preferences.shared.hideDiscover {
addDiscoverSection(to: &snapshot)
}
@ -172,7 +172,7 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate {
private func ownInstanceLoaded(_ instance: Instance) {
var snapshot = self.dataSource.snapshot()
if mastodonController.instanceFeatures.instanceType.isMastodon,
if mastodonController.instanceFeatures.trends,
!snapshot.sectionIdentifiers.contains(.discover) {
snapshot.insertSections([.discover], afterSection: .bookmarks)
snapshot.appendItems([.trendingTags, .profileDirectory], toSection: .discover)

View File

@ -163,7 +163,7 @@ class MainSidebarViewController: UIViewController {
snapshot.appendItems([
.tab(.compose)
], toSection: .compose)
if mastodonController.instanceFeatures.instanceType.isMastodon,
if mastodonController.instanceFeatures.trends,
!Preferences.shared.hideDiscover {
snapshot.insertSections([.discover], afterSection: .compose)
}
@ -188,7 +188,7 @@ class MainSidebarViewController: UIViewController {
}
private func ownInstanceLoaded(_ instance: Instance) {
if mastodonController.instanceFeatures.instanceType.isMastodon {
if mastodonController.instanceFeatures.trends {
var snapshot = self.dataSource.snapshot()
if !snapshot.sectionIdentifiers.contains(.discover) {
snapshot.appendSections([.discover])