mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			154 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			154 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			Swift
		
	
| // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | |
| 
 | |
| import UIKit
 | |
| import SessionUIKit
 | |
| 
 | |
| final class FakeChatView: UIView {
 | |
|     private let spacing = Values.mediumSpacing
 | |
|     
 | |
|     var contentOffset: CGPoint {
 | |
|         get { return scrollView.contentOffset }
 | |
|         set { scrollView.contentOffset = newValue }
 | |
|     }
 | |
|     
 | |
|     private lazy var chatBubbles = [
 | |
|         getChatBubble(withText: "view_fake_chat_bubble_1".localized(), wasSentByCurrentUser: true),
 | |
|         getChatBubble(withText: "view_fake_chat_bubble_2".localized(), wasSentByCurrentUser: false),
 | |
|         getChatBubble(withText: "view_fake_chat_bubble_3".localized(), wasSentByCurrentUser: true),
 | |
|         getChatBubble(withText: "view_fake_chat_bubble_4".localized(), wasSentByCurrentUser: false),
 | |
|         getChatBubble(withText: "view_fake_chat_bubble_5".localized(), wasSentByCurrentUser: false)
 | |
|     ]
 | |
|     
 | |
|     private lazy var scrollView: UIScrollView = {
 | |
|         let result = UIScrollView()
 | |
|         result.showsHorizontalScrollIndicator = false
 | |
|         result.showsVerticalScrollIndicator = false
 | |
|         return result
 | |
|     }()
 | |
|     
 | |
|     private static let bubbleWidth = CGFloat(224)
 | |
|     private static let bubbleCornerRadius = CGFloat(10)
 | |
|     private static let startDelay: TimeInterval = 1
 | |
|     private static let animationDuration: TimeInterval = 0.4
 | |
|     private static let chatDelay: TimeInterval = 1.5
 | |
|     private static let popAnimationStartScale: CGFloat = 0.6
 | |
|     
 | |
|     override init(frame: CGRect) {
 | |
|         super.init(frame: frame)
 | |
|         setUpViewHierarchy()
 | |
|         animate()
 | |
|     }
 | |
|     
 | |
|     required init?(coder: NSCoder) {
 | |
|         super.init(coder: coder)
 | |
|         setUpViewHierarchy()
 | |
|         animate()
 | |
|     }
 | |
|     
 | |
|     private func setUpViewHierarchy() {
 | |
|         let stackView = UIStackView(arrangedSubviews: chatBubbles)
 | |
|         stackView.axis = .vertical
 | |
|         stackView.spacing = spacing
 | |
|         stackView.alignment = .fill
 | |
|         stackView.set(.width, to: UIScreen.main.bounds.width)
 | |
|         let vInset = Values.smallSpacing
 | |
|         stackView.layoutMargins = UIEdgeInsets(top: vInset, leading: Values.veryLargeSpacing, bottom: vInset, trailing: Values.veryLargeSpacing)
 | |
|         stackView.isLayoutMarginsRelativeArrangement = true
 | |
|         scrollView.addSubview(stackView)
 | |
|         stackView.pin(to: scrollView)
 | |
|         addSubview(scrollView)
 | |
|         scrollView.pin(to: self)
 | |
|         let height = chatBubbles.reduce(0) { $0 + $1.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize).height } + CGFloat(chatBubbles.count - 1) * spacing + 2 * vInset
 | |
|         scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: height)
 | |
|     }
 | |
|     
 | |
|     private func getChatBubble(withText text: String, wasSentByCurrentUser: Bool) -> UIView {
 | |
|         let result = UIView()
 | |
|         let bubbleView = UIView()
 | |
|         bubbleView.set(.width, to: FakeChatView.bubbleWidth)
 | |
|         bubbleView.themeShadowColor = .black
 | |
|         bubbleView.layer.cornerRadius = FakeChatView.bubbleCornerRadius
 | |
|         bubbleView.layer.shadowRadius = (ThemeManager.currentTheme.interfaceStyle == .light ? 4 : 8)
 | |
|         bubbleView.layer.shadowOpacity = (ThemeManager.currentTheme.interfaceStyle == .light ? 0.16 : 0.24)
 | |
|         bubbleView.layer.shadowOffset = CGSize.zero
 | |
|         
 | |
|         bubbleView.themeBackgroundColor = (wasSentByCurrentUser ?
 | |
|             .messageBubble_outgoingBackground :
 | |
|             .messageBubble_incomingBackground
 | |
|         )
 | |
|         
 | |
|         let label = UILabel()
 | |
|         label.font = .boldSystemFont(ofSize: Values.mediumFontSize)
 | |
|         label.text = text
 | |
|         label.themeTextColor = (wasSentByCurrentUser ?
 | |
|             .messageBubble_outgoingText :
 | |
|             .messageBubble_incomingText
 | |
|         )
 | |
|         label.lineBreakMode = .byWordWrapping
 | |
|         label.numberOfLines = 0
 | |
|         bubbleView.addSubview(label)
 | |
|         label.pin(to: bubbleView, withInset: 12)
 | |
|         
 | |
|         result.addSubview(bubbleView)
 | |
|         bubbleView.pin(.top, to: .top, of: result)
 | |
|         result.pin(.bottom, to: .bottom, of: bubbleView)
 | |
|         
 | |
|         if wasSentByCurrentUser {
 | |
|             bubbleView.pin(.trailing, to: .trailing, of: result)
 | |
|         }
 | |
|         else {
 | |
|             result.pin(.leading, to: .leading, of: bubbleView)
 | |
|         }
 | |
|         
 | |
|         return result
 | |
|     }
 | |
|     
 | |
|     private func animate() {
 | |
|         let animationDuration = FakeChatView.animationDuration
 | |
|         let delayBetweenMessages = FakeChatView.chatDelay
 | |
|         chatBubbles.forEach { $0.alpha = 0 }
 | |
|         
 | |
|         Timer.scheduledTimer(withTimeInterval: FakeChatView.startDelay, repeats: false) { [weak self] _ in
 | |
|             self?.showChatBubble(at: 0)
 | |
|             Timer.scheduledTimer(withTimeInterval: 1.5 * delayBetweenMessages, repeats: false) { _ in
 | |
|                 self?.showChatBubble(at: 1)
 | |
|                 Timer.scheduledTimer(withTimeInterval: 1.5 * delayBetweenMessages, repeats: false) { _ in
 | |
|                     self?.showChatBubble(at: 2)
 | |
|                     UIView.animate(withDuration: animationDuration) {
 | |
|                         guard let self = self else { return }
 | |
|                         self.scrollView.contentOffset = CGPoint(x: 0, y: self.chatBubbles[0].height() + self.spacing)
 | |
|                     }
 | |
|                     Timer.scheduledTimer(withTimeInterval: 1.5 * delayBetweenMessages, repeats: false) { _ in
 | |
|                         self?.showChatBubble(at: 3)
 | |
|                         UIView.animate(withDuration: animationDuration) {
 | |
|                             guard let self = self else { return }
 | |
|                             self.scrollView.contentOffset = CGPoint(x: 0, y: self.chatBubbles[0].height() + self.spacing + self.chatBubbles[1].height() + self.spacing)
 | |
|                         }
 | |
|                         Timer.scheduledTimer(withTimeInterval: delayBetweenMessages, repeats: false) { _ in
 | |
|                             self?.showChatBubble(at: 4)
 | |
|                             UIView.animate(withDuration: animationDuration) {
 | |
|                                 guard let self = self else { return }
 | |
|                                 self.scrollView.contentOffset = CGPoint(x: 0, y: self.scrollView.contentSize.height - self.scrollView.bounds.height)
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     private func showChatBubble(at index: Int) {
 | |
|         let chatBubble = chatBubbles[index]
 | |
|         
 | |
|         UIView.animate(withDuration: FakeChatView.animationDuration) {
 | |
|             chatBubble.alpha = 1
 | |
|         }
 | |
|         let scale = FakeChatView.popAnimationStartScale
 | |
|         chatBubble.transform = CGAffineTransform(scaleX: scale, y: scale)
 | |
|         
 | |
|         UIView.animate(withDuration: FakeChatView.animationDuration, delay: 0, usingSpringWithDamping: 0.68, initialSpringVelocity: 4, options: .curveEaseInOut, animations: {
 | |
|             chatBubble.transform = CGAffineTransform(scaleX: 1, y: 1)
 | |
|         }, completion: nil)
 | |
|     }
 | |
| }
 |