Skip to content
Snippets Groups Projects
Commit 32a363d5 authored by Bruno Muniz's avatar Bruno Muniz :apple:
Browse files

Fixed bubbles and cell configuration

parent 80b177b0
No related branches found
No related tags found
2 merge requests!40v1.1.2b166,!38Using new database structure
......@@ -329,26 +329,23 @@ extension GroupChatController: UICollectionViewDataSource {
let canReply: () -> Bool = { item.status == .sent || item.status == .received }
let performReply: () -> Void = { [weak self] in
//self?.viewModel.didRequestReply(item)
self?.viewModel.didRequestReply(item)
}
let name: (Data) -> String = viewModel.getName(from:)
let text: (Data) -> String = viewModel.getText(from:)
let showRound: (String?) -> Void = viewModel.showRoundFrom(_:)
let replyContent: (Data) -> (String, String) = viewModel.getReplyContent(for:)
if item.status == .received {
if item.replyMessageId != nil {
let cell: IncomingGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
// Bubbler.buildReplyGroup(
// bubble: cell.leftView,
// with: item,
// reply: .init(
// text: text(item.payload.reply!.messageId),
// sender: name(item.payload.reply!.senderId)
// ),
// sender: name(item.sender)
// )
Bubbler.buildReplyGroup(
bubble: cell.leftView,
with: item,
reply: replyContent(item.replyMessageId!),
sender: name(item.senderId)
)
cell.canReply = canReply()
cell.performReply = performReply
......@@ -357,7 +354,12 @@ extension GroupChatController: UICollectionViewDataSource {
return cell
} else {
let cell: IncomingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
// Bubbler.buildGroup(bubble: cell.leftView, with: item, with: name(item.sender))
Bubbler.buildGroup(
bubble: cell.leftView,
with: item,
with: name(item.senderId)
)
cell.canReply = canReply()
cell.performReply = performReply
cell.leftView.didTapShowRound = { showRound(item.roundURL) }
......@@ -368,15 +370,12 @@ extension GroupChatController: UICollectionViewDataSource {
if item.replyMessageId != nil {
let cell: OutgoingFailedGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
// Bubbler.buildReplyGroup(
// bubble: cell.rightView,
// with: item,
// reply: .init(
// text: text(item.payload.reply!.messageId),
// sender: name(item.payload.reply!.senderId)
// ),
// sender: name(item.sender)
// )
Bubbler.buildReplyGroup(
bubble: cell.rightView,
with: item,
reply: replyContent(item.replyMessageId!),
sender: name(item.senderId)
)
cell.canReply = canReply()
cell.performReply = performReply
......@@ -385,7 +384,12 @@ extension GroupChatController: UICollectionViewDataSource {
} else {
let cell: OutgoingFailedGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
// Bubbler.buildGroup(bubble: cell.rightView, with: item, with: name(item.sender))
Bubbler.buildGroup(
bubble: cell.rightView,
with: item,
with: name(item.senderId)
)
cell.canReply = canReply()
cell.performReply = performReply
......@@ -395,15 +399,12 @@ extension GroupChatController: UICollectionViewDataSource {
if item.replyMessageId != nil {
let cell: OutgoingGroupReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
// Bubbler.buildReplyGroup(
// bubble: cell.rightView,
// with: item,
// reply: .init(
// text: text(item.payload.reply!.messageId),
// sender: name(item.payload.reply!.senderId)
// ),
// sender: name(item.sender)
// )
Bubbler.buildReplyGroup(
bubble: cell.rightView,
with: item,
reply: replyContent(item.replyMessageId!),
sender: name(item.senderId)
)
cell.canReply = canReply()
cell.performReply = performReply
......@@ -413,7 +414,12 @@ extension GroupChatController: UICollectionViewDataSource {
} else {
let cell: OutgoingGroupTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
// Bubbler.buildGroup(bubble: cell.rightView, with: item, with: name(item.sender))
Bubbler.buildGroup(
bubble: cell.rightView,
with: item,
with: name(item.senderId)
)
cell.canReply = canReply()
cell.performReply = performReply
cell.rightView.didTapShowRound = { showRound(item.roundURL) }
......@@ -537,7 +543,7 @@ extension GroupChatController: UICollectionViewDelegate {
}
let reply = UIAction(title: Localized.Chat.BubbleMenu.reply, state: .off) { [weak self] _ in
//self?.viewModel.didRequestReply(item)
self?.viewModel.didRequestReply(item)
}
let delete = UIAction(title: Localized.Chat.BubbleMenu.delete, state: .off) { [weak self] _ in
......
......@@ -489,10 +489,9 @@ extension SingleChatController: UICollectionViewDataSource {
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
let name: (Data) -> String = viewModel.getName(from:)
let text: (Data) -> String = viewModel.getText(from:)
let showRound: (String?) -> Void = viewModel.showRoundFrom(_:)
let item = sections[indexPath.section].elements[indexPath.item]
let replyContent: (Data) -> (String, String) = viewModel.getReplyContent(for:)
let performReply: () -> Void = { [weak self] in self?.viewModel.didRequestReply(item) }
let factory = CellFactory.combined(factories: [
......@@ -503,9 +502,9 @@ extension SingleChatController: UICollectionViewDataSource {
.incomingText(performReply: performReply, showRound: showRound),
.outgoingText(performReply: performReply, showRound: showRound),
.outgoingFailedText(performReply: performReply),
.incomingReply(performReply: performReply, name: name, text: text, showRound: showRound),
.outgoingReply(performReply: performReply, name: name, text: text, showRound: showRound),
.outgoingFailedReply(performReply: performReply, name: name, text: text)
.incomingReply(performReply: performReply, replyContent: replyContent, showRound: showRound),
.outgoingReply(performReply: performReply, replyContent: replyContent, showRound: showRound),
.outgoingFailedReply(performReply: performReply, replyContent: replyContent)
])
return factory(item: item, collectionView: collectionView, indexPath: indexPath)
......
import UIKit
import Shared
import XXModels
final class Bubbler {
static func build(
audioBubble: AudioMessageView,
with item: ChatItem
with item: Message
) {
audioBubble.dateLabel.text = item.date.asHoursAndMinutes()
......@@ -41,7 +42,7 @@ final class Bubbler {
static func build(
imageBubble: ImageMessageView,
with item: ChatItem
with item: Message
) {
// let progress = item.payload.attachment!.progress
// imageBubble.progressLabel.text = String(format: "%.1f%%", progress * 100)
......@@ -80,9 +81,9 @@ final class Bubbler {
static func build(
bubble: StackMessageView,
with item: ChatItem
with item: Message
) {
bubble.textView.text = item.payload.text
bubble.textView.text = item.text
bubble.senderLabel.removeFromSuperview()
bubble.dateLabel.text = item.date.asHoursAndMinutes()
......@@ -135,14 +136,14 @@ final class Bubbler {
static func buildReply(
bubble: ReplyStackMessageView,
with item: ChatItem,
reply: ReplyModel
with item: Message,
reply: (contactTitle: String, messageText: String)
) {
bubble.dateLabel.text = item.date.asHoursAndMinutes()
bubble.textView.text = item.payload.text
bubble.textView.text = item.text
bubble.replyView.message.text = reply.text
bubble.replyView.title.text = reply.sender
bubble.replyView.message.text = reply.messageText
bubble.replyView.title.text = reply.contactTitle
let roundButtonColor: UIColor
......@@ -195,4 +196,112 @@ final class Bubbler {
)
bubble.roundButton.setAttributedTitle(attrString, for: .normal)
}
static func buildReplyGroup(
bubble: ReplyStackMessageView,
with item: Message,
reply: (contactTitle: String, messageText: String),
sender: String
) {
bubble.dateLabel.text = item.date.asHoursAndMinutes()
bubble.textView.text = item.text
bubble.replyView.message.text = reply.messageText
bubble.replyView.title.text = reply.contactTitle
let roundButtonColor: UIColor
switch item.status {
case .received, .receiving:
bubble.senderLabel.text = sender
bubble.backgroundColor = Asset.neutralWhite.color
bubble.textView.textColor = Asset.neutralActive.color
bubble.dateLabel.textColor = Asset.neutralDisabled.color
roundButtonColor = Asset.neutralDisabled.color
bubble.replyView.container.backgroundColor = Asset.brandDefault.color
bubble.replyView.space.backgroundColor = Asset.brandPrimary.color
bubble.lockerImageView.removeFromSuperview()
bubble.revertBottomStackOrder()
case .sendingFailed, .sendingTimedOut:
bubble.senderLabel.removeFromSuperview()
bubble.backgroundColor = Asset.accentDanger.color
bubble.textView.textColor = Asset.neutralWhite.color
bubble.dateLabel.textColor = Asset.neutralWhite.color
roundButtonColor = Asset.neutralWhite.color
bubble.replyView.space.backgroundColor = Asset.neutralWhite.color
bubble.replyView.container.backgroundColor = Asset.brandLight.color
case .sent, .sending:
bubble.senderLabel.removeFromSuperview()
bubble.textView.textColor = Asset.neutralWhite.color
bubble.backgroundColor = Asset.brandBubble.color
bubble.dateLabel.textColor = Asset.neutralWhite.color
roundButtonColor = Asset.neutralWhite.color
bubble.replyView.space.backgroundColor = Asset.neutralWhite.color
bubble.replyView.container.backgroundColor = Asset.brandLight.color
case .receivingFailed:
fatalError()
}
let attrString = NSAttributedString(
string: "show mix",
attributes: [
.underlineStyle: NSUnderlineStyle.single.rawValue,
.underlineColor: roundButtonColor,
.foregroundColor: roundButtonColor,
.font: Fonts.Mulish.regular.font(size: 12.0) as Any
]
)
bubble.roundButton.setAttributedTitle(attrString, for: .normal)
}
static func buildGroup(
bubble: StackMessageView,
with item: Message,
with senderName: String
) {
bubble.textView.text = item.text
bubble.dateLabel.text = item.date.asHoursAndMinutes()
let roundButtonColor: UIColor
switch item.status {
case .received, .receiving:
bubble.senderLabel.text = senderName
bubble.backgroundColor = Asset.neutralWhite.color
bubble.textView.textColor = Asset.neutralActive.color
bubble.dateLabel.textColor = Asset.neutralDisabled.color
roundButtonColor = Asset.neutralDisabled.color
bubble.lockerImageView.removeFromSuperview()
bubble.revertBottomStackOrder()
case .sendingFailed, .sendingTimedOut:
bubble.senderLabel.removeFromSuperview()
bubble.backgroundColor = Asset.accentDanger.color
bubble.textView.textColor = Asset.neutralWhite.color
bubble.dateLabel.textColor = Asset.neutralWhite.color
roundButtonColor = Asset.neutralWhite.color
case .sent, .sending:
bubble.senderLabel.removeFromSuperview()
bubble.backgroundColor = Asset.brandBubble.color
bubble.textView.textColor = Asset.neutralWhite.color
bubble.dateLabel.textColor = Asset.neutralWhite.color
roundButtonColor = Asset.neutralWhite.color
case .receivingFailed:
fatalError()
}
let attrString = NSAttributedString(
string: "show mix",
attributes: [
.underlineStyle: NSUnderlineStyle.single.rawValue,
.underlineColor: roundButtonColor,
.foregroundColor: roundButtonColor,
.font: Fonts.Mulish.regular.font(size: 12.0) as Any
]
)
bubble.roundButton.setAttributedTitle(attrString, for: .normal)
}
}
import UIKit
import Shared
import Combine
import XXModels
import Voxophone
import AVFoundation
struct CellFactory {
var canBuild: (ChatItem) -> Bool
var canBuild: (Message) -> Bool
var build: (ChatItem, UICollectionView, IndexPath) -> UICollectionViewCell
var build: (Message, UICollectionView, IndexPath) -> UICollectionViewCell
func callAsFunction(
item: ChatItem,
item: Message,
collectionView: UICollectionView,
indexPath: IndexPath
) -> UICollectionViewCell {
......@@ -236,14 +237,13 @@ extension CellFactory {
extension CellFactory {
static func outgoingReply(
performReply: @escaping () -> Void,
name: @escaping (Data) -> String,
text: @escaping (Data) -> String,
replyContent: @escaping (Data) -> (String, String),
showRound: @escaping (String?) -> Void
) -> Self {
.init(
canBuild: { item in
(item.status == .sent || item.status == .sending)
&& item.payload.reply != nil
&& item.replyMessageId != nil
}, build: { item, collectionView, indexPath in
let cell: OutgoingReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
......@@ -251,10 +251,7 @@ extension CellFactory {
Bubbler.buildReply(
bubble: cell.rightView,
with: item,
reply: .init(
text: text(item.payload.reply!.messageId),
sender: name(item.payload.reply!.senderId)
)
reply: replyContent(item.replyMessageId!)
)
cell.canReply = item.status == .sent
......@@ -267,14 +264,13 @@ extension CellFactory {
static func incomingReply(
performReply: @escaping () -> Void,
name: @escaping (Data) -> String,
text: @escaping (Data) -> String,
replyContent: @escaping (Data) -> (String, String),
showRound: @escaping (String?) -> Void
) -> Self {
.init(
canBuild: { item in
item.status == .received
&& item.payload.reply != nil
&& item.replyMessageId != nil
}, build: { item, collectionView, indexPath in
let cell: IncomingReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
......@@ -282,10 +278,7 @@ extension CellFactory {
Bubbler.buildReply(
bubble: cell.leftView,
with: item,
reply: .init(
text: text(item.payload.reply!.messageId),
sender: name(item.payload.reply!.senderId)
)
reply: replyContent(item.replyMessageId!)
)
cell.canReply = item.status == .received
cell.performReply = performReply
......@@ -298,13 +291,12 @@ extension CellFactory {
static func outgoingFailedReply(
performReply: @escaping () -> Void,
name: @escaping (Data) -> String,
text: @escaping (Data) -> String
replyContent: @escaping (Data) -> (String, String)
) -> Self {
.init(
canBuild: { item in
(item.status == .sendingFailed || item.status == .sendingTimedOut)
&& item.payload.reply != nil
&& item.replyMessageId != nil
}, build: { item, collectionView, indexPath in
let cell: OutgoingFailedReplyCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
......@@ -312,10 +304,7 @@ extension CellFactory {
Bubbler.buildReply(
bubble: cell.rightView,
with: item,
reply: .init(
text: text(item.payload.reply!.messageId),
sender: name(item.payload.reply!.senderId)
)
reply: replyContent(item.replyMessageId!)
)
cell.canReply = false
......@@ -334,7 +323,7 @@ extension CellFactory {
.init(
canBuild: { item in
item.status == .received
&& item.payload.reply == nil
&& item.replyMessageId == nil
}, build: { item, collectionView, indexPath in
let cell: IncomingTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
......@@ -356,7 +345,7 @@ extension CellFactory {
.init(
canBuild: { item in
(item.status == .sending || item.status == .sent)
&& item.payload.reply == nil
&& item.replyMessageId == nil
}, build: { item, collectionView, indexPath in
let cell: OutgoingTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
......@@ -375,7 +364,7 @@ extension CellFactory {
.init(
canBuild: { item in
(item.status == .sendingFailed || item.status == .sendingTimedOut)
&& item.payload.reply == nil
&& item.replyMessageId == nil
}, build: { item, collectionView, indexPath in
let cell: OutgoingFailedTextCell = collectionView.dequeueReusableCell(forIndexPath: indexPath)
......@@ -412,9 +401,9 @@ struct ActionFactory {
}
static func build(
from item: ChatItem,
from item: Message,
action: Action,
closure: @escaping (ChatItem) -> Void
closure: @escaping (Message) -> Void
) -> UIAction? {
switch action {
......
......@@ -88,6 +88,19 @@ final class GroupChatViewModel {
stagedReply = nil
}
func getReplyContent(for messageId: Data) -> (String, String) {
guard let message = try? session.dbManager.fetchMessages(.init(networkId: messageId)).first else {
return ("[DELETED]", "[DELETED]")
}
guard let contact = try? session.dbManager.fetchContacts(.init(id: [message.senderId])).first else {
return ("You", message.text)
}
let contactTitle = (contact.nickname ?? contact.username) ?? "Fetching username..."
return (contactTitle, message.text)
}
func getName(from senderId: Data) -> String {
guard let contact = try? session.dbManager.fetchContacts(.init(id: [senderId])).first else {
return "You"
......@@ -96,17 +109,22 @@ final class GroupChatViewModel {
return (contact.nickname ?? contact.username) ?? "Fetching username..."
}
func getText(from messageId: Data) -> String {
guard let message = try? session.dbManager.fetchMessages(.init(networkId: messageId)).first else {
return "[DELETED]"
func didRequestReply(_ message: Message) {
guard let networkId = message.networkId else { return }
let senderTitle: String = {
if message.senderId == session.myId {
return "You"
} else {
guard let contact = try? session.dbManager.fetchContacts(.init(id: [message.senderId])).first else {
return "Error"
}
return message.text
return (contact.nickname ?? contact.username) ?? "Fetching username..."
}
}()
func didRequestReply(_ message: Message) {
guard let networkId = message.networkId else { return }
stagedReply = Reply(messageId: networkId, senderId: message.senderId)
replySubject.send((getName(from: message.senderId), message.text))
replySubject.send((senderTitle, message.text))
}
}
......@@ -181,6 +181,8 @@ final class SingleChatViewModel {
}
func didRequestReply(_ message: Message) {
guard let networkId = message.networkId else { return }
let senderTitle: String = {
if message.senderId == session.myId {
return "You"
......@@ -190,15 +192,20 @@ final class SingleChatViewModel {
}()
replySubject.send((senderTitle, message.text))
stagedReply = Reply(messageId: message.networkId!, senderId: message.senderId)
stagedReply = Reply(messageId: networkId, senderId: message.senderId)
}
func getText(from messageId: Data) -> String {
func getReplyContent(for messageId: Data) -> (String, String) {
guard let message = try? session.dbManager.fetchMessages(.init(networkId: messageId)).first else {
return "[DELETED]"
return ("[DELETED]", "[DELETED]")
}
guard let contact = try? session.dbManager.fetchContacts(.init(id: [message.senderId])).first else {
return ("You", message.text)
}
return message.text
let contactTitle = (contact.nickname ?? contact.username) ?? "Fetching username..."
return (contactTitle, message.text)
}
func showRoundFrom(_ roundURL: String?) {
......@@ -217,10 +224,6 @@ final class SingleChatViewModel {
sectionsRelay.value.flatMap(\.elements).first(where: { $0.id == id })
}
func getName(from senderId: Data) -> String {
senderId == session.myId ? "You" : contact.nickname ?? contact.username!
}
func itemAt(indexPath: IndexPath) -> Message? {
guard sectionsRelay.value.count > indexPath.section else { return nil }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment