Add language-selector (#690)
For now, it searches for German servers only because.
This commit is contained in:
parent
6b0547d3d4
commit
7c8c5fe214
|
@ -267,6 +267,7 @@
|
||||||
"server_picker": {
|
"server_picker": {
|
||||||
"title": "Pick Server",
|
"title": "Pick Server",
|
||||||
"button": {
|
"button": {
|
||||||
|
"language": "Language",
|
||||||
"category": {
|
"category": {
|
||||||
"all": "All",
|
"all": "All",
|
||||||
"all_accessiblity_description": "Category: All",
|
"all_accessiblity_description": "Category: All",
|
||||||
|
|
|
@ -13,6 +13,7 @@ import MastodonLocalization
|
||||||
/// Note: update Equatable when change case
|
/// Note: update Equatable when change case
|
||||||
enum CategoryPickerItem {
|
enum CategoryPickerItem {
|
||||||
case all
|
case all
|
||||||
|
case language(language: String?)
|
||||||
case category(category: Mastodon.Entity.Category)
|
case category(category: Mastodon.Entity.Category)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +23,12 @@ extension CategoryPickerItem {
|
||||||
switch self {
|
switch self {
|
||||||
case .all:
|
case .all:
|
||||||
return L10n.Scene.ServerPicker.Button.Category.all
|
return L10n.Scene.ServerPicker.Button.Category.all
|
||||||
|
case .language(let language):
|
||||||
|
if let language {
|
||||||
|
return language
|
||||||
|
} else {
|
||||||
|
return L10n.Scene.ServerPicker.Button.language
|
||||||
|
}
|
||||||
case .category(let category):
|
case .category(let category):
|
||||||
switch category.category {
|
switch category.category {
|
||||||
case .academia:
|
case .academia:
|
||||||
|
@ -58,6 +65,13 @@ extension CategoryPickerItem {
|
||||||
switch self {
|
switch self {
|
||||||
case .all:
|
case .all:
|
||||||
return L10n.Scene.ServerPicker.Button.Category.allAccessiblityDescription
|
return L10n.Scene.ServerPicker.Button.Category.allAccessiblityDescription
|
||||||
|
case .language(let language):
|
||||||
|
if let language {
|
||||||
|
return language
|
||||||
|
} else {
|
||||||
|
return L10n.Scene.ServerPicker.Button.language
|
||||||
|
}
|
||||||
|
|
||||||
case .category(let category):
|
case .category(let category):
|
||||||
switch category.category {
|
switch category.category {
|
||||||
case .academia:
|
case .academia:
|
||||||
|
@ -98,6 +112,8 @@ extension CategoryPickerItem: Equatable {
|
||||||
return true
|
return true
|
||||||
case (.category(let categoryLeft), .category(let categoryRight)):
|
case (.category(let categoryLeft), .category(let categoryRight)):
|
||||||
return categoryLeft.category.rawValue == categoryRight.category.rawValue
|
return categoryLeft.category.rawValue == categoryRight.category.rawValue
|
||||||
|
case (.language(let languageLeft), .language(let languageRight)):
|
||||||
|
return languageLeft == languageRight
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -109,6 +125,12 @@ extension CategoryPickerItem: Hashable {
|
||||||
switch self {
|
switch self {
|
||||||
case .all:
|
case .all:
|
||||||
hasher.combine(String(describing: CategoryPickerItem.all.self))
|
hasher.combine(String(describing: CategoryPickerItem.all.self))
|
||||||
|
case .language(let language):
|
||||||
|
if let language {
|
||||||
|
return hasher.combine(language)
|
||||||
|
} else {
|
||||||
|
return hasher.combine("no_language_selected")
|
||||||
|
}
|
||||||
case .category(let category):
|
case .category(let category):
|
||||||
hasher.combine(category.category.rawValue)
|
hasher.combine(category.category.rawValue)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,10 @@ extension CategoryPickerSection {
|
||||||
guard let _ = dependency else { return nil }
|
guard let _ = dependency else { return nil }
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self), for: indexPath) as! PickServerCategoryCollectionViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: PickServerCategoryCollectionViewCell.self), for: indexPath) as! PickServerCategoryCollectionViewCell
|
||||||
cell.categoryView.titleLabel.text = item.title
|
cell.categoryView.titleLabel.text = item.title
|
||||||
|
|
||||||
|
let isLanguage = (item == .language(language: nil))
|
||||||
|
cell.categoryView.chevron.isHidden = (isLanguage == false)
|
||||||
|
|
||||||
cell.observe(\.isSelected, options: [.initial, .new]) { cell, _ in
|
cell.observe(\.isSelected, options: [.initial, .new]) { cell, _ in
|
||||||
|
|
||||||
let textColor: UIColor
|
let textColor: UIColor
|
||||||
|
@ -41,6 +45,7 @@ extension CategoryPickerSection {
|
||||||
cell.categoryView.backgroundColor = backgroundColor
|
cell.categoryView.backgroundColor = backgroundColor
|
||||||
cell.categoryView.titleLabel.textColor = textColor
|
cell.categoryView.titleLabel.textColor = textColor
|
||||||
cell.categoryView.layer.borderColor = borderColor.cgColor
|
cell.categoryView.layer.borderColor = borderColor.cgColor
|
||||||
|
cell.categoryView.chevron.tintColor = textColor
|
||||||
}
|
}
|
||||||
.store(in: &cell.observations)
|
.store(in: &cell.observations)
|
||||||
|
|
||||||
|
|
|
@ -391,6 +391,7 @@ extension MastodonPickServerViewController: PickServerServerSectionTableHeaderVi
|
||||||
func pickServerServerSectionTableHeaderView(_ headerView: PickServerServerSectionTableHeaderView, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
func pickServerServerSectionTableHeaderView(_ headerView: PickServerServerSectionTableHeaderView, collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
guard let diffableDataSource = headerView.diffableDataSource else { return }
|
guard let diffableDataSource = headerView.diffableDataSource else { return }
|
||||||
let item = diffableDataSource.itemIdentifier(for: indexPath)
|
let item = diffableDataSource.itemIdentifier(for: indexPath)
|
||||||
|
//TODO: @zeitschlag Consider language etc. also: show menu
|
||||||
viewModel.selectCategoryItem.value = item ?? .all
|
viewModel.selectCategoryItem.value = item ?? .all
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ class MastodonPickServerViewModel: NSObject {
|
||||||
var categoryPickerItems: [CategoryPickerItem] = {
|
var categoryPickerItems: [CategoryPickerItem] = {
|
||||||
var items: [CategoryPickerItem] = []
|
var items: [CategoryPickerItem] = []
|
||||||
items.append(.all)
|
items.append(.all)
|
||||||
|
items.append(.language(language: nil))
|
||||||
items.append(contentsOf: APIService.stubCategories().map { CategoryPickerItem.category(category: $0) })
|
items.append(contentsOf: APIService.stubCategories().map { CategoryPickerItem.category(category: $0) })
|
||||||
return items
|
return items
|
||||||
}()
|
}()
|
||||||
|
@ -156,6 +157,9 @@ extension MastodonPickServerViewModel {
|
||||||
switch selectCategoryItem {
|
switch selectCategoryItem {
|
||||||
case .all:
|
case .all:
|
||||||
return MastodonPickServerViewModel.filterServers(servers: indexedServers, category: nil, searchText: searchText)
|
return MastodonPickServerViewModel.filterServers(servers: indexedServers, category: nil, searchText: searchText)
|
||||||
|
case .language(let language):
|
||||||
|
//TODO: @zeitschlag Cache selected language
|
||||||
|
return MastodonPickServerViewModel.filterServers(servers: indexedServers, language: "de", category: nil, searchText: searchText)
|
||||||
case .category(let category):
|
case .category(let category):
|
||||||
return MastodonPickServerViewModel.filterServers(servers: indexedServers, category: category.category.rawValue, searchText: searchText)
|
return MastodonPickServerViewModel.filterServers(servers: indexedServers, category: category.category.rawValue, searchText: searchText)
|
||||||
}
|
}
|
||||||
|
@ -210,16 +214,16 @@ extension MastodonPickServerViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonPickServerViewModel {
|
extension MastodonPickServerViewModel {
|
||||||
private static func filterServers(servers: [Mastodon.Entity.Server], category: String?, searchText: String) -> [Mastodon.Entity.Server] {
|
private static func filterServers(servers: [Mastodon.Entity.Server], language: String? = nil, category: String?, searchText: String) -> [Mastodon.Entity.Server] {
|
||||||
return servers
|
let filteredServers = servers
|
||||||
// 1. Filter the category
|
// 1. Filter the category
|
||||||
.filter {
|
.filter {
|
||||||
guard let category = category else { return true }
|
guard let category = category else { return true }
|
||||||
return $0.category.caseInsensitiveCompare(category) == .orderedSame
|
return $0.category.caseInsensitiveCompare(category) == .orderedSame
|
||||||
}
|
}
|
||||||
// 2. Filter the searchText
|
// 2. Filter the searchText
|
||||||
.filter {
|
.filter {
|
||||||
let searchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
|
let searchText = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
guard !searchText.isEmpty else {
|
guard !searchText.isEmpty else {
|
||||||
|
@ -227,6 +231,11 @@ extension MastodonPickServerViewModel {
|
||||||
}
|
}
|
||||||
return $0.domain.lowercased().contains(searchText.lowercased())
|
return $0.domain.lowercased().contains(searchText.lowercased())
|
||||||
}
|
}
|
||||||
|
.filter {
|
||||||
|
guard let language else { return true }
|
||||||
|
return $0.language.lowercased() == language.lowercased()
|
||||||
|
}
|
||||||
|
return filteredServers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1205,6 +1205,8 @@ public enum L10n {
|
||||||
/// Pick server
|
/// Pick server
|
||||||
public static let title = L10n.tr("Localizable", "Scene.ServerPicker.Title", fallback: "Pick server")
|
public static let title = L10n.tr("Localizable", "Scene.ServerPicker.Title", fallback: "Pick server")
|
||||||
public enum Button {
|
public enum Button {
|
||||||
|
/// Language
|
||||||
|
public static let language = L10n.tr("Localizable", "Scene.ServerPicker.Button.Language", fallback: "Language")
|
||||||
/// See Less
|
/// See Less
|
||||||
public static let seeLess = L10n.tr("Localizable", "Scene.ServerPicker.Button.SeeLess", fallback: "See Less")
|
public static let seeLess = L10n.tr("Localizable", "Scene.ServerPicker.Button.SeeLess", fallback: "See Less")
|
||||||
/// See More
|
/// See More
|
||||||
|
|
|
@ -428,6 +428,7 @@ uploaded to Mastodon.";
|
||||||
"Scene.ServerPicker.Button.Category.Tech" = "tech";
|
"Scene.ServerPicker.Button.Category.Tech" = "tech";
|
||||||
"Scene.ServerPicker.Button.SeeLess" = "See Less";
|
"Scene.ServerPicker.Button.SeeLess" = "See Less";
|
||||||
"Scene.ServerPicker.Button.SeeMore" = "See More";
|
"Scene.ServerPicker.Button.SeeMore" = "See More";
|
||||||
|
"Scene.ServerPicker.Button.Language" = "Language";
|
||||||
"Scene.ServerPicker.EmptyState.BadNetwork" = "Something went wrong while loading the data. Check your internet connection.";
|
"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.FindingServers" = "Finding available servers...";
|
||||||
"Scene.ServerPicker.EmptyState.NoResults" = "No results";
|
"Scene.ServerPicker.EmptyState.NoResults" = "No results";
|
||||||
|
|
|
@ -419,6 +419,7 @@ uploaded to Mastodon.";
|
||||||
"Scene.ServerPicker.Button.Category.Tech" = "tech";
|
"Scene.ServerPicker.Button.Category.Tech" = "tech";
|
||||||
"Scene.ServerPicker.Button.SeeLess" = "See Less";
|
"Scene.ServerPicker.Button.SeeLess" = "See Less";
|
||||||
"Scene.ServerPicker.Button.SeeMore" = "See More";
|
"Scene.ServerPicker.Button.SeeMore" = "See More";
|
||||||
|
"Scene.ServerPicker.Button.Language" = "Language";
|
||||||
"Scene.ServerPicker.EmptyState.BadNetwork" = "Something went wrong while loading the data. Check your internet connection.";
|
"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.FindingServers" = "Finding available servers...";
|
||||||
"Scene.ServerPicker.EmptyState.NoResults" = "No results";
|
"Scene.ServerPicker.EmptyState.NoResults" = "No results";
|
||||||
|
|
Loading…
Reference in New Issue