git.iko.soy/dashared/GDproject
on master help sign in
Working on pagination. Still something left. Removed a lot of unnecessary information!
bce7fa1Darya Rednikina
GDproject.xcodeproj/project.pbxproj−4
@@ -36,7 +36,6 @@
36 12E36DA3221424ED006FCDD7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 12E36DA2221424ED006FCDD7 /* Assets.xcassets */; };
36 12E36DA3221424ED006FCDD7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 12E36DA2221424ED006FCDD7 /* Assets.xcassets */; };
37 12E36DA6221424ED006FCDD7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12E36DA4221424ED006FCDD7 /* LaunchScreen.storyboard */; };
37 12E36DA6221424ED006FCDD7 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 12E36DA4221424ED006FCDD7 /* LaunchScreen.storyboard */; };
38 12E36DB72214400A006FCDD7 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DB62214400A006FCDD7 /* Post.swift */; };
38 12E36DB72214400A006FCDD7 /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DB62214400A006FCDD7 /* Post.swift */; };
39− 12E36DB922144016006FCDD7 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DB822144016006FCDD7 /* User.swift */; };
40 12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DC922144635006FCDD7 /* NewPostViewController.swift */; };
39 12E36DCA22144635006FCDD7 /* NewPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DC922144635006FCDD7 /* NewPostViewController.swift */; };
41 12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCB22144725006FCDD7 /* PostViewCell.swift */; };
40 12E36DCC22144725006FCDD7 /* PostViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCB22144725006FCDD7 /* PostViewCell.swift */; };
42 12E36DCE22144756006FCDD7 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCD22144756006FCDD7 /* Constants.swift */; };
41 12E36DCE22144756006FCDD7 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12E36DCD22144756006FCDD7 /* Constants.swift */; };
@@ -121,7 +120,6 @@
121 12E36DA5221424ED006FCDD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
120 12E36DA5221424ED006FCDD7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
122 12E36DA7221424ED006FCDD7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
121 12E36DA7221424ED006FCDD7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
123 12E36DB62214400A006FCDD7 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
122 12E36DB62214400A006FCDD7 /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = "<group>"; };
124− 12E36DB822144016006FCDD7 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
125 12E36DC922144635006FCDD7 /* NewPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPostViewController.swift; sourceTree = "<group>"; };
123 12E36DC922144635006FCDD7 /* NewPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPostViewController.swift; sourceTree = "<group>"; };
126 12E36DCB22144725006FCDD7 /* PostViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewCell.swift; sourceTree = "<group>"; };
124 12E36DCB22144725006FCDD7 /* PostViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewCell.swift; sourceTree = "<group>"; };
127 12E36DCD22144756006FCDD7 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
125 12E36DCD22144756006FCDD7 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
@@ -248,7 +246,6 @@
248 124CC7022221C00C009DF531 /* Model.swift */,
246 124CC7022221C00C009DF531 /* Model.swift */,
249 12E36DB62214400A006FCDD7 /* Post.swift */,
247 12E36DB62214400A006FCDD7 /* Post.swift */,
250 12D7D136221D78E800B35452 /* Channel.swift */,
248 12D7D136221D78E800B35452 /* Channel.swift */,
251− 12E36DB822144016006FCDD7 /* User.swift */,
252 );
249 );
253 path = "Simple model";
250 path = "Simple model";
254 sourceTree = "<group>";
251 sourceTree = "<group>";
@@ -379,7 +376,6 @@
379 12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */,
376 12E36DD522156559006FCDD7 /* MyStackView.swift in Sources */,
380 12D7D137221D78E800B35452 /* Channel.swift in Sources */,
377 12D7D137221D78E800B35452 /* Channel.swift in Sources */,
381 1291BE3622218DBF009D3F23 /* LogInCoordinator1.swift in Sources */,
378 1291BE3622218DBF009D3F23 /* LogInCoordinator1.swift in Sources */,
382− 12E36DB922144016006FCDD7 /* User.swift in Sources */,
383 1210A0BB223940310080686D /* SimplifiedChannelsList.swift in Sources */,
379 1210A0BB223940310080686D /* SimplifiedChannelsList.swift in Sources */,
384 125BD5812217314A008A3575 /* NewsVC.swift in Sources */,
380 125BD5812217314A008A3575 /* NewsVC.swift in Sources */,
385 12E36DB72214400A006FCDD7 /* Post.swift in Sources */,
381 12E36DB72214400A006FCDD7 /* Post.swift in Sources */,
GDproject/Controller/ News and channels/NewsController.swift+9−120
@@ -13,49 +13,23 @@ import Cartography
13protocol UpdateableWithChannel: class {
13protocol UpdateableWithChannel: class {
14 var channel: Model.Channels? { get set }
14 var channel: Model.Channels? { get set }
15}
15}
16−protocol NewPostDelegate {
16+
17− func addPost(post: Post)
18−}
19protocol UpdateableWithUser: class {
17protocol UpdateableWithUser: class {
20 var user: Model.Users? { get set }
18 var user: Model.Users? { get set }
21}
19}
22// MARK:- Controller with posts and channels availiable.
20// MARK:- Controller with posts and channels availiable.
23// Search is availiable within every table (posts and channels). Has button-functionality for boths post and chnnels
21// Search is availiable within every table (posts and channels). Has button-functionality for boths post and chnnels
24−class NewsController: UIViewController, UISearchControllerDelegate, NewPostDelegate, UpdateableWithChannel
22+class NewsController: UIViewController, UISearchControllerDelegate, UpdateableWithChannel
25{
23{
26 var changedChannelName: ((String)->())?
24 var changedChannelName: ((String)->())?
27
25
28 @IBOutlet weak var tableView: UITableView!
26 @IBOutlet weak var tableView: UITableView!
29
27
30− var dictionary: [Int: Model.Users]? {
31− didSet {
32−
33− var newPosts: [Model.Posts] = []
34−
35− posts!.forEach({ (post) in
36−
37− newPosts.append(Model.Posts(body: post.body, authorId: post.authorId, id: post.id, user: dictionary![post.authorId]!, date: post.updated, tags: post.tags))
38−
39− post.tags.forEach { Model.Channels.fullTags.insert($0) }
40−
41− })
42−
43− news.dataSourse = newPosts
44− tableView.reloadData()
45− }
46− }
47−
48− var posts: [Model.Posts]?
49−
50 var channel: Model.Channels?
28 var channel: Model.Channels?
51− var anonymousChannel: (users: [Int: Model.Users],posts: [Model.Posts])?
29+ var anonymousChannel: (users: [Int: Model.Users], posts: [Model.Posts])?
52
30
53 // MARK: - Output -
31 // MARK: - Output -
54 var onSelectChannel: (() -> Void)?
32 var onSelectChannel: (() -> Void)?
55−
56− func addPost(post: Post) {
57− //news.dataSourse.insert(post, at: 0)
58− }
59
33
60 var searchController = UISearchController(searchResultsController: nil)
34 var searchController = UISearchController(searchResultsController: nil)
61
35
@@ -101,16 +75,6 @@ class NewsController: UIViewController, UISearchControllerDelegate, NewPostDeleg
101 print("news clear")
75 print("news clear")
102 }
76 }
103
77
104− let label : UILabel = {
105− let label = UILabel()
106− label.text = "No posts to display yet!"
107− label.font = UIFont.systemFont(ofSize: 18)
108− label.textColor = .black
109− label.isHidden = true
110− label.numberOfLines = 0
111− return label
112− }()
113−
114 override func viewWillAppear(_ animated: Bool) {
78 override func viewWillAppear(_ animated: Bool) {
115 super.viewWillAppear(animated)
79 super.viewWillAppear(animated)
116 searchController.isActive = false
80 searchController.isActive = false
@@ -127,26 +91,23 @@ class NewsController: UIViewController, UISearchControllerDelegate, NewPostDeleg
127 if let channel = channel, let id = channel.id {
91 if let channel = channel, let id = channel.id {
128
92
129 Model.getChannel(with: id) { [weak self] in
93 Model.getChannel(with: id) { [weak self] in
130− self?.posts = $0.posts
94+ self?.news.dataSourse = $0.posts
131− self?.dictionary = $0.users
95+ self?.news.dictionary = $0.users
132 self?.refreshContr.endRefreshing()
96 self?.refreshContr.endRefreshing()
133 self?.changedChannelName?(channel.name)
97 self?.changedChannelName?(channel.name)
134 }
98 }
135−
136− } else if let _ = posts {
137− print("here!")
138 } else {
99 } else {
139 Model.getLast { [weak self] in
100 Model.getLast { [weak self] in
140− self?.posts = $0.posts
101+ self?.news.dataSourse = $0.posts
141− self?.dictionary = $0.users
102+ self?.news.dictionary = $0.users
142 self?.refreshContr.endRefreshing()
103 self?.refreshContr.endRefreshing()
143 self?.changedChannelName?("General")
104 self?.changedChannelName?("General")
144 }
105 }
145 }
106 }
146 default:
107 default:
147 if let anonChannel = anonymousChannel {
108 if let anonChannel = anonymousChannel {
148− posts = anonChannel.posts
109+ news.dataSourse = anonChannel.posts
149− dictionary = anonChannel.users
110+ news.dictionary = anonChannel.users
150 changedChannelName?("Anonymous")
111 changedChannelName?("Anonymous")
151 }
112 }
152 }
113 }
@@ -157,76 +118,4 @@ class NewsController: UIViewController, UISearchControllerDelegate, NewPostDeleg
157 tableView.dataSource = news
118 tableView.dataSource = news
158 tableView.reloadData()
119 tableView.reloadData()
159 }
120 }
160−
161−
162− // for animating the banner
163− var topConstraint: NSLayoutConstraint?
164−
165− let bannerView: UIView = {
166− let view = UIView()
167− view.backgroundColor = .blue
168− view.layer.cornerRadius = 25.0
169− view.clipsToBounds = true
170− return view
171− }()
172−
173− let statusLabel: UILabel = {
174− let label = UILabel()
175− label.text = "-"
176− label.textColor = .white
177− label.textAlignment = .center
178− return label
179− }()
180−
181− // MARK:- banner
182− private func setUpBanner()
183− {
184− view.addSubview(bannerView)
185− bannerView.addSubview(statusLabel)
186− statusLabel.edgesToSuperview()
187−
188− let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
189−
190− bannerView.addGestureRecognizer(tap)
191− topConstraint = NSLayoutConstraint(item: bannerView, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .top, multiplier: 1, constant: -300)
192− view.addConstraint(topConstraint!)
193−
194− bannerView.edgesToSuperview(excluding: [.bottom, .top, .left], insets: .right(20), usingSafeArea: true)
195− bannerView.height(50)
196− bannerView.width(50)
197− }
198−
199− // when table is scrolling no deletion is availiable
200− @objc func handleTap(sender: UITapGestureRecognizer? = nil) {
201− let indexPath = IndexPath(row: 0, section: 0)
202− self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
203−// isBannerVisible = false
204−// changeConstraint(isVisible: false)
205− }
206−
207− // animation for banner
208− func changeConstraint(isVisible: Bool){
209− topConstraint?.constant = isVisible ? 50 : -300
210−
211− UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: {
212− self.view.layoutIfNeeded()
213− }) { (completed) in
214−
215− }
216− }
217−
218− var isBannerVisible: Bool = false
219−
220− func scrollViewDidScroll(_ scrollView: UIScrollView) {
221− print(scrollView.contentOffset.y)
222− if scrollView.contentOffset.y >= 50 && !isBannerVisible{
223− isBannerVisible = true
224− changeConstraint(isVisible: true)
225− }
226−
227− if isBannerVisible && scrollView.contentOffset.y == 0{
228− isBannerVisible = false
229− changeConstraint(isVisible: false)
230− }
231− }
232}
121}
GDproject/Controller/ News and channels/NewsVC.swift+29−15
@@ -25,18 +25,29 @@ struct PostCellData{
25 }
25 }
26}
26}
27
27
28−class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
28+class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
29+
29
30
30 var onChannelDidChange: ((([Int: Model.Users],[Model.Posts]))->())?
31 var onChannelDidChange: ((([Int: Model.Users],[Model.Posts]))->())?
31
32
32 var onFullPost: ((HeaderType, Model.Posts)->())?
33 var onFullPost: ((HeaderType, Model.Posts)->())?
33
34
34− var dataSourse: [Model.Posts] = [] {
35+ var dictionary: [Int: Model.Users] = [:] {
35 didSet {
36 didSet {
36− cellDataSourse = []
37+
37− dataSourse.forEach { (item) in
38+ dataSourse = dataSourse.map {
38− cellDataSourse.append(PostCellData(attributedData: PostCellData.create(with: item.body)))
39+ var copy = $0
40+ copy.user = dictionary[$0.authorId]
41+ return copy
39 }
42 }
43+
44+ (viewController as? NewsController)?.tableView.reloadData()
45+ }
46+ }
47+
48+ var dataSourse: [Model.Posts] = [] {
49+ didSet {
50+ cellDataSourse = dataSourse.map { PostCellData(attributedData: PostCellData.create(with: $0.body)) }
40 }
51 }
41 }
52 }
42
53
@@ -96,18 +107,21 @@ class NewsVC: UIViewController, UITableViewDelegate, UITableViewDataSource{
96 func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
107 func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
97 return 100.0
108 return 100.0
98 }
109 }
110+
111+ func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
112+ {
113+ if indexPath.row == cellDataSourse.count - 1
114+ {
115+ // check this!
116+ Model.getLast(on: 10, from: dataSourse.last?.id ?? 0)
117+ { [weak self] in
118+ self?.dataSourse.append(contentsOf: $0.posts)
119+ $0.users.forEach { self?.dictionary[$0.key] = $0.value }
120+ }
121+ }
122+ }
99}
123}
100
124
101−//extension NewsVC {
102−// override func prepare(for segue: UIStoryboardSegue, sender: Any?)
103−// {
104−// if let currentCell = sender as? PostViewCell,
105−// let vc = segue.destination as? FullPostController {
106−//
107−// }
108−// }
109−//}
110−
111enum HeaderType {
125enum HeaderType {
112 case NONE
126 case NONE
113 case NEWS
127 case NEWS
GDproject/Controller/Coordinators/ChannelsCoordinator.swift+3−2
@@ -74,8 +74,9 @@ class ChannelsCoordinator: BaseCoordinator{
74 [weak self, weak mainContentVC] (tuple) in print("hep")
74 [weak self, weak mainContentVC] (tuple) in print("hep")
75 switch mainContentVC!.news.type {
75 switch mainContentVC!.news.type {
76 case .ANONYMOUS:
76 case .ANONYMOUS:
77+ print("nothing to diplay")
77− mainContentVC!.posts = tuple.1
78+ // mainContentVC!.posts = tuple.1
78− mainContentVC!.dictionary = tuple.0
79+ //mainContentVC!.dictionary = tuple.0
79 default:
80 default:
80 let vc = self!.presentNewsController()
81 let vc = self!.presentNewsController()
81 (vc.primaryContentViewController as! NewsController).anonymousChannel = tuple
82 (vc.primaryContentViewController as! NewsController).anonymousChannel = tuple
GDproject/Simple model/Model.swift+24−4
@@ -45,6 +45,7 @@ class Model{
45 }
45 }
46
46
47 struct Posts: Codable {
47 struct Posts: Codable {
48+
48 var body: [Attachments]
49 var body: [Attachments]
49 var authorId: Int
50 var authorId: Int
50 var id: Int
51 var id: Int
@@ -205,15 +206,34 @@ class Model{
205 }
206 }
206 }
207 }
207
208
209+ struct PostsLastRequest: Codable {
210+ var limit: Int
211+ var exclusiveFrom: Int?
212+ var request: [Int] = []
213+
214+ enum CodingKeys: String, CodingKey {
215+ case limit
216+ case exclusiveFrom
217+ case request
218+ }
219+
220+ func encode(to encoder: Encoder) throws {
221+ var container = encoder.container(keyedBy: CodingKeys.self)
222+ try container.encode(limit, forKey: .limit)
223+ try container.encode(exclusiveFrom, forKey: .exclusiveFrom)
224+ try container.encode(request, forKey: .request)
225+ }
226+ }
208
227
209− static func getLast(completion: @escaping (((users:[Int: Users], posts:[Posts]))->())){
228+ static func getLast(on limit: Int = 10, from pointInTime: Int? = nil, completion: @escaping (((users:[Int: Users], posts:[Posts]))->()))
210− let jsonString = "30"
229+ {
211− var request = URLRequest(url: postsLastURL)
230+ let postRequest = PostsLastRequest(limit: limit, exclusiveFrom: pointInTime, request: [])
212
231
232+ var request = URLRequest(url: postsLastURL)
233+ request.httpBody = try? JSONEncoder().encode(postRequest)
213 request.httpMethod = "POST"
234 request.httpMethod = "POST"
214
235
215 // insert json data to the request
236 // insert json data to the request
216− request.httpBody = jsonString.data(using: .utf8)
217 request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
237 request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
218
238
219 AF.request(request).responseJSON {
239 AF.request(request).responseJSON {
GDproject/Simple model/Post.swift−26
@@ -9,31 +9,6 @@
9import Foundation
9import Foundation
10import UIKit
10import UIKit
11
11
12−struct Post {
13− var dataArray: [Media]
14− var fromUser: User
15− var atDate: String
16− var comments: [Comment] = []
17−
18− var hashtags: [String] = ["ФКН", "Подбельский", "НИУВШЭ", "Шершаков", "ПАД", "Интересное","Мемы","Забавное","Учеба","Наука"]
19−
20− init(dataArray: [Media], from: User, date: String, comments: [Comment] = [])
21− {
22− self.dataArray = dataArray
23− fromUser = from
24− atDate = date
25− self.comments = comments
26− }
27−
28− init(dataArray: [Media]) {
29− self.dataArray = dataArray
30− fromUser = User(name: "vbogomazova", id: 2, fullName: "Богомазова Вероника Львовна")
31− atDate = "23.03.19 в 23:33"
32− }
33−
34−}
35−
36−
37enum Media{
12enum Media{
38 case text(String)
13 case text(String)
39 case image([UIImage])
14 case image([UIImage])
@@ -41,7 +16,6 @@ enum Media{
41}
16}
42
17
43struct Comment {
18struct Comment {
44− var from: User
45 var atTime: String
19 var atTime: String
46 var withData: String
20 var withData: String
47}
21}
GDproject/Simple model/User.swiftdeleted−41
@@ -1,41 +0,0 @@
1−//
2−// User.swift
3−// NewsFeed
4−//
5−// Created by cstore on 12/01/2019.
6−// Copyright © 2019 drHSE. All rights reserved.
7−//
8−
9−import Foundation
10−import UIKit
11−
12−struct User {
13− //var photo: UIImage? = #imageLiteral(resourceName: "image")
14− var login: String
15− var id: Int
16− var fullName: String
17− var initials: (surname: String, name: String, optional: String?) = ("Богомазова","Вероника","Львовна")
18− var placeOfWork: String?
19− var faculty: String?
20− let posts: [Post] = []
21−
22−
23− init(name: String, id: Int, fullName: String) {
24− self.login = name
25− self.id = id
26− self.fullName = fullName
27− }
28−
29− init(surname: String, name: String, optional: String?, emailName: String, id: Int, place: String?, faculty: String?)
30− {
31− self.id = id
32− self.login = emailName
33− self.initials = (surname, name, optional)
34−
35− self.fullName = "\(surname) \(name) \(optional ?? "")"
36− self.placeOfWork = place
37− if let f = faculty {
38− self.faculty = f
39− }
40− }
41−}