totals, timer

This commit is contained in:
spaced4ndy
2024-06-27 22:23:07 +04:00
parent 1d83140c1d
commit 44720ecb0c
2 changed files with 185 additions and 137 deletions
@@ -15,6 +15,7 @@ struct ServersSummaryView: View {
@State private var selectedServerType: PresentedServerType = .smp
@State private var selectedSMPServer: String? = nil
@State private var selectedXFTPServer: String? = nil
@State private var timer: Timer? = nil
@State private var alert: SomeAlert?
enum PresentedUserCategory {
@@ -33,9 +34,6 @@ struct ServersSummaryView: View {
.navigationTitle("Servers info")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
reloadButton()
}
ToolbarItem(placement: .navigationBarTrailing) {
shareButton()
}
@@ -43,10 +41,25 @@ struct ServersSummaryView: View {
}
.onAppear {
getServersSummary()
startTimer()
}
.onDisappear {
stopTimer()
}
.alert(item: $alert) { $0.alert }
}
private func startTimer() {
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
getServersSummary()
}
}
func stopTimer() {
timer?.invalidate()
timer = nil
}
private func shareButton() -> some View {
Button {
if let serversSummary = serversSummary {
@@ -65,14 +78,6 @@ struct ServersSummaryView: View {
return String(decoding: data, as: UTF8.self)
}
private func reloadButton() -> some View {
Button {
getServersSummary()
} label: {
Image(systemName: "arrow.counterclockwise")
}
}
@ViewBuilder private func viewBody() -> some View {
if let summ = serversSummary {
List {
@@ -84,8 +89,8 @@ struct ServersSummaryView: View {
.pickerStyle(.segmented)
Picker("Server type", selection: $selectedServerType) {
Text("SMP").tag(PresentedServerType.smp)
Text("XFTP").tag(PresentedServerType.xftp)
Text("Messages").tag(PresentedServerType.smp)
Text("Files").tag(PresentedServerType.xftp)
}
.pickerStyle(.segmented)
}
@@ -95,59 +100,71 @@ struct ServersSummaryView: View {
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, "Current session")
}
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.")
}
resetStatsButtonSection()
} else {
noCategoryInfoText()
SMPSubsView(subs: summ.allSMPTotal.subs)
ServerSessionsView(sess: summ.allSMPTotal.sessions)
if summ.allUsedSMP.count > 0 {
smpServersListView(summ.allUsedSMP, showReconnectButton: true, summ.statsStartedAt, "Current app session")
}
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.")
}
SMPStatsView(stats: summ.allSMPTotal.stats, statsStartedAt: summ.statsStartedAt)
resetStatsButtonSection()
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, "Current session")
}
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.")
}
resetStatsButtonSection()
} else {
noCategoryInfoText()
SMPSubsView(subs: summ.userSMPTotal.subs)
ServerSessionsView(sess: summ.userSMPTotal.sessions)
if summ.userUsedSMP.count > 0 {
smpServersListView(summ.userUsedSMP, showReconnectButton: true, summ.statsStartedAt, "Current app session")
}
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.")
}
SMPStatsView(stats: summ.userSMPTotal.stats, statsStartedAt: summ.statsStartedAt)
resetStatsButtonSection()
case (.allUsers, .xftp):
if summ.allUsedXFTP.count > 0 || summ.allPrevXFTP.count > 0 {
if summ.allUsedXFTP.count > 0 {
xftpServersListView(summ.allUsedXFTP, summ.statsStartedAt, "Current session")
}
if summ.allPrevXFTP.count > 0 {
xftpServersListView(summ.allPrevXFTP, summ.statsStartedAt, "Previously used")
}
resetStatsButtonSection()
} else {
noCategoryInfoText()
ServerSessionsView(sess: summ.allXFTPTotal.sessions)
if summ.allUsedXFTP.count > 0 {
xftpServersListView(summ.allUsedXFTP, summ.statsStartedAt, "Current app session")
}
if summ.allPrevXFTP.count > 0 {
xftpServersListView(summ.allPrevXFTP, summ.statsStartedAt, "Previously used")
}
XFTPStatsView(stats: summ.allXFTPTotal.stats, statsStartedAt: summ.statsStartedAt)
resetStatsButtonSection()
case (.currentUser, .xftp):
if summ.userUsedXFTP.count > 0 || summ.userPrevXFTP.count > 0 {
if summ.userUsedXFTP.count > 0 {
xftpServersListView(summ.userUsedXFTP, summ.statsStartedAt, "Current session")
}
if summ.userPrevXFTP.count > 0 {
xftpServersListView(summ.userPrevXFTP, summ.statsStartedAt, "Previously used")
}
resetStatsButtonSection()
} else {
noCategoryInfoText()
ServerSessionsView(sess: summ.userXFTPTotal.sessions)
if summ.userUsedXFTP.count > 0 {
xftpServersListView(summ.userUsedXFTP, summ.statsStartedAt, "Current app session")
}
if summ.userPrevXFTP.count > 0 {
xftpServersListView(summ.userPrevXFTP, summ.statsStartedAt, "Previously used")
}
XFTPStatsView(stats: summ.userXFTPTotal.stats, statsStartedAt: summ.statsStartedAt)
resetStatsButtonSection()
}
}
} else {
@@ -240,18 +257,6 @@ struct ServersSummaryView: View {
}
}
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 resetStatsButtonSection() -> some View {
Section {
Button {
@@ -383,13 +388,13 @@ struct SMPServerSummaryView: View {
Section {
Text(summary.smpServer)
.textSelection(.enabled)
if let known = summary.known, !known {
Button {
// TODO
} label: {
Text("TODO Add as known")
}
}
// if let known = summary.known, !known {
// Button {
// // TODO
// } label: {
// Text("Add as known")
// }
// }
} header: {
Text("Server address")
} footer: {
@@ -403,15 +408,15 @@ struct SMPServerSummaryView: View {
}
if let subs = summary.subs {
subsSection(subs)
SMPSubsView(subs: subs)
}
if let sess = summary.sessions {
sessionsSection(sess)
ServerSessionsView(sess: sess)
}
if let stats = summary.stats {
statsSection(stats)
SMPStatsView(stats: stats, statsStartedAt: statsStartedAt)
}
}
.alert(item: $alert) { $0.alert }
@@ -448,28 +453,42 @@ struct SMPServerSummaryView: View {
}
}
}
}
private func subsSection(_ subs: SMPServerSubs) -> some View {
struct SMPSubsView: View {
var subs: SMPServerSubs
var body: some View {
Section {
infoRow("Active", "\(subs.ssActive)")
infoRow("Pending", "\(subs.ssPending)")
infoRow("Total", "\(subs.ssActive + subs.ssPending)")
} header: {
HStack {
Text("Subscriptions")
Text("Message subscriptions")
SubscriptionStatusView(activeSubs: subs.ssActive, pendingSubs: subs.ssPending)
}
}
}
}
private func sessionsSection(_ sess: ServerSessions) -> some View {
Section("Sessions") {
struct ServerSessionsView: View {
var sess: ServerSessions
var body: some View {
Section("Transport sessions") {
infoRow("Connected", "\(sess.ssConnected)")
infoRow("Errors", "\(sess.ssErrors)")
infoRow("Connecting", "\(sess.ssConnecting)")
}
}
}
private func statsSection(_ stats: AgentSMPServerStatsData) -> some View {
struct SMPStatsView: View {
var stats: AgentSMPServerStatsData
var statsStartedAt: Date
var body: some View {
Section("Statistics") {
infoRow("Starting from", localTimestamp(statsStartedAt))
infoRow("Messages sent directly", "\(stats._sentDirect)")
@@ -488,10 +507,14 @@ struct SMPServerSummaryView: View {
indentedInfoRow("other errors", "\(stats._recvErrs)")
infoRow("Messages acknowledged", "\(stats._ackMsgs)")
indentedInfoRow("attempts", "\(stats._ackAttempts)")
indentedInfoRow("NO_MSG errors", "\(stats._ackNoMsgErrs)")
indentedInfoRow("other errors", "\(stats._ackOtherErrs)")
infoRow("Connections created", "\(stats._connCreated)")
indentedInfoRow("secured", "\(stats._connSecured)")
indentedInfoRow("completed", "\(stats._connCompleted)")
infoRow("Connections deleted", "\(stats._connDeleted)")
indentedInfoRow("attempts", "\(stats._connDelAttempts)")
indentedInfoRow("errors", "\(stats._connDelErrs)")
infoRow("Connections subscribed", "\(stats._connSubscribed)")
indentedInfoRow("attempts", "\(stats._connSubAttempts)")
indentedInfoRow("errors", "\(stats._connSubErrs)")
@@ -518,13 +541,13 @@ struct XFTPServerSummaryView: View {
Section {
Text(summary.xftpServer)
.textSelection(.enabled)
if let known = summary.known, !known {
Button {
// TODO
} label: {
Text("TODO Add as known")
}
}
// if let known = summary.known, !known {
// Button {
// // TODO
// } label: {
// Text("Add as known")
// }
// }
} header: {
Text("Server address")
} footer: {
@@ -534,25 +557,17 @@ struct XFTPServerSummaryView: View {
}
if let sess = summary.sessions {
sessionsSection(sess)
ServerSessionsView(sess: sess)
}
inProgressSection()
if let stats = summary.stats {
statsSection(stats)
XFTPStatsView(stats: stats, statsStartedAt: statsStartedAt)
}
}
}
private func sessionsSection(_ sess: ServerSessions) -> some View {
Section("Sessions") {
infoRow("Connected", "\(sess.ssConnected)")
infoRow("Errors", "\(sess.ssErrors)")
infoRow("Connecting", "\(sess.ssConnecting)")
}
}
private func inProgressSection() -> some View {
Section("In progress") {
localizedInfoRow("Download", boolYesNo(summary.rcvInProgress))
@@ -564,14 +579,24 @@ struct XFTPServerSummaryView: View {
private func boolYesNo(_ b: Bool) -> LocalizedStringKey {
b ? "yes" : "no"
}
}
private func statsSection(_ stats: AgentXFTPServerStatsData) -> some View {
struct XFTPStatsView: View {
var stats: AgentXFTPServerStatsData
var statsStartedAt: Date
var body: some View {
let kb: Int64 = 1024
let prettyUploadsSize = ByteCountFormatter.string(fromByteCount: stats._uploadsSize * kb, countStyle: .binary)
let prettyDownloadsSize = ByteCountFormatter.string(fromByteCount: stats._downloadsSize * kb, countStyle: .binary)
Section("Statistics") {
infoRow("Starting from", localTimestamp(statsStartedAt))
infoRow("Chunks uploaded", "\(stats._uploads)")
indentedInfoRow("size", prettyUploadsSize)
indentedInfoRow("attempts", "\(stats._uploadAttempts)")
indentedInfoRow("errors", "\(stats._uploadErrs)")
infoRow("Chunks downloaded", "\(stats._downloads)")
indentedInfoRow("size", prettyDownloadsSize)
indentedInfoRow("attempts", "\(stats._downloadAttempts)")
indentedInfoRow("AUTH errors", "\(stats._downloadAuthErrs)")
indentedInfoRow("other errors", "\(stats._downloadErrs)")
+56 -33
View File
@@ -2255,29 +2255,41 @@ public struct PresentedServersSummary: Codable {
public var currentUserServers: ServersSummary
public var allUsersServers: ServersSummary
public var allSMPTotal: SMPTotals { self.allUsersServers.smpTotals }
public var allUsedSMP: [SMPServerSummary] { self.allUsersServers.currentlyUsedSMPServers }
public var allPrevSMP: [SMPServerSummary] { self.allUsersServers.previouslyUsedSMPServers }
public var allProxSMP: [SMPServerSummary] { self.allUsersServers.onlyProxiedSMPServers }
public var userSMPTotal: SMPTotals { self.currentUserServers.smpTotals }
public var userUsedSMP: [SMPServerSummary] { self.currentUserServers.currentlyUsedSMPServers }
public var userPrevSMP: [SMPServerSummary] { self.currentUserServers.previouslyUsedSMPServers }
public var userProxSMP: [SMPServerSummary] { self.currentUserServers.onlyProxiedSMPServers }
public var allXFTPTotal: XFTPTotals { self.allUsersServers.xftpTotals }
public var allUsedXFTP: [XFTPServerSummary] { self.allUsersServers.currentlyUsedXFTPServers }
public var allPrevXFTP: [XFTPServerSummary] { self.allUsersServers.previouslyUsedXFTPServers }
public var userXFTPTotal: XFTPTotals { self.currentUserServers.xftpTotals }
public var userUsedXFTP: [XFTPServerSummary] { self.currentUserServers.currentlyUsedXFTPServers }
public var userPrevXFTP: [XFTPServerSummary] { self.currentUserServers.previouslyUsedXFTPServers }
}
public struct ServersSummary: Codable {
public var smpTotals: SMPTotals
public var currentlyUsedSMPServers: [SMPServerSummary]
public var previouslyUsedSMPServers: [SMPServerSummary]
public var onlyProxiedSMPServers: [SMPServerSummary]
public var xftpTotals: XFTPTotals
public var currentlyUsedXFTPServers: [XFTPServerSummary]
public var previouslyUsedXFTPServers: [XFTPServerSummary]
}
public struct SMPTotals: Codable {
public var sessions: ServerSessions
public var subs: SMPServerSubs
public var stats: AgentSMPServerStatsData
}
public struct SMPServerSummary: Codable, Identifiable {
public var smpServer: String
public var known: Bool?
@@ -2305,29 +2317,38 @@ public struct SMPServerSubs: Codable {
}
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 _ackMsgs: Int
public var _ackAttempts: 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 var _sentDirect: Int64
public var _sentViaProxy: Int64
public var _sentProxied: Int64
public var _sentDirectAttempts: Int64
public var _sentViaProxyAttempts: Int64
public var _sentProxiedAttempts: Int64
public var _sentAuthErrs: Int64
public var _sentQuotaErrs: Int64
public var _sentExpiredErrs: Int64
public var _sentOtherErrs: Int64
public var _recvMsgs: Int64
public var _recvDuplicates: Int64
public var _recvCryptoErrs: Int64
public var _recvErrs: Int64
public var _ackMsgs: Int64
public var _ackAttempts: Int64
public var _ackNoMsgErrs: Int64
public var _ackOtherErrs: Int64
public var _connCreated: Int64
public var _connSecured: Int64
public var _connCompleted: Int64
public var _connDeleted: Int64
public var _connDelAttempts: Int64
public var _connDelErrs: Int64
public var _connSubscribed: Int64
public var _connSubAttempts: Int64
public var _connSubErrs: Int64
}
public struct XFTPTotals: Codable {
public var sessions: ServerSessions
public var stats: AgentXFTPServerStatsData
}
public struct XFTPServerSummary: Codable, Identifiable {
@@ -2343,14 +2364,16 @@ public struct XFTPServerSummary: Codable, Identifiable {
}
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
public var _uploads: Int64
public var _uploadsSize: Int64
public var _uploadAttempts: Int64
public var _uploadErrs: Int64
public var _downloads: Int64
public var _downloadsSize: Int64
public var _downloadAttempts: Int64
public var _downloadAuthErrs: Int64
public var _downloadErrs: Int64
public var _deletions: Int64
public var _deleteAttempts: Int64
public var _deleteErrs: Int64
}