forked from shadowfacts/Tusker
Clean up instance type/feature detection
Add akkoma detection
This commit is contained in:
parent
603e989879
commit
99a1c76cb1
|
@ -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?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
|
|
Loading…
Reference in New Issue