Skip to content

Latest commit

 

History

History
141 lines (105 loc) · 5.6 KB

README.md

File metadata and controls

141 lines (105 loc) · 5.6 KB

IGStoriesClone

An example project created to show an advanced use case of IGListKit and to fully recreate the awesome Instagram Stories feature on Instagram.

Features

  • 3d cube animation
  • Bring up tapped story with custom presentation
  • IGListKit Diffing to make the collection fast
  • Multiple Story support
  • Multiple Story Items per Story (videos)
  • Automatic scrolling when Story is done
  • Go back a story item with a tap gesture
  • Go forward a story item with a tap gesture
  • Automatic transition if there are no Stories left

Example clips

Clips 1-2

Clips 3-4

Clip 5

Installation

Go to your terminal and clone the repository...Done!

Usage

For customization, go to ViewController.swift and the Assets folder and add your own movies/profile pictures locally

import UIKit
import IGListKit

class ViewController: UIViewController, ListAdapterDataSource {
    
    private var storyModel = [StoryModel]()
    
    lazy var adapter: ListAdapter = {
        return ListAdapter(updater: ListAdapterUpdater(), viewController: self)
    }()
    
    let collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
        collectionView.backgroundColor = .white
        return collectionView
    }()
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        adapter.performUpdates(animated: true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let stories = modelGenerators()
        let model = StoryModel(stories: stories)
        storyModel = [model]
        view.addSubview(collectionView)
        adapter.collectionView = collectionView
        adapter.dataSource = self
    }
    
    private func modelGenerators() -> [Story] {
        // Users
        let user1 = User(id: UUID().uuidString, profilePic: Bundle.main.url(forResource: "jeromeythehomie", withExtension: "jpg")!, handle: "jeromeythehomie")
        let user2 = User(id: UUID().uuidString, profilePic: Bundle.main.url(forResource: "mattlee077", withExtension: "jpg")!, handle: "mattlee077")
        let user3 = User(id: UUID().uuidString, profilePic: Bundle.main.url(forResource: "asethics", withExtension: "jpg")!, handle: "asethics")
        let user4 = User(id: UUID().uuidString, profilePic: Bundle.main.url(forResource: "nat.pat33", withExtension: "jpg")!, handle: "nat.pat33")
        
        // Story Items
        let storyItem1 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_0021", withExtension: "mov")!)
        let storyItem2 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_0460", withExtension: "mov")!)
        let storyItem3 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1539", withExtension: "mov")!)
        let storyItem4 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1636", withExtension: "mov")!)
        let storyItem5 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1691", withExtension: "mov")!)
        let storyItem6 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1704", withExtension: "mov")!)
        let storyItem7 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1705", withExtension: "mov")!)
        let storyItem8 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1706", withExtension: "mov")!)
        let storyItem9 = StoryItem(id: UUID().uuidString, url: Bundle.main.url(forResource: "IMG_1707", withExtension: "mov")!)

        // Stories
        let story1 = Story(user: user1, isRead: false, storyItems: [storyItem1, storyItem2, storyItem3])
        let story2 = Story(user: user2, isRead: false, storyItems: [storyItem4, storyItem5, storyItem6, storyItem7])
        let story3 = Story(user: user3, isRead: false, storyItems: [storyItem8])
        let story4 = Story(user: user4, isRead: false, storyItems: [storyItem9])
        let stories = [story1, story2, story3, story4]
        return stories

    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        collectionView.frame = view.bounds
    }
    
    func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
        return storyModel
    }
    
    func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {        
        return StorySectionController()
    }
    
    func emptyView(for listAdapter: ListAdapter) -> UIView? {return nil}
}

To-do and future releases

  • Fix AVQueuePlayer "flickering" between Stories
  • Dismissing animation and last cell detection with proper animation
  • Pull-to-refresh the Stories such that if the Story has been read, we move it to the end.
  • Fix light gray circle background appearence when read (need help with this one)
  • ** For some reason there's a bug on iPhone X, XS, etc. where the cube animation is slow (need help with this one)

Jerome Isaacs