-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AI 챗봇 앱 [STEP 3] Jin, Harry #48
base: d_Jin
Are you sure you want to change the base?
Changes from all commits
a55c00b
74ac336
47e93e4
27a8ea8
8daa429
6be965b
87daa5b
f40dd14
511026b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"color" : { | ||
"color-space" : "display-p3", | ||
"components" : { | ||
"alpha" : "1.000", | ||
"blue" : "0.541", | ||
"green" : "0.475", | ||
"red" : "0.918" | ||
} | ||
}, | ||
"idiom" : "universal" | ||
}, | ||
{ | ||
"appearances" : [ | ||
{ | ||
"appearance" : "luminosity", | ||
"value" : "dark" | ||
} | ||
], | ||
"color" : { | ||
"color-space" : "display-p3", | ||
"components" : { | ||
"alpha" : "1.000", | ||
"blue" : "0.541", | ||
"green" : "0.475", | ||
"red" : "0.918" | ||
} | ||
}, | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"color" : { | ||
"color-space" : "display-p3", | ||
"components" : { | ||
"alpha" : "1.000", | ||
"blue" : "0.714", | ||
"green" : "0.925", | ||
"red" : "1.000" | ||
} | ||
}, | ||
"idiom" : "universal" | ||
}, | ||
{ | ||
"appearances" : [ | ||
{ | ||
"appearance" : "luminosity", | ||
"value" : "dark" | ||
} | ||
], | ||
"color" : { | ||
"color-space" : "display-p3", | ||
"components" : { | ||
"alpha" : "1.000", | ||
"blue" : "0.714", | ||
"green" : "0.925", | ||
"red" : "1.000" | ||
} | ||
}, | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import Foundation | ||
|
||
enum Section { | ||
case chat | ||
} | ||
|
||
struct ChatRoomModel: Hashable { | ||
let id: UUID = UUID() | ||
let content: String | ||
let role: Role | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import UIKit | ||
|
||
final class ChatBubbleView: UIView { | ||
|
||
let bubbleLayer = CAShapeLayer() | ||
|
||
let chatLabel: UILabel = { | ||
let label = UILabel() | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
label.numberOfLines = 0 | ||
return label | ||
}() | ||
|
||
var outcoming = Role.user | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 적절한 이름인가요 ? |
||
|
||
override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
commonInit() | ||
} | ||
|
||
required init?(coder aDecoder: NSCoder) { | ||
super.init(coder: aDecoder) | ||
commonInit() | ||
} | ||
|
||
private func commonInit() -> Void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
layer.addSublayer(bubbleLayer) | ||
addSubview(chatLabel) | ||
|
||
NSLayoutConstraint.activate([ | ||
chatLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 12.0), | ||
chatLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -12.0), | ||
chatLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 12.0), | ||
chatLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -12.0), | ||
]) | ||
} | ||
|
||
override func layoutSubviews() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 무엇을 해주는 메서드인가요 ? |
||
super.layoutSubviews() | ||
|
||
let width = bounds.size.width | ||
let height = bounds.size.height | ||
|
||
let bezierPath = UIBezierPath() | ||
|
||
if outcoming == .user { | ||
bezierPath.move(to: CGPoint(x: width - 22, y: height)) | ||
bezierPath.addLine(to: CGPoint(x: 17, y: height)) | ||
bezierPath.addCurve(to: CGPoint(x: 0, y: height - 17), controlPoint1: CGPoint(x: 7.61, y: height), controlPoint2: CGPoint(x: 0, y: height - 7.61)) | ||
bezierPath.addLine(to: CGPoint(x: 0, y: 17)) | ||
bezierPath.addCurve(to: CGPoint(x: 17, y: 0), controlPoint1: CGPoint(x: 0, y: 7.61), controlPoint2: CGPoint(x: 7.61, y: 0)) | ||
bezierPath.addLine(to: CGPoint(x: width - 21, y: 0)) | ||
bezierPath.addCurve(to: CGPoint(x: width - 4, y: 17), controlPoint1: CGPoint(x: width - 11.61, y: 0), controlPoint2: CGPoint(x: width - 4, y: 7.61)) | ||
bezierPath.addLine(to: CGPoint(x: width - 4, y: height - 11)) | ||
bezierPath.addCurve(to: CGPoint(x: width, y: height), controlPoint1: CGPoint(x: width - 4, y: height - 1), controlPoint2: CGPoint(x: width, y: height)) | ||
bezierPath.addLine(to: CGPoint(x: width + 0.05, y: height - 0.01)) | ||
bezierPath.addCurve(to: CGPoint(x: width - 11.04, y: height - 4.04), controlPoint1: CGPoint(x: width - 4.07, y: height + 0.43), controlPoint2: CGPoint(x: width - 8.16, y: height - 1.06)) | ||
bezierPath.addCurve(to: CGPoint(x: width - 22, y: height), controlPoint1: CGPoint(x: width - 16, y: height), controlPoint2: CGPoint(x: width - 19, y: height)) | ||
bezierPath.close() | ||
} else { | ||
bezierPath.move(to: CGPoint(x: 22, y: height)) | ||
bezierPath.addLine(to: CGPoint(x: width - 17, y: height)) | ||
bezierPath.addCurve(to: CGPoint(x: width, y: height - 17), controlPoint1: CGPoint(x: width - 7.61, y: height), controlPoint2: CGPoint(x: width, y: height - 7.61)) | ||
bezierPath.addLine(to: CGPoint(x: width, y: 17)) | ||
bezierPath.addCurve(to: CGPoint(x: width - 17, y: 0), controlPoint1: CGPoint(x: width, y: 7.61), controlPoint2: CGPoint(x: width - 7.61, y: 0)) | ||
bezierPath.addLine(to: CGPoint(x: 21, y: 0)) | ||
bezierPath.addCurve(to: CGPoint(x: 4, y: 17), controlPoint1: CGPoint(x: 11.61, y: 0), controlPoint2: CGPoint(x: 4, y: 7.61)) | ||
bezierPath.addLine(to: CGPoint(x: 4, y: height - 11)) | ||
bezierPath.addCurve(to: CGPoint(x: 0, y: height), controlPoint1: CGPoint(x: 4, y: height - 1), controlPoint2: CGPoint(x: 0, y: height)) | ||
bezierPath.addLine(to: CGPoint(x: -0.05, y: height - 0.01)) | ||
bezierPath.addCurve(to: CGPoint(x: 11.04, y: height - 4.04), controlPoint1: CGPoint(x: 4.07, y: height + 0.43), controlPoint2: CGPoint(x: 8.16, y: height - 1.06)) | ||
bezierPath.addCurve(to: CGPoint(x: 22, y: height), controlPoint1: CGPoint(x: 16, y: height), controlPoint2: CGPoint(x: 19, y: height)) | ||
bezierPath.close() | ||
} | ||
|
||
bubbleLayer.fillColor = (outcoming == .user) ? UIColor(named: "SunshineYellow")?.cgColor : UIColor(white: 0.90, alpha: 1.0).cgColor | ||
|
||
bubbleLayer.path = bezierPath.cgPath | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import UIKit | ||
|
||
final class ChatRoomCell: UICollectionViewListCell { | ||
static let identifier = "ChatRoomCell" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다른방법은 없을까요? |
||
|
||
var viewModel: ChatRoomCellViewModel! { | ||
didSet { setupViewModel() } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 다른 곳의 컨벤션과는 다른 모습이네요. |
||
} | ||
|
||
var bubbleView = ChatBubbleView() | ||
var leadingOrTrailingConstraint = NSLayoutConstraint() | ||
|
||
override init(frame: CGRect) { | ||
super.init(frame: .zero) | ||
commonInit() | ||
} | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
override func prepareForReuse() { | ||
super.prepareForReuse() | ||
commonInit() | ||
} | ||
|
||
private func commonInit() { | ||
bubbleView.translatesAutoresizingMaskIntoConstraints = false | ||
contentView.addSubview(bubbleView) | ||
|
||
NSLayoutConstraint.activate([ | ||
bubbleView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12.0), | ||
bubbleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12.0), | ||
bubbleView.widthAnchor.constraint(lessThanOrEqualTo: contentView.widthAnchor, multiplier: 0.66) | ||
]) | ||
} | ||
|
||
private func setupViewModel() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. setupViewModel |
||
|
||
bubbleView.chatLabel.text = viewModel.contentMessage | ||
bubbleView.outcoming = viewModel.contentRole | ||
|
||
leadingOrTrailingConstraint.isActive = false | ||
if viewModel.contentRole == .user { | ||
leadingOrTrailingConstraint = bubbleView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12.0) | ||
} else { | ||
leadingOrTrailingConstraint = bubbleView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12.0) | ||
} | ||
leadingOrTrailingConstraint.isActive = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. layoutIfNeeded 는 언제 사용될까요 ? 한번 공부해보시면 좋을 것 같습니다. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import Foundation | ||
import Combine | ||
|
||
final class ChatRoomCellViewModel { | ||
@Published var contentMessage: String = "" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @published는 왜 사용하신걸까요 ? |
||
@Published var contentRole: Role = .user | ||
|
||
private let message: ChatRoomModel | ||
|
||
init(message: ChatRoomModel) { | ||
self.message = message | ||
|
||
setupBinding() | ||
} | ||
|
||
private func setupBinding() { | ||
contentMessage = message.content | ||
contentRole = message.role | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ChatRoomModel 은 좋지않은 이름입니다. 모든게 다 model아닌가요 ?