mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-27 09:34:49 +00:00
wip
This commit is contained in:
@@ -1334,6 +1334,13 @@ func apiGetVersion() throws -> CoreVersionInfo {
|
||||
throw r
|
||||
}
|
||||
|
||||
func getAgentServersSummary() throws -> PresentedServersSummary {
|
||||
let userId = try currentUserId("getAgentServersSummary")
|
||||
let r = chatSendCmdSync(.getAgentServersSummary(userId: userId))
|
||||
if case let .agentServersSummary(_, serversSummary) = r { return serversSummary }
|
||||
throw r
|
||||
}
|
||||
|
||||
private func currentUserId(_ funcName: String) throws -> Int64 {
|
||||
if let userId = ChatModel.shared.currentUser?.userId {
|
||||
return userId
|
||||
|
||||
@@ -64,7 +64,7 @@ struct ChatListView: View {
|
||||
ConnectDesktopView()
|
||||
}
|
||||
.sheet(isPresented: $showServersSummary) {
|
||||
Text("Servers summary view")
|
||||
ServersSummaryView()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ struct ChatListView: View {
|
||||
showServersSummary = true
|
||||
} label: {
|
||||
Image(systemName: "wifi")
|
||||
.foregroundColor(.accentColor)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
//
|
||||
// ServersSummaryView.swift
|
||||
// SimpleX (iOS)
|
||||
//
|
||||
// Created by spaced4ndy on 25.06.2024.
|
||||
// Copyright © 2024 SimpleX Chat. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
struct ServersSummaryView: View {
|
||||
@State private var serversSummary: PresentedServersSummary? = nil
|
||||
@State private var selectedUserCategory: PresentedUserCategory = .allUsers
|
||||
@State private var selectedServerType: PresentedServerType = .smp
|
||||
@State private var selectedSMPServer: String? = nil
|
||||
|
||||
enum PresentedUserCategory {
|
||||
case currentUser
|
||||
case allUsers
|
||||
}
|
||||
|
||||
enum PresentedServerType {
|
||||
case smp
|
||||
case xftp
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
viewBody()
|
||||
.navigationTitle("Servers info")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
reloadButton()
|
||||
}
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
shareButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
getServersSummary()
|
||||
}
|
||||
}
|
||||
|
||||
private func shareButton() -> some View {
|
||||
Button {
|
||||
if let serversSummary = serversSummary {
|
||||
showShareSheet(items: [encodeJSON(serversSummary)]) // TODO prettyJSON
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "square.and.arrow.up")
|
||||
}
|
||||
.disabled(serversSummary == nil)
|
||||
}
|
||||
|
||||
private func reloadButton() -> some View {
|
||||
Button {
|
||||
getServersSummary()
|
||||
} label: {
|
||||
Image(systemName: "arrow.counterclockwise")
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func viewBody() -> some View {
|
||||
if let summ = serversSummary {
|
||||
List {
|
||||
Group {
|
||||
Picker("User selection", selection: $selectedUserCategory) {
|
||||
Text("All users").tag(PresentedUserCategory.allUsers)
|
||||
Text("Current user").tag(PresentedUserCategory.currentUser)
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
|
||||
Picker("Server type", selection: $selectedServerType) {
|
||||
Text("SMP").tag(PresentedServerType.smp)
|
||||
Text("XFTP").tag(PresentedServerType.xftp)
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
}
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowSeparator(.hidden)
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
|
||||
switch (selectedUserCategory, selectedServerType) {
|
||||
case (.allUsers, .smp):
|
||||
if summ.allUsedSMP.count > 0 || summ.allPrevSMP.count > 0 || summ.allProxSMP.count > 0 {
|
||||
if summ.allUsedSMP.count > 0 {
|
||||
smpServersListView(summ.allUsedSMP, showReconnectButton: true, summ.statsStartedAt, "Currently used")
|
||||
}
|
||||
if summ.allPrevSMP.count > 0 {
|
||||
smpServersListView(summ.allPrevSMP, showReconnectButton: false, summ.statsStartedAt, "Previously used")
|
||||
}
|
||||
if summ.allProxSMP.count > 0 {
|
||||
smpServersListView(summ.allProxSMP, showReconnectButton: false, summ.statsStartedAt, "Proxied", "You are not connected to these servers directly.")
|
||||
}
|
||||
} else {
|
||||
noCategoryInfoText()
|
||||
}
|
||||
case (.currentUser, .smp):
|
||||
if summ.userUsedSMP.count > 0 || summ.userPrevSMP.count > 0 || summ.userProxSMP.count > 0 {
|
||||
if summ.userUsedSMP.count > 0 {
|
||||
smpServersListView(summ.userUsedSMP, showReconnectButton: true, summ.statsStartedAt, "Currently used")
|
||||
}
|
||||
if summ.userPrevSMP.count > 0 {
|
||||
smpServersListView(summ.userPrevSMP, showReconnectButton: false, summ.statsStartedAt, "Previously used")
|
||||
}
|
||||
if summ.userProxSMP.count > 0 {
|
||||
smpServersListView(summ.userProxSMP, showReconnectButton: false, summ.statsStartedAt, "Proxied", "You are not connected to these servers directly.")
|
||||
}
|
||||
} else {
|
||||
noCategoryInfoText()
|
||||
}
|
||||
case (.allUsers, .xftp):
|
||||
if summ.allUsedXFTP.count > 0 || summ.allPrevXFTP.count > 0 {
|
||||
if summ.allUsedXFTP.count > 0 {
|
||||
xftpServersListView(summ.allUsedXFTP, "Currently used")
|
||||
}
|
||||
if summ.allPrevXFTP.count > 0 {
|
||||
xftpServersListView(summ.allPrevXFTP, "Previously used")
|
||||
}
|
||||
} else {
|
||||
noCategoryInfoText()
|
||||
}
|
||||
case (.currentUser, .xftp):
|
||||
if summ.userUsedXFTP.count > 0 || summ.userPrevXFTP.count > 0 {
|
||||
if summ.userUsedXFTP.count > 0 {
|
||||
xftpServersListView(summ.userUsedXFTP, "Currently used")
|
||||
}
|
||||
if summ.userPrevXFTP.count > 0 {
|
||||
xftpServersListView(summ.userPrevXFTP, "Previously used")
|
||||
}
|
||||
} else {
|
||||
noCategoryInfoText()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("No info, try to reload")
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder private func smpServersListView(
|
||||
_ servers: [SMPServerSummary],
|
||||
showReconnectButton: Bool,
|
||||
_ statsStartedAt: Date,
|
||||
_ header: LocalizedStringKey? = nil,
|
||||
_ footer: LocalizedStringKey? = nil
|
||||
) -> some View {
|
||||
let sortedServers = servers.sorted { serverAddress($0.smpServer).compare(serverAddress($1.smpServer)) == .orderedAscending }
|
||||
Section {
|
||||
ForEach(sortedServers) { server in
|
||||
smpServerView(server, showReconnectButton, statsStartedAt)
|
||||
}
|
||||
} header: {
|
||||
if let header = header {
|
||||
Text(header)
|
||||
}
|
||||
} footer: {
|
||||
if let footer = footer {
|
||||
Text(footer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func smpServerView(_ server: SMPServerSummary, _ showReconnectButton: Bool, _ statsStartedAt: Date) -> some View {
|
||||
NavigationLink(tag: server.id, selection: $selectedSMPServer) {
|
||||
SMPServerSummaryView(
|
||||
summary: server,
|
||||
showReconnectButton: showReconnectButton,
|
||||
statsStartedAt: statsStartedAt
|
||||
)
|
||||
.navigationBarTitle("SMP server")
|
||||
.navigationBarTitleDisplayMode(.large)
|
||||
} label: {
|
||||
Text(serverAddress(server.smpServer))
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
|
||||
private func serverAddress(_ server: String) -> String {
|
||||
parseServerAddress(server)?.hostnames.first ?? server
|
||||
}
|
||||
|
||||
@ViewBuilder private func xftpServersListView(
|
||||
_ servers: [XFTPServerSummary],
|
||||
_ header: LocalizedStringKey? = nil,
|
||||
_ footer: LocalizedStringKey? = nil
|
||||
) -> some View {
|
||||
let sortedServers = servers.sorted { serverAddress($0.xftpServer).compare(serverAddress($1.xftpServer)) == .orderedAscending }
|
||||
Section {
|
||||
ForEach(sortedServers) { server in
|
||||
xftpServer(server)
|
||||
}
|
||||
} header: {
|
||||
if let header = header {
|
||||
Text(header)
|
||||
}
|
||||
} footer: {
|
||||
if let footer = footer {
|
||||
Text(footer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func xftpServer(_ server: XFTPServerSummary) -> some View {
|
||||
Text(serverAddress(server.xftpServer))
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
private func noCategoryInfoText() -> some View {
|
||||
ZStack {
|
||||
Rectangle()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.foregroundColor(Color.clear)
|
||||
Text("No info")
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowSeparator(.hidden)
|
||||
}
|
||||
|
||||
private func getServersSummary() {
|
||||
do {
|
||||
serversSummary = try getAgentServersSummary()
|
||||
} catch let error {
|
||||
logger.error("getAgentServersSummary error: \(responseError(error))")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SMPServerSummaryView: View {
|
||||
var summary: SMPServerSummary
|
||||
var showReconnectButton: Bool
|
||||
var statsStartedAt: Date
|
||||
|
||||
var body: some View {
|
||||
List {
|
||||
Section {
|
||||
Text(summary.smpServer)
|
||||
.textSelection(.enabled)
|
||||
if let known = summary.known, !known {
|
||||
Button {
|
||||
// TODO
|
||||
} label: {
|
||||
Text("TODO Add as known")
|
||||
}
|
||||
}
|
||||
} header: {
|
||||
Text("Server address")
|
||||
} footer: {
|
||||
if let known = summary.known, known {
|
||||
// TODO open settings?
|
||||
Text("Server can be configured in **Settings** -> **Network & servers** -> **SMP servers**")
|
||||
}
|
||||
}
|
||||
|
||||
if showReconnectButton {
|
||||
Section {
|
||||
Button {
|
||||
// TODO
|
||||
} label: {
|
||||
Text("TODO Reconnect")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let sess = summary.sessions {
|
||||
Section("Sessions") {
|
||||
infoRow("Connected", "\(sess.ssConnected)")
|
||||
infoRow("Errors", "\(sess.ssErrors)")
|
||||
infoRow("Connecting", "\(sess.ssConnecting)")
|
||||
}
|
||||
}
|
||||
|
||||
if let subs = summary.subs {
|
||||
Section("Subscriptions") {
|
||||
infoRow("Active", "\(subs.ssActive)")
|
||||
infoRow("Pending", "\(subs.ssPending)")
|
||||
}
|
||||
}
|
||||
|
||||
if let stats = summary.stats {
|
||||
Section("Statistics") {
|
||||
infoRow("Messages sent directly", "\(stats._sentDirect)")
|
||||
infoRow(" attempts", "\(stats._sentDirectAttempts)")
|
||||
infoRow("Messages sent via proxy", "\(stats._sentViaProxy)")
|
||||
infoRow(" attempts", "\(stats._sentViaProxyAttempts)")
|
||||
infoRow("Messages sent to proxy", "\(stats._sentProxied)")
|
||||
infoRow(" attempts", "\(stats._sentProxiedAttempts)")
|
||||
infoRow("Send AUTH errors", "\(stats._sentAuthErrs)")
|
||||
infoRow(" QUOTA errors", "\(stats._sentQuotaErrs)")
|
||||
infoRow(" expired", "\(stats._sentExpiredErrs)")
|
||||
infoRow(" other errors", "\(stats._sentOtherErrs)")
|
||||
infoRow("Messages received", "\(stats._recvMsgs)")
|
||||
infoRow(" duplicates", "\(stats._recvDuplicates)")
|
||||
infoRow(" decryption", "\(stats._recvCryptoErrs)")
|
||||
infoRow(" other errors", "\(stats._recvErrs)")
|
||||
infoRow("Connections created", "\(stats._connCreated)")
|
||||
infoRow(" secured", "\(stats._connSecured)")
|
||||
infoRow(" completed", "\(stats._connCompleted)")
|
||||
infoRow("Connections deleted", "\(stats._connDeleted)")
|
||||
infoRow("Connections subscribed", "\(stats._connSubscribed)")
|
||||
infoRow(" attempts", "\(stats._connSubAttempts)")
|
||||
infoRow(" errors", "\(stats._connSubErrs)")
|
||||
infoRow("From", localTimestamp(statsStartedAt))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ServersSummaryView()
|
||||
}
|
||||
@@ -153,6 +153,7 @@
|
||||
641753592C2AC158005415B4 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 641753542C2AC158005415B4 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a */; };
|
||||
6417535A2C2AC158005415B4 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 641753552C2AC158005415B4 /* libgmpxx.a */; };
|
||||
6417535B2C2AC158005415B4 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 641753562C2AC158005415B4 /* libffi.a */; };
|
||||
6417535D2C2ACD77005415B4 /* ServersSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6417535C2C2ACD77005415B4 /* ServersSummaryView.swift */; };
|
||||
6419EC562AB8BC8B004A607A /* ContextInvitingContactMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */; };
|
||||
6419EC582AB97507004A607A /* CIMemberCreatedContactView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */; };
|
||||
6432857C2925443C00FBE5C8 /* GroupPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */; };
|
||||
@@ -448,6 +449,7 @@
|
||||
641753542C2AC158005415B4 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a"; path = "Libraries/libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a"; sourceTree = "<group>"; };
|
||||
641753552C2AC158005415B4 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmpxx.a; path = Libraries/libgmpxx.a; sourceTree = "<group>"; };
|
||||
641753562C2AC158005415B4 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libffi.a; path = Libraries/libffi.a; sourceTree = "<group>"; };
|
||||
6417535C2C2ACD77005415B4 /* ServersSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServersSummaryView.swift; sourceTree = "<group>"; };
|
||||
6419EC552AB8BC8B004A607A /* ContextInvitingContactMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextInvitingContactMemberView.swift; sourceTree = "<group>"; };
|
||||
6419EC572AB97507004A607A /* CIMemberCreatedContactView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIMemberCreatedContactView.swift; sourceTree = "<group>"; };
|
||||
6432857B2925443C00FBE5C8 /* GroupPreferencesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupPreferencesView.swift; sourceTree = "<group>"; };
|
||||
@@ -802,6 +804,7 @@
|
||||
5C13730A28156D2700F43030 /* ContactConnectionView.swift */,
|
||||
5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */,
|
||||
18415835CBD939A9ABDC108A /* UserPicker.swift */,
|
||||
6417535C2C2ACD77005415B4 /* ServersSummaryView.swift */,
|
||||
);
|
||||
path = ChatList;
|
||||
sourceTree = "<group>";
|
||||
@@ -1256,6 +1259,7 @@
|
||||
5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */,
|
||||
5C9329412929248A0090FFF9 /* ScanProtocolServer.swift in Sources */,
|
||||
8C7DF3202B7CDB0A00C886D0 /* MigrateFromDevice.swift in Sources */,
|
||||
6417535D2C2ACD77005415B4 /* ServersSummaryView.swift in Sources */,
|
||||
64AA1C6C27F3537400AC7277 /* DeletedItemView.swift in Sources */,
|
||||
5C93293F2928E0FD0090FFF9 /* AudioRecPlay.swift in Sources */,
|
||||
5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */,
|
||||
|
||||
@@ -122,6 +122,7 @@ public enum ChatCommand {
|
||||
case apiEndCall(contact: Contact)
|
||||
case apiGetCallInvitations
|
||||
case apiCallStatus(contact: Contact, callStatus: WebRTCCallStatus)
|
||||
// WebRTC calls /
|
||||
case apiGetNetworkStatuses
|
||||
case apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64))
|
||||
case apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool)
|
||||
@@ -142,6 +143,7 @@ public enum ChatCommand {
|
||||
case apiStandaloneFileInfo(url: String)
|
||||
// misc
|
||||
case showVersion
|
||||
case getAgentServersSummary(userId: Int64)
|
||||
case string(String)
|
||||
|
||||
public var cmdString: String {
|
||||
@@ -301,6 +303,7 @@ public enum ChatCommand {
|
||||
case let .apiDownloadStandaloneFile(userId, link, file): return "/_download \(userId) \(link) \(file.filePath)"
|
||||
case let .apiStandaloneFileInfo(link): return "/_download info \(link)"
|
||||
case .showVersion: return "/version"
|
||||
case let .getAgentServersSummary(userId): return "/get servers summary \(userId)"
|
||||
case let .string(str): return str
|
||||
}
|
||||
}
|
||||
@@ -435,6 +438,7 @@ public enum ChatCommand {
|
||||
case .apiDownloadStandaloneFile: return "apiDownloadStandaloneFile"
|
||||
case .apiStandaloneFileInfo: return "apiStandaloneFileInfo"
|
||||
case .showVersion: return "showVersion"
|
||||
case .getAgentServersSummary: return "getAgentServersSummary"
|
||||
case .string: return "console command"
|
||||
}
|
||||
}
|
||||
@@ -663,6 +667,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
// misc
|
||||
case versionInfo(versionInfo: CoreVersionInfo, chatMigrations: [UpMigration], agentMigrations: [UpMigration])
|
||||
case cmdOk(user: UserRef?)
|
||||
case agentServersSummary(user: UserRef, serversSummary: PresentedServersSummary)
|
||||
case chatCmdError(user_: UserRef?, chatError: ChatError)
|
||||
case chatError(user_: UserRef?, chatError: ChatError)
|
||||
case archiveImported(archiveErrors: [ArchiveError])
|
||||
@@ -821,6 +826,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
case .contactPQEnabled: return "contactPQEnabled"
|
||||
case .versionInfo: return "versionInfo"
|
||||
case .cmdOk: return "cmdOk"
|
||||
case .agentServersSummary: return "agentServersSummary"
|
||||
case .chatCmdError: return "chatCmdError"
|
||||
case .chatError: return "chatError"
|
||||
case .archiveImported: return "archiveImported"
|
||||
@@ -984,6 +990,7 @@ public enum ChatResponse: Decodable, Error {
|
||||
case let .contactPQEnabled(u, contact, pqEnabled): return withUser(u, "contact: \(String(describing: contact))\npqEnabled: \(pqEnabled)")
|
||||
case let .versionInfo(versionInfo, chatMigrations, agentMigrations): return "\(String(describing: versionInfo))\n\nchat migrations: \(chatMigrations.map(\.upName))\n\nagent migrations: \(agentMigrations.map(\.upName))"
|
||||
case .cmdOk: return noDetails
|
||||
case let .agentServersSummary(u, serversSummary): return withUser(u, String(describing: serversSummary))
|
||||
case let .chatCmdError(u, chatError): return withUser(u, String(describing: chatError))
|
||||
case let .chatError(u, chatError): return withUser(u, String(describing: chatError))
|
||||
case let .archiveImported(archiveErrors): return String(describing: archiveErrors)
|
||||
@@ -2231,79 +2238,100 @@ public enum MsgType: String, Codable {
|
||||
case quota
|
||||
}
|
||||
|
||||
public struct AgentServersSummary: Decodable {
|
||||
var usersServersSummary: Dictionary<Int64, ServersSummary>
|
||||
// var totalServersSummary: ServersSummary
|
||||
public struct PresentedServersSummary: Codable {
|
||||
public var statsStartedAt: Date
|
||||
public var currentUserServers: ServersSummary
|
||||
public var allUsersServers: ServersSummary
|
||||
|
||||
public var allUsedSMP: [SMPServerSummary] { self.allUsersServers.currentlyUsedSMPServers }
|
||||
public var allPrevSMP: [SMPServerSummary] { self.allUsersServers.previouslyUsedSMPServers }
|
||||
public var allProxSMP: [SMPServerSummary] { self.allUsersServers.onlyProxiedSMPServers }
|
||||
|
||||
public var userUsedSMP: [SMPServerSummary] { self.currentUserServers.currentlyUsedSMPServers }
|
||||
public var userPrevSMP: [SMPServerSummary] { self.currentUserServers.previouslyUsedSMPServers }
|
||||
public var userProxSMP: [SMPServerSummary] { self.currentUserServers.onlyProxiedSMPServers }
|
||||
|
||||
public var allUsedXFTP: [XFTPServerSummary] { self.allUsersServers.currentlyUsedXFTPServers }
|
||||
public var allPrevXFTP: [XFTPServerSummary] { self.allUsersServers.previouslyUsedXFTPServers }
|
||||
|
||||
public var userUsedXFTP: [XFTPServerSummary] { self.currentUserServers.currentlyUsedXFTPServers }
|
||||
public var userPrevXFTP: [XFTPServerSummary] { self.currentUserServers.previouslyUsedXFTPServers }
|
||||
}
|
||||
|
||||
public struct ServersSummary: Decodable {
|
||||
var smpServersSummary: SMPServerSummary
|
||||
var xftpServersSummary: XFTPServerSummary
|
||||
public struct ServersSummary: Codable {
|
||||
public var currentlyUsedSMPServers: [SMPServerSummary]
|
||||
public var previouslyUsedSMPServers: [SMPServerSummary]
|
||||
public var onlyProxiedSMPServers: [SMPServerSummary]
|
||||
public var currentlyUsedXFTPServers: [XFTPServerSummary]
|
||||
public var previouslyUsedXFTPServers: [XFTPServerSummary]
|
||||
}
|
||||
|
||||
public struct SMPServerSummary: Decodable {
|
||||
var smpServer: String
|
||||
var usedForNewConnections: Bool
|
||||
var subscriptionsSummary: SMPServerSubsSummary?
|
||||
var workersSummary: SMPServerWorkersSummary
|
||||
var commandsStats: [CommandStat]
|
||||
var rcvMsgCounts: [SMPServerRcvMsgCounts]
|
||||
var deliveryInfo: SMPServerDeliveryInfo?
|
||||
public struct SMPServerSummary: Codable, Identifiable {
|
||||
public var smpServer: String
|
||||
public var known: Bool?
|
||||
public var sessions: ServerSessions?
|
||||
public var subs: SMPServerSubs?
|
||||
public var stats: AgentSMPServerStatsData?
|
||||
|
||||
public var id: String { smpServer }
|
||||
}
|
||||
|
||||
public struct XFTPServerSummary: Decodable {
|
||||
var xftpServer: String
|
||||
var usedForNewFiles: Bool
|
||||
var workersSummary: SMPServerWorkersSummary
|
||||
var commandsStats: [CommandStat]
|
||||
public struct ServerSessions: Codable {
|
||||
public var ssConnected: Int
|
||||
public var ssErrors: Int
|
||||
public var ssConnecting: Int
|
||||
}
|
||||
|
||||
public struct SMPServerSubsSummary: Decodable {
|
||||
var activeSubscriptions: [SMPServerSubInfo]
|
||||
var pendingSubscriptions: [SMPServerSubInfo]
|
||||
var removedSubscriptions: [SMPServerSubInfo]
|
||||
public struct SMPServerSubs: Codable {
|
||||
public var ssActive: Int
|
||||
public var ssPending: Int
|
||||
}
|
||||
|
||||
public struct SMPServerSubInfo: Decodable {
|
||||
var rcvId: String
|
||||
var subError: String?
|
||||
public struct AgentSMPServerStatsData: Codable {
|
||||
public var _sentDirect: Int
|
||||
public var _sentViaProxy: Int
|
||||
public var _sentProxied: Int
|
||||
public var _sentDirectAttempts: Int
|
||||
public var _sentViaProxyAttempts: Int
|
||||
public var _sentProxiedAttempts: Int
|
||||
public var _sentAuthErrs: Int
|
||||
public var _sentQuotaErrs: Int
|
||||
public var _sentExpiredErrs: Int
|
||||
public var _sentOtherErrs: Int
|
||||
public var _recvMsgs: Int
|
||||
public var _recvDuplicates: Int
|
||||
public var _recvCryptoErrs: Int
|
||||
public var _recvErrs: Int
|
||||
public var _connCreated: Int
|
||||
public var _connSecured: Int
|
||||
public var _connCompleted: Int
|
||||
public var _connDeleted: Int
|
||||
public var _connSubscribed: Int
|
||||
public var _connSubAttempts: Int
|
||||
public var _connSubErrs: Int
|
||||
}
|
||||
|
||||
public struct SMPServerWorkersSummary: Decodable {
|
||||
var smpDeliveryWorkers_: Dictionary<String, WorkersDetails>
|
||||
var asyncCmdWorker_: WorkersDetails
|
||||
var smpSubWorkers_: [String]
|
||||
public struct XFTPServerSummary: Codable, Identifiable {
|
||||
public var xftpServer: String
|
||||
public var known: Bool?
|
||||
public var sessions: ServerSessions?
|
||||
public var stats: AgentXFTPServerStatsData?
|
||||
public var rcvInProgress: Bool
|
||||
public var sndInProgress: Bool
|
||||
public var delInProgress: Bool
|
||||
|
||||
public var id: String { xftpServer }
|
||||
}
|
||||
|
||||
public struct SMPServerRcvMsgCounts: Decodable {
|
||||
var connId: String
|
||||
var total: Int
|
||||
var duplicate: Int
|
||||
}
|
||||
|
||||
public struct SMPServerDeliveryInfo: Decodable {
|
||||
var host: String
|
||||
var viaOnionHost: Bool
|
||||
var viaSocksProxy: Bool
|
||||
var smpProxy: String?
|
||||
}
|
||||
|
||||
public struct XFTPServerWorkersSummary: Decodable {
|
||||
var rcvWorker: WorkersDetails?
|
||||
var sndWorker: WorkersDetails?
|
||||
var delWorker: WorkersDetails?
|
||||
}
|
||||
|
||||
public struct WorkersDetails: Decodable {
|
||||
var restarts: Int
|
||||
var hasWork: Bool
|
||||
var hasAction: Bool
|
||||
}
|
||||
|
||||
public struct CommandStat: Decodable {
|
||||
var host: String
|
||||
var clientTs: Date
|
||||
var cmd: String
|
||||
var res: String
|
||||
var count: Int
|
||||
public struct AgentXFTPServerStatsData: Codable {
|
||||
public var _uploads: Int
|
||||
public var _uploadAttempts: Int
|
||||
public var _uploadErrs: Int
|
||||
public var _downloads: Int
|
||||
public var _downloadAttempts: Int
|
||||
public var _downloadAuthErrs: Int
|
||||
public var _downloadErrs: Int
|
||||
public var _deletions: Int
|
||||
public var _deleteAttempts: Int
|
||||
public var _deleteErrs: Int
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user