Bark/Controller/HomeViewController.swift
2025-05-15 15:22:30 +08:00

240 lines
9.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// ViewController.swift
// Bark
//
// Created by huangfeng on 2018/3/7.
// Copyright © 2018 Fin. All rights reserved.
//
import Material
import RxCocoa
import RxDataSources
import RxSwift
import UIKit
import UserNotifications
class HomeViewController: BaseViewController<HomeViewModel> {
let newButton: BKButton = {
let btn = BKButton()
btn.setImage(Icon.add, for: .normal)
btn.imageView?.tintColor = BKColor.grey.darken4
btn.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
return btn
}()
let serversButton: BKButton = {
let btn = BKButton()
btn.setImage(UIImage(named: "baseline_filter_drama_black_24pt"), for: .normal)
btn.imageView?.tintColor = BKColor.grey.darken4
btn.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
return btn
}()
let startButton: FABButton = {
let button = FABButton(title: NSLocalizedString("RegisterDevice"))
button.backgroundColor = BKColor.grey.lighten5
button.transition([.scale(0.75), .opacity(0)])
return button
}()
let tableView: UITableView = {
let tableView = UITableView()
tableView.separatorStyle = .none
tableView.backgroundColor = BKColor.background.primary
tableView.register(PreviewCardCell.self, forCellReuseIdentifier: "\(PreviewCardCell.self)")
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0)
return tableView
}()
override func makeUI() {
self.view.backgroundColor = BKColor.background.primary
navigationItem.setBarButtonItems(items: [
UIBarButtonItem(customView: newButton),
UIBarButtonItem(customView: serversButton)
], position: .right)
self.view.addSubview(self.tableView)
self.tableView.snp.makeConstraints { make in
make.top.right.bottom.left.equalToSuperview()
}
self.view.addSubview(self.startButton)
self.startButton.snp.makeConstraints { make in
make.width.height.equalTo(150)
make.centerX.equalToSuperview()
make.centerY.equalToSuperview().offset(-50)
}
Client.shared.currentTabBarController?
.tabBarItemDidClick
.filter { $0 == .service }
.subscribe(onNext: { [weak self] _ in
self?.tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true)
}).disposed(by: self.rx.disposeBag)
}
override func bindViewModel() {
// APP
let authorizationStatus = Single<UNAuthorizationStatus>.create { single -> Disposable in
UNUserNotificationCenter.current().getNotificationSettings { settings in
single(.success(settings.authorizationStatus))
}
return Disposables.create()
}
//
let startRequestAuthorization: () -> Observable<Bool> = {
Single<Bool>.create { single -> Disposable in
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge, .criticalAlert, .provisional], completionHandler: { (_ granted: Bool, _: Error?) in
single(.success(granted))
})
return Disposables.create()
}
.asObservable()
}
let output = viewModel.transform(
input: HomeViewModel.Input(
addCustomServerTap: newButton.rx.tap.asDriver(),
serverListTap: serversButton.rx.tap.asDriver(),
viewDidAppear: self.rx.methodInvoked(#selector(viewDidAppear(_:)))
.map { _ in () }
.asDriver(onErrorDriveWith: .empty()),
start: self.startButton.rx.tap.asDriver(),
clientState: Client.shared.state.asDriver(),
authorizationStatus: authorizationStatus,
startRequestAuthorizationCreator: startRequestAuthorization
)
)
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String, PreviewCardCellViewModel>> { _, tableView, _, item -> UITableViewCell in
if let cell = tableView.dequeueReusableCell(withIdentifier: "\(PreviewCardCell.self)") as? PreviewCardCell {
cell.bindViewModel(model: item)
return cell
}
return UITableViewCell()
}
//
output.title
.drive(self.navigationItem.rx.title)
.disposed(by: rx.disposeBag)
// TableView
output.previews
.drive(self.tableView.rx.items(dataSource: dataSource))
.disposed(by: rx.disposeBag)
//
output.push
.drive(onNext: { [weak self] viewModel in
self?.pushViewModel(viewModel: viewModel)
})
.disposed(by: rx.disposeBag)
output.present
.drive(onNext: { [weak self] viewModel in
self?.presentViewModel(viewModel: viewModel)
})
.disposed(by: rx.disposeBag)
// ping clienState
output.clienStateChanged
.drive(Client.shared.state)
.disposed(by: rx.disposeBag)
//
output.tableViewHidden
.map { !$0 }
.drive(self.tableView.rx.isHidden)
.disposed(by: rx.disposeBag)
output.tableViewHidden
.drive(self.startButton.rx.isHidden)
.disposed(by: rx.disposeBag)
//
output.registerForRemoteNotifications.drive(onNext: {
UIApplication.shared.registerForRemoteNotifications()
})
.disposed(by: rx.disposeBag)
//
output.showSnackbar
.drive(onNext: { [weak self] text in
self?.showSnackbar(text: text)
})
.disposed(by: rx.disposeBag)
// FAQ
output.alertServerError
.drive(onNext: { [weak self] error in
self?.alertServerError(error: error)
})
.disposed(by: rx.disposeBag)
// startButton
output.startButtonEnable
.drive(self.startButton.rx.isEnabled)
.disposed(by: rx.disposeBag)
//
output.copy
.drive(onNext: { [weak self] text in
UIPasteboard.general.string = text
self?.showSnackbar(text: NSLocalizedString("Copy"))
})
.disposed(by: rx.disposeBag)
//
output.preview
.drive(onNext: { url in
UIApplication.shared.open(url, options: [:], completionHandler: nil)
})
.disposed(by: rx.disposeBag)
// TableView
output.reloadData
.drive(onNext: { [weak self] in
self?.tableView.reloadData()
})
.disposed(by: rx.disposeBag)
}
func pushViewModel(viewModel: ViewModel) {
var viewController: UIViewController?
if let viewModel = viewModel as? NewServerViewModel {
viewController = NewServerViewController(viewModel: viewModel)
} else if let viewModel = viewModel as? SoundsViewModel {
viewController = SoundsViewController(viewModel: viewModel)
} else if let viewModel = viewModel as? CryptoSettingViewModel {
self.navigationController?.present(BarkNavigationController(rootViewController: CryptoSettingController(viewModel: viewModel)), animated: true)
return
}
if let viewController = viewController {
self.navigationController?.pushViewController(viewController, animated: true)
}
}
func presentViewModel(viewModel: ViewModel) {
if let viewModel = viewModel as? ServerListViewModel {
let controller = BarkSnackbarController(
rootViewController: BarkNavigationController(
rootViewController: ServerListViewController(viewModel: viewModel)))
self.navigationController?.present(controller, animated: true, completion: nil)
}
}
func alertServerError(error: String) {
let alertController = UIAlertController(title: NSLocalizedString("ServerError"), message: error, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("faq"), style: .default, handler: { [weak self] _ in
guard let url = try? NSLocalizedString("faqUrl").asURL() else {
return
}
self?.navigationController?.present(BarkSFSafariViewController(url: url), animated: true, completion: nil)
}))
alertController.addAction(UIAlertAction(title: NSLocalizedString("Cancel"), style: .cancel, handler: nil))
self.present(alertController, animated: true, completion: nil)
}
}