mirror of
https://github.com/Finb/Bark.git
synced 2025-12-08 21:36:01 +00:00
添加 ServerManager,支持多服务器。
This commit is contained in:
parent
043bab5569
commit
8572970c62
@ -107,7 +107,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
Client.shared.deviceToken.accept(deviceTokenString)
|
||||
|
||||
// 注册设备
|
||||
Client.shared.bindDeviceToken()
|
||||
ServerManager.shared.syncAllServers()
|
||||
}
|
||||
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
@ -206,9 +206,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
if (Client.shared.key?.count ?? 0) <= 0 {
|
||||
Client.shared.bindDeviceToken()
|
||||
}
|
||||
ServerManager.shared.syncAllServers()
|
||||
|
||||
// 设置 -1 可以清除应用角标,但不清除通知中心的推送
|
||||
// 设置 0 会将通知中心的所有推送一起清空掉
|
||||
|
||||
@ -10,10 +10,14 @@ import DefaultsKit
|
||||
import UIKit
|
||||
|
||||
enum BarkSettingKey: String {
|
||||
/// 存放key
|
||||
/// 存放key , 1.2.6 版本`之后`不再使用
|
||||
case key = "me.fin.bark.key"
|
||||
case servers = "me.fin.bark.servers"
|
||||
|
||||
/// 1.2.6 版本`之前`保存当前 server 的 key,不再使用
|
||||
case currentServer = "me.fin.bark.servers.current"
|
||||
/// 1.2.6 版本`之后`用于保存 server 的 id
|
||||
case currentServerId = "me.fin.bark.servers.currentServerId"
|
||||
|
||||
case selectedViewControllerIndex = "me.fin.bark.selectedViewControllerIndex"
|
||||
}
|
||||
|
||||
@ -38,56 +38,15 @@ class Client: NSObject {
|
||||
return version
|
||||
}()
|
||||
|
||||
private var _key: String?
|
||||
var key: String? {
|
||||
get {
|
||||
if _key == nil, let aKey = Settings[.key] {
|
||||
_key = aKey
|
||||
}
|
||||
return _key
|
||||
}
|
||||
set {
|
||||
_key = newValue
|
||||
Settings[.key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
enum ClienState {
|
||||
enum ClienState: Int, Codable {
|
||||
case ok
|
||||
case unRegister
|
||||
case serverError
|
||||
}
|
||||
|
||||
var deviceToken = BehaviorRelay<String?>(value: nil)
|
||||
var state = BehaviorRelay<ClienState>(value: .ok)
|
||||
|
||||
var dispose: Disposable?
|
||||
func bindDeviceToken() {
|
||||
if let token = deviceToken.value, token.count > 0 {
|
||||
dispose?.dispose()
|
||||
|
||||
dispose = BarkApi.provider
|
||||
.request(.register(
|
||||
key: key,
|
||||
devicetoken: token))
|
||||
.filterResponseError()
|
||||
.map { json -> ClienState in
|
||||
switch json {
|
||||
case .success(let json):
|
||||
if let key = json["data", "key"].rawString() {
|
||||
Client.shared.key = key
|
||||
return .ok
|
||||
}
|
||||
else {
|
||||
return .serverError
|
||||
}
|
||||
case .failure:
|
||||
return .serverError
|
||||
}
|
||||
}
|
||||
.bind(to: state)
|
||||
}
|
||||
}
|
||||
|
||||
func registerForRemoteNotifications() {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { (_ granted: Bool, _: Error?) -> Void in
|
||||
|
||||
@ -10,20 +10,27 @@ import UIKit
|
||||
|
||||
enum BarkApi {
|
||||
case ping(baseURL: String?)
|
||||
case register(key: String?, devicetoken: String) // 注册设备
|
||||
case register(address: String, key: String?, devicetoken: String) // 注册设备
|
||||
}
|
||||
|
||||
extension BarkApi: BarkTargetType {
|
||||
var baseURL: URL {
|
||||
if case let .ping(urlStr) = self, let url = URL(string: urlStr ?? "") {
|
||||
return url
|
||||
switch self {
|
||||
case let .ping(urlStr):
|
||||
if let url = URL(string: urlStr ?? "") {
|
||||
return url
|
||||
}
|
||||
case let .register(address, _, _):
|
||||
if let url = try? address.asURL() {
|
||||
return url
|
||||
}
|
||||
}
|
||||
return URL(string: ServerManager.shared.currentAddress)!
|
||||
return try! ServerManager.shared.currentServer.address.asURL()
|
||||
}
|
||||
|
||||
var parameters: [String: Any]? {
|
||||
switch self {
|
||||
case let .register(key, devicetoken):
|
||||
case let .register(_, key, devicetoken):
|
||||
var params = ["devicetoken": devicetoken]
|
||||
if let key = key {
|
||||
params["key"] = key
|
||||
|
||||
@ -23,7 +23,7 @@ extension BarkTargetType {
|
||||
}
|
||||
|
||||
var baseURL: URL {
|
||||
return URL(string: ServerManager.shared.currentAddress)!
|
||||
return URL(string: ServerManager.shared.currentServer.address)!
|
||||
}
|
||||
|
||||
var method: Moya.Method {
|
||||
@ -54,21 +54,6 @@ extension BarkTargetType {
|
||||
return Task.requestParameters(parameters: defaultParameters, encoding: parameterEncoding)
|
||||
}
|
||||
|
||||
static var networkActivityPlugin: PluginType {
|
||||
return NetworkActivityPlugin { change, _ in
|
||||
switch change {
|
||||
case .began:
|
||||
dispatch_sync_safely_main_queue {
|
||||
UIApplication.shared.isNetworkActivityIndicatorVisible = true
|
||||
}
|
||||
case .ended:
|
||||
dispatch_sync_safely_main_queue {
|
||||
UIApplication.shared.isNetworkActivityIndicatorVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 实现此协议的类,将自动获得用该类实例化的 provider 对象
|
||||
static var provider: RxSwift.Reactive<MoyaProvider<Self>> {
|
||||
let key = "\(Self.self)"
|
||||
@ -82,7 +67,7 @@ extension BarkTargetType {
|
||||
|
||||
/// 不被全局持有的 Provider ,使用时,需要持有它,否则将立即释放,请求随即终止
|
||||
static var weakProvider: RxSwift.Reactive<MoyaProvider<Self>> {
|
||||
var plugins: [PluginType] = [networkActivityPlugin]
|
||||
var plugins: [PluginType] = []
|
||||
#if DEBUG
|
||||
plugins.append(LogPlugin())
|
||||
#endif
|
||||
|
||||
@ -6,43 +6,95 @@
|
||||
// Copyright © 2018年 Fin. All rights reserved.
|
||||
//
|
||||
|
||||
import RxSwift
|
||||
import SwiftUI
|
||||
import UIKit
|
||||
|
||||
let defaultServer = "https://api.day.app"
|
||||
|
||||
class Server: Codable {
|
||||
let id: String
|
||||
let address: String
|
||||
var key: String
|
||||
var state: Client.ClienState
|
||||
init(id: String = UUID().uuidString, address: String, key: String, state: Client.ClienState = .ok) {
|
||||
self.id = id
|
||||
self.address = address
|
||||
self.key = key
|
||||
self.state = state
|
||||
}
|
||||
}
|
||||
|
||||
class ServerManager: NSObject {
|
||||
static let shared = ServerManager()
|
||||
override private init() {
|
||||
if let servers: Set<String> = Settings[.servers] {
|
||||
if let servers: [Server] = Settings[.servers] {
|
||||
self.servers = servers
|
||||
}
|
||||
|
||||
if servers.count <= 0 {
|
||||
servers = [Server(id: UUID().uuidString, address: defaultServer, key: "")]
|
||||
}
|
||||
self.currentServer = servers[0]
|
||||
|
||||
super.init()
|
||||
|
||||
// 将老版本数据转换成新版本
|
||||
if let address = Settings[.currentServer] {
|
||||
self.currentAddress = address
|
||||
let key = Settings[.key] ?? ""
|
||||
let server = Server(id: UUID().uuidString, address: address, key: key)
|
||||
|
||||
self.servers = []
|
||||
self.addServer(server: server)
|
||||
|
||||
Settings[.currentServerId] = server.id
|
||||
|
||||
// 清空老版本数据
|
||||
Settings[.currentServer] = nil
|
||||
Settings[.key] = nil
|
||||
}
|
||||
|
||||
if let currentServerId = Settings[.currentServerId] {
|
||||
self.setCurrentServer(serverId: currentServerId)
|
||||
}
|
||||
}
|
||||
|
||||
/// 所有的 server
|
||||
var servers: [Server] = []
|
||||
/// 当前选中的 server ,在教程页显示。
|
||||
private(set) var currentServer: Server
|
||||
|
||||
/// 更改当前选中的 server
|
||||
func setCurrentServer(serverId: String) {
|
||||
if let server = servers.first(where: { $0.id == serverId }) {
|
||||
currentServer = server
|
||||
}
|
||||
else {
|
||||
self.currentAddress = self.servers.first ?? defaultServer
|
||||
currentServer = servers.first!
|
||||
}
|
||||
super.init()
|
||||
Settings[.currentServerId] = serverId
|
||||
}
|
||||
|
||||
var servers: Set<String> = [defaultServer]
|
||||
var currentAddress: String {
|
||||
didSet {
|
||||
Settings[.currentServer] = currentAddress
|
||||
}
|
||||
/// 添加新的 server
|
||||
func addServer(server: Server) {
|
||||
self.servers.append(server)
|
||||
saveServers()
|
||||
}
|
||||
|
||||
func addServer(server: String) {
|
||||
self.servers.insert(server)
|
||||
Settings[.servers] = self.servers
|
||||
}
|
||||
|
||||
func removeServer(server: String) {
|
||||
self.servers.remove(server)
|
||||
/// 移除 server,移除后如果 server 为`空`, `会新增一个默认server`
|
||||
func removeServer(server: Server) {
|
||||
self.servers.removeAll { $0.id == server.id }
|
||||
if self.servers.count <= 0 {
|
||||
self.servers.insert(defaultServer)
|
||||
self.servers.append(
|
||||
Server(id: UUID().uuidString, address: defaultServer, key: "")
|
||||
)
|
||||
self.setCurrentServer(serverId: self.servers[0].id)
|
||||
}
|
||||
saveServers()
|
||||
}
|
||||
|
||||
/// 保存 servers
|
||||
func saveServers() {
|
||||
Settings[.servers] = self.servers
|
||||
}
|
||||
|
||||
@ -50,4 +102,55 @@ class ServerManager: NSObject {
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
var dispose: Disposable?
|
||||
/// 同步所有 server
|
||||
func syncAllServers() {
|
||||
guard let token = Client.shared.deviceToken.value, token.count > 0 else {
|
||||
return
|
||||
}
|
||||
dispose?.dispose()
|
||||
|
||||
let apis = servers.map { server in
|
||||
BarkApi.provider.request(
|
||||
.register(
|
||||
address: server.address,
|
||||
key: server.key,
|
||||
devicetoken: token))
|
||||
.filterResponseError()
|
||||
.map { result -> (Server, String, Client.ClienState) in
|
||||
|
||||
switch result {
|
||||
case .success(let json):
|
||||
if let key = json["data", "key"].rawString() {
|
||||
return (server, key, .ok)
|
||||
}
|
||||
else {
|
||||
return (server, "", .serverError)
|
||||
}
|
||||
case .failure:
|
||||
return (server, "", .serverError)
|
||||
}
|
||||
}.catch { _ in
|
||||
Observable.just((server, "", .serverError))
|
||||
}
|
||||
}
|
||||
|
||||
dispose = Observable
|
||||
.merge(apis)
|
||||
.subscribe { result in
|
||||
// 更新所有的 server 状态
|
||||
result.0.key = result.1
|
||||
result.0.state = result.2
|
||||
|
||||
// 通知客户端 当前 server 状态改变
|
||||
if result.0.id == self.currentServer.id {
|
||||
Client.shared.state.accept(result.2)
|
||||
}
|
||||
} onError: { _ in
|
||||
|
||||
} onCompleted: {
|
||||
self.saveServers()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ class HomeViewModel: ViewModel, ViewModelType {
|
||||
}()
|
||||
|
||||
func transform(input: Input) -> Output {
|
||||
let title = BehaviorRelay(value: URL(string: ServerManager.shared.currentAddress)?.host ?? "")
|
||||
let title = BehaviorRelay(value: URL(string: ServerManager.shared.currentServer.address)?.host ?? "")
|
||||
|
||||
let sectionModel = SectionModel(
|
||||
model: "previews",
|
||||
@ -127,7 +127,7 @@ class HomeViewModel: ViewModel, ViewModelType {
|
||||
let clienState = input.viewDidAppear
|
||||
.asObservable().flatMapLatest { _ -> Observable<Result<JSON, ApiError>> in
|
||||
BarkApi.provider
|
||||
.request(.ping(baseURL: ServerManager.shared.currentAddress))
|
||||
.request(.ping(baseURL: ServerManager.shared.currentServer.address))
|
||||
.filterResponseError()
|
||||
}
|
||||
.map { response -> Client.ClienState in
|
||||
|
||||
@ -76,8 +76,10 @@ class NewServerViewModel: ViewModel, ViewModelType {
|
||||
guard let strongSelf = self else { return }
|
||||
switch response {
|
||||
case .success:
|
||||
ServerManager.shared.currentAddress = strongSelf.url
|
||||
Client.shared.bindDeviceToken()
|
||||
let server = Server(address: strongSelf.url, key: "")
|
||||
ServerManager.shared.addServer(server: server)
|
||||
ServerManager.shared.setCurrentServer(serverId: server.id)
|
||||
ServerManager.shared.syncAllServers()
|
||||
|
||||
strongSelf.pop.accept(strongSelf.url)
|
||||
showSnackbar.accept(NSLocalizedString("AddedSuccessfully"))
|
||||
|
||||
@ -65,14 +65,14 @@ class PreviewCardCellViewModel: ViewModel {
|
||||
if UIScreen.main.bounds.size.width <= 320 {
|
||||
fontSize = 11
|
||||
}
|
||||
let serverUrl = URL(string: ServerManager.shared.currentAddress)!
|
||||
let serverUrl = URL(string: ServerManager.shared.currentServer.address)!
|
||||
let attrStr = NSMutableAttributedString(string: "")
|
||||
attrStr.append(NSAttributedString(string: serverUrl.absoluteString, attributes: [
|
||||
NSAttributedString.Key.foregroundColor: BKColor.grey.darken4,
|
||||
NSAttributedString.Key.font: RobotoFont.regular(with: fontSize)
|
||||
]))
|
||||
|
||||
attrStr.append(NSAttributedString(string: "/\(Client.shared.key ?? "Your Key")", attributes: [
|
||||
let key = ServerManager.shared.currentServer.key
|
||||
attrStr.append(NSAttributedString(string: "/\(key.count > 0 ? key : "Your Key")", attributes: [
|
||||
NSAttributedString.Key.foregroundColor: BKColor.grey.darken3,
|
||||
NSAttributedString.Key.font: RobotoFont.regular(with: fontSize)
|
||||
]))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user