Skip to content

Create a Tweets UI

Maximilian Mackh edited this page Apr 17, 2020 · 2 revisions
//
//  TweetViewController.swift
//  BaseComponents Playground
//
//  Created by mmackh on 15/02/2020.
//  Copyright © 2020 proconsult.at gmbh. All rights reserved.
//

import UIKit

import BaseComponents

class TweetCell: UITableViewCell {
    var scrollingView: ScrollingView?
    var imageWidth: CGFloat = 80
    var retweetSplitView: ScrollingSplitView?
    var tweetImageView: UIImageView?
    var actionView: ScrollingSplitView?
    var tweetLabel: PerformLabel?
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        separatorInset = .init(top: 0, left: imageWidth, bottom: 0, right: 0)
        
        self.scrollingView = contentView.addScrollingView(configurationHandler: { [weak self] (scrollingView) in
            
            scrollingView.addSubview(UIView(), layoutType: .fixed, value: 10)
            
            scrollingView.addScrollingSplitView(configurationHandler: { (splitView) in
                splitView.direction = .horizontal
                
                let usernameLabel = PerformLabel("Maximilian M")
                    .size(.body, .bold)
                splitView.addSubview(usernameLabel, layoutType: .automatic)
                
                splitView.addSubview(UIView(), layoutType: .fixed, value: 10)
                
                let handlerLabel = PerformLabel("@mmackh")
                    .size(.body)
                splitView.addSubview(handlerLabel, layoutType: .automatic)
                
                let timeLabel = PerformLabel("33m")
                    .size(.body, [.monoSpaceDigit,.bold])
                    .color(.text, .lightGray)
                    .align(.right)
                splitView.addSubview(timeLabel, layoutType: .percentage, value: 100)
                
            }) { (parentRect) -> ScrollingSplitViewLayoutInstruction in
                return .init(fixedLayoutTypeValue: 25, edgeInsets: .init(top: 0, left: self?.imageWidth ?? 0, bottom: 0, right: 15))
            }
            
            let tweetLabel = PerformLabel("""
                So Julio, how is your hobby app coming along? Did you solve the problem with CoreData?
                
                😅
                
                The code I wrote tonight:
                """)
                .size(.body)
            self?.tweetLabel = tweetLabel
            scrollingView.addSubview(tweetLabel, layoutType: .automatic, edgeInsets: .init(top: 0, left: self?.imageWidth ?? 0, bottom: 0, right: 15))
            
            scrollingView.addSubview(UIView(), layoutType: .fixed, value: 10)
            
            let tweetImageView = UIImageView()
                .image(urlString: "https://picsum.photos/id/1/800/800")
                .mode(.scaleAspectFill)
            tweetImageView.clipsToBounds = true
            self?.tweetImageView = tweetImageView
            scrollingView.addSubview(tweetImageView) { (parentRect) -> ScrollingViewLayoutInstruction in
                .init(layoutType: .fixed, value: parentRect.width * 0.6, edgeInsets: .init(top: 0, left: self?.imageWidth ?? 0, bottom: 0, right: 15))
            }
            
            scrollingView.addSubview(UIView(), layoutType: .fixed, value: 10)
            
            self?.retweetSplitView = scrollingView.addScrollingSplitView(configurationHandler: { (splitView) in
                let retweetLabel = UILabel("Retweeted by Brent Shadown")
                    .size(.body)
                    .color(.text, .lightGray)
                splitView.addSubview(retweetLabel, layoutType: .automatic)
                
            }) { (parentRect) -> ScrollingSplitViewLayoutInstruction in
                return .init(fixedLayoutTypeValue: 25, edgeInsets: .init(top: 0, left: self?.imageWidth ?? 0, bottom: 10, right: 15))
            }
            
            scrollingView.addSubview(UIView(), layoutType: .fixed, value: 10)
            
            self?.actionView = scrollingView.addScrollingSplitView(configurationHandler: { (splitView) in
                splitView.direction = .horizontal
                splitView.isHidden = true
                splitView.color(.background, .red)
            }) { (parentRect) -> ScrollingSplitViewLayoutInstruction in
                return .init(fixedLayoutTypeValue: 44)
            }
        })
        
        let thumbnailView = UIImageView()
        thumbnailView.frame = .init(x: 10, y: 10, width: 60, height: 60)
        thumbnailView.image(urlString: "https://picsum.photos/id/1/300/300")
        thumbnailView.clipsToBounds = true
        thumbnailView.layer.cornerRadius = 30
        contentView.addSubview(thumbnailView)
        
        //self.accessoryType = .disclosureIndicator
    }
    
    override func bindObject(_ obj: AnyObject) {
        
        let object: Int = obj as! Int
        
        self.retweetSplitView?.isHidden = (object % 2 == 0)
        self.tweetImageView?.isHidden = (object % 3 == 0)
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class TweetViewController: UIViewController {
    var selectedTweet: Int?
    
    lazy var dataRender: DataRender = { [weak self] in
        let config = DataRenderConfiguration(cellClass: TweetCell.self)
        let render = DataRender(configuration: config)
        render.adjustInsets = true
        render.itemAutomaticRowHeightCacheKeyHandler { (itemLayoutProperties) -> AnyHashable in
            return itemLayoutProperties.object as! AnyHashable
        }
        render.onSelect { (itemRenderProperties) in
            let cell = itemRenderProperties.cell as! TweetCell
            let updatedSelectedTweet = itemRenderProperties.object as? Int
            let currentlySelectedTweet = self?.selectedTweet ?? -1
            
            cell.actionView?.isHidden = false
            cell.scrollingView?.invalidateLayout()
            
            if currentlySelectedTweet == updatedSelectedTweet {
                self?.selectedTweet = nil
                itemRenderProperties.render?.recalculateAutomaticHeight(for: [currentlySelectedTweet], animated: true)
            } else {
                self?.selectedTweet = updatedSelectedTweet
                itemRenderProperties.render?.recalculateAutomaticHeight(for: [currentlySelectedTweet], animated: true)
                itemRenderProperties.render?.recalculateAutomaticHeight(for: [updatedSelectedTweet], animated: true)
                
            }
        }
        render.beforeBind { (itemRenderProperties) in
            let cell = itemRenderProperties.cell as! TweetCell
            cell.actionView?.isHidden = (self?.selectedTweet != itemRenderProperties.object as? Int)
        }
        render.tableView?.allowsMultipleSelection = false
        return render
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.color(.background, .white)
        
        view.addSplitView(configurationHandler: { [unowned self] (splitView) in
            splitView.direction = .horizontal
            
            splitView.insertSafeAreaInsetsPadding(form: self.view, paddingDirection: .left)
            
            splitView.addSubview(dataRender) { (parentRect) -> SplitViewLayoutInstruction in
                return .init(layoutType: .percentage, value: 100)
            }
            
            splitView.insertSafeAreaInsetsPadding(form: self.view, paddingDirection: .right)
            
        })
        
        DispatchQueue.global(qos: .userInteractive).async {
            
            var arr: [Int] = []
            for n in 0...1000 {
                arr.append(n)
            }
            DispatchQueue.main.async {
                
                self.dataRender.renderArray(arr)
            }
        }
    }
}
Clone this wiki locally