diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 14014342..0a215418 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -75,6 +75,7 @@ D6114E0F27F897D70080E273 /* History.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E0E27F897D70080E273 /* History.swift */; }; D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E1027F899B30080E273 /* TrendingLinksViewController.swift */; }; D6114E1327F89B440080E273 /* TrendingLinkTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E1227F89B440080E273 /* TrendingLinkTableViewCell.swift */; }; + D6114E1727F8BB210080E273 /* VersionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6114E1627F8BB210080E273 /* VersionTests.swift */; }; D611C2CF232DC61100C86A49 /* HashtagTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */; }; D611C2D0232DC61100C86A49 /* HashtagTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */; }; D61AC1D3232E928600C54D2D /* InstanceSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61AC1D2232E928600C54D2D /* InstanceSelector.swift */; }; @@ -492,6 +493,7 @@ D6114E0E27F897D70080E273 /* History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = History.swift; sourceTree = ""; }; D6114E1027F899B30080E273 /* TrendingLinksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingLinksViewController.swift; sourceTree = ""; }; D6114E1227F89B440080E273 /* TrendingLinkTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrendingLinkTableViewCell.swift; sourceTree = ""; }; + D6114E1627F8BB210080E273 /* VersionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionTests.swift; sourceTree = ""; }; D611C2CD232DC61100C86A49 /* HashtagTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTableViewCell.swift; sourceTree = ""; }; D611C2CE232DC61100C86A49 /* HashtagTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HashtagTableViewCell.xib; sourceTree = ""; }; D61AC1D2232E928600C54D2D /* InstanceSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceSelector.swift; sourceTree = ""; }; @@ -1642,6 +1644,7 @@ D6D4DDE4212518A200E1C4BB /* TuskerTests.swift */, D62FF04723D7CDD700909D6E /* AttributedStringHelperTests.swift */, D6E426AC25334DA500C02E1C /* FuzzyMatcherTests.swift */, + D6114E1627F8BB210080E273 /* VersionTests.swift */, D6D4DDE6212518A200E1C4BB /* Info.plist */, ); path = TuskerTests; @@ -2361,6 +2364,7 @@ files = ( D62FF04823D7CDD700909D6E /* AttributedStringHelperTests.swift in Sources */, D6E426AD25334DA500C02E1C /* FuzzyMatcherTests.swift in Sources */, + D6114E1727F8BB210080E273 /* VersionTests.swift in Sources */, D6D4DDE5212518A200E1C4BB /* TuskerTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved index f1c12db2..404a81ee 100644 --- a/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Tusker.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,52 +1,50 @@ { - "object": { - "pins": [ - { - "package": "PLCrashReporter", - "repositoryURL": "https://github.com/microsoft/plcrashreporter", - "state": { - "branch": null, - "revision": "de6b8f9db4b2a0aa859a5507550a70548e4da936", - "version": "1.8.1" - } - }, - { - "package": "SheetController", - "repositoryURL": "https://git.shadowfacts.net/shadowfacts/SheetController.git", - "state": { - "branch": "master", - "revision": "aa0f5192eaf19d01c89dbfa9ec5878a700376f23", - "version": null - } - }, - { - "package": "swift-system", - "repositoryURL": "https://github.com/apple/swift-system.git", - "state": { - "branch": null, - "revision": "836bc4557b74fe6d2660218d56e3ce96aff76574", - "version": "1.1.1" - } - }, - { - "package": "swift-url", - "repositoryURL": "https://github.com/karwa/swift-url", - "state": { - "branch": "main", - "revision": "9d06f9f89397de16c8942aa123c425568654fd6a", - "version": null - } - }, - { - "package": "SwiftSoup", - "repositoryURL": "https://github.com/scinfu/SwiftSoup.git", - "state": { - "branch": null, - "revision": "774dc9c7213085db8aa59595e27c1cd22e428904", - "version": "2.3.2" - } + "pins" : [ + { + "identity" : "plcrashreporter", + "kind" : "remoteSourceControl", + "location" : "https://github.com/microsoft/plcrashreporter", + "state" : { + "revision" : "de6b8f9db4b2a0aa859a5507550a70548e4da936", + "version" : "1.8.1" } - ] - }, - "version": 1 + }, + { + "identity" : "sheetcontroller", + "kind" : "remoteSourceControl", + "location" : "https://git.shadowfacts.net/shadowfacts/SheetController.git", + "state" : { + "branch" : "master", + "revision" : "aa0f5192eaf19d01c89dbfa9ec5878a700376f23" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "836bc4557b74fe6d2660218d56e3ce96aff76574", + "version" : "1.1.1" + } + }, + { + "identity" : "swift-url", + "kind" : "remoteSourceControl", + "location" : "https://github.com/karwa/swift-url", + "state" : { + "branch" : "main", + "revision" : "9d06f9f89397de16c8942aa123c425568654fd6a" + } + }, + { + "identity" : "swiftsoup", + "kind" : "remoteSourceControl", + "location" : "https://github.com/scinfu/SwiftSoup.git", + "state" : { + "revision" : "774dc9c7213085db8aa59595e27c1cd22e428904", + "version" : "2.3.2" + } + } + ], + "version" : 2 } diff --git a/Tusker/InstanceFeatures.swift b/Tusker/InstanceFeatures.swift index c365cd22..44f2e275 100644 --- a/Tusker/InstanceFeatures.swift +++ b/Tusker/InstanceFeatures.swift @@ -11,6 +11,7 @@ import Pachyderm struct InstanceFeatures { private(set) var instanceType = InstanceType.mastodon + private(set) var version: Version? private(set) var maxStatusChars = 500 var localOnlyPosts: Bool { @@ -33,6 +34,10 @@ struct InstanceFeatures { instanceType != .pixelfed } + var trendingStatusesAndLinks: Bool { + instanceType == .mastodon && version != nil && version! >= Version(3, 5, 0) + } + mutating func update(instance: Instance, nodeInfo: NodeInfo?) { let ver = instance.version.lowercased() if ver.contains("glitch") { @@ -47,6 +52,8 @@ struct InstanceFeatures { instanceType = .mastodon } + version = Version(string: ver) + maxStatusChars = instance.maxStatusCharacters ?? 500 } } @@ -69,3 +76,56 @@ extension InstanceFeatures { } } } + +extension InstanceFeatures { + struct Version: Equatable, Comparable { + let major: Int + let minor: Int + let patch: Int + + init(_ major: Int, _ minor: Int, _ patch: Int) { + self.major = major + self.minor = minor + self.patch = patch + } + + init?(string: String) { + let regex = try! NSRegularExpression(pattern: "^(\\d+)\\.(\\d+)\\.(\\d+).*$") + guard let match = regex.firstMatch(in: string, range: NSRange(location: 0, length: string.utf16.count)), + match.numberOfRanges == 4 else { + return nil + } + let majorStr = (string as NSString).substring(with: match.range(at: 1)) + let minorStr = (string as NSString).substring(with: match.range(at: 2)) + let patchStr = (string as NSString).substring(with: match.range(at: 3)) + guard let major = Int(majorStr), + let minor = Int(minorStr), + let patch = Int(patchStr) else { + return nil + } + self.major = major + self.minor = minor + self.patch = patch + } + + static func ==(lhs: Version, rhs: Version) -> Bool { + return lhs.major == rhs.major && lhs.minor == rhs.minor && lhs.patch == rhs.patch + } + + static func < (lhs: InstanceFeatures.Version, rhs: InstanceFeatures.Version) -> Bool { + if lhs.major < rhs.major { + return true + } else if lhs.major > rhs.major { + return false + } else if lhs.minor < rhs.minor { + return true + } else if lhs.minor > rhs.minor { + return false + } else if lhs.patch < rhs.patch { + return true + } else { + return false + } + } + } +} diff --git a/Tusker/Screens/Explore/ExploreViewController.swift b/Tusker/Screens/Explore/ExploreViewController.swift index 5f9ba696..2cc36b02 100644 --- a/Tusker/Screens/Explore/ExploreViewController.swift +++ b/Tusker/Screens/Explore/ExploreViewController.swift @@ -155,8 +155,11 @@ class ExploreViewController: UIViewController, UICollectionViewDelegate { private func addDiscoverSection(to snapshot: inout NSDiffableDataSourceSnapshot) { snapshot.insertSections([.discover], afterSection: .bookmarks) - // todo: check version - snapshot.appendItems([.trendingStatuses, .trendingTags, .trendingLinks, .profileDirectory], toSection: .discover) + snapshot.appendItems([.trendingTags, .profileDirectory], toSection: .discover) + if mastodonController.instanceFeatures.trendingStatusesAndLinks { + snapshot.insertItems([.trendingStatuses], beforeItem: .trendingTags) + snapshot.insertItems([.trendingLinks], afterItem: .trendingTags) + } } private func ownInstanceLoaded(_ instance: Instance) { diff --git a/Tusker/Screens/Main/MainSidebarViewController.swift b/Tusker/Screens/Main/MainSidebarViewController.swift index f152f671..5cf4ec3d 100644 --- a/Tusker/Screens/Main/MainSidebarViewController.swift +++ b/Tusker/Screens/Main/MainSidebarViewController.swift @@ -162,28 +162,27 @@ class MainSidebarViewController: UIViewController { var discoverSnapshot = NSDiffableDataSourceSectionSnapshot() discoverSnapshot.append([.discoverHeader]) discoverSnapshot.append([ - .trendingStatuses, .trendingTags, - .trendingLinks, .profileDirectory, ], to: .discoverHeader) + if mastodonController.instanceFeatures.trendingStatusesAndLinks { + discoverSnapshot.insert([.trendingStatuses], before: .trendingTags) + discoverSnapshot.insert([.trendingLinks], after: .trendingTags) + } dataSource.apply(discoverSnapshot, to: .discover) } private func ownInstanceLoaded(_ instance: Instance) { - var snapshot = self.dataSource.snapshot() - if mastodonController.instanceFeatures.instanceType.isMastodon, - !snapshot.sectionIdentifiers.contains(.discover) { - snapshot.insertSections([.discover], afterSection: .compose) - snapshot.appendItems([ - .trendingTags, - .profileDirectory, - ], toSection: .discover) + if mastodonController.instanceFeatures.instanceType.isMastodon { + var snapshot = self.dataSource.snapshot() + if !snapshot.sectionIdentifiers.contains(.discover) { + snapshot.appendSections([.discover]) + dataSource.apply(snapshot, animatingDifferences: false) + } + applyDiscoverSectionSnapshot() } let prevSelected = collectionView.indexPathsForSelectedItems - dataSource.apply(snapshot, animatingDifferences: false) - if let prevSelected = prevSelected?.first { collectionView.selectItem(at: prevSelected, animated: false, scrollPosition: .top) } diff --git a/TuskerTests/VersionTests.swift b/TuskerTests/VersionTests.swift new file mode 100644 index 00000000..a8f726f9 --- /dev/null +++ b/TuskerTests/VersionTests.swift @@ -0,0 +1,27 @@ +// +// VersionTests.swift +// TuskerTests +// +// Created by Shadowfacts on 4/2/22. +// Copyright © 2022 Shadowfacts. All rights reserved. +// + +import XCTest +@testable import Tusker + +class VersionTests: XCTestCase { + + typealias Version = InstanceFeatures.Version + + func testParseVersion() { + XCTAssertEqual(Version(string: "1.2.3"), Version(1, 2, 3)) + XCTAssertEqual(Version(string: "asdf"), nil) + } + + func testComparison() { + XCTAssertLessThan(Version(1, 2, 3), Version(1, 2, 4)) + XCTAssertLessThan(Version(1, 2, 3), Version(1, 3, 0)) + XCTAssertLessThan(Version(1, 2, 3), Version(2, 0, 0)) + } + +}