mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 21:06:00 +00:00
Voice message UI polish (part 2) (#1995)
* Update compund * Fix create poll screen bin button style * Fix timeline menu description for voice messages * Fix bin button in ComposerToolbar * Add VoiceMessageButtonStyle * Update compound & fix breaking changes * Fix voice message bin size * Refactor VoiceMessageRecordingButton * Fix preview tests
This commit is contained in:
@@ -49,8 +49,6 @@ internal enum Asset {
|
||||
internal static let inlineCode = ImageAsset(name: "images/inline-code")
|
||||
internal static let italic = ImageAsset(name: "images/italic")
|
||||
internal static let link = ImageAsset(name: "images/link")
|
||||
internal static let micFill = ImageAsset(name: "images/mic-fill")
|
||||
internal static let mic = ImageAsset(name: "images/mic")
|
||||
internal static let numberedList = ImageAsset(name: "images/numbered-list")
|
||||
internal static let quote = ImageAsset(name: "images/quote")
|
||||
internal static let sendMessage = ImageAsset(name: "images/send-message")
|
||||
|
||||
@@ -53,7 +53,7 @@ struct VoiceMessageButton: View {
|
||||
.frame(width: buttonSize, height: buttonSize)
|
||||
}
|
||||
.animation(nil, value: state)
|
||||
.buttonStyle(.plain)
|
||||
.buttonStyle(VoiceMessageButtonStyle())
|
||||
.disabled(state == .loading)
|
||||
.background(Circle().foregroundColor(.compound.bgCanvasDefault))
|
||||
}
|
||||
@@ -73,12 +73,20 @@ struct VoiceMessageButton: View {
|
||||
.scaledToFit()
|
||||
.frame(width: imageWidth, height: imageHeight)
|
||||
.offset(x: offset)
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
.accessibilityLabel(accessibilityLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct VoiceMessageButtonStyle: ButtonStyle {
|
||||
@Environment(\.isEnabled) var isEnabled: Bool
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
configuration.label
|
||||
.foregroundColor(isEnabled ? .compound.textSecondary.opacity(configuration.isPressed ? 0.6 : 1) : .compound.iconDisabled)
|
||||
}
|
||||
}
|
||||
|
||||
extension VoiceMessageButton.State {
|
||||
init(state: AudioPlayerPlaybackState) {
|
||||
switch state {
|
||||
|
||||
@@ -25,7 +25,6 @@ struct ComposerToolbar: View {
|
||||
|
||||
@FocusState private var composerFocused: Bool
|
||||
@ScaledMetric private var sendButtonIconSize = 16
|
||||
@ScaledMetric private var trashButtonIconSize = 24
|
||||
@ScaledMetric(relativeTo: .title) private var spinnerSize = 44
|
||||
@ScaledMetric(relativeTo: .title) private var closeRTEButtonSize = 30
|
||||
|
||||
@@ -288,18 +287,14 @@ struct ComposerToolbar: View {
|
||||
}
|
||||
|
||||
private var voiceMessageTrashButton: some View {
|
||||
Button {
|
||||
Button(role: .destructive) {
|
||||
context.send(viewAction: .deleteVoiceMessageRecording)
|
||||
} label: {
|
||||
CompoundIcon(\.delete)
|
||||
.font(.compound.bodyLG)
|
||||
.foregroundColor(.compound.textCriticalPrimary)
|
||||
.frame(width: trashButtonIconSize, height: trashButtonIconSize)
|
||||
.padding(EdgeInsets(top: 10, leading: 11, bottom: 10, trailing: 11))
|
||||
.fixedSize()
|
||||
.accessibilityLabel(L10n.a11yDelete)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.buttonStyle(.compound(.plain))
|
||||
.accessibilityLabel(L10n.a11yDelete)
|
||||
}
|
||||
|
||||
private var voiceMessageRecordingButtonTooltipView: some View {
|
||||
|
||||
@@ -18,7 +18,6 @@ import Compound
|
||||
import SwiftUI
|
||||
|
||||
struct VoiceMessageRecordingButton: View {
|
||||
@ScaledMetric private var buttonIconSize = 24
|
||||
@State private var buttonPressed = false
|
||||
|
||||
var startRecording: (() -> Void)?
|
||||
@@ -38,14 +37,11 @@ struct VoiceMessageRecordingButton: View {
|
||||
stopRecording?()
|
||||
}
|
||||
}
|
||||
.fixedSize()
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var voiceMessageButtonImage: some View {
|
||||
(buttonPressed ? Image(asset: Asset.Images.micFill) : Image(asset: Asset.Images.mic))
|
||||
.resizable()
|
||||
.frame(width: buttonIconSize, height: buttonIconSize)
|
||||
CompoundIcon(buttonPressed ? \.micOnSolid : \.micOnOutline)
|
||||
.foregroundColor(.compound.iconSecondary)
|
||||
.padding(EdgeInsets(top: 6, leading: 6, bottom: 6, trailing: 6))
|
||||
.accessibilityLabel(L10n.a11yVoiceMessageRecord)
|
||||
|
||||
@@ -139,12 +139,11 @@ private struct CreatePollOptionView: View {
|
||||
var body: some View {
|
||||
HStack {
|
||||
if editMode?.wrappedValue == .active {
|
||||
Button(action: deleteAction) {
|
||||
Button(role: .destructive, action: deleteAction) {
|
||||
CompoundIcon(\.delete)
|
||||
.foregroundColor(.compound.iconCriticalPrimary)
|
||||
}
|
||||
.disabled(!canDeleteItem)
|
||||
.buttonStyle(.plain)
|
||||
.buttonStyle(.compound(.plain))
|
||||
.accessibilityLabel(L10n.actionRemove)
|
||||
}
|
||||
TextField(text: $text) {
|
||||
|
||||
@@ -167,7 +167,7 @@ struct RoomScreen: View {
|
||||
Button {
|
||||
context.send(viewAction: .presentCall)
|
||||
} label: {
|
||||
Label(L10n.actionJoin, icon: \.videoCall)
|
||||
Label(L10n.actionJoin, icon: \.videoCallSolid)
|
||||
.labelStyle(.titleAndIcon)
|
||||
}
|
||||
.buttonStyle(ElementCallButtonStyle())
|
||||
@@ -175,7 +175,7 @@ struct RoomScreen: View {
|
||||
Button {
|
||||
context.send(viewAction: .presentCall)
|
||||
} label: {
|
||||
CompoundIcon(\.videoCall)
|
||||
CompoundIcon(\.videoCallSolid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ struct EncryptedHistoryRoomTimelineView: View {
|
||||
.font(.compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.textInfoPrimary)
|
||||
} icon: {
|
||||
CompoundIcon(\.info, size: .small, relativeTo: .compound.bodyMDSemibold)
|
||||
CompoundIcon(\.infoSolid, size: .small, relativeTo: .compound.bodyMDSemibold)
|
||||
.foregroundColor(.compound.iconInfoPrimary)
|
||||
}
|
||||
.labelStyle(EncryptedHistoryLabelStyle())
|
||||
|
||||
@@ -193,7 +193,7 @@ public struct TimelineItemMenu: View {
|
||||
.font(.compound.bodySMSemibold)
|
||||
.foregroundColor(.compound.textPrimary)
|
||||
|
||||
Text(item.body.trimmingCharacters(in: .whitespacesAndNewlines))
|
||||
Text(item.timelineMenuDescription)
|
||||
.font(.compound.bodyMD)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.lineLimit(1)
|
||||
|
||||
+1
-1
@@ -134,7 +134,7 @@ struct SecureBackupRecoveryKeyScreen: View {
|
||||
|
||||
HStack(alignment: .top) {
|
||||
if context.viewState.recoveryKey == nil {
|
||||
CompoundIcon(\.info, size: .small, relativeTo: .compound.bodySM)
|
||||
CompoundIcon(\.infoSolid, size: .small, relativeTo: .compound.bodySM)
|
||||
}
|
||||
|
||||
Text(context.viewState.recoveryKeySubtitle)
|
||||
|
||||
@@ -59,6 +59,15 @@ extension EventBasedTimelineItemProtocol {
|
||||
self is EncryptedRoomTimelineItem
|
||||
}
|
||||
|
||||
var timelineMenuDescription: String {
|
||||
switch self {
|
||||
case is VoiceMessageRoomTimelineItem:
|
||||
return L10n.commonVoiceMessage
|
||||
default:
|
||||
return body.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
}
|
||||
|
||||
func additionalWhitespaces(timelineStyle: TimelineStyle) -> Int {
|
||||
guard timelineStyle == .bubbles else {
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user