forked from shadowfacts/Tusker
Add "Add Account" placeholder to fast account switcher
This commit is contained in:
parent
2f7c7bae5e
commit
2cfefc9432
|
@ -17,6 +17,10 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
private var launchActivity: NSUserActivity?
|
private var launchActivity: NSUserActivity?
|
||||||
|
|
||||||
|
var rootViewController: TuskerRootViewController? {
|
||||||
|
window?.rootViewController as? TuskerRootViewController
|
||||||
|
}
|
||||||
|
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||||
guard let windowScene = scene as? UIWindowScene else { return }
|
guard let windowScene = scene as? UIWindowScene else { return }
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
if url.host == "x-callback-url" {
|
if url.host == "x-callback-url" {
|
||||||
_ = XCBManager.handle(url: url)
|
_ = XCBManager.handle(url: url)
|
||||||
} else if var components = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
} else if var components = URLComponents(url: url, resolvingAgainstBaseURL: false),
|
||||||
let rootViewController = window!.rootViewController as? TuskerRootViewController {
|
let rootViewController = rootViewController {
|
||||||
components.scheme = "https"
|
components.scheme = "https"
|
||||||
let query = components.string!
|
let query = components.string!
|
||||||
rootViewController.performSearch(query: query)
|
rootViewController.performSearch(query: query)
|
||||||
|
@ -202,6 +206,12 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showAddAccount() {
|
||||||
|
rootViewController?.presentPreferences {
|
||||||
|
NotificationCenter.default.post(name: .addAccount, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MainSceneDelegate: OnboardingViewControllerDelegate {
|
extension MainSceneDelegate: OnboardingViewControllerDelegate {
|
||||||
|
|
|
@ -101,7 +101,13 @@ class FastAccountSwitcherViewController: UIViewController {
|
||||||
|
|
||||||
private func createAccountViews() {
|
private func createAccountViews() {
|
||||||
accountsStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
accountsStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
|
||||||
accountViews = []
|
|
||||||
|
let addAccountPlaceholder = FastSwitchingAccountView()
|
||||||
|
accountsStack.addArrangedSubview(addAccountPlaceholder)
|
||||||
|
|
||||||
|
accountViews = [
|
||||||
|
addAccountPlaceholder
|
||||||
|
]
|
||||||
|
|
||||||
for account in LocalData.shared.accounts {
|
for account in LocalData.shared.accounts {
|
||||||
let accountView = FastSwitchingAccountView(account: account)
|
let accountView = FastSwitchingAccountView(account: account)
|
||||||
|
@ -122,19 +128,30 @@ class FastAccountSwitcherViewController: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func switchAccount(newIndex: Int, hapticFeedback: Bool = true) {
|
private func switchAccount(newIndex: Int, hapticFeedback: Bool = true) {
|
||||||
let account = LocalData.shared.accounts[newIndex]
|
if newIndex == 0 { // add account placeholder
|
||||||
|
|
||||||
if account.id != LocalData.shared.mostRecentAccountID {
|
|
||||||
if hapticFeedback {
|
if hapticFeedback {
|
||||||
selectionChangedFeedbackGenerator?.impactOccurred()
|
selectionChangedFeedbackGenerator?.impactOccurred()
|
||||||
}
|
}
|
||||||
selectionChangedFeedbackGenerator = nil
|
selectionChangedFeedbackGenerator = nil
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
(self.view.window!.windowScene!.delegate as! MainSceneDelegate).activateAccount(account, animated: true)
|
(self.view.window!.windowScene!.delegate as! MainSceneDelegate).showAddAccount()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
hide()
|
let account = LocalData.shared.accounts[newIndex - 1]
|
||||||
|
|
||||||
|
if account.id != LocalData.shared.mostRecentAccountID {
|
||||||
|
if hapticFeedback {
|
||||||
|
selectionChangedFeedbackGenerator?.impactOccurred()
|
||||||
|
}
|
||||||
|
selectionChangedFeedbackGenerator = nil
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
(self.view.window!.windowScene!.delegate as! MainSceneDelegate).activateAccount(account, animated: true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,6 @@ import UIKit
|
||||||
|
|
||||||
class FastSwitchingAccountView: UIView {
|
class FastSwitchingAccountView: UIView {
|
||||||
|
|
||||||
let account: LocalData.UserAccountInfo
|
|
||||||
|
|
||||||
private static let selectedColor = UIColor { (traits) in
|
private static let selectedColor = UIColor { (traits) in
|
||||||
if traits.userInterfaceStyle == .dark {
|
if traits.userInterfaceStyle == .dark {
|
||||||
return UIColor(hue: 211 / 360, saturation: 85 / 100, brightness: 100 / 100, alpha: 1)
|
return UIColor(hue: 211 / 360, saturation: 85 / 100, brightness: 100 / 100, alpha: 1)
|
||||||
|
@ -39,21 +37,32 @@ class FastSwitchingAccountView: UIView {
|
||||||
|
|
||||||
private let usernameLabel = UILabel()
|
private let usernameLabel = UILabel()
|
||||||
private let instanceLabel = UILabel()
|
private let instanceLabel = UILabel()
|
||||||
|
private let avatarImageView = UIImageView()
|
||||||
|
|
||||||
private var avatarRequest: ImageCache.Request?
|
private var avatarRequest: ImageCache.Request?
|
||||||
|
|
||||||
init(account: LocalData.UserAccountInfo) {
|
init(account: LocalData.UserAccountInfo) {
|
||||||
self.account = account
|
|
||||||
|
|
||||||
super.init(frame: .zero)
|
super.init(frame: .zero)
|
||||||
|
commonInit()
|
||||||
|
setupAccount(account: account)
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
commonInit()
|
||||||
|
setupPlaceholder()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func commonInit() {
|
||||||
usernameLabel.textColor = .white
|
usernameLabel.textColor = .white
|
||||||
usernameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .headline), size: 0)
|
usernameLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .headline), size: 0)
|
||||||
usernameLabel.text = account.username
|
|
||||||
|
|
||||||
instanceLabel.textColor = .white
|
instanceLabel.textColor = .white
|
||||||
instanceLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .subheadline), size: 0)
|
instanceLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .subheadline), size: 0)
|
||||||
instanceLabel.text = account.instanceURL.host!
|
|
||||||
|
|
||||||
let stackView = UIStackView(arrangedSubviews: [
|
let stackView = UIStackView(arrangedSubviews: [
|
||||||
usernameLabel,
|
usernameLabel,
|
||||||
|
@ -64,12 +73,11 @@ class FastSwitchingAccountView: UIView {
|
||||||
stackView.alignment = .trailing
|
stackView.alignment = .trailing
|
||||||
addSubview(stackView)
|
addSubview(stackView)
|
||||||
|
|
||||||
let avatarImageView = UIImageView()
|
|
||||||
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
|
avatarImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
avatarImageView.layer.masksToBounds = true
|
avatarImageView.layer.masksToBounds = true
|
||||||
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 40
|
avatarImageView.layer.cornerRadius = Preferences.shared.avatarStyle.cornerRadiusFraction * 40
|
||||||
avatarImageView.image = UIImage(systemName: Preferences.shared.avatarStyle == .circle ? "person.crop.circle" : "person.crop.square")
|
avatarImageView.image = UIImage(systemName: Preferences.shared.avatarStyle == .circle ? "person.crop.circle" : "person.crop.square")
|
||||||
avatarImageView.contentMode = .scaleAspectFit
|
avatarImageView.contentMode = .scaleAspectFill
|
||||||
addSubview(avatarImageView)
|
addSubview(avatarImageView)
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
@ -84,22 +92,30 @@ class FastSwitchingAccountView: UIView {
|
||||||
stackView.centerYAnchor.constraint(equalTo: avatarImageView.centerYAnchor),
|
stackView.centerYAnchor.constraint(equalTo: avatarImageView.centerYAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
updateLabelColors()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupAccount(account: LocalData.UserAccountInfo) {
|
||||||
|
usernameLabel.text = account.username
|
||||||
|
instanceLabel.text = account.instanceURL.host!
|
||||||
let controller = MastodonController.getForAccount(account)
|
let controller = MastodonController.getForAccount(account)
|
||||||
controller.getOwnAccount { [weak self] (result) in
|
controller.getOwnAccount { [weak self] (result) in
|
||||||
guard let self = self,
|
guard let self = self,
|
||||||
case let .success(account) = result,
|
case let .success(account) = result,
|
||||||
let avatar = account.avatar else { return }
|
let avatar = account.avatar else { return }
|
||||||
self.avatarRequest = ImageCache.avatars.get(avatar) { [weak avatarImageView] (_, image) in
|
self.avatarRequest = ImageCache.avatars.get(avatar) { [weak self] (_, image) in
|
||||||
guard let avatarImageView = avatarImageView, let image = image else { return }
|
guard let self = self, let image = image else { return }
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
avatarImageView.image = image
|
self.avatarImageView.image = image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
private func setupPlaceholder() {
|
||||||
fatalError("init(coder:) has not been implemented")
|
usernameLabel.text = "Add Account"
|
||||||
|
instanceLabel.isHidden = true
|
||||||
|
avatarImageView.image = UIImage(systemName: "plus")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateLabelColors() {
|
private func updateLabelColors() {
|
||||||
|
@ -113,6 +129,7 @@ class FastSwitchingAccountView: UIView {
|
||||||
}
|
}
|
||||||
usernameLabel.textColor = color
|
usernameLabel.textColor = color
|
||||||
instanceLabel.textColor = color
|
instanceLabel.textColor = color
|
||||||
|
avatarImageView.tintColor = color
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,8 +86,14 @@ extension AccountSwitchingContainerViewController: TuskerRootViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func performSearch(query: String) {
|
func performSearch(query: String) {
|
||||||
|
loadViewIfNeeded()
|
||||||
root.performSearch(query: query)
|
root.performSearch(query: query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func presentPreferences(completion: (() -> Void)?) {
|
||||||
|
loadViewIfNeeded()
|
||||||
|
root.presentPreferences(completion: completion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AccountSwitchingContainerViewController: BackgroundableViewController {
|
extension AccountSwitchingContainerViewController: BackgroundableViewController {
|
||||||
|
|
|
@ -441,6 +441,10 @@ extension MainSplitViewController: TuskerRootViewController {
|
||||||
searchViewController.searchController.searchBar.text = query
|
searchViewController.searchController.searchBar.text = query
|
||||||
searchViewController.resultsController.performSearch(query: query)
|
searchViewController.resultsController.performSearch(query: query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func presentPreferences(completion: (() -> Void)?) {
|
||||||
|
present(PreferencesNavigationController(mastodonController: mastodonController), animated: true, completion: completion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MainSplitViewController: BackgroundableViewController {
|
extension MainSplitViewController: BackgroundableViewController {
|
||||||
|
|
|
@ -262,6 +262,10 @@ extension MainTabBarViewController: TuskerRootViewController {
|
||||||
exploreController.searchController.searchBar.text = query
|
exploreController.searchController.searchBar.text = query
|
||||||
exploreController.resultsController.performSearch(query: query)
|
exploreController.resultsController.performSearch(query: query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func presentPreferences(completion: (() -> Void)?) {
|
||||||
|
present(PreferencesNavigationController(mastodonController: mastodonController), animated: true, completion: completion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MainTabBarViewController: BackgroundableViewController {
|
extension MainTabBarViewController: BackgroundableViewController {
|
||||||
|
|
|
@ -13,4 +13,5 @@ protocol TuskerRootViewController: UIViewController {
|
||||||
func select(tab: MainTabBarViewController.Tab)
|
func select(tab: MainTabBarViewController.Tab)
|
||||||
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController?
|
func getTabController(tab: MainTabBarViewController.Tab) -> UIViewController?
|
||||||
func performSearch(query: String)
|
func performSearch(query: String)
|
||||||
|
func presentPreferences(completion: (() -> Void)?)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue