mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2024-12-15 10:24:32 +01:00
0a9689c67f
* Basic fake language picker support * Recognize languages from post text * Exclude suggested languages from recents * Load recent languages from Settings object * Send the language to the API * Persist the used language to settings * Always show the currently selected language in the list * Fix crash * Add support for picking arbitrary lanuages * Fix display of 3 letter language codes * Improve label to include endonym too * Limit to 3 recent languages * Reduce lower bound for displaying language suggestions * Fix saving recent language when publishing * Fix tint color of language picker button * Add a badge to prompt users to change language * Dismiss the badge even if you pick the same language * Read language names in the language if possible * Use a compressed font for 3-letter codes Also use `minimumScaleFactor` to shrink troublesome codes to fit Co-Authored-By: samhenrigold <49251320+samhenrigold@users.noreply.github.com> * Remove .vscode/launch.json * Add message to fatalError() Co-authored-by: samhenrigold <49251320+samhenrigold@users.noreply.github.com>
73 lines
3.0 KiB
Swift
73 lines
3.0 KiB
Swift
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||
|
||
import MastodonLocalization
|
||
import SwiftUI
|
||
|
||
struct LanguagePicker: View {
|
||
let onSelect: (String) -> Void
|
||
|
||
@Environment(\.dismiss) private var dismiss
|
||
@Environment(\.dynamicTypeSize) private var dynamicTypeSize
|
||
|
||
@State private var query = ""
|
||
@State private var languages: [Language] = {
|
||
let locales = Locale.availableIdentifiers.map(Locale.init(identifier:))
|
||
var languages: [String: Language] = [:]
|
||
for locale in locales {
|
||
if let code = locale.languageCode,
|
||
let endonym = locale.localizedString(forLanguageCode: code),
|
||
let exonym = Locale.current.localizedString(forLanguageCode: code) {
|
||
// don’t overwrite the “base” language
|
||
if let lang = languages[code], !(lang.localeId ?? "").contains("_") { continue }
|
||
languages[code] = Language(endonym: endonym, exonym: exonym, id: code, localeId: locale.identifier)
|
||
}
|
||
}
|
||
return languages.values.sorted(using: KeyPathComparator(\.id))
|
||
}()
|
||
|
||
var body: some View {
|
||
NavigationView {
|
||
let filteredLanguages = query.isEmpty ? languages : languages.filter { $0.contains(query) }
|
||
List(filteredLanguages) { lang in
|
||
let endonym = Text(lang.endonym)
|
||
let exonym: Text = {
|
||
if lang.exonymIsDifferent {
|
||
return Text("(\(lang.exonym))").foregroundColor(.secondary)
|
||
}
|
||
return Text("")
|
||
}()
|
||
Button(action: { onSelect(lang.id) }) {
|
||
if #available(iOS 16.0, *) {
|
||
ViewThatFits(in: .horizontal) {
|
||
HStack(spacing: 0) { endonym; Text(" "); exonym }
|
||
VStack(alignment: .leading) { endonym; exonym }
|
||
}
|
||
} else {
|
||
// less optimal because if you’re using an LTR language, RTL languages
|
||
// will read as “ ([exonym])[endonym]” (and vice versa in RTL locales)
|
||
Text("\(endonym)\(exonym)")
|
||
}
|
||
}
|
||
.tint(.primary)
|
||
.accessibilityLabel(Text(lang.label))
|
||
}.toolbar {
|
||
ToolbarItem(placement: .cancellationAction) {
|
||
Button(L10n.Common.Controls.Actions.cancel) {
|
||
dismiss()
|
||
}
|
||
}
|
||
}
|
||
.listStyle(.plain)
|
||
.searchable(text: $query, placement: .navigationBarDrawer(displayMode: .always))
|
||
.navigationTitle(L10n.Scene.Compose.Language.title)
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
}.navigationViewStyle(.stack)
|
||
}
|
||
}
|
||
|
||
struct SwiftUIView_Previews: PreviewProvider {
|
||
static var previews: some View {
|
||
LanguagePicker(onSelect: { _ in })
|
||
}
|
||
}
|