add to top bar connect
This commit is contained in:
parent
4a2636879d
commit
7c1d46ab77
@ -27,6 +27,10 @@ struct TopBarView: View {
|
|||||||
return title == "Profile"
|
return title == "Profile"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var shouldShowConnectionStatus: Bool {
|
||||||
|
viewModel.socketState != .connected
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
HStack {
|
HStack {
|
||||||
@ -43,7 +47,10 @@ struct TopBarView: View {
|
|||||||
|
|
||||||
// Spacer()
|
// Spacer()
|
||||||
|
|
||||||
if isHomeTab{
|
if shouldShowConnectionStatus {
|
||||||
|
connectionStatusView
|
||||||
|
Spacer()
|
||||||
|
} else if isHomeTab{
|
||||||
Text("Yobble")
|
Text("Yobble")
|
||||||
.font(.largeTitle)
|
.font(.largeTitle)
|
||||||
.fontWeight(.bold)
|
.fontWeight(.bold)
|
||||||
@ -129,6 +136,16 @@ struct TopBarView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private extension TopBarView {
|
private extension TopBarView {
|
||||||
|
var connectionStatusView: some View {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
Text(NSLocalizedString("Подключение", comment: ""))
|
||||||
|
.font(.headline)
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var normalizedRevealProgress: CGFloat {
|
private var normalizedRevealProgress: CGFloat {
|
||||||
guard isChatsTab else { return 0 }
|
guard isChatsTab else { return 0 }
|
||||||
return max(0, min(chatSearchRevealProgress, 1))
|
return max(0, min(chatSearchRevealProgress, 1))
|
||||||
|
|||||||
@ -1473,6 +1473,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Подключение" : {
|
||||||
|
|
||||||
},
|
},
|
||||||
"Подтверждение пароля" : {
|
"Подтверждение пароля" : {
|
||||||
"comment" : "Подтверждение пароля",
|
"comment" : "Подтверждение пароля",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import Combine
|
||||||
#if canImport(SocketIO)
|
#if canImport(SocketIO)
|
||||||
import SocketIO
|
import SocketIO
|
||||||
#endif
|
#endif
|
||||||
@ -6,10 +7,28 @@ import SocketIO
|
|||||||
final class SocketService {
|
final class SocketService {
|
||||||
static let shared = SocketService()
|
static let shared = SocketService()
|
||||||
|
|
||||||
|
enum ConnectionState: Equatable {
|
||||||
|
case disconnected
|
||||||
|
case connecting
|
||||||
|
case connected
|
||||||
|
}
|
||||||
|
|
||||||
private let syncQueue = DispatchQueue(label: "org.yobble.socket.service")
|
private let syncQueue = DispatchQueue(label: "org.yobble.socket.service")
|
||||||
private var currentToken: String?
|
private var currentToken: String?
|
||||||
private var currentAuthPayload: [String: Any] = [:]
|
private var currentAuthPayload: [String: Any] = [:]
|
||||||
|
|
||||||
|
private let connectionStateSubject = CurrentValueSubject<ConnectionState, Never>(.disconnected)
|
||||||
|
|
||||||
|
var connectionStatePublisher: AnyPublisher<ConnectionState, Never> {
|
||||||
|
connectionStateSubject
|
||||||
|
.removeDuplicates()
|
||||||
|
.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentConnectionState: ConnectionState {
|
||||||
|
connectionStateSubject.value
|
||||||
|
}
|
||||||
|
|
||||||
#if canImport(SocketIO)
|
#if canImport(SocketIO)
|
||||||
private var manager: SocketManager?
|
private var manager: SocketManager?
|
||||||
private var socket: SocketIOClient?
|
private var socket: SocketIOClient?
|
||||||
@ -17,6 +36,19 @@ final class SocketService {
|
|||||||
|
|
||||||
private init() {}
|
private init() {}
|
||||||
|
|
||||||
|
private func updateConnectionState(_ state: ConnectionState) {
|
||||||
|
let sendState: () -> Void = { [weak self] in
|
||||||
|
guard let self, self.connectionStateSubject.value != state else { return }
|
||||||
|
self.connectionStateSubject.send(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
if Thread.isMainThread {
|
||||||
|
sendState()
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.async(execute: sendState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func connectForCurrentUser() {
|
func connectForCurrentUser() {
|
||||||
syncQueue.async { [weak self] in
|
syncQueue.async { [weak self] in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
@ -68,8 +100,10 @@ final class SocketService {
|
|||||||
currentToken = token
|
currentToken = token
|
||||||
currentAuthPayload = ["token": token]
|
currentAuthPayload = ["token": token]
|
||||||
setupSocket(with: token)
|
setupSocket(with: token)
|
||||||
|
updateConnectionState(.connecting)
|
||||||
socket?.connect(withPayload: currentAuthPayload)
|
socket?.connect(withPayload: currentAuthPayload)
|
||||||
#else
|
#else
|
||||||
|
updateConnectionState(.disconnected)
|
||||||
if AppConfig.DEBUG {
|
if AppConfig.DEBUG {
|
||||||
print("[SocketService] SocketIO framework not available; skipping connection")
|
print("[SocketService] SocketIO framework not available; skipping connection")
|
||||||
}
|
}
|
||||||
@ -112,14 +146,17 @@ final class SocketService {
|
|||||||
|
|
||||||
socket.on(clientEvent: .connect) { _, _ in
|
socket.on(clientEvent: .connect) { _, _ in
|
||||||
if AppConfig.DEBUG { print("[SocketService] Connected") }
|
if AppConfig.DEBUG { print("[SocketService] Connected") }
|
||||||
|
self.updateConnectionState(.connected)
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.on(clientEvent: .disconnect) { data, _ in
|
socket.on(clientEvent: .disconnect) { data, _ in
|
||||||
if AppConfig.DEBUG { print("[SocketService] Disconnected: \(data)") }
|
if AppConfig.DEBUG { print("[SocketService] Disconnected: \(data)") }
|
||||||
|
self.updateConnectionState(.disconnected)
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.on(clientEvent: .error) { data, _ in
|
socket.on(clientEvent: .error) { data, _ in
|
||||||
if AppConfig.DEBUG { print("[SocketService] Error: \(data)") }
|
if AppConfig.DEBUG { print("[SocketService] Error: \(data)") }
|
||||||
|
self.updateConnectionState(.disconnected)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
@ -131,6 +168,7 @@ final class SocketService {
|
|||||||
manager?.disconnect()
|
manager?.disconnect()
|
||||||
socket = nil
|
socket = nil
|
||||||
manager = nil
|
manager = nil
|
||||||
|
updateConnectionState(.disconnected)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
private func disconnectInternal() { }
|
private func disconnectInternal() { }
|
||||||
|
|||||||
@ -16,9 +16,11 @@ class LoginViewModel: ObservableObject {
|
|||||||
@Published var showError: Bool = false
|
@Published var showError: Bool = false
|
||||||
@Published var errorMessage: String = ""
|
@Published var errorMessage: String = ""
|
||||||
@Published var isLoggedIn: Bool = false
|
@Published var isLoggedIn: Bool = false
|
||||||
|
@Published var socketState: SocketService.ConnectionState
|
||||||
|
|
||||||
private let authService = AuthService()
|
private let authService = AuthService()
|
||||||
private let socketService = SocketService.shared
|
private let socketService = SocketService.shared
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
private enum DefaultsKeys {
|
private enum DefaultsKeys {
|
||||||
static let currentUser = "currentUser"
|
static let currentUser = "currentUser"
|
||||||
@ -26,12 +28,23 @@ class LoginViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
|
socketState = socketService.currentConnectionState
|
||||||
|
observeSocketState()
|
||||||
// loadStoredUser()
|
// loadStoredUser()
|
||||||
|
|
||||||
// Запускаем автологин
|
// Запускаем автологин
|
||||||
autoLogin()
|
autoLogin()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func observeSocketState() {
|
||||||
|
socketService.connectionStatePublisher
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] state in
|
||||||
|
self?.socketState = state
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
func autoLogin() {
|
func autoLogin() {
|
||||||
authService.autoLogin { [weak self] success, error in
|
authService.autoLogin { [weak self] success, error in
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user