fix: register may fail due to locale parameter issue

This commit is contained in:
CMK 2021-11-04 19:24:46 +08:00
parent cd9d7982bc
commit 6117c903f1
4 changed files with 202 additions and 89 deletions

View File

@ -607,6 +607,8 @@
DBF1D24E269DAF5D00C1C08A /* SearchDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF1D24D269DAF5D00C1C08A /* SearchDetailViewController.swift */; };
DBF1D251269DB01200C1C08A /* SearchHistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF1D250269DB01200C1C08A /* SearchHistoryViewController.swift */; };
DBF1D257269DBAC600C1C08A /* SearchDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF1D256269DBAC600C1C08A /* SearchDetailViewModel.swift */; };
DBF3B73F2733EAED00E21627 /* local-codes.json in Resources */ = {isa = PBXBuildFile; fileRef = DBF3B73E2733EAED00E21627 /* local-codes.json */; };
DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */; };
DBF7A0FC26830C33004176A2 /* FPSIndicator in Frameworks */ = {isa = PBXBuildFile; productRef = DBF7A0FB26830C33004176A2 /* FPSIndicator */; };
DBF8AE16263293E400C9C23C /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF8AE15263293E400C9C23C /* NotificationService.swift */; };
DBF8AE1A263293E400C9C23C /* NotificationService.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DBF8AE13263293E400C9C23C /* NotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
@ -1426,6 +1428,8 @@
DBF1D24D269DAF5D00C1C08A /* SearchDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchDetailViewController.swift; sourceTree = "<group>"; };
DBF1D250269DB01200C1C08A /* SearchHistoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHistoryViewController.swift; sourceTree = "<group>"; };
DBF1D256269DBAC600C1C08A /* SearchDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchDetailViewModel.swift; sourceTree = "<group>"; };
DBF3B73E2733EAED00E21627 /* local-codes.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "local-codes.json"; sourceTree = "<group>"; };
DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLocalCode.swift; sourceTree = "<group>"; };
DBF53F5F25C14E88008AAC7B /* Mastodon.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = Mastodon.xctestplan; path = Mastodon/Mastodon.xctestplan; sourceTree = "<group>"; };
DBF53F6025C14E9D008AAC7B /* MastodonSDK.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MastodonSDK.xctestplan; sourceTree = "<group>"; };
DBF8AE13263293E400C9C23C /* NotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
@ -2212,6 +2216,7 @@
isa = PBXGroup;
children = (
164F0EBB267D4FE400249499 /* BoopSound.caf */,
DBF3B73E2733EAED00E21627 /* local-codes.json */,
DB427DDE25BAA00100D1B89D /* Assets.xcassets */,
DB118A8125E4B6E600FAB162 /* Preview Assets.xcassets */,
DB564BCE269F2F83001E39A7 /* Localizable.stringsdict */,
@ -3146,6 +3151,7 @@
DBBC24D626A54BCB00398BB9 /* MastodonRegex.swift */,
DBBC24D826A54BCB00398BB9 /* MastodonMetricFormatter.swift */,
DBFEF07626A691FB006D7ED1 /* MastodonAuthenticationBox.swift */,
DBF3B7402733EB9400E21627 /* MastodonLocalCode.swift */,
);
path = Helper;
sourceTree = "<group>";
@ -3663,6 +3669,7 @@
DB427DDF25BAA00100D1B89D /* Assets.xcassets in Resources */,
DB427DDD25BAA00100D1B89D /* Main.storyboard in Resources */,
DBA4B0F626C269880077136E /* Intents.stringsdict in Resources */,
DBF3B73F2733EAED00E21627 /* local-codes.json in Resources */,
DB118A8225E4B6E600FAB162 /* Preview Assets.xcassets in Resources */,
DB2B3ABC25E37E15007045F9 /* InfoPlist.strings in Resources */,
DB68A05D25E9055900CFDF14 /* Settings.bundle in Resources */,
@ -4400,6 +4407,7 @@
2D38F1FE25CD481700561493 /* StatusProvider.swift in Sources */,
DB1EE7B2267F9525000CC337 /* StatusProvider+StatusNodeDelegate.swift in Sources */,
5B24BBE2262DB19100A9381B /* APIService+Report.swift in Sources */,
DBF3B7412733EB9400E21627 /* MastodonLocalCode.swift in Sources */,
DB4F096A269EDAD200D62E92 /* SearchResultViewModel+State.swift in Sources */,
5BB04FF5262F0E6D0043BFF6 /* ReportSection.swift in Sources */,
DBA94436265CBB7400C537E1 /* ProfileFieldItem.swift in Sources */,

View File

@ -0,0 +1,12 @@
//
// MastodonLocalCode.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-11-4.
//
import Foundation
// https://github.com/gunchleoc/mastodon/blob/ed6153b8f24d3a8f5a124cc95683bd1f20aec882/app/helpers/settings_helper.rb
// last update 2021/11/4
typealias MastodonLocalCode = [String: String]

View File

@ -0,0 +1,80 @@
{
"af": "Afrikaans",
"ar": "العربية",
"ast": "Asturianu",
"bg": "Български",
"bn": "বাংলা",
"br": "Breton",
"ca": "Català",
"co": "Corsu",
"cs": "Čeština",
"cy": "Cymraeg",
"da": "Dansk",
"de": "Deutsch",
"el": "Ελληνικά",
"en": "English",
"eo": "Esperanto",
"es-AR": "Español (Argentina)",
"es": "Español",
"et": "Eesti",
"eu": "Euskara",
"fa": "فارسی",
"fi": "Suomi",
"fr": "Français",
"ga": "Gaeilge",
"gd": "Gàidhlig",
"gl": "Galego",
"he": "עברית",
"hi": "हिन्दी",
"hr": "Hrvatski",
"hu": "Magyar",
"hy": "Հայերեն",
"id": "Bahasa Indonesia",
"io": "Ido",
"is": "Íslenska",
"it": "Italiano",
"ja": "日本語",
"ka": "ქართული",
"kab": "Taqbaylit",
"kk": "Қазақша",
"kn": "ಕನ್ನಡ",
"ko": "한국어",
"ku": "سۆرانی",
"lt": "Lietuvių",
"lv": "Latviešu",
"mk": "Македонски",
"ml": "മലയാളം",
"mr": "मराठी",
"ms": "Bahasa Melayu",
"nl": "Nederlands",
"nn": "Nynorsk",
"no": "Norsk",
"oc": "Occitan",
"pl": "Polski",
"pt-BR": "Português (Brasil)",
"pt-PT": "Português (Portugal)",
"pt": "Português",
"ro": "Română",
"ru": "Русский",
"sa": "संस्कृतम्",
"sc": "Sardu",
"si": "සිංහල",
"sk": "Slovenčina",
"sl": "Slovenščina",
"sq": "Shqip",
"sr-Latn": "Srpski (latinica)",
"sr": "Српски",
"sv": "Svenska",
"ta": "தமிழ்",
"te": "తెలుగు",
"th": "ไทย",
"tr": "Türkçe",
"uk": "Українська",
"ur": "اُردُو",
"vi": "Tiếng Việt",
"zgh": "ⵜⴰⵎⴰⵣⵉⵖⵜ",
"zh-CN": "简体中文",
"zh-HK": "繁體中文(香港)",
"zh-TW": "繁體中文(臺灣)",
"zh": "中文"
}

View File

@ -15,6 +15,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
var disposeBag = Set<AnyCancellable>()
var observations = Set<NSKeyValueObservation>()
private(set) lazy var viewModel = WelcomeViewModel(context: context)
let welcomeIllustrationView = WelcomeIllustrationView()
@ -23,7 +24,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:)))
private(set) lazy var logoImageView: UIImageView = {
let image = view.traitCollection.userInterfaceIdiom == .phone ? Asset.Scene.Welcome.mastodonLogo.image : Asset.Scene.Welcome.mastodonLogoBlackLarge.image
let image = Asset.Scene.Welcome.mastodonLogo.image
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
@ -40,15 +41,15 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
return label
}()
private(set) lazy var signUpButton: PrimaryActionButton = {
private(set) lazy var signUpButton: PrimaryActionButton = {
let button = PrimaryActionButton()
button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false
button.setTitle(L10n.Common.Controls.Actions.signUp, for: .normal)
let backgroundImageColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? .white : Asset.Colors.brandBlue.color
let backgroundImageHighlightedColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? UIColor(white: 0.8, alpha: 1.0) : Asset.Colors.brandBlueDarken20.color
let backgroundImageColor: UIColor = .white
let backgroundImageHighlightedColor: UIColor = UIColor(white: 0.8, alpha: 1.0)
button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal)
button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted)
let titleColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? Asset.Colors.brandBlue.color : UIColor.white
let titleColor: UIColor = Asset.Colors.brandBlue.color
button.setTitleColor(titleColor, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
@ -58,7 +59,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
let button = UIButton(type: .system)
button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold))
button.setTitle(L10n.Common.Controls.Actions.signIn, for: .normal)
let titleColor: UIColor = traitCollection.userInterfaceIdiom == .phone ? UIColor.white.withAlphaComponent(0.8) : Asset.Colors.brandBlue.color
let titleColor: UIColor = UIColor.white.withAlphaComponent(0.8)
button.setTitleColor(titleColor, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
@ -75,6 +76,8 @@ extension WelcomeViewController {
override func viewDidLoad() {
super.viewDidLoad()
// preferredContentSize = CGSize(width: 547, height: 678)
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.largeTitleDisplayMode = .never
view.overrideUserInterfaceStyle = .light
@ -106,16 +109,31 @@ extension WelcomeViewController {
self.navigationItem.leftBarButtonItem = needsShowDismissEntry ? self.dismissBarButtonItem : nil
}
.store(in: &disposeBag)
view.observe(\.frame, options: [.initial, .new]) { [weak self] view, _ in
guard let self = self else { return }
switch view.traitCollection.userInterfaceIdiom {
case .phone:
break
default:
self.welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.isHidden = view.frame.height < 800
}
}
.store(in: &observations)
}
override func viewSafeAreaInsetsDidChange() {
super.viewSafeAreaInsetsDidChange()
// shift illustration down for non-notch phone
var overlap: CGFloat = 5
// shift illustration down for non-notch phone
if view.safeAreaInsets.bottom == 0 {
overlap += 56
}
// shift illustration down for iPad modal
if UIDevice.current.userInterfaceIdiom != .phone {
overlap += 20
}
welcomeIllustrationViewBottomAnchorLayoutConstraint?.constant = overlap
}
@ -137,85 +155,80 @@ extension WelcomeViewController {
}
// set illustration for phone
if traitCollection.userInterfaceIdiom == .phone {
guard welcomeIllustrationView.superview == nil else {
return
}
welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false
welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5)
view.addSubview(welcomeIllustrationView)
NSLayoutConstraint.activate([
view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15),
welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15),
welcomeIllustrationViewBottomAnchorLayoutConstraint!
])
welcomeIllustrationView.cloudBaseImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5)
)
welcomeIllustrationView.rightHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10)
)
welcomeIllustrationView.leftHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15)
)
welcomeIllustrationView.centerHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25)
)
let topPaddingView = UIView()
topPaddingView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(topPaddingView)
NSLayoutConstraint.activate([
topPaddingView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor),
topPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor),
topPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor),
])
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(welcomeIllustrationView.elephantOnAirplaneWithContrailImageView)
NSLayoutConstraint.activate([
view.leftAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 12), // add 12pt bleeding
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor),
// make a little bit large
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.84),
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.heightAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor, multiplier: 105.0/318.0),
])
let bottomPaddingView = UIView()
bottomPaddingView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bottomPaddingView)
NSLayoutConstraint.activate([
bottomPaddingView.topAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.bottomAnchor),
bottomPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor),
bottomPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor),
bottomPaddingView.bottomAnchor.constraint(equalTo: view.centerYAnchor),
bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 4),
])
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt)
)
view.bringSubviewToFront(logoImageView)
view.bringSubviewToFront(sloganLabel)
}
// set slogan for non-phone
if traitCollection.userInterfaceIdiom != .phone {
guard sloganLabel.superview == nil else {
return
}
view.addSubview(sloganLabel)
NSLayoutConstraint.activate([
sloganLabel.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 16),
view.readableContentGuide.trailingAnchor.constraint(equalTo: sloganLabel.trailingAnchor, constant: 16),
sloganLabel.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 168),
])
guard welcomeIllustrationView.superview == nil else {
return
}
view.bringSubviewToFront(sloganLabel)
welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false
welcomeIllustrationViewBottomAnchorLayoutConstraint = welcomeIllustrationView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 5)
view.addSubview(welcomeIllustrationView)
NSLayoutConstraint.activate([
view.leftAnchor.constraint(equalTo: welcomeIllustrationView.leftAnchor, constant: 15),
welcomeIllustrationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 15),
welcomeIllustrationViewBottomAnchorLayoutConstraint!
])
welcomeIllustrationView.cloudBaseImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -5, maxX: 5, minY: -5, maxY: 5)
)
welcomeIllustrationView.rightHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -15, maxX: 25, minY: -10, maxY: 10)
)
welcomeIllustrationView.leftHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -25, maxX: 15, minY: -15, maxY: 15)
)
welcomeIllustrationView.centerHillImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -14, maxX: 14, minY: -5, maxY: 25)
)
let topPaddingView = UIView()
topPaddingView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(topPaddingView)
NSLayoutConstraint.activate([
topPaddingView.topAnchor.constraint(equalTo: logoImageView.bottomAnchor),
topPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor),
topPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor),
])
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(welcomeIllustrationView.elephantOnAirplaneWithContrailImageView)
NSLayoutConstraint.activate([
view.leftAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.leftAnchor, constant: 12), // add 12pt bleeding
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.topAnchor.constraint(equalTo: topPaddingView.bottomAnchor),
// make a little bit large
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.84),
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.heightAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.widthAnchor, multiplier: 105.0/318.0),
])
let bottomPaddingView = UIView()
bottomPaddingView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bottomPaddingView)
NSLayoutConstraint.activate([
bottomPaddingView.topAnchor.constraint(equalTo: welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.bottomAnchor),
bottomPaddingView.leadingAnchor.constraint(equalTo: logoImageView.leadingAnchor),
bottomPaddingView.trailingAnchor.constraint(equalTo: logoImageView.trailingAnchor),
bottomPaddingView.bottomAnchor.constraint(equalTo: view.centerYAnchor),
bottomPaddingView.heightAnchor.constraint(equalTo: topPaddingView.heightAnchor, multiplier: 4),
])
welcomeIllustrationView.elephantOnAirplaneWithContrailImageView.addMotionEffect(
UIInterpolatingMotionEffect.motionEffect(minX: -20, maxX: 12, minY: -20, maxY: 12) // maxX should not larger then the bleeding (12pt)
)
view.bringSubviewToFront(logoImageView)
view.bringSubviewToFront(sloganLabel)
// set slogan for non-phone
// if traitCollection.userInterfaceIdiom != .phone {
// guard sloganLabel.superview == nil else {
// return
// }
// view.addSubview(sloganLabel)
// NSLayoutConstraint.activate([
// sloganLabel.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 16),
// view.readableContentGuide.trailingAnchor.constraint(equalTo: sloganLabel.trailingAnchor, constant: 16),
// sloganLabel.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 168),
// ])
// }
}
}
@ -261,12 +274,12 @@ extension WelcomeViewController: UIAdaptivePresentationControllerDelegate {
// make underneath view controller alive to fix layout issue due to view life cycle
return .fullScreen
default:
switch traitCollection.horizontalSizeClass {
case .regular:
return .pageSheet
default:
return .fullScreen
}
return .formSheet
// switch traitCollection.horizontalSizeClass {
// case .regular:
// default:
// return .fullScreen
// }
}
}