Skip to content

Commit

Permalink
Adjust layout and colors of the voice recording view
Browse files Browse the repository at this point in the history
  • Loading branch information
laevandus committed Jan 8, 2025
1 parent af374ba commit 0240cfa
Show file tree
Hide file tree
Showing 41 changed files with 206 additions and 44 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Upcoming

### ✅ Added
- Colors and images for voice recording view [#704](https://github.com/GetStream/stream-chat-swiftui/pull/704)
- `ColorPalette.voiceMessageCurrentUserBackground` and `ColorPalette.voiceMessageOtherUserBackground`
- `ColorPalette.voiceMessageCurrentUserRecordingBackground` and `ColorPalette.voiceMessageOtherUserRecordingBackground`
- `ColorPalette.voiceMessageControlBackground`
- `Images.pauseFilled`

### 🐞 Fixed
- Use bright color for typing indicator animation in dark mode [#702](https://github.com/GetStream/stream-chat-swiftui/pull/702)

### 🔄 Changed
- Support theming and update layout of `VoiceRecordingContainerView` [#704](https://github.com/GetStream/stream-chat-swiftui/pull/704)

# [4.69.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.69.0)
_December 18, 2024_

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct AddedVoiceRecordingsView: View {
let recording = addedVoiceRecordings[i]
VoiceRecordingView(
handler: voiceRecordingHandler,
textColor: textColor(currentUser: true),
addedVoiceRecording: recording,
index: i
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public struct VoiceRecordingContainerView<Factory: ViewFactory>: View {
}

public var body: some View {
VStack {
VStack(spacing: 0) {
VStack {
if let quotedMessage = utils.messageCachingUtils.quotedMessage(for: message) {
factory.makeQuotedMessageView(
Expand All @@ -49,24 +49,26 @@ public struct VoiceRecordingContainerView<Factory: ViewFactory>: View {
scrolledId: $scrolledId
)
}

ForEach(message.voiceRecordingAttachments, id: \.self) { attachment in
VoiceRecordingView(
handler: handler,
addedVoiceRecording: AddedVoiceRecording(
url: attachment.payload.voiceRecordingURL,
duration: attachment.payload.duration ?? 0,
waveform: attachment.payload.waveformData ?? []
),
index: index(for: attachment)
)
VStack(spacing: 2) {
ForEach(message.voiceRecordingAttachments, id: \.self) { attachment in
VoiceRecordingView(
handler: handler,
textColor: textColor(for: message),
addedVoiceRecording: AddedVoiceRecording(
url: attachment.payload.voiceRecordingURL,
duration: attachment.payload.duration ?? 0,
waveform: attachment.payload.waveformData ?? []
),
index: index(for: attachment)
)
.padding(.all, 8)
.background(Color(recordingItemBackgroundColor))
.roundWithBorder(cornerRadius: 14)
}
}
}
.padding(.all, 8)
.background(Color(colors.background8))
.cornerRadius(16)
if !message.text.isEmpty {
AttachmentTextView(message: message)
AttachmentTextView(message: message, injectedBackgroundColor: bubbleBackgroundColor)
.frame(maxWidth: .infinity)
}
}
Expand Down Expand Up @@ -94,11 +96,28 @@ public struct VoiceRecordingContainerView<Factory: ViewFactory>: View {
}
.modifier(
factory.makeMessageViewModifier(
for: MessageModifierInfo(message: message, isFirst: isFirst)
for: MessageModifierInfo(
message: message,
isFirst: isFirst,
injectedBackgroundColor: bubbleBackgroundColor,
cornerRadius: 16
)
)
)
}

private var bubbleBackgroundColor: UIColor {
message.isSentByCurrentUser ?
colors.voiceMessageCurrentUserBackground :
colors.voiceMessageOtherUserBackground
}

private var recordingItemBackgroundColor: UIColor {
message.isSentByCurrentUser ?
colors.voiceMessageCurrentUserRecordingBackground :
colors.voiceMessageOtherUserRecordingBackground
}

private func index(for attachment: ChatMessageVoiceRecordingAttachment) -> Int {
message.voiceRecordingAttachments.firstIndex(of: attachment) ?? 0
}
Expand All @@ -114,6 +133,7 @@ struct VoiceRecordingView: View {
@State var rate: AudioPlaybackRate = .normal
@ObservedObject var handler: VoiceRecordingHandler

let textColor: Color
let addedVoiceRecording: AddedVoiceRecording
let index: Int

Expand All @@ -135,10 +155,17 @@ struct VoiceRecordingView: View {
Button(action: {
handlePlayTap()
}, label: {
Image(systemName: isPlaying ? "pause.fill" : "play.fill")
.padding(.all, 8)
Image(uiImage: isPlaying ? images.pauseFilled : images.playFilled)
.frame(width: 36, height: 36)
.foregroundColor(.primary)
.modifier(ShadowViewModifier(firstRadius: 2, firstY: 4))
.modifier(
ShadowViewModifier(
backgroundColor: colors.voiceMessageControlBackground,
cornerRadius: 18,
firstRadius: 2,
firstY: 4
)
)
})
.opacity(loading ? 0 : 1)
.overlay(loading ? ProgressView() : nil)
Expand All @@ -152,6 +179,7 @@ struct VoiceRecordingView: View {
)
.bold()
.lineLimit(1)
.foregroundColor(textColor)

HStack {
RecordingDurationView(
Expand Down Expand Up @@ -199,7 +227,7 @@ struct VoiceRecordingView: View {
Image(uiImage: images.fileAac)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 36)
.frame(height: 40)
}
}
.onReceive(handler.$context, perform: { value in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,11 @@ public struct AttachmentTextView: View {
@Injected(\.fonts) private var fonts

var message: ChatMessage
let injectedBackgroundColor: UIColor?

public init(message: ChatMessage) {
public init(message: ChatMessage, injectedBackgroundColor: UIColor? = nil) {
self.message = message
self.injectedBackgroundColor = injectedBackgroundColor
}

public var body: some View {
Expand All @@ -127,6 +129,9 @@ public struct AttachmentTextView: View {
}

private var backgroundColor: UIColor {
if let injectedBackgroundColor {
return injectedBackgroundColor
}
var colors = colors
if message.isSentByCurrentUser {
if message.type == .ephemeral {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,9 @@ extension View {
return Color(colors.messageOtherUserTextColor)
}
}

func textColor(currentUser: Bool) -> Color {
@Injected(\.colors) var colors
return currentUser ? Color(colors.messageCurrentUserTextColor) : Color(colors.messageOtherUserTextColor)
}
}
6 changes: 6 additions & 0 deletions Sources/StreamChatSwiftUI/ColorPalette.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ public struct ColorPalette {
public lazy var reactionCurrentUserColor: UIColor? = UIColor(tintColor)
public lazy var reactionOtherUserColor: UIColor? = textLowEmphasis
public lazy var selectedReactionBackgroundColor: UIColor? = nil
public var voiceMessageCurrentUserBackground: UIColor = .streamInnerBorder
public var voiceMessageOtherUserBackground: UIColor = .streamBarsBackground
public var voiceMessageCurrentUserRecordingBackground: UIColor = .streamBarsBackground
public var voiceMessageOtherUserRecordingBackground: UIColor = .streamBarsBackground
public var voiceMessageControlBackground: UIColor = .streamWhiteStatic

// MARK: - Composer

Expand Down Expand Up @@ -114,6 +119,7 @@ private extension UIColor {
static let streamInnerBorder = mode(0xdbdde1, 0x272a30)
static let streamHighlight = mode(0xfbf4dd, 0x333024)
static let streamDisabled = mode(0xb4b7bb, 0x4c525c)
static let streamBarsBackground = mode(0xffffff, 0x17191c)

// Currently we are not using the correct shadow color from figma's color palette. This is to avoid
// an issue with snapshots inconsistency between Intel vs M1. We can't use shadows with transparency.
Expand Down
1 change: 1 addition & 0 deletions Sources/StreamChatSwiftUI/Images.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ public class Images {
public var play: UIImage = loadImageSafely(with: "play")
public var playFilled: UIImage = UIImage(systemName: "play.fill")!
public var pause: UIImage = loadImageSafely(with: "pause")
public var pauseFilled: UIImage = loadImageSafely(with: "pause.fill")

public var checkmarkFilled: UIImage = UIImage(systemName: "checkmark.circle.fill")!

Expand Down
3 changes: 2 additions & 1 deletion Sources/StreamChatSwiftUI/Utils/Modifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import SwiftUI
struct ShadowViewModifier: ViewModifier {
@Injected(\.colors) private var colors

var backgroundColor: UIColor = .systemBackground
var cornerRadius: CGFloat = 16
var firstRadius: CGFloat = 10
var firstY: CGFloat = 12

func body(content: Content) -> some View {
content.background(Color(UIColor.systemBackground))
content.background(Color(backgroundColor))
.cornerRadius(cornerRadius)
.modifier(ShadowModifier(firstRadius: firstRadius, firstY: firstY))
.overlay(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,28 @@ class ChatChannelTestHelpers {
return fileAttachments
}

static func voiceRecordingAttachments(count: Int) -> [AnyChatMessageAttachment] {
(0..<count).map { index in
let title = index == 0 ? "Recording" : "Recording-\(index)"
let payload = VoiceRecordingAttachmentPayload(
title: title,
voiceRecordingRemoteURL: .localYodaImage,
file: try! .init(url: .localYodaImage),
duration: Double(index) + 5.0,
waveformData: [0, 0.1, 0.5, 1],
extraData: nil
)
return ChatMessageVoiceRecordingAttachment(
id: .unique,
type: .voiceRecording,
payload: payload,
downloadingState: nil,
uploadingState: nil
).asAnyAttachment
}
}

static var voiceRecordingAttachments: [AnyChatMessageAttachment] {
let payload = VoiceRecordingAttachmentPayload(
title: "Recording",
voiceRecordingRemoteURL: .localYodaImage,
file: try! .init(url: .localYodaImage),
duration: 5,
waveformData: [0, 0.1, 0.5, 1],
extraData: nil
)
let attachment = ChatMessageVoiceRecordingAttachment(
id: .unique,
type: .voiceRecording,
payload: payload,
downloadingState: nil,
uploadingState: nil
).asAnyAttachment

return [attachment]
voiceRecordingAttachments(count: 1)
}
}
Loading

0 comments on commit 0240cfa

Please sign in to comment.