Merge pull request #76 from marcusziade/feature/add-accessibility-labels

This commit is contained in:
jack
2025-07-10 17:07:34 +02:00
committed by GitHub
+25
View File
@@ -184,6 +184,7 @@ struct ContentView: View {
.foregroundColor(textColor) .foregroundColor(textColor)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.accessibilityLabel("Back to main chat")
Spacer() Spacer()
@@ -191,6 +192,7 @@ struct ContentView: View {
Image(systemName: "lock.fill") Image(systemName: "lock.fill")
.font(.system(size: 14)) .font(.system(size: 14))
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
.accessibilityLabel("Private chat with \(privatePeerNick)")
Text("\(privatePeerNick)") Text("\(privatePeerNick)")
.font(.system(size: 16, weight: .medium, design: .monospaced)) .font(.system(size: 16, weight: .medium, design: .monospaced))
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
@@ -208,6 +210,8 @@ struct ContentView: View {
.foregroundColor(viewModel.isFavorite(peerID: privatePeerID) ? Color.yellow : textColor) .foregroundColor(viewModel.isFavorite(peerID: privatePeerID) ? Color.yellow : textColor)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.accessibilityLabel(viewModel.isFavorite(peerID: privatePeerID) ? "Remove from favorites" : "Add to favorites")
.accessibilityHint("Double tap to toggle favorite status")
} else if let currentChannel = viewModel.currentChannel { } else if let currentChannel = viewModel.currentChannel {
// Channel header // Channel header
Button(action: { Button(action: {
@@ -222,6 +226,7 @@ struct ContentView: View {
.foregroundColor(textColor) .foregroundColor(textColor)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.accessibilityLabel("Back to main chat")
Spacer() Spacer()
@@ -236,6 +241,7 @@ struct ContentView: View {
Image(systemName: "lock.fill") Image(systemName: "lock.fill")
.font(.system(size: 14)) .font(.system(size: 14))
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
.accessibilityLabel("Password protected channel")
} }
Text("channel: \(currentChannel)") Text("channel: \(currentChannel)")
.font(.system(size: 16, weight: .medium, design: .monospaced)) .font(.system(size: 16, weight: .medium, design: .monospaced))
@@ -254,6 +260,7 @@ struct ContentView: View {
.font(.system(size: 16)) .font(.system(size: 16))
.foregroundColor(Color.yellow) .foregroundColor(Color.yellow)
.help("Messages in this channel are being saved locally") .help("Messages in this channel are being saved locally")
.accessibilityLabel("Message retention enabled")
} }
// Save button - only for channel owner // Save button - only for channel owner
@@ -267,6 +274,7 @@ struct ContentView: View {
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.help(viewModel.retentionEnabledChannels.contains(currentChannel) ? "Disable message retention" : "Enable message retention") .help(viewModel.retentionEnabledChannels.contains(currentChannel) ? "Disable message retention" : "Enable message retention")
.accessibilityLabel(viewModel.retentionEnabledChannels.contains(currentChannel) ? "Disable message retention" : "Enable message retention")
} }
// Password button for channel creator only // Password button for channel creator only
@@ -286,6 +294,7 @@ struct ContentView: View {
.foregroundColor(viewModel.passwordProtectedChannels.contains(currentChannel) ? Color.yellow : textColor) .foregroundColor(viewModel.passwordProtectedChannels.contains(currentChannel) ? Color.yellow : textColor)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.accessibilityLabel(viewModel.passwordProtectedChannels.contains(currentChannel) ? "Remove channel password" : "Set channel password")
} }
// Leave channel button // Leave channel button
@@ -351,12 +360,14 @@ struct ContentView: View {
Image(systemName: "number") Image(systemName: "number")
.font(.system(size: 12)) .font(.system(size: 12))
.foregroundColor(Color.blue) .foregroundColor(Color.blue)
.accessibilityLabel("Unread channel messages")
} }
if !viewModel.unreadPrivateMessages.isEmpty { if !viewModel.unreadPrivateMessages.isEmpty {
Image(systemName: "envelope.fill") Image(systemName: "envelope.fill")
.font(.system(size: 12)) .font(.system(size: 12))
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
.accessibilityLabel("Unread private messages")
} }
let otherPeersCount = viewModel.connectedPeers.filter { $0 != viewModel.meshService.myPeerID }.count let otherPeersCount = viewModel.connectedPeers.filter { $0 != viewModel.meshService.myPeerID }.count
@@ -366,8 +377,10 @@ struct ContentView: View {
// People icon with count // People icon with count
Image(systemName: "person.2.fill") Image(systemName: "person.2.fill")
.font(.system(size: 11)) .font(.system(size: 11))
.accessibilityLabel("\(otherPeersCount) connected \(otherPeersCount == 1 ? "person" : "people")")
Text("\(otherPeersCount)") Text("\(otherPeersCount)")
.font(.system(size: 12, design: .monospaced)) .font(.system(size: 12, design: .monospaced))
.accessibilityHidden(true)
// Channels icon with count (only if there are channels) // Channels icon with count (only if there are channels)
if channelCount > 0 { if channelCount > 0 {
@@ -375,8 +388,10 @@ struct ContentView: View {
.font(.system(size: 12, design: .monospaced)) .font(.system(size: 12, design: .monospaced))
Image(systemName: "square.split.2x2") Image(systemName: "square.split.2x2")
.font(.system(size: 11)) .font(.system(size: 11))
.accessibilityLabel("\(channelCount) active \(channelCount == 1 ? "channel" : "channels")")
Text("\(channelCount)") Text("\(channelCount)")
.font(.system(size: 12, design: .monospaced)) .font(.system(size: 12, design: .monospaced))
.accessibilityHidden(true)
} }
} }
.foregroundColor(viewModel.isConnected ? textColor : Color.red) .foregroundColor(viewModel.isConnected ? textColor : Color.red)
@@ -719,6 +734,8 @@ struct ContentView: View {
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.padding(.trailing, 12) .padding(.trailing, 12)
.accessibilityLabel("Send message")
.accessibilityHint(messageText.isEmpty ? "Enter a message to send" : "Double tap to send")
} }
.padding(.vertical, 8) .padding(.vertical, 8)
.background(backgroundColor.opacity(0.95)) .background(backgroundColor.opacity(0.95))
@@ -740,6 +757,7 @@ struct ContentView: View {
HStack(spacing: 4) { HStack(spacing: 4) {
Image(systemName: "square.split.2x2") Image(systemName: "square.split.2x2")
.font(.system(size: 10)) .font(.system(size: 10))
.accessibilityHidden(true)
Text("CHANNELS") Text("CHANNELS")
.font(.system(size: 11, weight: .bold, design: .monospaced)) .font(.system(size: 11, weight: .bold, design: .monospaced))
} }
@@ -775,6 +793,7 @@ struct ContentView: View {
Image(systemName: "lock.fill") Image(systemName: "lock.fill")
.font(.system(size: 10)) .font(.system(size: 10))
.foregroundColor(secondaryTextColor) .foregroundColor(secondaryTextColor)
.accessibilityLabel("Password protected")
} }
Text(channel) Text(channel)
@@ -835,6 +854,7 @@ struct ContentView: View {
) )
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.accessibilityLabel(viewModel.passwordProtectedChannels.contains(channel) ? "Remove password" : "Set password")
} }
// Leave button // Leave button
@@ -907,6 +927,7 @@ struct ContentView: View {
HStack(spacing: 4) { HStack(spacing: 4) {
Image(systemName: "person.2.fill") Image(systemName: "person.2.fill")
.font(.system(size: 10)) .font(.system(size: 10))
.accessibilityHidden(true)
Text("PEOPLE") Text("PEOPLE")
.font(.system(size: 11, weight: .bold, design: .monospaced)) .font(.system(size: 11, weight: .bold, design: .monospaced))
} }
@@ -978,14 +999,17 @@ struct ContentView: View {
Image(systemName: "person.fill") Image(systemName: "person.fill")
.font(.system(size: 10)) .font(.system(size: 10))
.foregroundColor(textColor) .foregroundColor(textColor)
.accessibilityLabel("You")
} else if viewModel.unreadPrivateMessages.contains(peerID) { } else if viewModel.unreadPrivateMessages.contains(peerID) {
Image(systemName: "envelope.fill") Image(systemName: "envelope.fill")
.font(.system(size: 12)) .font(.system(size: 12))
.foregroundColor(Color.orange) .foregroundColor(Color.orange)
.accessibilityLabel("Unread message from \(displayName)")
} else { } else {
Circle() Circle()
.fill(viewModel.getRSSIColor(rssi: rssi, colorScheme: colorScheme)) .fill(viewModel.getRSSIColor(rssi: rssi, colorScheme: colorScheme))
.frame(width: 8, height: 8) .frame(width: 8, height: 8)
.accessibilityLabel("Signal strength: \(rssi > -60 ? "excellent" : rssi > -70 ? "good" : rssi > -80 ? "fair" : "poor")")
} }
// Favorite star (not for self) // Favorite star (not for self)
@@ -998,6 +1022,7 @@ struct ContentView: View {
.foregroundColor(isFavorite ? Color.yellow : secondaryTextColor) .foregroundColor(isFavorite ? Color.yellow : secondaryTextColor)
} }
.buttonStyle(.plain) .buttonStyle(.plain)
.accessibilityLabel(isFavorite ? "Remove \(displayName) from favorites" : "Add \(displayName) to favorites")
} }
// Peer name // Peer name