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.deviceToken.accept(deviceTokenString)
|
||||||
|
|
||||||
// 注册设备
|
// 注册设备
|
||||||
Client.shared.bindDeviceToken()
|
ServerManager.shared.syncAllServers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
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) {
|
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||||
if (Client.shared.key?.count ?? 0) <= 0 {
|
ServerManager.shared.syncAllServers()
|
||||||
Client.shared.bindDeviceToken()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置 -1 可以清除应用角标,但不清除通知中心的推送
|
// 设置 -1 可以清除应用角标,但不清除通知中心的推送
|
||||||
// 设置 0 会将通知中心的所有推送一起清空掉
|
// 设置 0 会将通知中心的所有推送一起清空掉
|
||||||
|
|||||||
@ -10,10 +10,14 @@ import DefaultsKit
|
|||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
enum BarkSettingKey: String {
|
enum BarkSettingKey: String {
|
||||||
/// 存放key
|
/// 存放key , 1.2.6 版本`之后`不再使用
|
||||||
case key = "me.fin.bark.key"
|
case key = "me.fin.bark.key"
|
||||||
case servers = "me.fin.bark.servers"
|
case servers = "me.fin.bark.servers"
|
||||||
|
|
||||||
|
/// 1.2.6 版本`之前`保存当前 server 的 key,不再使用
|
||||||
case currentServer = "me.fin.bark.servers.current"
|
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"
|
case selectedViewControllerIndex = "me.fin.bark.selectedViewControllerIndex"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,56 +38,15 @@ class Client: NSObject {
|
|||||||
return version
|
return version
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var _key: String?
|
enum ClienState: Int, Codable {
|
||||||
var key: String? {
|
|
||||||
get {
|
|
||||||
if _key == nil, let aKey = Settings[.key] {
|
|
||||||
_key = aKey
|
|
||||||
}
|
|
||||||
return _key
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
_key = newValue
|
|
||||||
Settings[.key] = newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ClienState {
|
|
||||||
case ok
|
case ok
|
||||||
case unRegister
|
case unRegister
|
||||||
case serverError
|
case serverError
|
||||||
}
|
}
|
||||||
|
|
||||||
var deviceToken = BehaviorRelay<String?>(value: nil)
|
var deviceToken = BehaviorRelay<String?>(value: nil)
|
||||||
var state = BehaviorRelay<ClienState>(value: .ok)
|
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() {
|
func registerForRemoteNotifications() {
|
||||||
let center = UNUserNotificationCenter.current()
|
let center = UNUserNotificationCenter.current()
|
||||||
center.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { (_ granted: Bool, _: Error?) -> Void in
|
center.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { (_ granted: Bool, _: Error?) -> Void in
|
||||||
|
|||||||
@ -10,20 +10,27 @@ import UIKit
|
|||||||
|
|
||||||
enum BarkApi {
|
enum BarkApi {
|
||||||
case ping(baseURL: String?)
|
case ping(baseURL: String?)
|
||||||
case register(key: String?, devicetoken: String) // 注册设备
|
case register(address: String, key: String?, devicetoken: String) // 注册设备
|
||||||
}
|
}
|
||||||
|
|
||||||
extension BarkApi: BarkTargetType {
|
extension BarkApi: BarkTargetType {
|
||||||
var baseURL: URL {
|
var baseURL: URL {
|
||||||
if case let .ping(urlStr) = self, let url = URL(string: urlStr ?? "") {
|
switch self {
|
||||||
return url
|
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]? {
|
var parameters: [String: Any]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .register(key, devicetoken):
|
case let .register(_, key, devicetoken):
|
||||||
var params = ["devicetoken": devicetoken]
|
var params = ["devicetoken": devicetoken]
|
||||||
if let key = key {
|
if let key = key {
|
||||||
params["key"] = key
|
params["key"] = key
|
||||||
|
|||||||
@ -23,7 +23,7 @@ extension BarkTargetType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var baseURL: URL {
|
var baseURL: URL {
|
||||||
return URL(string: ServerManager.shared.currentAddress)!
|
return URL(string: ServerManager.shared.currentServer.address)!
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: Moya.Method {
|
var method: Moya.Method {
|
||||||
@ -54,21 +54,6 @@ extension BarkTargetType {
|
|||||||
return Task.requestParameters(parameters: defaultParameters, encoding: parameterEncoding)
|
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 对象
|
/// 实现此协议的类,将自动获得用该类实例化的 provider 对象
|
||||||
static var provider: RxSwift.Reactive<MoyaProvider<Self>> {
|
static var provider: RxSwift.Reactive<MoyaProvider<Self>> {
|
||||||
let key = "\(Self.self)"
|
let key = "\(Self.self)"
|
||||||
@ -82,7 +67,7 @@ extension BarkTargetType {
|
|||||||
|
|
||||||
/// 不被全局持有的 Provider ,使用时,需要持有它,否则将立即释放,请求随即终止
|
/// 不被全局持有的 Provider ,使用时,需要持有它,否则将立即释放,请求随即终止
|
||||||
static var weakProvider: RxSwift.Reactive<MoyaProvider<Self>> {
|
static var weakProvider: RxSwift.Reactive<MoyaProvider<Self>> {
|
||||||
var plugins: [PluginType] = [networkActivityPlugin]
|
var plugins: [PluginType] = []
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
plugins.append(LogPlugin())
|
plugins.append(LogPlugin())
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -6,43 +6,95 @@
|
|||||||
// Copyright © 2018年 Fin. All rights reserved.
|
// Copyright © 2018年 Fin. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import RxSwift
|
||||||
|
import SwiftUI
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
let defaultServer = "https://api.day.app"
|
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 {
|
class ServerManager: NSObject {
|
||||||
static let shared = ServerManager()
|
static let shared = ServerManager()
|
||||||
override private init() {
|
override private init() {
|
||||||
if let servers: Set<String> = Settings[.servers] {
|
if let servers: [Server] = Settings[.servers] {
|
||||||
self.servers = 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] {
|
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 {
|
else {
|
||||||
self.currentAddress = self.servers.first ?? defaultServer
|
currentServer = servers.first!
|
||||||
}
|
}
|
||||||
super.init()
|
Settings[.currentServerId] = serverId
|
||||||
}
|
}
|
||||||
|
|
||||||
var servers: Set<String> = [defaultServer]
|
/// 添加新的 server
|
||||||
var currentAddress: String {
|
func addServer(server: Server) {
|
||||||
didSet {
|
self.servers.append(server)
|
||||||
Settings[.currentServer] = currentAddress
|
saveServers()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func addServer(server: String) {
|
/// 移除 server,移除后如果 server 为`空`, `会新增一个默认server`
|
||||||
self.servers.insert(server)
|
func removeServer(server: Server) {
|
||||||
Settings[.servers] = self.servers
|
self.servers.removeAll { $0.id == server.id }
|
||||||
}
|
|
||||||
|
|
||||||
func removeServer(server: String) {
|
|
||||||
self.servers.remove(server)
|
|
||||||
if self.servers.count <= 0 {
|
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
|
Settings[.servers] = self.servers
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,4 +102,55 @@ class ServerManager: NSObject {
|
|||||||
required init?(coder aDecoder: NSCoder) {
|
required init?(coder aDecoder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
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 {
|
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(
|
let sectionModel = SectionModel(
|
||||||
model: "previews",
|
model: "previews",
|
||||||
@ -127,7 +127,7 @@ class HomeViewModel: ViewModel, ViewModelType {
|
|||||||
let clienState = input.viewDidAppear
|
let clienState = input.viewDidAppear
|
||||||
.asObservable().flatMapLatest { _ -> Observable<Result<JSON, ApiError>> in
|
.asObservable().flatMapLatest { _ -> Observable<Result<JSON, ApiError>> in
|
||||||
BarkApi.provider
|
BarkApi.provider
|
||||||
.request(.ping(baseURL: ServerManager.shared.currentAddress))
|
.request(.ping(baseURL: ServerManager.shared.currentServer.address))
|
||||||
.filterResponseError()
|
.filterResponseError()
|
||||||
}
|
}
|
||||||
.map { response -> Client.ClienState in
|
.map { response -> Client.ClienState in
|
||||||
|
|||||||
@ -76,8 +76,10 @@ class NewServerViewModel: ViewModel, ViewModelType {
|
|||||||
guard let strongSelf = self else { return }
|
guard let strongSelf = self else { return }
|
||||||
switch response {
|
switch response {
|
||||||
case .success:
|
case .success:
|
||||||
ServerManager.shared.currentAddress = strongSelf.url
|
let server = Server(address: strongSelf.url, key: "")
|
||||||
Client.shared.bindDeviceToken()
|
ServerManager.shared.addServer(server: server)
|
||||||
|
ServerManager.shared.setCurrentServer(serverId: server.id)
|
||||||
|
ServerManager.shared.syncAllServers()
|
||||||
|
|
||||||
strongSelf.pop.accept(strongSelf.url)
|
strongSelf.pop.accept(strongSelf.url)
|
||||||
showSnackbar.accept(NSLocalizedString("AddedSuccessfully"))
|
showSnackbar.accept(NSLocalizedString("AddedSuccessfully"))
|
||||||
|
|||||||
@ -65,14 +65,14 @@ class PreviewCardCellViewModel: ViewModel {
|
|||||||
if UIScreen.main.bounds.size.width <= 320 {
|
if UIScreen.main.bounds.size.width <= 320 {
|
||||||
fontSize = 11
|
fontSize = 11
|
||||||
}
|
}
|
||||||
let serverUrl = URL(string: ServerManager.shared.currentAddress)!
|
let serverUrl = URL(string: ServerManager.shared.currentServer.address)!
|
||||||
let attrStr = NSMutableAttributedString(string: "")
|
let attrStr = NSMutableAttributedString(string: "")
|
||||||
attrStr.append(NSAttributedString(string: serverUrl.absoluteString, attributes: [
|
attrStr.append(NSAttributedString(string: serverUrl.absoluteString, attributes: [
|
||||||
NSAttributedString.Key.foregroundColor: BKColor.grey.darken4,
|
NSAttributedString.Key.foregroundColor: BKColor.grey.darken4,
|
||||||
NSAttributedString.Key.font: RobotoFont.regular(with: fontSize)
|
NSAttributedString.Key.font: RobotoFont.regular(with: fontSize)
|
||||||
]))
|
]))
|
||||||
|
let key = ServerManager.shared.currentServer.key
|
||||||
attrStr.append(NSAttributedString(string: "/\(Client.shared.key ?? "Your Key")", attributes: [
|
attrStr.append(NSAttributedString(string: "/\(key.count > 0 ? key : "Your Key")", attributes: [
|
||||||
NSAttributedString.Key.foregroundColor: BKColor.grey.darken3,
|
NSAttributedString.Key.foregroundColor: BKColor.grey.darken3,
|
||||||
NSAttributedString.Key.font: RobotoFont.regular(with: fontSize)
|
NSAttributedString.Key.font: RobotoFont.regular(with: fontSize)
|
||||||
]))
|
]))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user