on 317137e help sign in
15 files changed+39−443
since splitsnapshots
unifiedsplit
Melk.xcodeproj/project.pbxproj+2−14 Melk.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/Melk.xcscheme+3−3 Melk/CardContainer.swift−100 Melk/CardView.swift+11−126 Melk/CollectionView.swift+2−4 Melk/MainCoordinator.swift+2−8 Melk/MainViewController.swift+2−22 Melk/SecondaryCoordinator.swift−12 Melk/SecondaryViewController.swift+2−111 Melk/StackView.swift+1−3 Melk/StreamingParser.swift+1−1 Melk/TableViewCells.swift+3−12 Melk/VKData.swift+8−8 Melk/VKServer.swift+2−2 README.md−17
Melk.xcodeproj/project.pbxproj+2−14
@@ -10,7 +10,6 @@
1010 0919AEA71F0D3D9D00894FFA /* SecondaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */; };
1111 0919AEA91F0D459600894FFA /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEA81F0D459600894FFA /* CardView.swift */; };
1212 0919AEAD1F0D706700894FFA /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEAC1F0D706700894FFA /* StackView.swift */; };
13− 09231E351F2394ED007C836D /* CardContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09231E341F2394ED007C836D /* CardContainer.swift */; };
1413 09939A561F097DA90014719D /* TableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09939A551F097DA90014719D /* TableViewCells.swift */; };
1514 09A456361F0ED9A800BAC32D /* CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A456351F0ED9A800BAC32D /* CollectionView.swift */; };
1615 09AFAB041F159C9200EBD200 /* StreamingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AFAB031F159C9200EBD200 /* StreamingService.swift */; };
@@ -70,7 +69,6 @@
7069 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryViewController.swift; sourceTree = "<group>"; };
7170 0919AEA81F0D459600894FFA /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = "<group>"; };
7271 0919AEAC1F0D706700894FFA /* StackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackView.swift; sourceTree = "<group>"; };
73− 09231E341F2394ED007C836D /* CardContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardContainer.swift; sourceTree = "<group>"; };
7472 09939A551F097DA90014719D /* TableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCells.swift; sourceTree = "<group>"; };
7573 09A456351F0ED9A800BAC32D /* CollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = "<group>"; };
7674 09AFAAFF1F159AE300EBD200 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/iOS/SwiftyJSON.framework; sourceTree = SOURCE_ROOT; };
@@ -119,21 +117,11 @@
119117/* End PBXFrameworksBuildPhase section */
120118
121119/* Begin PBXGroup section */
122− 09231E331F2394C5007C836D /* Card */ = {
123− isa = PBXGroup;
124− children = (
125− 0919AEA81F0D459600894FFA /* CardView.swift */,
126− 09231E341F2394ED007C836D /* CardContainer.swift */,
127− );
128− name = Card;
129− sourceTree = "<group>";
130− };
131120 098397F71F1E887F008C88DD /* Main */ = {
132121 isa = PBXGroup;
133122 children = (
134123 09BF420F1F0833C100AFAD57 /* MainCoordinator.swift */,
135124 09BF42551F08413000AFAD57 /* MainViewController.swift */,
136− 09939A551F097DA90014719D /* TableViewCells.swift */,
137125 );
138126 name = Main;
139127 sourceTree = "<group>";
@@ -188,11 +176,12 @@
188176 098397F71F1E887F008C88DD /* Main */,
189177 098397F81F1E888F008C88DD /* Secondary */,
190178 098397F91F1E88A3008C88DD /* Streaming */,
191− 09231E331F2394C5007C836D /* Card */,
192179 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */,
193180 09BF42111F08341B00AFAD57 /* MyWeirdness.swift */,
194181 09BF42121F08341B00AFAD57 /* PublicCrap.swift */,
195182 09F03F351F1674ED000CE916 /* VKServer.swift */,
183+ 0919AEA81F0D459600894FFA /* CardView.swift */,
184+ 09939A551F097DA90014719D /* TableViewCells.swift */,
196185 09BF420D1F0833A700AFAD57 /* LocalVKDataTypes.swift */,
197186 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */,
198187 09BF42171F08352E00AFAD57 /* VKData.swift */,
@@ -305,7 +294,6 @@
305294 09BF42181F08352E00AFAD57 /* VKData.swift in Sources */,
306295 09BF42101F0833C100AFAD57 /* MainCoordinator.swift in Sources */,
307296 09A456361F0ED9A800BAC32D /* CollectionView.swift in Sources */,
308− 09231E351F2394ED007C836D /* CardContainer.swift in Sources */,
309297 09BF42131F08341B00AFAD57 /* MyWeirdness.swift in Sources */,
310298 0919AEA91F0D459600894FFA /* CardView.swift in Sources */,
311299 09BF42321F08388100AFAD57 /* SecondaryCoordinator.swift in Sources */,
Melk.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/Melk.xcscheme+3−3
@@ -42,9 +42,9 @@
4242 </AdditionalOptions>
4343 </TestAction>
4444 <LaunchAction
45− buildConfiguration = "Release"
46− selectedDebuggerIdentifier = ""
47− selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
45+ buildConfiguration = "Debug"
46+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
47+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
4848 launchStyle = "0"
4949 useCustomWorkingDirectory = "NO"
5050 ignoresPersistentStateOnLaunch = "NO"
Melk/CardContainer.swiftdeleted−100
@@ -1,100 +0,0 @@
1−//
2−// CardContainer.swift
3−// Melk
4−//
5−// Created by Ilya Kos on 7/22/17.
6−// Copyright © 2017 Ilya Kos. All rights reserved.
7−//
8−
9−import UIKit
10−
11−class CardContainer: UIView {
12−
13− func animate() {
14− blurView.effect = blur
15− card.transform = smallTransform
16− card.layer.opacity = 0
17− shadowView.layer.opacity = 0
18− shadowView.transform = smallTransform
19− shadowView.layer.shadowRadius = 0
20− UIView.animate(withDuration: 0.5, delay: 0, options: [.curveEaseInOut], animations: {
21− self.card.transform = self.normalTransform
22− self.shadowView.transform = self.normalTransform
23− self.shadowView.layer.shadowRadius = self.shadowRadius
24− self.shadowView.layer.opacity = 1
25− self.blurView.effect = nil
26− self.card.layer.opacity = 1
27− }, completion: nil)
28− }
29−
30− // MARK: Passthrough to CardView
31− var post: WallPost? {
32− get {
33− return card.post
34− }
35− set {
36− card.post = newValue
37− }
38− }
39−
40− var minWidth: CGFloat {
41− get {
42− return card.minWidth
43− }
44− set {
45− card.minWidth = newValue
46− }
47− }
48−
49−
50− var height: CGFloat {
51− get {
52− return card.height
53− }
54− set {
55− card.height = newValue
56− }
57− }
58−
59− private let card: CardView
60− private let blurView = UIVisualEffectView()
61− private let shadowView = UIView()
62− private let blur = UIBlurEffect(style: UIBlurEffectStyle.light)
63− private let scale: CGFloat = 0.5
64− private let smallTransform: CGAffineTransform
65− private let normalTransform = CGAffineTransform(scaleX: 1, y: 1)
66− private let shadowRadius: CGFloat = 12
67− private let shadowOpacity: Float = 0.15
68− private let shadowOffset: CGFloat = 16
69−
70− override init(frame: CGRect) {
71− card = CardView(frame: frame)
72− smallTransform = CGAffineTransform(scaleX: scale, y: scale)
73− super.init(frame: frame)
74− shadowView.layer.shadowColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).cgColor
75− shadowView.layer.shadowRadius = shadowRadius
76− shadowView.layer.shadowOpacity = shadowOpacity
77− shadowView.backgroundColor = UIColor.clear
78− shadowView.clipsToBounds = false
79− shadowView.layer.shadowOffset = CGSize.zero
80− addSubview(shadowView)
81− addSubview(card)
82− addSubview(blurView)
83− }
84−
85− required init?(coder aDecoder: NSCoder) {
86− fatalError("init(coder:) has not been implemented")
87− }
88−
89− override func layoutSubviews() {
90− super.layoutSubviews()
91− card.layoutIfNeeded()
92− self.frame = card.frame
93− shadowView.layer.shadowPath = CGPath(roundedRect: card.frame, cornerWidth: card.layer.cornerRadius, cornerHeight: card.layer.cornerRadius,
94− transform: nil)
95− shadowView.layer.shadowOffset.height = shadowOffset
96− shadowView.frame = card.frame
97− blurView.frame = CGRect(x: -shadowRadius, y: 0, width: card.frame.width + shadowRadius*2, height: card.frame.height + shadowRadius + shadowOffset)
98− }
99−
100−}
Melk/CardView.swift+11−126
@@ -12,51 +12,21 @@ class CardView: UIView {
1212
1313 var post: WallPost? {
1414 didSet {
15−// print(post?.owner)
15+ print(post?.owner)
1616 update()
1717 }
1818 }
19− var minWidth: CGFloat = 300 {
20− didSet {
21−// update()
22− }
23− }
24− var height: CGFloat = 400 {
25− didSet {
26−// update()
27− }
28− }
2919
3020 override init(frame: CGRect) {
3121 super.init(frame: frame)
3222 layer.masksToBounds = true
3323 layer.cornerRadius = 20
34− gradient.colors = [#colorLiteral(red: 0.9841352105, green: 0.9841352105, blue: 0.9841352105, alpha: 1).cgColor, #colorLiteral(red: 0.9456828237, green: 0.9456828237, blue: 0.9456828237, alpha: 1).cgColor]
35− gradient.startPoint = CGPoint(x: 0.5, y: 0)
36− gradient.endPoint = CGPoint(x: 0.5, y: 1)
37− layer.addSublayer(gradient)
38−// backgroundColor = #colorLiteral(red: 0.9638966278, green: 0.9734401588, blue: 0.9734401588, alpha: 1)
24+ backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
3925 }
4026
4127 required init?(coder aDecoder: NSCoder) {
4228 fatalError("init(coder:) has not been implemented")
4329 }
44−
45− private let gradient = CAGradientLayer()
46−
47−
48− private let padding = CGPoint(x: 32, y: 32)
49− private let vPadding1: CGFloat = 16
50− private let vPadding2: CGFloat = 16
51− private var minTextHeight: CGFloat {
52− return CGFloat(height * 0.2)
53− }
54− private let gradientRatio: CGFloat = 0.2
55− private let minGradientAmount: CGFloat = 70
56− private let hiddenByGradient: CGFloat = 10
57− private var maxAttachmentDim: CGFloat {
58− return minWidth / 2.3
59− }
6030
6131// private let avatar = UIImage()
6232// private let name = UIImage()
@@ -65,13 +35,14 @@ class CardView: UIView {
6535 subviews.map {$0.removeFromSuperview()}
6636
6737 let largeStack = StackView(axis: .vertical, alignment: .left)
68− largeStack.padding = padding
38+ largeStack.padding = CGPoint(x: 32, y: 32)
6939 addSubview(largeStack)
7040
7141 let userView = StackView(axis: .horizontal, alignment: .center)
42+// userView.backgroundColor = #colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1)
7243
7344
74− let avatarDim: CGFloat = 64
45+ let avatarDim: CGFloat = 50
7546 let avatar = UIImageView()
7647 post?.owner?.avatar?.load(into: avatar)
7748 avatar.layer.cornerRadius = avatarDim/2
@@ -81,116 +52,30 @@ class CardView: UIView {
8152 avatar.frame.size = CGSize(width: avatarDim, height: avatarDim)
8253 userView.addArrangedSubview(.view(avatar))
8354
84− userView.addArrangedSubview(.spacer(16))
55+ userView.addArrangedSubview(.spacer(8))
8556
8657 let userName = UILabel()
8758 let firstName = post?.owner?.firstName ?? ""
8859 let lastName = post?.owner?.lastName ?? ""
8960 userName.text = "\(firstName) \(lastName)"
9061 userName.font = UIFont.systemFont(ofSize: 28, weight: UIFontWeightHeavy)
91− userName.textColor = UIColor.darkText
9262 userName.sizeToFit()
9363 userView.addArrangedSubview(.view(userName))
94−
95− userView.layoutIfNeeded()
64+ userView.frame.origin = CGPoint(x: 16, y: 16)
9665
9766 largeStack.addArrangedSubview(.view(userView))
9867
99− largeStack.addArrangedSubview(.spacer(vPadding1))
100−
101−
102− let width = max(minWidth - 2 * padding.x, userView.frame.width)
103−
104−
105− let photoView = CollectionView()
106− photoView.alignment = .top
107− photoView.horizontalPadding = 8
108− photoView.verticalPadding = 8
109− photoView.padding = CGPoint.zero
110− photoView.maxWidth = width
111− var maxPhotoDim: CGFloat = maxAttachmentDim
112− if let attachments = post?.attachments {
113− for attachment in attachments {
114− if let v = attachment.value {
115− switch v {
116− case .photo(let photo):
117− if var pWidth = photo.width.value >>> {CGFloat($0)},
118− var pHeight = photo.height.value >>> {CGFloat($0)} {
119− let photoV = UIImageView()
120− photoV.layer.minificationFilter = kCAFilterTrilinear
121− photoV.contentMode = .scaleAspectFill
122− photo.image?.load(into: photoV)
123− var k: CGFloat!
124− if pWidth > pHeight {
125− k = CGFloat(pWidth) / maxPhotoDim
126− } else {
127− k = CGFloat(pHeight) / maxPhotoDim
128− }
129− pWidth /= k
130− pHeight /= k
131− photoV.frame.size = CGSize(width: pWidth, height: pHeight)
132− photoView.addArrangedSubview(photoV)
133− }
134−
135− default:
136− break // TODO: Handle other data types
137− }
138− }
139− }
140− }
141− photoView.layoutIfNeeded()
142−
143− var textHeight = height
144− textHeight -= padding.y * 2 + vPadding1 + userView.frame.height
145− if let count = post?.attachments.count{
146− if count > 0 {
147− textHeight -= vPadding2 + photoView.frame.height
148− }
149− }
150− print(textHeight)
151− textHeight = max(textHeight, minTextHeight)
152− print(textHeight)
68+ largeStack.addArrangedSubview(.spacer(16))
15369
15470 let body = UILabel()
15571 body.numberOfLines = 0
156− let bodyWidth: Double = Double(width)
72+ let bodyWidth: Double = 300
15773 body.font = UIFont.systemFont(ofSize: 22, weight: UIFontWeightSemibold)
158− body.text = post?.body
159− body.textColor = UIColor.darkText
74+ body.text = post?.body ?? "Spicy jalapeno flank landjaeger sausage tongue tail fatback frankfurter. Meatball tongue tail short ribs pastrami. Short ribs chicken pig tenderloin sausage pork. Corned beef t-bone pancetta jerky chuck picanha venison, turducken tenderloin shoulder boudin drumstick hamburger. Pork meatball meatloaf prosciutto pig andouille. Sirloin bacon hamburger short ribs pork cupim shank biltong turducken bresaola kevin prosciutto shoulder meatball. Strip steak frankfurter pork chop biltong jowl beef rump venison pancetta turkey tongue."
16075 let size = body.textRect(forBounds: CGRect(x: 0, y: 0, width: bodyWidth, height: Double.infinity), limitedToNumberOfLines: 0).size
161− body.frame.size.width = size.width
162− if size.height > textHeight {
163− body.frame.size.height = textHeight
164− let maskView = UIView()
165− let maskLayer = CAGradientLayer()
166− maskLayer.colors = [UIColor.black.cgColor, UIColor.clear.cgColor]
167− maskLayer.endPoint = CGPoint(x: 0.5, y: 1 - (hiddenByGradient/textHeight))
168− let minPoint = minGradientAmount / textHeight
169− maskLayer.startPoint = CGPoint(x: 0.5, y: 1 - max(minPoint, gradientRatio))
170− print(maskLayer.startPoint)
171− maskLayer.frame = body.bounds
172− maskView.frame = body.bounds
173− maskView.layer.addSublayer(maskLayer)
174− body.mask = maskView
175− } else {
176− body.frame.size.height = size.height
177− }
76+ body.frame.size = size
17877
17978 largeStack.addArrangedSubview(.view(body))
18079
181− if let count = post?.attachments.count{
182− if count > 0 {
183− largeStack.addArrangedSubview(.spacer(vPadding2))
184− largeStack.addArrangedSubview(.view(photoView))
185− }
186− }
187−
188− largeStack.layoutIfNeeded()
189−
190− frame.size = CGSize(width: width + padding.x * 2, height: min(height, largeStack.frame.height))
191−
192− gradient.frame = self.bounds
193− gradient.endPoint = CGPoint(x: 0.5, y: bounds.height / height)
194−
19580 }
19681}
Melk/CollectionView.swift+2−4
@@ -68,7 +68,7 @@ class CollectionView: UIView {
6868 var firstStack = true
6969
7070 for view in arrangedSubviews {
71−// print("new view")
71+ print("new view")
7272 if firstView {
7373 lastStack.addArrangedSubview(.view(view))
7474 firstView = false
@@ -94,9 +94,7 @@ class CollectionView: UIView {
9494 }
9595 }
9696 lastStack.layoutIfNeeded()
97− if !firstStack {
98− largeStack.addArrangedSubview(.spacer(verticalPadding))
99− }
97+ largeStack.addArrangedSubview(.spacer(verticalPadding))
10098 largeStack.addArrangedSubview(.view(lastStack))
10199 largeStack.frame.origin = CGPoint.zero
102100 largeStack.layoutIfNeeded()
Melk/MainCoordinator.swift+2−8
@@ -27,14 +27,6 @@ class MainCoordinator {
2727 deleteRealmIfMigrationNeeded: true)
2828
2929 navC = UINavigationController(rootViewController: mainVC)
30−
31− mainVC.present = { tags in
32− if tags.count > 0 {
33− self.secondaryCoord.present(tag: tags.first!)
34− self.stream.rules = tags
35− self.stream.connect()
36− }
37− }
3830 updateScreens()
3931 stream.handleResult = { result in
4032 self.secondaryCoord.add(result: result)
@@ -52,6 +44,8 @@ class MainCoordinator {
5244// }
5345 print("didAuthorize")
5446 window.rootViewController = navC
47+ stream.rules = ["я", "а"]
48+ stream.connect()
5549 }
5650
5751 func updateScreens() {
Melk/MainViewController.swift+2−22
@@ -29,9 +29,7 @@ class MainViewController: UIViewController {
2929 }
3030
3131 @objc private func presentTags() {
32− present?(
33− mainView.tags.flatMap({$0}).filter({$0 != ""})
34− )
32+
3533 }
3634}
3735
@@ -47,8 +45,6 @@ class MainView: UIView {
4745 tableView.rowHeight = UITableViewAutomaticDimension
4846 tableView.register(TitleTableViewCell.self, forCellReuseIdentifier: TitleTableViewCell.identifier)
4947 tableView.register(TagTableViewCell.self, forCellReuseIdentifier: TagTableViewCell.identifier)
50− tableView.separatorStyle = .none
51− tableView.allowsSelection = false
5248 setNeedsLayout()
5349 }
5450
@@ -56,17 +52,6 @@ class MainView: UIView {
5652 tableView.frame = bounds
5753 }
5854
59− fileprivate var tags: [String?] = [nil] {
60− didSet {
61− if tags.last! != nil && tags.last! != "" {
62− if tags.count < 10 {
63− tags.append(nil)
64− tableView.insertRows(at: [IndexPath.init(row: tags.count - 1, section: 0)], with: .automatic)
65− }
66− }
67− }
68− }
69−
7055 required init?(coder aDecoder: NSCoder) {
7156 fatalError("init(coder:) has not been implemented")
7257 }
@@ -77,18 +62,13 @@ extension MainView: UITableViewDataSource {
7762 if let cell = tableView.dequeueReusableCell(withIdentifier: TagTableViewCell.identifier) as? TagTableViewCell {
7863// cell.titleText = "Testing testing 1 2 3"
7964 cell.style = indexPath.item == 0 ? .large : .normal
80− let index = indexPath.row
81− cell.tagDidChange = { tag in
82− self.tags[index] = tag
83− }
84− cell.tagString = tags[index]
8565 return cell
8666 }
8767 return UITableViewCell()
8868 }
8969
9070 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
91− return tags.count
71+ return 3
9272 }
9373
9474 func numberOfSections(in tableView: UITableView) -> Int {
Melk/SecondaryCoordinator.swift−12
@@ -12,21 +12,12 @@ class SecondaryCoordinator {
1212
1313 var windows: [UIWindow] = []
1414
15− private var didStartPresenting = false
16− private var tag: String = ""
17−
1815 func add(result: StreamingServiceResult) {
1916 for vc in VCs {
2017 vc.add(result: result)
2118 }
2219 }
2320
24− func present(tag newTag: String) {
25− didStartPresenting = true
26− self.tag = newTag
27− VCs.map({ $0.present(tag: newTag) })
28− }
29−
3021 init() {
3122
3223 }
@@ -45,9 +36,6 @@ class SecondaryCoordinator {
4536 VCs.append(VC)
4637 window.rootViewController = VC
4738 windows.append(window)
48− if didStartPresenting {
49− VC.present(tag: tag)
50− }
5139 }
5240 }
5341}
Melk/SecondaryViewController.swift+2−111
@@ -19,10 +19,6 @@ class SecondaryViewController: UIViewController {
1919 sView.add(result: result)
2020 }
2121
22− func present(tag: String) {
23− sView.present(tag: tag)
24− }
25−
2622 required init?(coder aDecoder: NSCoder) {
2723 fatalError("init(coder:) has not been implemented")
2824 }
@@ -31,123 +27,18 @@ class SecondaryViewController: UIViewController {
3127}
3228
3329class SecondaryView: UIView {
34−
35− var mainTag: String? {
36− get {
37− return tagLabel.text
38− }
39− set {
40− tagLabel.text = newValue
41−
42− }
43− }
44−
45−
46− private let spacer: CGFloat = 32
47− private let bottomSpacer: CGFloat = 64
48− private let tagSpacer: CGFloat = 32
49− private let tagLabel = UILabel()
50− private let melkLabel = UILabel()
51−
52− func present(tag: String) {
53− UIView.perform(.delete, on: [melkLabel], options: [], animations: nil) { (_) in
54− self.melkLabel.removeFromSuperview()
55− self.mainTag = tag
56− self.tagLabel.sizeToFit()
57− self.layoutIfNeeded(animated: true)
58− }
59− }
60−
6130 func add(result: StreamingServiceResult) {
6231 switch result {
6332 case .post(let post):
64− let card = CardContainer()
65− card.minWidth = min(bounds.width / 2.3, 550)
66− card.height = cardHeight
6733 card.post = post
68− cards.addArrangedSubview(.spacer(spacer))
69− cards.addArrangedSubview(.view(card))
70− card.animate()
7134 }
72− self.layoutIfNeeded(animated: true)
73−// self.setNeedsLayout(animated: true) // Doesn't work for some reason
7435 }
7536
76−// private let card = CardView()
77− private let cards = StackView(axis: .horizontal, alignment: .top)
37+ let card = CardView(frame: CGRect(x: 20, y: 20, width: 600, height: 300))
7838
7939 override init(frame: CGRect) {
8040 super.init(frame: frame)
81− backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
82− addSubview(cards)
83−
84− melkLabel.text = "Melk"
85− melkLabel.font = UIFont.systemFont(ofSize: 200, weight: UIFontWeightHeavy)
86− melkLabel.textColor = #colorLiteral(red: 0.9601849914, green: 0.9601849914, blue: 0.9601849914, alpha: 1)
87− addSubview(melkLabel)
88−
89− tagLabel.font = UIFont.systemFont(ofSize: 69, weight: UIFontWeightBold)
90− tagLabel.textColor = #colorLiteral(red: 0.3176470588, green: 0.3179988265, blue: 0.3179988265, alpha: 1)
91− addSubview(tagLabel)
92− }
93−
94− func setNeedsLayout(animated: Bool) {
95− self.animate = animated
96− self.setNeedsLayout()
97− }
98− func layoutIfNeeded(animated: Bool) {
99− self.animate = animated
100− self.layoutIfNeeded()
101− }
102− private var animate: Bool = false
103−
104− private func cleanCards() {
105− var offset = 0
106− outLoop: for (i, element) in cards.arrangedSubviews.enumerated() {
107− switch element {
108− case .view(let card):
109− let cardFrame = convert(card.frame, from: cards)
110− if cardFrame.intersects(bounds) {
111− break outLoop
112− } else {
113− cards.arrangedSubviews.remove(at: i-1-offset)
114− cards.arrangedSubviews.remove(at: i-1-offset)
115− offset += 2
116− }
117− case .spacer(_):
118− break
119− }
120− }
121− }
122−
123− private let padding = CGPoint(x: 32, y: 16)
124− private var cardHeight: CGFloat = 400
125−
126− override func layoutSubviews() {
127− super.layoutSubviews()
128−
129− melkLabel.sizeToFit()
130− melkLabel.center = center
131−
132− let updates = {
133− self.tagLabel.sizeToFit()
134− self.tagLabel.center.x = self.center.x
135− self.tagLabel.frame.origin.y = self.tagSpacer
136− self.cards.frame.origin.y = self.tagLabel.frame.maxY + self.padding.y
137− self.cards.layoutIfNeeded()
138− self.cards.frame.origin.x = self.frame.width - self.padding.x - self.cards.frame.width
139− }
140− if animate {
141− UIView.animate(withDuration: 0.7, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.6, options: [], animations: updates, completion: { _ in
142− self.cleanCards()
143− })
144−// UIView.animate(withDuration: 0.4, delay: 0.0, options: [.curveEaseOut], animations: updates, completion: nil)
145− } else {
146− updates()
147− self.cleanCards()
148− }
149− cardHeight = bounds.height - tagLabel.frame.height - padding.y - tagSpacer - bottomSpacer
150− animate = false
41+ addSubview(card)
15142 }
15243
15344 required init?(coder aDecoder: NSCoder) {
Melk/StackView.swift+1−3
@@ -44,8 +44,6 @@ class StackView: UIView {
4444 super.layoutSubviews()
4545 print("laying out subviews")
4646
47− subviews.map({$0.removeFromSuperview()}) // TODO: There must be a better way!
48−
4947 var height: CGFloat = 0
5048 var width: CGFloat = 0
5149 switch axis {
@@ -64,7 +62,7 @@ class StackView: UIView {
6462 height += a
6563 }
6664 case .view(let view):
67− view.layoutIfNeeded()
65+
6866 switch axis {
6967 case .horizontal:
7068 view.frame.origin.x = width
Melk/StreamingParser.swift+1−1
@@ -50,7 +50,7 @@ class StreamingParser {
5050 let complete = {
5151 comp -= 1
5252 if comp == 0 {
53−// print(post.owner)
53+ print(post.owner)
5454 completion(.post(post))
5555 }
5656 }
Melk/TableViewCells.swift+3−12
@@ -57,12 +57,6 @@ class TagTableViewCell: UITableViewCell {
5757 }
5858 }
5959
60− var tagDidChange: ((String?) -> ())?
61−
62− @objc private func textDidChange() {
63− tagDidChange?(tagString)
64− }
65−
6660 var style: TagStyle = .normal {
6761 didSet {
6862 updateStyle()
@@ -76,9 +70,6 @@ class TagTableViewCell: UITableViewCell {
7670
7771 textField.borderStyle = .roundedRect
7872 textField.adjustsFontSizeToFitWidth = false
79− textField.autocapitalizationType = .none
80− textField.autocorrectionType = .no
81− textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged)
8273
8374 contentView.addSubview(textField)
8475// textField.delegate = self
@@ -101,7 +92,7 @@ class TagTableViewCell: UITableViewCell {
10192 CGRect.infinite, limitedToNumberOfLines: 1)
10293 .height + 2*2
10394
104− let frame = CGRect(x: 16, y: style == .large ? 32 : 4, width: bounds.width - 16*2, height: height)
95+ let frame = CGRect(x: 16, y: 8, width: bounds.width - 16*2, height: height)
10596 textField.frame = frame
10697 print(textField.frame)
10798 }
@@ -112,8 +103,8 @@ class TagTableViewCell: UITableViewCell {
112103
113104
114105 static let identifier = "io.Melk.tagTableViewCell"
115− static let largeHeight: CGFloat = 37.5 + 16 + 32
116− static let normalHeight: CGFloat = 28.0 + 4*2
106+ static let largeHeight: CGFloat = 37.5 + 8*2
107+ static let normalHeight: CGFloat = 28.0 + 8*2
117108}
118109
119110//extension TagTableViewCell: UITextFieldDelegate {
Melk/VKData.swift+8−8
@@ -49,7 +49,7 @@ class VKData {
4949 }
5050 user.birthday = formatter.date(from: birthday)
5151 }
52− user.avatar = RealmPhoto.by(user.avatarID, surl: json["photo_100"].string)// was "photo_max"
52+ user.avatar = RealmPhoto.by(user.avatarID, surl: json["photo_max"].string)
5353 user.photo = RealmPhoto.by(user.photoID, surl: json["photo_max_orig"].string)
5454 if let friendStat = json["friend_status"].int {
5555 user.friendStatus = FriendStatus(rawValue: friendStat)
@@ -289,13 +289,13 @@ class VKData {
289289 photo.width.value = json["width"].int
290290 photo.height.value = json["height"].int
291291 var surl: String?
292−// if let imageSurl = json["photo_2560"].string {
293−// surl = imageSurl
294−// } else if let imageSurl = json["photo_1280"].string {
295−// surl = imageSurl
296−// } else if let imageSurl = json["photo_807"].string {
297−// surl = imageSurl
298− /*} else*/ if let imageSurl = json["photo_604"].string {
292+ if let imageSurl = json["photo_2560"].string {
293+ surl = imageSurl
294+ } else if let imageSurl = json["photo_1280"].string {
295+ surl = imageSurl
296+ } else if let imageSurl = json["photo_807"].string {
297+ surl = imageSurl
298+ } else if let imageSurl = json["photo_604"].string {
299299 surl = imageSurl
300300 } else if let imageSurl = json["photo_130"].string {
301301 surl = imageSurl
Melk/VKServer.swift+2−2
@@ -81,7 +81,7 @@ class VKServer {
8181 let id = user.id
8282 let params: Parameters = [
8383 "user_ids": id,
84− "fields": "photo_100"
84+ "fields": "photo_max"
8585 ]
8686 Alamofire.request(url(for: "users.get"), parameters: params)
8787 .validate().responseData { (response) in
@@ -118,6 +118,6 @@ class VKServer {
118118}
119119
120120fileprivate func url(`for` method: String) -> URL {
121− let surl = "https://api.vk.com/method/\(method)?access_token=\(accessKey)&v=\(vkAPIVersion)&lang=0"
121+ let surl = "https://api.vk.com/method/\(method)?access_token=\(accessKey)&v=\(vkAPIVersion)"
122122 return URL.init(string: surl)!
123123}
README.mddeleted−17
@@ -1,17 +0,0 @@
1−# Melk
2−
3−_Might not work properly with new streaming API. This project was developed while the API was in beta._
4−
5−[![Melk demo](http://img.youtube.com/vi/9SNc0bLDCL0/0.jpg)](http://www.youtube.com/watch?v=9SNc0bLDCL0)
6−
7−При проведении различных мероприятий организаторы довольно часто призывают людей, посещающих эти мероприятия, выложить у себя в соц сети что-нибудь об этом мероприятии, чаще всего под мероприятие даже выделяется отдельный хештег.
8−
9−Для привлечения внимания к хештегу и поощрения его использования можно выводить некоторые из выложенных с хештегом записей туда, где все смогут это увидеть.
10−
11−При проведении больших мероприятий желательно использовать большое количество независимых систем, чтобы если летит что-то одно, все остальное продолжало работать.
12−
13−Полноценный десктопный компьютер для данной цели не нужен, поэтому приложение работает просто на телефоне или планшете.
14−
15−Самый первый хештег или ключевое слово будет крупно показано вместе со всеми записями.
16−
17−После того, как будет нажата кнопка “Present”, записи с основным хештегом будут выводиться на любые подключенные к устройству экраны.