mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-17 01:15:55 +00:00
ios: improve chat list layout (#4537)
This commit is contained in:
committed by
GitHub
parent
493ad14b39
commit
2ff4619ca4
@@ -257,6 +257,9 @@ struct SendMessageView: View {
|
||||
var body: some View {
|
||||
Button(action: {}) {
|
||||
Image(systemName: "mic.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundColor(theme.colors.primary)
|
||||
}
|
||||
.disabled(disabled)
|
||||
@@ -310,6 +313,9 @@ struct SendMessageView: View {
|
||||
}
|
||||
} label: {
|
||||
Image(systemName: "mic")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
}
|
||||
.disabled(composeState.inProgress)
|
||||
|
||||
@@ -9,30 +9,37 @@
|
||||
import SwiftUI
|
||||
import SimpleXChat
|
||||
|
||||
let dynamicSizes: [
|
||||
DynamicTypeSize: (
|
||||
rowHeight: CGFloat,
|
||||
profileImageSize: CGFloat,
|
||||
mediaSize: CGFloat,
|
||||
chatInfoSize: CGFloat,
|
||||
unreadCorner: CGFloat,
|
||||
unreadPadding: CGFloat
|
||||
)
|
||||
] = [
|
||||
.xSmall: (68, 55, 33, 18, 9, 3),
|
||||
.small: (72, 57, 34, 18, 9, 3),
|
||||
.medium: (76, 60, 36, 18, 10, 4),
|
||||
.large: (80, 63, 38, 20, 10, 4),
|
||||
.xLarge: (88, 67, 41, 20, 10, 4),
|
||||
.xxLarge: (94, 71, 44, 22, 11, 4),
|
||||
.xxxLarge: (104, 75, 48, 24, 12, 5),
|
||||
.accessibility1: (104, 75, 48, 24, 12, 5),
|
||||
.accessibility2: (114, 75, 48, 24, 12, 5),
|
||||
.accessibility3: (124, 75, 48, 24, 12, 5),
|
||||
.accessibility4: (134, 75, 48, 24, 12, 5),
|
||||
.accessibility5: (144, 75, 48, 24, 12, 5)
|
||||
typealias DynamicSizes = (
|
||||
rowHeight: CGFloat,
|
||||
profileImageSize: CGFloat,
|
||||
mediaSize: CGFloat,
|
||||
incognitoSize: CGFloat,
|
||||
chatInfoSize: CGFloat,
|
||||
unreadCorner: CGFloat,
|
||||
unreadPadding: CGFloat
|
||||
)
|
||||
|
||||
private let dynamicSizes: [DynamicTypeSize: DynamicSizes] = [
|
||||
.xSmall: (68, 55, 33, 22, 18, 9, 3),
|
||||
.small: (72, 57, 34, 22, 18, 9, 3),
|
||||
.medium: (76, 60, 36, 22, 18, 10, 4),
|
||||
.large: (80, 63, 38, 24, 20, 10, 4),
|
||||
.xLarge: (88, 67, 41, 24, 20, 10, 4),
|
||||
.xxLarge: (100, 71, 44, 27, 22, 11, 4),
|
||||
.xxxLarge: (110, 75, 48, 30, 24, 12, 5),
|
||||
.accessibility1: (110, 75, 48, 30, 24, 12, 5),
|
||||
.accessibility2: (114, 75, 48, 30, 24, 12, 5),
|
||||
.accessibility3: (124, 75, 48, 30, 24, 12, 5),
|
||||
.accessibility4: (134, 75, 48, 30, 24, 12, 5),
|
||||
.accessibility5: (144, 75, 48, 30, 24, 12, 5)
|
||||
]
|
||||
|
||||
private let defaultDynamicSizes: DynamicSizes = dynamicSizes[.large]!
|
||||
|
||||
func dynamicSize(_ font: DynamicTypeSize) -> DynamicSizes {
|
||||
dynamicSizes[font] ?? defaultDynamicSizes
|
||||
}
|
||||
|
||||
struct ChatListNavLink: View {
|
||||
@EnvironmentObject var chatModel: ChatModel
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
|
||||
@@ -22,14 +22,14 @@ struct ChatPreviewView: View {
|
||||
|
||||
@AppStorage(DEFAULT_PRIVACY_SHOW_CHAT_PREVIEWS) private var showChatPreviews = true
|
||||
|
||||
var dynamicMediaSize: CGFloat { dynamicSizes[userFont]?.mediaSize ?? 36 }
|
||||
var dynamicChatInfoSize: CGFloat { dynamicSizes[userFont]?.chatInfoSize ?? 18 }
|
||||
var dynamicMediaSize: CGFloat { dynamicSize(userFont).mediaSize }
|
||||
var dynamicChatInfoSize: CGFloat { dynamicSize(userFont).chatInfoSize }
|
||||
|
||||
var body: some View {
|
||||
let cItem = chat.chatItems.last
|
||||
return HStack(spacing: 8) {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
ChatInfoImage(chat: chat, size: dynamicSizes[userFont]?.profileImageSize ?? 63)
|
||||
ChatInfoImage(chat: chat, size: dynamicSize(userFont).profileImageSize)
|
||||
chatPreviewImageOverlayIcon()
|
||||
.padding([.bottom, .trailing], 1)
|
||||
}
|
||||
@@ -77,7 +77,7 @@ struct ChatPreviewView: View {
|
||||
checkActiveContentPreview(chat, ci, mc)
|
||||
}
|
||||
chatStatusImage()
|
||||
.padding(.top, 26)
|
||||
.padding(.top, dynamicChatInfoSize * 1.44)
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
@@ -198,10 +198,10 @@ struct ChatPreviewView: View {
|
||||
unreadCountText(s.unreadCount)
|
||||
.font(userFont <= .xxxLarge ? .caption : .caption2)
|
||||
.foregroundColor(.white)
|
||||
.padding(.horizontal, dynamicSizes[userFont]?.unreadPadding ?? 4)
|
||||
.padding(.horizontal, dynamicSize(userFont).unreadPadding)
|
||||
.frame(minWidth: dynamicChatInfoSize, minHeight: dynamicChatInfoSize)
|
||||
.background(chat.chatInfo.ntfsEnabled || chat.chatInfo.chatType == .local ? theme.colors.primary : theme.colors.secondary)
|
||||
.cornerRadius(dynamicSizes[userFont]?.unreadCorner ?? 10)
|
||||
.cornerRadius(dynamicSize(userFont).unreadCorner)
|
||||
} else if !chat.chatInfo.ntfsEnabled && chat.chatInfo.chatType != .local {
|
||||
Image(systemName: "speaker.slash.fill")
|
||||
.resizable()
|
||||
@@ -372,41 +372,42 @@ struct ChatPreviewView: View {
|
||||
}
|
||||
|
||||
@ViewBuilder private func chatStatusImage() -> some View {
|
||||
let size = dynamicSize(userFont).incognitoSize
|
||||
switch chat.chatInfo {
|
||||
case let .direct(contact):
|
||||
if contact.active && contact.activeConn != nil {
|
||||
switch (chatModel.contactNetworkStatus(contact)) {
|
||||
case .connected: incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary)
|
||||
case .connected: incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary, size: size)
|
||||
case .error:
|
||||
Image(systemName: "exclamationmark.circle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 17, height: 17)
|
||||
.frame(width: dynamicChatInfoSize, height: dynamicChatInfoSize)
|
||||
.foregroundColor(theme.colors.secondary)
|
||||
default:
|
||||
ProgressView()
|
||||
}
|
||||
} else {
|
||||
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary)
|
||||
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary, size: size)
|
||||
}
|
||||
case .group:
|
||||
if progressByTimeout {
|
||||
ProgressView()
|
||||
} else {
|
||||
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary)
|
||||
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary, size: size)
|
||||
}
|
||||
default:
|
||||
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary)
|
||||
incognitoIcon(chat.chatInfo.incognito, theme.colors.secondary, size: size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder func incognitoIcon(_ incognito: Bool, _ secondaryColor: Color) -> some View {
|
||||
@ViewBuilder func incognitoIcon(_ incognito: Bool, _ secondaryColor: Color, size: CGFloat) -> some View {
|
||||
if incognito {
|
||||
Image(systemName: "theatermasks")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 22, height: 22)
|
||||
.frame(width: size, height: size)
|
||||
.foregroundColor(secondaryColor)
|
||||
} else {
|
||||
EmptyView()
|
||||
|
||||
@@ -13,6 +13,7 @@ struct ContactConnectionView: View {
|
||||
@EnvironmentObject var m: ChatModel
|
||||
@ObservedObject var chat: Chat
|
||||
@EnvironmentObject var theme: AppTheme
|
||||
@Environment(\.dynamicTypeSize) private var userFont: DynamicTypeSize
|
||||
@State private var localAlias = ""
|
||||
@FocusState private var aliasTextFieldFocused: Bool
|
||||
@State private var showContactConnectionInfo = false
|
||||
@@ -62,7 +63,7 @@ struct ContactConnectionView: View {
|
||||
ZStack(alignment: .topTrailing) {
|
||||
Text(contactConnection.description)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
incognitoIcon(contactConnection.incognito, theme.colors.secondary)
|
||||
incognitoIcon(contactConnection.incognito, theme.colors.secondary, size: dynamicSize(userFont).incognitoSize)
|
||||
.padding(.top, 26)
|
||||
.frame(maxWidth: .infinity, alignment: .trailing)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ struct ContactRequestView: View {
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 8) {
|
||||
ChatInfoImage(chat: chat, size: dynamicSizes[userFont]?.profileImageSize ?? 63)
|
||||
ChatInfoImage(chat: chat, size: dynamicSize(userFont).profileImageSize)
|
||||
.padding(.leading, 4)
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
HStack(alignment: .top) {
|
||||
|
||||
Reference in New Issue
Block a user