Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
0540041
Viper: Created project
mohannazakizadeh Apr 23, 2022
baffcc7
Viper: Added top rated movies module
mohannazakizadeh Apr 23, 2022
9e42dcf
Viper: Added popular movies module and favorite movies module
mohannazakizadeh Apr 23, 2022
f26a2ec
Viper: Added Tab bar Module and initial setup
mohannazakizadeh Apr 23, 2022
79525ed
Viper: Fixed TabBar details
mohannazakizadeh Apr 24, 2022
00612e3
Viper: added test for tabBarViewContorller
mohannazakizadeh Apr 24, 2022
68e7160
.
mohannazakizadeh Apr 24, 2022
bcb85f4
Revert "."
mohannazakizadeh Apr 24, 2022
fa13cbd
Revert "Revert ".""
mohannazakizadeh Apr 24, 2022
b17394c
Viper: Added Network layer and service methods configuration
mohannazakizadeh Apr 26, 2022
7508c6b
Viper: Added initial requirements for core data
mohannazakizadeh Apr 27, 2022
23b7515
Viper: added movies collection module
mohannazakizadeh Apr 27, 2022
3c3bdb6
Viper: Added needed functions to get movie image
mohannazakizadeh Apr 27, 2022
c7475e5
Viper: Added movies filter options module and some methods to top rat…
mohannazakizadeh Apr 28, 2022
eef4113
Viper: fixed collection view
mohannazakizadeh Apr 28, 2022
b602749
Viper: Fixed info.plist root
mohannazakizadeh Apr 28, 2022
80435fc
Added caching image for collection view
mohannazakizadeh Apr 28, 2022
b320921
Added popular movies needed things
mohannazakizadeh Apr 28, 2022
6594713
Created watchlist module
mohannazakizadeh Apr 28, 2022
1eed8dc
changed way of loading collection view
mohannazakizadeh Apr 28, 2022
7cf4411
fixed deleting movies from core data and scrolling to top of the vies…
mohannazakizadeh Apr 29, 2022
94ae0db
fixed adding repetitious movie to watchlist
mohannazakizadeh Apr 29, 2022
e24b445
Added movie details view and custom bottom sheet for it
mohannazakizadeh Apr 29, 2022
492e298
fixed showing bottom sheet also added get movie details from url
mohannazakizadeh Apr 29, 2022
9a75c66
fixed showing movie details bottom sheet constraints
mohannazakizadeh Apr 30, 2022
d10577d
Added core data prevents from repetitious data
mohannazakizadeh Apr 30, 2022
03e6108
Added showing movie details to popular and watchlist movies
mohannazakizadeh Apr 30, 2022
0f65840
Added sorting movies in watchlist
mohannazakizadeh Apr 30, 2022
9dea8c6
Added view for empty watchlist
mohannazakizadeh May 1, 2022
da61371
added top rated movies module test
mohannazakizadeh May 1, 2022
bcce382
Added test for popular movies module
mohannazakizadeh May 1, 2022
aa47df7
Added watchlist movies tests and minor renamings
mohannazakizadeh May 2, 2022
f061bf0
Added swift lint and needed changes
mohannazakizadeh May 3, 2022
e6e4c01
updated swiftlint
mohannazakizadeh May 3, 2022
4e42c87
Added network layer test
mohannazakizadeh May 3, 2022
a8f8cf5
state
mohannazakizadeh May 3, 2022
3c9eeea
Added mvvmc module
mohannazakizadeh May 5, 2022
9c17e2e
Finished mvvm module
mohannazakizadeh May 6, 2022
c53e5c6
minor fixess
mohannazakizadeh May 6, 2022
06a0400
userstate
mohannazakizadeh May 6, 2022
688e332
Updated Readme
mohannazakizadeh May 6, 2022
3f9deb3
Added coordinator tests
mohannazakizadeh May 6, 2022
8009cce
Merge branch 'MovieApplication' of https://github.com/mohannazakizade…
mohannazakizadeh May 6, 2022
71eeac4
fixed some issues
mohannazakizadeh May 10, 2022
a56b774
final changes
mohannazakizadeh May 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Movie-Application/Movie-Application.xcodeproj/project.xcworkspace/xcuserdata/mohanna.xcuserdatad/UserInterfaceState.xcuserstate
Binary file added Movie-Application/.DS_Store
Binary file not shown.
2,190 changes: 2,190 additions & 0 deletions Movie-Application/Movie-Application.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array/>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "7EDAA637-189A-4B08-9700-4333CD4B155D"
type = "1"
version = "2.0">
</Bucket>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Movie-Application.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
</dict>
<key>MovieApplicationMVVM.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>5</integer>
</dict>
</dict>
</dict>
</plist>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "48AC48E8-1543-4BF6-B8B5-9D9A4006B557"
type = "0"
version = "2.0">
</Bucket>
Binary file added Movie-Application/Movie-Application/.DS_Store
Binary file not shown.
78 changes: 78 additions & 0 deletions Movie-Application/Movie-Application/App/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//
// AppDelegate.swift
// Movie-Application
//
// Created by Mohanna Zakizadeh on 4/23/22.
//

import UIKit
import CoreData

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

// swiftlint: disable all

func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}

// MARK: UISceneSession Lifecycle

func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}


lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "FavoriteMovieModel")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {

/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()

// MARK: - Core Data Saving support

func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {

let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
96 changes: 96 additions & 0 deletions Movie-Application/Movie-Application/App/Interfaces.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// Interfaces.swift
// VIPER
//
// Created by Tibor Bödecs on 2019. 05. 16..
// Copyright © 2019. Tibor Bödecs. All rights reserved.
//

import Foundation

// MARK: - interfaces

public protocol RouterPresenterInterface: AnyObject {

}

public protocol InteractorPresenterInterface: AnyObject {

}

public protocol PresenterRouterInterface: AnyObject {

}

public protocol PresenterInteractorInterface: AnyObject {

}

public protocol PresenterViewInterface: AnyObject {

}

public protocol ViewPresenterInterface: AnyObject {

}

// MARK: - viper

public protocol RouterInterface: RouterPresenterInterface {
associatedtype PresenterRouter

var presenter: PresenterRouter! { get set }
}

public protocol InteractorInterface: InteractorPresenterInterface {
associatedtype PresenterInteractor

var presenter: PresenterInteractor! { get set }
}

public protocol PresenterInterface: PresenterRouterInterface, PresenterInteractorInterface, PresenterViewInterface {
associatedtype RouterPresenter
associatedtype InteractorPresenter
associatedtype ViewPresenter

var router: RouterPresenter! { get set }
var interactor: InteractorPresenter! { get set }
var view: ViewPresenter! { get set }
}

public protocol ViewInterface: ViewPresenterInterface {
associatedtype PresenterView

var presenter: PresenterView! { get set }
}

public protocol EntityInterface {

}

// MARK: - module

public protocol ModuleInterface {

associatedtype View where View: ViewInterface
associatedtype Presenter where Presenter: PresenterInterface
associatedtype Router where Router: RouterInterface
associatedtype Interactor where Interactor: InteractorInterface

func assemble(view: View, presenter: Presenter, router: Router, interactor: Interactor)
}

public extension ModuleInterface {

func assemble(view: View, presenter: Presenter, router: Router, interactor: Interactor) {
view.presenter = (presenter as? Self.View.PresenterView)

presenter.view = (view as? Self.Presenter.ViewPresenter)
presenter.interactor = (interactor as? Self.Presenter.InteractorPresenter)
presenter.router = (router as? Self.Presenter.RouterPresenter)

interactor.presenter = (presenter as? Self.Interactor.PresenterInteractor)

router.presenter = (presenter as? Self.Router.PresenterRouter)
}
}
54 changes: 54 additions & 0 deletions Movie-Application/Movie-Application/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// SceneDelegate.swift
// Movie-Application
//
// Created by Mohanna Zakizadeh on 4/23/22.
//

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// swiftlint: disable all
var window: UIWindow?


func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }

let window = UIWindow(windowScene: windowScene)
window.rootViewController = TabBarViewContorller()
window.makeKeyAndVisible()
self.window = window
}

func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}

func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}

func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}

func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}

func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}


}

84 changes: 84 additions & 0 deletions Movie-Application/Movie-Application/App/TabBarViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//
// TabBarViewController.swift
// Movie-Application
//
// Created by Mohanna Zakizadeh on 4/24/22.
//

import UIKit

final class TabBarViewContorller: UITabBarController {

// MARK: - Properties
var topRatedMoviesViewController: UIViewController!
var popularMoviesViewController: UIViewController!
var favoriteMoviesViewController: UIViewController!

let topRatedIcon = UIImage(systemName: "list.number")
let favoriteIcon = UIImage(systemName: "bookmark")
let popularIcon = UIImage(systemName: "flame")

// MARK: - Lifecycle
deinit {
NotificationCenter.default.removeObserver(self)
}

override func viewDidLoad() {
super.viewDidLoad()

topRatedMoviesViewController = setupTopRatedMoviesViewController()
popularMoviesViewController = setupPopularMoviesViewController()
favoriteMoviesViewController = setupFavoriteMoviesViewController()

self.viewControllers = [popularMoviesViewController, topRatedMoviesViewController, favoriteMoviesViewController]
self.selectedIndex = 1
self.toolbarItems = []

// notification observed in order to switch between tabs
NotificationCenter.default.addObserver(forName: Self.selectedTabNotification,
object: nil, queue: nil) { notification in
if notification.userInfo?["selectedTab"] as? Int == 0 {
self.selectedIndex = 0
}
}

}

// MARK: - Private functions
func setupTopRatedMoviesViewController() -> UIViewController {
let topRatedViewController = TopRatedMoviesModule().build()
let tabBarItem = UITabBarItem(title: "Top Rated", image: topRatedIcon, tag: 0)
topRatedViewController.tabBarItem = tabBarItem
return topRatedViewController
}

func setupPopularMoviesViewController() -> UIViewController {
let popularViewController = PopularMoviesModule().build()
popularViewController.tabBarItem = UITabBarItem(title: "Popular",
image: popularIcon,
selectedImage: UIImage(systemName: "flame.fill"))
return popularViewController
}

func setupFavoriteMoviesViewController() -> UIViewController {
let favoriteViewController = WatchlistMoviesModule().build()
favoriteViewController.tabBarItem = UITabBarItem(title: "WatchList",
image: favoriteIcon,
selectedImage: UIImage(systemName: "bookmark.fill"))
return favoriteViewController
}

override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
NotificationCenter.default.post(name: TabBarViewContorller.tabBarDidTapNotification, object: nil)
}
}

extension TabBarViewContorller {
static var tabBarDidTapNotification: NSNotification.Name {
NSNotification.Name(rawValue: "TabBarViewContorller.tabBarDidTapNotification")
}

static var selectedTabNotification: NSNotification.Name {
NSNotification.Name("TabBarViewContorller.selectedTabNotification")
}
}
Binary file not shown.
Binary file not shown.
Loading