Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Localization/StringsConvertor/input/Base.lproj/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"search": {
"placeholder": "Search name or URL"
},
"category_ignored_message": "No servers found in the “%s” category. Here are results from other categories:",
"no_server_selected_hint": "We’ll pick a server based on your language if you continue without making a selection."
},
"privacy": {
Expand Down
1 change: 1 addition & 0 deletions Localization/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
"search": {
"placeholder": "Search name or URL"
},
"category_ignored_message": "No servers found in the “%s” category. Here are results from other categories:",
"no_server_selected_hint": "We’ll pick a server based on your language if you continue without making a selection."
},
"privacy": {
Expand Down
4 changes: 4 additions & 0 deletions Mastodon.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
62FD27D12893707600B205C5 /* BookmarkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D02893707600B205C5 /* BookmarkViewController.swift */; };
62FD27D32893707B00B205C5 /* BookmarkViewController+DataSourceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D22893707B00B205C5 /* BookmarkViewController+DataSourceProvider.swift */; };
62FD27D52893708A00B205C5 /* BookmarkViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62FD27D42893708A00B205C5 /* BookmarkViewModel+Diffable.swift */; };
852198A82A4F304500D137AC /* PickServerMessageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 852198A72A4F304500D137AC /* PickServerMessageTableViewCell.swift */; };
855149C8295F1C5F00943D96 /* UIInterfaceOrientationMask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 855149C7295F1C5F00943D96 /* UIInterfaceOrientationMask.swift */; };
855149CA29606D6400943D96 /* PortraitAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 855149C929606D6400943D96 /* PortraitAlertController.swift */; };
85904C02293BC0EB0011C817 /* ImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85904C01293BC0EB0011C817 /* ImageProvider.swift */; };
Expand Down Expand Up @@ -749,6 +750,7 @@
7CB58D292DA7ACEF179A9050 /* Pods-Mastodon.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.profile.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.profile.xcconfig"; sourceTree = "<group>"; };
7CEFFAE9AF9284B13C0A758D /* Pods-MastodonTests.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.asdk - debug.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.asdk - debug.xcconfig"; sourceTree = "<group>"; };
819CEC9DCAD8E8E7BD85A7BB /* Pods-Mastodon.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk.xcconfig"; sourceTree = "<group>"; };
852198A72A4F304500D137AC /* PickServerMessageTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerMessageTableViewCell.swift; sourceTree = "<group>"; };
855149C7295F1C5F00943D96 /* UIInterfaceOrientationMask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIInterfaceOrientationMask.swift; sourceTree = "<group>"; };
855149C929606D6400943D96 /* PortraitAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortraitAlertController.swift; sourceTree = "<group>"; };
85904C01293BC0EB0011C817 /* ImageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageProvider.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1357,6 +1359,7 @@
children = (
0FB3D33725E6401400AAD544 /* PickServerCell.swift */,
DB0F814F264D1E2500F2A12B /* PickServerLoaderTableViewCell.swift */,
852198A72A4F304500D137AC /* PickServerMessageTableViewCell.swift */,
);
path = TableViewCell;
sourceTree = "<group>";
Expand Down Expand Up @@ -3648,6 +3651,7 @@
DB5B549F2833A72500DEF8B2 /* FamiliarFollowersViewModel+Diffable.swift in Sources */,
DB6B351E2601FAEE00DC1E11 /* ComposeStatusAttachmentCollectionViewCell.swift in Sources */,
DB8F7076279E954700E1225B /* DataSourceFacade+Follow.swift in Sources */,
852198A82A4F304500D137AC /* PickServerMessageTableViewCell.swift in Sources */,
DB63F7542799491600455B82 /* DataSourceFacade+SearchHistory.swift in Sources */,
DB7A9F912818EAF10016AF98 /* MastodonRegisterView.swift in Sources */,
DBF1572F27046F1A00EC00B7 /* SecondaryPlaceholderViewController.swift in Sources */,
Expand Down
62 changes: 34 additions & 28 deletions Mastodon/Scene/Onboarding/PickServer/CategoryPickerItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,39 @@ enum CategoryPickerItem {
case category(category: Mastodon.Entity.Category)
}

extension Mastodon.Entity.Category.Kind {
var label: String {
switch self {
case .academia:
return L10n.Scene.ServerPicker.Button.Category.academia
case .activism:
return L10n.Scene.ServerPicker.Button.Category.activism
case .food:
return L10n.Scene.ServerPicker.Button.Category.food
case .furry:
return L10n.Scene.ServerPicker.Button.Category.furry
case .games:
return L10n.Scene.ServerPicker.Button.Category.games
case .general:
return L10n.Scene.ServerPicker.Button.Category.general
case .journalism:
return L10n.Scene.ServerPicker.Button.Category.journalism
case .lgbt:
return L10n.Scene.ServerPicker.Button.Category.lgbt
case .regional:
return L10n.Scene.ServerPicker.Button.Category.regional
case .art:
return L10n.Scene.ServerPicker.Button.Category.art
case .music:
return L10n.Scene.ServerPicker.Button.Category.music
case .tech:
return L10n.Scene.ServerPicker.Button.Category.tech
case ._other:
return "-" // FIXME:
}
}
}

extension CategoryPickerItem {

var title: String {
Expand All @@ -38,34 +71,7 @@ extension CategoryPickerItem {
return L10n.Scene.ServerPicker.Button.signupSpeed
}
case .category(let category):
switch category.category {
case .academia:
return L10n.Scene.ServerPicker.Button.Category.academia
case .activism:
return L10n.Scene.ServerPicker.Button.Category.activism
case .food:
return L10n.Scene.ServerPicker.Button.Category.food
case .furry:
return L10n.Scene.ServerPicker.Button.Category.furry
case .games:
return L10n.Scene.ServerPicker.Button.Category.games
case .general:
return L10n.Scene.ServerPicker.Button.Category.general
case .journalism:
return L10n.Scene.ServerPicker.Button.Category.journalism
case .lgbt:
return L10n.Scene.ServerPicker.Button.Category.lgbt
case .regional:
return L10n.Scene.ServerPicker.Button.Category.regional
case .art:
return L10n.Scene.ServerPicker.Button.Category.art
case .music:
return L10n.Scene.ServerPicker.Button.Category.music
case .tech:
return L10n.Scene.ServerPicker.Button.Category.tech
case ._other:
return "-" // FIXME:
}
return category.category.label
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,13 @@ extension MastodonPickServerViewModel {

loadIndexedServerStateMachine.enter(LoadIndexedServerState.Loading.self)

Publishers.CombineLatest(
Publishers.CombineLatest3(
filteredIndexedServers,
selectCategoryItem,
unindexedServers
)
.receive(on: DispatchQueue.main)
.sink(receiveValue: { [weak self] indexedServers, unindexedServers in
.sink(receiveValue: { [weak self] indexedServers, selectCategoryItem, unindexedServers in
guard let self = self else { return }
guard let diffableDataSource = self.diffableDataSource else { return }

Expand All @@ -69,14 +70,21 @@ extension MastodonPickServerViewModel {

// TODO: handle filter
var serverItems: [PickServerItem] = []
for server in indexedServers {
let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false)
attribute.isLast.value = false
let item = PickServerItem.server(server: server, attribute: attribute)
guard !serverItems.contains(item) else { continue }
serverItems.append(item)
if let indexedServers {
if indexedServers.didIgnoreCategory,
indexedServers.servers.isNotEmpty,
case .category(let category) = selectCategoryItem {
serverItems.append(.message(attribute: .categoryIgnored(category: category.category)))
}
for server in indexedServers.servers {
let attribute = oldSnapshotServerItemAttributeDict[server.domain] ?? PickServerItem.ServerItemAttribute(isLast: false, isExpand: false)
attribute.isLast.value = false
let item = PickServerItem.server(server: server, attribute: attribute)
guard !serverItems.contains(item) else { continue }
serverItems.append(item)
}
}

if let unindexedServers = unindexedServers {
if !unindexedServers.isEmpty {
for server in unindexedServers {
Expand All @@ -87,7 +95,8 @@ extension MastodonPickServerViewModel {
serverItems.append(item)
}
} else {
if indexedServers.isEmpty && !self.isLoadingIndexedServers.value {
if (indexedServers?.servers.isEmpty ?? true),
!self.isLoadingIndexedServers.value {
serverItems.append(.loader(attribute: PickServerItem.LoaderItemAttribute(isLast: false, isEmptyResult: true)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class MastodonPickServerViewModel: NSObject {
stateMachine.enter(LoadIndexedServerState.Initial.self)
return stateMachine
}()
let filteredIndexedServers = CurrentValueSubject<[Mastodon.Entity.Server], Never>([])
let filteredIndexedServers = CurrentValueSubject<FilteredServers?, Never>(nil)
let servers = CurrentValueSubject<[Mastodon.Entity.Server], Error>([])
let selectedServer = CurrentValueSubject<Mastodon.Entity.Server?, Never>(nil)
let error = CurrentValueSubject<Error?, Never>(nil)
Expand Down Expand Up @@ -126,7 +126,7 @@ extension MastodonPickServerViewModel {
(selectedLanguage, manualApprovalRequired)
}
)
.map { [weak self] indexedServers, selectCategoryItem, searchText, filters -> [Mastodon.Entity.Server] in
.map { [weak self] indexedServers, selectCategoryItem, searchText, filters in
var indexedServers = indexedServers

var _indexedServers: [Mastodon.Entity.Server] = []
Expand Down Expand Up @@ -249,7 +249,11 @@ extension MastodonPickServerViewModel {
}

extension MastodonPickServerViewModel {
private static func filterServers(servers: [Mastodon.Entity.Server], language: String? = nil, manualApprovalRequired: Bool? = nil, category: String?, searchText: String) -> [Mastodon.Entity.Server] {
struct FilteredServers {
let servers: [Mastodon.Entity.Server]
let didIgnoreCategory: Bool
}
private static func filterServers(servers: [Mastodon.Entity.Server], language: String? = nil, manualApprovalRequired: Bool? = nil, category: String?, searchText: String) -> FilteredServers {
let filteredServers = servers
// 1. Filter the category
.filter {
Expand All @@ -275,7 +279,14 @@ extension MastodonPickServerViewModel {
print("\($0.domain) \($0.approvalRequired) < \(manualApprovalRequired)")
return $0.approvalRequired == manualApprovalRequired
}
return filteredServers

// if there are no results when filtering by category, drop the category filter
if category != nil, filteredServers.isEmpty {
let result = filterServers(servers: servers, language: language, manualApprovalRequired: manualApprovalRequired, category: nil, searchText: searchText)
return FilteredServers(servers: result.servers, didIgnoreCategory: true)
}

return FilteredServers(servers: filteredServers, didIgnoreCategory: false)
}
}

Expand Down
7 changes: 7 additions & 0 deletions Mastodon/Scene/Onboarding/PickServer/PickServerItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import MastodonSDK
enum PickServerItem {
case server(server: Mastodon.Entity.Server, attribute: ServerItemAttribute)
case loader(attribute: LoaderItemAttribute)
case message(attribute: MessageItemAttribute)
}

extension PickServerItem {
Expand Down Expand Up @@ -53,6 +54,10 @@ extension PickServerItem {
hasher.combine(id)
}
}

enum MessageItemAttribute: Equatable, Hashable {
case categoryIgnored(category: Mastodon.Entity.Category.Kind)
}
}

extension PickServerItem: Equatable {
Expand All @@ -75,6 +80,8 @@ extension PickServerItem: Hashable {
hasher.combine(server.domain)
case .loader(let attribute):
hasher.combine(attribute)
case .message(let attribute):
hasher.combine(attribute)
}
}
}
19 changes: 18 additions & 1 deletion Mastodon/Scene/Onboarding/PickServer/PickServerSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import UIKit
import MastodonSDK
import MastodonLocalization
import Kanna
import AlamofireImage

Expand All @@ -22,7 +23,8 @@ extension PickServerSection {
) -> UITableViewDiffableDataSource<PickServerSection, PickServerItem> {
tableView.register(PickServerCell.self, forCellReuseIdentifier: String(describing: PickServerCell.self))
tableView.register(PickServerLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: PickServerLoaderTableViewCell.self))

tableView.register(PickServerMessageTableViewCell.self, forCellReuseIdentifier: String(describing: PickServerMessageTableViewCell.self))

return UITableViewDiffableDataSource(tableView: tableView) { [
weak dependency
] tableView, indexPath, item -> UITableViewCell? in
Expand All @@ -36,6 +38,10 @@ extension PickServerSection {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerLoaderTableViewCell.self), for: indexPath) as! PickServerLoaderTableViewCell
PickServerSection.configure(cell: cell, attribute: attribute)
return cell
case .message(let message):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PickServerMessageTableViewCell.self), for: indexPath) as! PickServerMessageTableViewCell
PickServerSection.configure(cell: cell, attribute: message)
return cell
}
}
}
Expand Down Expand Up @@ -112,3 +118,14 @@ extension PickServerSection {
}

}

extension PickServerSection {

static func configure(cell: PickServerMessageTableViewCell, attribute: PickServerItem.MessageItemAttribute) {
switch attribute {
case .categoryIgnored(let category):
cell.messageLabel.text = L10n.Scene.ServerPicker.categoryIgnoredMessage(category.label)
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// PickServerMessageTableViewCell.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021-5-13.
//

import UIKit
import Combine
import MastodonAsset
import MastodonCore
import MastodonUI
import MastodonLocalization

public final class PickServerMessageTableViewCell: UITableViewCell {

let messageLabel: UILabel = {
let label = UILabel()
label.textColor = Asset.Colors.Label.secondary.color
label.textAlignment = .center
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 14, weight: .semibold))
label.numberOfLines = 0
return label
}()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
_init()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}

}

extension PickServerMessageTableViewCell {

public func _init() {
selectionStyle = .none
backgroundColor = .clear

messageLabel.translatesAutoresizingMaskIntoConstraints = false
messageLabel.setContentCompressionResistancePriority(.required, for: .vertical)
contentView.addSubview(messageLabel)
NSLayoutConstraint.activate([
messageLabel.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
contentView.readableContentGuide.trailingAnchor.constraint(equalTo: messageLabel.trailingAnchor),
messageLabel.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor),
messageLabel.bottomAnchor.constraint(equalTo: contentView.layoutMarginsGuide.bottomAnchor),
])
}

}

#if canImport(SwiftUI) && DEBUG
import SwiftUI

struct PickServerMessageTableViewCell_Previews: PreviewProvider {

static var previews: some View {
UIViewPreview(width: 375) {
let view = PickServerMessageTableViewCell()
view.messageLabel.text = "Hello, world!"
return view
}
.previewLayout(.fixed(width: 375, height: 100))
}

}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,10 @@ public enum L10n {
}
}
public enum ServerPicker {
/// No servers found in the “%@” category. Here are results from other categories:
public static func categoryIgnoredMessage(_ p1: Any) -> String {
return L10n.tr("Localizable", "Scene.ServerPicker.CategoryIgnoredMessage", String(describing: p1), fallback: "No servers found in the “%@” category. Here are results from other categories:")
}
/// We’ll pick a server based on your language if you continue without making a selection.
public static let noServerSelectedHint = L10n.tr("Localizable", "Scene.ServerPicker.NoServerSelectedHint", fallback: "We’ll pick a server based on your language if you continue without making a selection.")
/// Pick Server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ uploaded to Mastodon.";
"Scene.ServerPicker.Button.SeeLess" = "See Less";
"Scene.ServerPicker.Button.SeeMore" = "See More";
"Scene.ServerPicker.Button.SignupSpeed" = "Sign-up Speed";
"Scene.ServerPicker.CategoryIgnoredMessage" = "No servers found in the “%@” category. Here are results from other categories:";
"Scene.ServerPicker.EmptyState.BadNetwork" = "Something went wrong while loading the data. Check your internet connection.";
"Scene.ServerPicker.EmptyState.FindingServers" = "Finding available servers...";
"Scene.ServerPicker.EmptyState.NoResults" = "No results";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extension Mastodon.Entity {

/// # Reference
/// https://joinmastodon.org/communities
public enum Kind: RawRepresentable, Codable, Sendable {
public enum Kind: RawRepresentable, Hashable, Codable, Sendable {

case general
case regional
Expand Down