From 76b033afed8bbe74756ebe9f8a1937b27dba9255 Mon Sep 17 00:00:00 2001 From: CMK Date: Thu, 5 Aug 2021 16:17:54 +0800 Subject: [PATCH] feat: make servers meet user preferred language display first --- Mastodon.xcodeproj/project.pbxproj | 17 ++++++++ .../xcschemes/xcschememanagement.plist | 8 ++-- .../xcshareddata/swiftpm/Package.resolved | 9 +++++ ...rverViewModel+LoadIndexedServerState.swift | 8 +--- .../MastodonPickServerViewModel.swift | 40 ++++++++++++++++++- 5 files changed, 70 insertions(+), 12 deletions(-) diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 025678de..e2fffb8d 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -280,6 +280,7 @@ DB4FFC2C269EC39600D62E92 /* SearchTransitionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4FFC2A269EC39600D62E92 /* SearchTransitionController.swift */; }; DB51D172262832380062B7A1 /* BlurHashDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB51D170262832380062B7A1 /* BlurHashDecode.swift */; }; DB51D173262832380062B7A1 /* BlurHashEncode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB51D171262832380062B7A1 /* BlurHashEncode.swift */; }; + DB552D4F26BBD10C00E481F6 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = DB552D4E26BBD10C00E481F6 /* OrderedCollections */; }; DB564BD0269F2F83001E39A7 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DB564BCE269F2F83001E39A7 /* Localizable.stringsdict */; }; DB564BD3269F3B35001E39A7 /* StatusFilterService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB564BD2269F3B35001E39A7 /* StatusFilterService.swift */; }; DB59F0FE25EF5D96001F1DAB /* StatusProvider+UITableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB59F0FD25EF5D96001F1DAB /* StatusProvider+UITableViewDelegate.swift */; }; @@ -1311,6 +1312,7 @@ DB6804862637CD4C00430867 /* AppShared.framework in Frameworks */, DBF96326262EC0A6001D8D25 /* AuthenticationServices.framework in Frameworks */, DBAC6483267D0B21007FE9FD /* DifferenceKit in Frameworks */, + DB552D4F26BBD10C00E481F6 /* OrderedCollections in Frameworks */, 2D61336925C18A4F00CAE157 /* AlamofireNetworkActivityIndicator in Frameworks */, DB01E23326A98F0900C3965B /* MastodonMeta in Frameworks */, DBAC64A1267E6D02007FE9FD /* Fuzi in Frameworks */, @@ -3081,6 +3083,7 @@ DBC6462A26A1738900B0E31B /* MastodonUI */, DB01E23226A98F0900C3965B /* MastodonMeta */, DB01E23426A98F0900C3965B /* MetaTextKit */, + DB552D4E26BBD10C00E481F6 /* OrderedCollections */, ); productName = Mastodon; productReference = DB427DD225BAA00100D1B89D /* Mastodon.app */; @@ -3328,6 +3331,7 @@ DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator" */, DB0E2D2C26833FF600865C3C /* XCRemoteSwiftPackageReference "Nuke-FLAnimatedImage-Plugin" */, DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit" */, + DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections" */, ); productRefGroup = DB427DD325BAA00100D1B89D /* Products */; projectDirPath = ""; @@ -5644,6 +5648,14 @@ minimumVersion = 4.1.0; }; }; + DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/apple/swift-collections.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.0.5; + }; + }; DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git"; @@ -5752,6 +5764,11 @@ package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */; productName = AlamofireImage; }; + DB552D4E26BBD10C00E481F6 /* OrderedCollections */ = { + isa = XCSwiftPackageProductDependency; + package = DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections" */; + productName = OrderedCollections; + }; DB68050F2637D0F800430867 /* KeychainAccess */ = { isa = XCSwiftPackageProductDependency; package = DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess" */; diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 4bf0e25a..09c042d8 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,12 +7,12 @@ AppShared.xcscheme_^#shared#^_ orderHint - 24 + 26 CoreDataStack.xcscheme_^#shared#^_ orderHint - 25 + 24 Mastodon - ASDK.xcscheme_^#shared#^_ @@ -42,7 +42,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 28 + 27 MastodonIntents.xcscheme_^#shared#^_ @@ -62,7 +62,7 @@ ShareActionExtension.xcscheme_^#shared#^_ orderHint - 26 + 25 SuppressBuildableAutocreation diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index c6a46992..67c613bf 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -136,6 +136,15 @@ "version": "5.11.1" } }, + { + "package": "swift-collections", + "repositoryURL": "https://github.com/apple/swift-collections.git", + "state": { + "branch": null, + "revision": "0959ba76a1d4a98fd11163aa83fd49c25b93bfae", + "version": "0.0.5" + } + }, { "package": "swift-nio", "repositoryURL": "https://github.com/apple/swift-nio.git", diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+LoadIndexedServerState.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+LoadIndexedServerState.swift index 1cb9b508..0c4910d1 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+LoadIndexedServerState.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel+LoadIndexedServerState.swift @@ -55,13 +55,7 @@ extension MastodonPickServerViewModel.LoadIndexedServerState { } receiveValue: { [weak self] response in guard let _ = self else { return } stateMachine.enter(Idle.self) - - // ignore approval required servers - var servers = response.value - if viewModel.mode == .signUp { - servers = servers.filter { !$0.approvalRequired } - } - viewModel.indexedServers.value = servers + viewModel.indexedServers.value = response.value } .store(in: &viewModel.disposeBag) } diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift index ef9275b0..7a648011 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewModel.swift @@ -11,6 +11,7 @@ import Combine import GameplayKit import MastodonSDK import CoreDataStack +import OrderedCollections class MastodonPickServerViewModel: NSObject { @@ -167,7 +168,44 @@ extension MastodonPickServerViewModel { searchText.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main).removeDuplicates() ) .map { indexedServers, selectCategoryItem, searchText -> [Mastodon.Entity.Server] in - // Filter the indexed servers from joinmastodon.org + // ignore approval required servers when sign-up + var indexedServers = indexedServers + if self.mode == .signUp { + indexedServers = indexedServers.filter { !$0.approvalRequired } + } + + // group by language user preferred language first. Then sort by `totalUsers` + var languageToServersMapping = OrderedDictionary() + for language in Locale.preferredLanguages { + let local = Locale(identifier: language) + guard let languageCode = local.languageCode else { continue } + // skip if key duplicate + guard !languageToServersMapping.keys.contains(languageCode) else { continue } + // append to dict + languageToServersMapping[languageCode] = indexedServers + .filter { $0.language.lowercased() == languageCode.lowercased() } + .sorted(by: { $0.totalUsers > $1.totalUsers }) + } + // sort remains servers by `totalUsers` + let remainsServers = indexedServers + .filter { server in + return !languageToServersMapping.contains { _, servers in servers.contains(server) } + } + .sorted(by: { $0.totalUsers > $1.totalUsers }) + + var _indexedServers: [Mastodon.Entity.Server] = [] + for key in languageToServersMapping.keys { + _indexedServers.append(contentsOf: languageToServersMapping[key] ?? []) + } + _indexedServers.append(contentsOf: remainsServers) + + if _indexedServers.count == indexedServers.count { + indexedServers = _indexedServers + } else { + assertionFailure("should not change dataset size") + } + + // Filter the indexed servers by category or search text switch selectCategoryItem { case .all: return MastodonPickServerViewModel.filterServers(servers: indexedServers, category: nil, searchText: searchText)