on da6d4a5 help sign in
Cartfile+1−4
since splitsnapshots
unifiedsplit
@@ -1,8 +1,5 @@
1github "Alamofire/Alamofire"
1github "Alamofire/Alamofire"
2−# github "WE-St0r/SwiftyVK"
2+github "WE-St0r/SwiftyVK"
3github "kean/Nuke" ~> 4.0
3github "kean/Nuke" ~> 4.0
4github "realm/realm-cocoa.git"
4github "realm/realm-cocoa.git"
5github "tidwall/SwiftWebSocket"
5github "tidwall/SwiftWebSocket"
6−# github "SwiftyJSON/SwiftyJSON"
7−# github "utahiosmac/Marshal"
8−github "Anviking/Decodable"
Cartfile.resolved+1−1
@@ -1,5 +1,5 @@
1github "Alamofire/Alamofire" "4.5.0"
1github "Alamofire/Alamofire" "4.5.0"
2−github "Anviking/Decodable" "v0.5.1"
2+github "WE-St0r/SwiftyVK" "2.0.8"
3github "kean/Nuke" "4.1.2"
3github "kean/Nuke" "4.1.2"
4github "realm/realm-cocoa" "v2.8.3"
4github "realm/realm-cocoa" "v2.8.3"
5github "tidwall/SwiftWebSocket" "2.6.5"
5github "tidwall/SwiftWebSocket" "2.6.5"
Melk.xcodeproj/project.pbxproj+40−92
@@ -10,10 +10,8 @@
10 0919AEA71F0D3D9D00894FFA /* SecondaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */; };
10 0919AEA71F0D3D9D00894FFA /* SecondaryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */; };
11 0919AEA91F0D459600894FFA /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEA81F0D459600894FFA /* CardView.swift */; };
11 0919AEA91F0D459600894FFA /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEA81F0D459600894FFA /* CardView.swift */; };
12 0919AEAD1F0D706700894FFA /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEAC1F0D706700894FFA /* StackView.swift */; };
12 0919AEAD1F0D706700894FFA /* StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0919AEAC1F0D706700894FFA /* StackView.swift */; };
13− 09231E351F2394ED007C836D /* CardContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09231E341F2394ED007C836D /* CardContainer.swift */; };
14 09939A561F097DA90014719D /* TableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09939A551F097DA90014719D /* TableViewCells.swift */; };
13 09939A561F097DA90014719D /* TableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09939A551F097DA90014719D /* TableViewCells.swift */; };
15 09A456361F0ED9A800BAC32D /* CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A456351F0ED9A800BAC32D /* CollectionView.swift */; };
14 09A456361F0ED9A800BAC32D /* CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09A456351F0ED9A800BAC32D /* CollectionView.swift */; };
16− 09AFAB041F159C9200EBD200 /* StreamingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09AFAB031F159C9200EBD200 /* StreamingService.swift */; };
17 09B781591F11630D0007D2BF /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = 09B781581F11630D0007D2BF /* .gitignore */; };
15 09B781591F11630D0007D2BF /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = 09B781581F11630D0007D2BF /* .gitignore */; };
18 09BF41EF1F07F71F00AFAD57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */; };
16 09BF41EF1F07F71F00AFAD57 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */; };
19 09BF41F61F07F71F00AFAD57 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 09BF41F51F07F71F00AFAD57 /* Assets.xcassets */; };
17 09BF41F61F07F71F00AFAD57 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 09BF41F51F07F71F00AFAD57 /* Assets.xcassets */; };
@@ -25,41 +23,37 @@
25 09BF42141F08341B00AFAD57 /* PublicCrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42121F08341B00AFAD57 /* PublicCrap.swift */; };
23 09BF42141F08341B00AFAD57 /* PublicCrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42121F08341B00AFAD57 /* PublicCrap.swift */; };
26 09BF42161F0834D400AFAD57 /* VKPublicCrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */; };
24 09BF42161F0834D400AFAD57 /* VKPublicCrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */; };
27 09BF42181F08352E00AFAD57 /* VKData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42171F08352E00AFAD57 /* VKData.swift */; };
25 09BF42181F08352E00AFAD57 /* VKData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42171F08352E00AFAD57 /* VKData.swift */; };
26+ 09BF421A1F08357E00AFAD57 /* VkServices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42191F08357E00AFAD57 /* VkServices.swift */; };
27+ 09BF42261F0835B200AFAD57 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42021F080A5700AFAD57 /* Alamofire.framework */; };
28+ 09BF42271F0835B200AFAD57 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42021F080A5700AFAD57 /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
29+ 09BF42281F0835B200AFAD57 /* Nuke.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42031F080A5700AFAD57 /* Nuke.framework */; };
30+ 09BF42291F0835B200AFAD57 /* Nuke.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42031F080A5700AFAD57 /* Nuke.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
31+ 09BF422A1F0835B200AFAD57 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42041F080A5700AFAD57 /* Realm.framework */; };
32+ 09BF422B1F0835B200AFAD57 /* Realm.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42041F080A5700AFAD57 /* Realm.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
33+ 09BF422C1F0835B200AFAD57 /* RealmSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42051F080A5700AFAD57 /* RealmSwift.framework */; };
34+ 09BF422D1F0835B200AFAD57 /* RealmSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42051F080A5700AFAD57 /* RealmSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
35+ 09BF422E1F0835B200AFAD57 /* SwiftyVK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42061F080A5700AFAD57 /* SwiftyVK.framework */; };
36+ 09BF422F1F0835B200AFAD57 /* SwiftyVK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42061F080A5700AFAD57 /* SwiftyVK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
28 09BF42321F08388100AFAD57 /* SecondaryCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42311F08388100AFAD57 /* SecondaryCoordinator.swift */; };
37 09BF42321F08388100AFAD57 /* SecondaryCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42311F08388100AFAD57 /* SecondaryCoordinator.swift */; };
38+ 09BF42341F083B5800AFAD57 /* SwiftWebSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */; };
39+ 09BF42351F083B6000AFAD57 /* SwiftWebSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */; };
40+ 09BF42361F083B6000AFAD57 /* SwiftWebSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
29 09BF42561F08413000AFAD57 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42551F08413000AFAD57 /* MainViewController.swift */; };
41 09BF42561F08413000AFAD57 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09BF42551F08413000AFAD57 /* MainViewController.swift */; };
30− 09F03F231F164E7E000CE916 /* StreamingParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F03F221F164E7E000CE916 /* StreamingParser.swift */; };
31− 09F03F261F165884000CE916 /* Decodable.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09F03F241F165876000CE916 /* Decodable.framework */; };
32− 09F03F271F165884000CE916 /* Decodable.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09F03F241F165876000CE916 /* Decodable.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
33− 09F03F281F165884000CE916 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09AFAAFF1F159AE300EBD200 /* SwiftyJSON.framework */; };
34− 09F03F291F165884000CE916 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09AFAAFF1F159AE300EBD200 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
35− 09F03F2A1F165884000CE916 /* SwiftWebSocket.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */; };
36− 09F03F2B1F165884000CE916 /* SwiftWebSocket.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
37− 09F03F2C1F165884000CE916 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42021F080A5700AFAD57 /* Alamofire.framework */; };
38− 09F03F2D1F165884000CE916 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42021F080A5700AFAD57 /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
39− 09F03F2E1F165884000CE916 /* Nuke.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42031F080A5700AFAD57 /* Nuke.framework */; };
40− 09F03F2F1F165884000CE916 /* Nuke.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42031F080A5700AFAD57 /* Nuke.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
41− 09F03F301F165884000CE916 /* Realm.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42041F080A5700AFAD57 /* Realm.framework */; };
42− 09F03F311F165884000CE916 /* Realm.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42041F080A5700AFAD57 /* Realm.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
43− 09F03F321F165884000CE916 /* RealmSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42051F080A5700AFAD57 /* RealmSwift.framework */; };
44− 09F03F331F165884000CE916 /* RealmSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 09BF42051F080A5700AFAD57 /* RealmSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
45− 09F03F361F1674ED000CE916 /* VKServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F03F351F1674ED000CE916 /* VKServer.swift */; };
46− 09F0D79E1F129DCB00A13751 /* Streaming.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09F0D79D1F129DCB00A13751 /* Streaming.swift */; };
47/* End PBXBuildFile section */
42/* End PBXBuildFile section */
48
43
49/* Begin PBXCopyFilesBuildPhase section */
44/* Begin PBXCopyFilesBuildPhase section */
50− 09F03F341F165884000CE916 /* Embed Frameworks */ = {
45+ 09BF42301F0835B200AFAD57 /* Embed Frameworks */ = {
51 isa = PBXCopyFilesBuildPhase;
46 isa = PBXCopyFilesBuildPhase;
52 buildActionMask = 2147483647;
47 buildActionMask = 2147483647;
53 dstPath = "";
48 dstPath = "";
54 dstSubfolderSpec = 10;
49 dstSubfolderSpec = 10;
55 files = (
50 files = (
56− 09F03F311F165884000CE916 /* Realm.framework in Embed Frameworks */,
51+ 09BF422B1F0835B200AFAD57 /* Realm.framework in Embed Frameworks */,
52+ 09BF42271F0835B200AFAD57 /* Alamofire.framework in Embed Frameworks */,
53+ 09BF42361F083B6000AFAD57 /* SwiftWebSocket.framework in Embed Frameworks */,
57− 09F03F291F165884000CE916 /* SwiftyJSON.framework in Embed Frameworks */,
54+ 09BF422F1F0835B200AFAD57 /* SwiftyVK.framework in Embed Frameworks */,
58− 09F03F331F165884000CE916 /* RealmSwift.framework in Embed Frameworks */,
55+ 09BF422D1F0835B200AFAD57 /* RealmSwift.framework in Embed Frameworks */,
59− 09F03F271F165884000CE916 /* Decodable.framework in Embed Frameworks */,
60− 09F03F2F1F165884000CE916 /* Nuke.framework in Embed Frameworks */,
56+ 09BF42291F0835B200AFAD57 /* Nuke.framework in Embed Frameworks */,
61− 09F03F2B1F165884000CE916 /* SwiftWebSocket.framework in Embed Frameworks */,
62− 09F03F2D1F165884000CE916 /* Alamofire.framework in Embed Frameworks */,
63 );
57 );
64 name = "Embed Frameworks";
58 name = "Embed Frameworks";
65 runOnlyForDeploymentPostprocessing = 0;
59 runOnlyForDeploymentPostprocessing = 0;
@@ -70,11 +64,8 @@
70 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryViewController.swift; sourceTree = "<group>"; };
64 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryViewController.swift; sourceTree = "<group>"; };
71 0919AEA81F0D459600894FFA /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = "<group>"; };
65 0919AEA81F0D459600894FFA /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = "<group>"; };
72 0919AEAC1F0D706700894FFA /* StackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StackView.swift; sourceTree = "<group>"; };
66 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>"; };
74 09939A551F097DA90014719D /* TableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCells.swift; sourceTree = "<group>"; };
67 09939A551F097DA90014719D /* TableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCells.swift; sourceTree = "<group>"; };
75 09A456351F0ED9A800BAC32D /* CollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = "<group>"; };
68 09A456351F0ED9A800BAC32D /* CollectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = "<group>"; };
76− 09AFAAFF1F159AE300EBD200 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/iOS/SwiftyJSON.framework; sourceTree = SOURCE_ROOT; };
77− 09AFAB031F159C9200EBD200 /* StreamingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StreamingService.swift; sourceTree = "<group>"; };
78 09B781581F11630D0007D2BF /* .gitignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .gitignore; path = ../.gitignore; sourceTree = "<group>"; };
69 09B781581F11630D0007D2BF /* .gitignore */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .gitignore; path = ../.gitignore; sourceTree = "<group>"; };
79 09BF41EB1F07F71F00AFAD57 /* Melk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Melk.app; sourceTree = BUILT_PRODUCTS_DIR; };
70 09BF41EB1F07F71F00AFAD57 /* Melk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Melk.app; sourceTree = BUILT_PRODUCTS_DIR; };
80 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
71 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -86,19 +77,17 @@
86 09BF42031F080A5700AFAD57 /* Nuke.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nuke.framework; path = Carthage/Build/iOS/Nuke.framework; sourceTree = SOURCE_ROOT; };
77 09BF42031F080A5700AFAD57 /* Nuke.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nuke.framework; path = Carthage/Build/iOS/Nuke.framework; sourceTree = SOURCE_ROOT; };
87 09BF42041F080A5700AFAD57 /* Realm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Realm.framework; path = Carthage/Build/iOS/Realm.framework; sourceTree = SOURCE_ROOT; };
78 09BF42041F080A5700AFAD57 /* Realm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Realm.framework; path = Carthage/Build/iOS/Realm.framework; sourceTree = SOURCE_ROOT; };
88 09BF42051F080A5700AFAD57 /* RealmSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmSwift.framework; path = Carthage/Build/iOS/RealmSwift.framework; sourceTree = SOURCE_ROOT; };
79 09BF42051F080A5700AFAD57 /* RealmSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmSwift.framework; path = Carthage/Build/iOS/RealmSwift.framework; sourceTree = SOURCE_ROOT; };
80+ 09BF42061F080A5700AFAD57 /* SwiftyVK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyVK.framework; path = Carthage/Build/iOS/SwiftyVK.framework; sourceTree = SOURCE_ROOT; };
89 09BF420D1F0833A700AFAD57 /* LocalVKDataTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalVKDataTypes.swift; sourceTree = "<group>"; };
81 09BF420D1F0833A700AFAD57 /* LocalVKDataTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalVKDataTypes.swift; sourceTree = "<group>"; };
90 09BF420F1F0833C100AFAD57 /* MainCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainCoordinator.swift; sourceTree = "<group>"; };
82 09BF420F1F0833C100AFAD57 /* MainCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainCoordinator.swift; sourceTree = "<group>"; };
91 09BF42111F08341B00AFAD57 /* MyWeirdness.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyWeirdness.swift; sourceTree = "<group>"; };
83 09BF42111F08341B00AFAD57 /* MyWeirdness.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyWeirdness.swift; sourceTree = "<group>"; };
92 09BF42121F08341B00AFAD57 /* PublicCrap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PublicCrap.swift; sourceTree = "<group>"; };
84 09BF42121F08341B00AFAD57 /* PublicCrap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PublicCrap.swift; sourceTree = "<group>"; };
93 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VKPublicCrap.swift; sourceTree = "<group>"; };
85 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VKPublicCrap.swift; sourceTree = "<group>"; };
94 09BF42171F08352E00AFAD57 /* VKData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VKData.swift; sourceTree = "<group>"; };
86 09BF42171F08352E00AFAD57 /* VKData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VKData.swift; sourceTree = "<group>"; };
87+ 09BF42191F08357E00AFAD57 /* VkServices.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VkServices.swift; sourceTree = "<group>"; };
95 09BF42311F08388100AFAD57 /* SecondaryCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryCoordinator.swift; sourceTree = "<group>"; };
88 09BF42311F08388100AFAD57 /* SecondaryCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondaryCoordinator.swift; sourceTree = "<group>"; };
96 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftWebSocket.framework; path = Carthage/Build/iOS/SwiftWebSocket.framework; sourceTree = SOURCE_ROOT; };
89 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftWebSocket.framework; path = Carthage/Build/iOS/SwiftWebSocket.framework; sourceTree = SOURCE_ROOT; };
97 09BF42551F08413000AFAD57 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
90 09BF42551F08413000AFAD57 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
98− 09F03F221F164E7E000CE916 /* StreamingParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StreamingParser.swift; sourceTree = "<group>"; };
99− 09F03F241F165876000CE916 /* Decodable.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Decodable.framework; path = Carthage/Build/iOS/Decodable.framework; sourceTree = SOURCE_ROOT; };
100− 09F03F351F1674ED000CE916 /* VKServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VKServer.swift; sourceTree = "<group>"; };
101− 09F0D79D1F129DCB00A13751 /* Streaming.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Streaming.swift; sourceTree = "<group>"; };
102/* End PBXFileReference section */
91/* End PBXFileReference section */
103
92
104/* Begin PBXFrameworksBuildPhase section */
93/* Begin PBXFrameworksBuildPhase section */
@@ -106,57 +95,19 @@
106 isa = PBXFrameworksBuildPhase;
95 isa = PBXFrameworksBuildPhase;
107 buildActionMask = 2147483647;
96 buildActionMask = 2147483647;
108 files = (
97 files = (
109− 09F03F301F165884000CE916 /* Realm.framework in Frameworks */,
98+ 09BF422A1F0835B200AFAD57 /* Realm.framework in Frameworks */,
110− 09F03F281F165884000CE916 /* SwiftyJSON.framework in Frameworks */,
99+ 09BF42261F0835B200AFAD57 /* Alamofire.framework in Frameworks */,
100+ 09BF42341F083B5800AFAD57 /* SwiftWebSocket.framework in Frameworks */,
101+ 09BF422E1F0835B200AFAD57 /* SwiftyVK.framework in Frameworks */,
111− 09F03F321F165884000CE916 /* RealmSwift.framework in Frameworks */,
102+ 09BF422C1F0835B200AFAD57 /* RealmSwift.framework in Frameworks */,
112− 09F03F261F165884000CE916 /* Decodable.framework in Frameworks */,
113− 09F03F2E1F165884000CE916 /* Nuke.framework in Frameworks */,
103+ 09BF42281F0835B200AFAD57 /* Nuke.framework in Frameworks */,
114− 09F03F2A1F165884000CE916 /* SwiftWebSocket.framework in Frameworks */,
104+ 09BF42351F083B6000AFAD57 /* SwiftWebSocket.framework in Frameworks */,
115− 09F03F2C1F165884000CE916 /* Alamofire.framework in Frameworks */,
116 );
105 );
117 runOnlyForDeploymentPostprocessing = 0;
106 runOnlyForDeploymentPostprocessing = 0;
118 };
107 };
119/* End PBXFrameworksBuildPhase section */
108/* End PBXFrameworksBuildPhase section */
120
109
121/* Begin PBXGroup section */
110/* 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− };
131− 098397F71F1E887F008C88DD /* Main */ = {
132− isa = PBXGroup;
133− children = (
134− 09BF420F1F0833C100AFAD57 /* MainCoordinator.swift */,
135− 09BF42551F08413000AFAD57 /* MainViewController.swift */,
136− 09939A551F097DA90014719D /* TableViewCells.swift */,
137− );
138− name = Main;
139− sourceTree = "<group>";
140− };
141− 098397F81F1E888F008C88DD /* Secondary */ = {
142− isa = PBXGroup;
143− children = (
144− 09BF42311F08388100AFAD57 /* SecondaryCoordinator.swift */,
145− 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */,
146− );
147− name = Secondary;
148− sourceTree = "<group>";
149− };
150− 098397F91F1E88A3008C88DD /* Streaming */ = {
151− isa = PBXGroup;
152− children = (
153− 09AFAB031F159C9200EBD200 /* StreamingService.swift */,
154− 09F03F221F164E7E000CE916 /* StreamingParser.swift */,
155− 09F0D79D1F129DCB00A13751 /* Streaming.swift */,
156− );
157− name = Streaming;
158− sourceTree = "<group>";
159− };
160 09A456341F0ED98800BAC32D /* Public */ = {
111 09A456341F0ED98800BAC32D /* Public */ = {
161 isa = PBXGroup;
112 isa = PBXGroup;
162 children = (
113 children = (
@@ -185,16 +136,18 @@
185 09BF41ED1F07F71F00AFAD57 /* Melk */ = {
136 09BF41ED1F07F71F00AFAD57 /* Melk */ = {
186 isa = PBXGroup;
137 isa = PBXGroup;
187 children = (
138 children = (
188− 098397F71F1E887F008C88DD /* Main */,
189− 098397F81F1E888F008C88DD /* Secondary */,
190− 098397F91F1E88A3008C88DD /* Streaming */,
191− 09231E331F2394C5007C836D /* Card */,
192 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */,
139 09BF41EE1F07F71F00AFAD57 /* AppDelegate.swift */,
193 09BF42111F08341B00AFAD57 /* MyWeirdness.swift */,
140 09BF42111F08341B00AFAD57 /* MyWeirdness.swift */,
194 09BF42121F08341B00AFAD57 /* PublicCrap.swift */,
141 09BF42121F08341B00AFAD57 /* PublicCrap.swift */,
195− 09F03F351F1674ED000CE916 /* VKServer.swift */,
142+ 09BF420F1F0833C100AFAD57 /* MainCoordinator.swift */,
143+ 09BF42311F08388100AFAD57 /* SecondaryCoordinator.swift */,
144+ 0919AEA81F0D459600894FFA /* CardView.swift */,
145+ 0919AEA61F0D3D9D00894FFA /* SecondaryViewController.swift */,
146+ 09BF42551F08413000AFAD57 /* MainViewController.swift */,
147+ 09939A551F097DA90014719D /* TableViewCells.swift */,
196 09BF420D1F0833A700AFAD57 /* LocalVKDataTypes.swift */,
148 09BF420D1F0833A700AFAD57 /* LocalVKDataTypes.swift */,
197 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */,
149 09BF42151F0834D400AFAD57 /* VKPublicCrap.swift */,
150+ 09BF42191F08357E00AFAD57 /* VkServices.swift */,
198 09BF42171F08352E00AFAD57 /* VKData.swift */,
151 09BF42171F08352E00AFAD57 /* VKData.swift */,
199 09BF41F51F07F71F00AFAD57 /* Assets.xcassets */,
152 09BF41F51F07F71F00AFAD57 /* Assets.xcassets */,
200 09BF41F71F07F71F00AFAD57 /* LaunchScreen.storyboard */,
153 09BF41F71F07F71F00AFAD57 /* LaunchScreen.storyboard */,
@@ -210,13 +163,12 @@
210 09BF420C1F080A5F00AFAD57 /* Dependencies */ = {
163 09BF420C1F080A5F00AFAD57 /* Dependencies */ = {
211 isa = PBXGroup;
164 isa = PBXGroup;
212 children = (
165 children = (
213− 09F03F241F165876000CE916 /* Decodable.framework */,
214− 09AFAAFF1F159AE300EBD200 /* SwiftyJSON.framework */,
215 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */,
166 09BF42331F083B5800AFAD57 /* SwiftWebSocket.framework */,
216 09BF42021F080A5700AFAD57 /* Alamofire.framework */,
167 09BF42021F080A5700AFAD57 /* Alamofire.framework */,
217 09BF42031F080A5700AFAD57 /* Nuke.framework */,
168 09BF42031F080A5700AFAD57 /* Nuke.framework */,
218 09BF42041F080A5700AFAD57 /* Realm.framework */,
169 09BF42041F080A5700AFAD57 /* Realm.framework */,
219 09BF42051F080A5700AFAD57 /* RealmSwift.framework */,
170 09BF42051F080A5700AFAD57 /* RealmSwift.framework */,
171+ 09BF42061F080A5700AFAD57 /* SwiftyVK.framework */,
220 );
172 );
221 name = Dependencies;
173 name = Dependencies;
222 sourceTree = "<group>";
174 sourceTree = "<group>";
@@ -231,7 +183,7 @@
231 09BF41E71F07F71F00AFAD57 /* Sources */,
183 09BF41E71F07F71F00AFAD57 /* Sources */,
232 09BF41E81F07F71F00AFAD57 /* Frameworks */,
184 09BF41E81F07F71F00AFAD57 /* Frameworks */,
233 09BF41E91F07F71F00AFAD57 /* Resources */,
185 09BF41E91F07F71F00AFAD57 /* Resources */,
234− 09F03F341F165884000CE916 /* Embed Frameworks */,
186+ 09BF42301F0835B200AFAD57 /* Embed Frameworks */,
235 );
187 );
236 buildRules = (
188 buildRules = (
237 );
189 );
@@ -297,21 +249,17 @@
297 buildActionMask = 2147483647;
249 buildActionMask = 2147483647;
298 files = (
250 files = (
299 09939A561F097DA90014719D /* TableViewCells.swift in Sources */,
251 09939A561F097DA90014719D /* TableViewCells.swift in Sources */,
300− 09F03F361F1674ED000CE916 /* VKServer.swift in Sources */,
301 0919AEAD1F0D706700894FFA /* StackView.swift in Sources */,
252 0919AEAD1F0D706700894FFA /* StackView.swift in Sources */,
302 09BF42141F08341B00AFAD57 /* PublicCrap.swift in Sources */,
253 09BF42141F08341B00AFAD57 /* PublicCrap.swift in Sources */,
303 09BF42161F0834D400AFAD57 /* VKPublicCrap.swift in Sources */,
254 09BF42161F0834D400AFAD57 /* VKPublicCrap.swift in Sources */,
304− 09F0D79E1F129DCB00A13751 /* Streaming.swift in Sources */,
305 09BF42181F08352E00AFAD57 /* VKData.swift in Sources */,
255 09BF42181F08352E00AFAD57 /* VKData.swift in Sources */,
306 09BF42101F0833C100AFAD57 /* MainCoordinator.swift in Sources */,
256 09BF42101F0833C100AFAD57 /* MainCoordinator.swift in Sources */,
307 09A456361F0ED9A800BAC32D /* CollectionView.swift in Sources */,
257 09A456361F0ED9A800BAC32D /* CollectionView.swift in Sources */,
308− 09231E351F2394ED007C836D /* CardContainer.swift in Sources */,
258+ 09BF421A1F08357E00AFAD57 /* VkServices.swift in Sources */,
309 09BF42131F08341B00AFAD57 /* MyWeirdness.swift in Sources */,
259 09BF42131F08341B00AFAD57 /* MyWeirdness.swift in Sources */,
310 0919AEA91F0D459600894FFA /* CardView.swift in Sources */,
260 0919AEA91F0D459600894FFA /* CardView.swift in Sources */,
311 09BF42321F08388100AFAD57 /* SecondaryCoordinator.swift in Sources */,
261 09BF42321F08388100AFAD57 /* SecondaryCoordinator.swift in Sources */,
312 09BF41EF1F07F71F00AFAD57 /* AppDelegate.swift in Sources */,
262 09BF41EF1F07F71F00AFAD57 /* AppDelegate.swift in Sources */,
313− 09AFAB041F159C9200EBD200 /* StreamingService.swift in Sources */,
314− 09F03F231F164E7E000CE916 /* StreamingParser.swift in Sources */,
315 09BF420E1F0833A700AFAD57 /* LocalVKDataTypes.swift in Sources */,
263 09BF420E1F0833A700AFAD57 /* LocalVKDataTypes.swift in Sources */,
316 09BF42561F08413000AFAD57 /* MainViewController.swift in Sources */,
264 09BF42561F08413000AFAD57 /* MainViewController.swift in Sources */,
317 0919AEA71F0D3D9D00894FFA /* SecondaryViewController.swift in Sources */,
265 0919AEA71F0D3D9D00894FFA /* SecondaryViewController.swift in Sources */,
Melk.xcodeproj/xcuserdata/ilya.xcuserdatad/xcschemes/Melk.xcscheme+3−3
@@ -42,9 +42,9 @@
42 </AdditionalOptions>
42 </AdditionalOptions>
43 </TestAction>
43 </TestAction>
44 <LaunchAction
44 <LaunchAction
45− buildConfiguration = "Release"
45+ buildConfiguration = "Debug"
46− selectedDebuggerIdentifier = ""
46+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
47− selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
47+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
48 launchStyle = "0"
48 launchStyle = "0"
49 useCustomWorkingDirectory = "NO"
49 useCustomWorkingDirectory = "NO"
50 ignoresPersistentStateOnLaunch = "NO"
50 ignoresPersistentStateOnLaunch = "NO"
Melk/AppDelegate.swift−7
@@ -7,7 +7,6 @@
7//
7//
8
8
9import UIKit
9import UIKit
10−//import SwiftyVK
11
10
12@UIApplicationMain
11@UIApplicationMain
13class AppDelegate: UIResponder, UIApplicationDelegate {
12class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -23,7 +22,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
23 mainWindow.screen = UIScreen.main
22 mainWindow.screen = UIScreen.main
24 mainWindow.makeKeyAndVisible()
23 mainWindow.makeKeyAndVisible()
25 coordinator = MainCoordinator(window: mainWindow)
24 coordinator = MainCoordinator(window: mainWindow)
26− coordinator.start()
27
25
28 NotificationCenter.default.addObserver(forName: NSNotification.Name.UIScreenDidConnect, object: nil, queue: OperationQueue.main) { (_) in
26 NotificationCenter.default.addObserver(forName: NSNotification.Name.UIScreenDidConnect, object: nil, queue: OperationQueue.main) { (_) in
29 self.updateScreens()
27 self.updateScreens()
@@ -36,11 +34,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
36 // Override point for customization after application launch.
34 // Override point for customization after application launch.
37 return true
35 return true
38 }
36 }
39−
40− func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
41− return true
42− }
43−
44
37
45 func applicationWillResignActive(_ application: UIApplication) {
38 func applicationWillResignActive(_ application: UIApplication) {
46 // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
39 // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
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+10−126
@@ -12,51 +12,20 @@ class CardView: UIView {
12
12
13 var post: WallPost? {
13 var post: WallPost? {
14 didSet {
14 didSet {
15−// print(post?.owner)
16 update()
15 update()
17 }
16 }
18 }
17 }
19− var minWidth: CGFloat = 300 {
20− didSet {
21−// update()
22− }
23− }
24− var height: CGFloat = 400 {
25− didSet {
26−// update()
27− }
28− }
29
18
30 override init(frame: CGRect) {
19 override init(frame: CGRect) {
31 super.init(frame: frame)
20 super.init(frame: frame)
32 layer.masksToBounds = true
21 layer.masksToBounds = true
33 layer.cornerRadius = 20
22 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)
23+ backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
39 }
24 }
40
25
41 required init?(coder aDecoder: NSCoder) {
26 required init?(coder aDecoder: NSCoder) {
42 fatalError("init(coder:) has not been implemented")
27 fatalError("init(coder:) has not been implemented")
43 }
28 }
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− }
60
29
61// private let avatar = UIImage()
30// private let avatar = UIImage()
62// private let name = UIImage()
31// private let name = UIImage()
@@ -65,13 +34,14 @@ class CardView: UIView {
65 subviews.map {$0.removeFromSuperview()}
34 subviews.map {$0.removeFromSuperview()}
66
35
67 let largeStack = StackView(axis: .vertical, alignment: .left)
36 let largeStack = StackView(axis: .vertical, alignment: .left)
68− largeStack.padding = padding
37+ largeStack.padding = CGPoint(x: 32, y: 32)
69 addSubview(largeStack)
38 addSubview(largeStack)
70
39
71 let userView = StackView(axis: .horizontal, alignment: .center)
40 let userView = StackView(axis: .horizontal, alignment: .center)
41+// userView.backgroundColor = #colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1)
72
42
73
43
74− let avatarDim: CGFloat = 64
44+ let avatarDim: CGFloat = 50
75 let avatar = UIImageView()
45 let avatar = UIImageView()
76 post?.owner?.avatar?.load(into: avatar)
46 post?.owner?.avatar?.load(into: avatar)
77 avatar.layer.cornerRadius = avatarDim/2
47 avatar.layer.cornerRadius = avatarDim/2
@@ -81,116 +51,30 @@ class CardView: UIView {
81 avatar.frame.size = CGSize(width: avatarDim, height: avatarDim)
51 avatar.frame.size = CGSize(width: avatarDim, height: avatarDim)
82 userView.addArrangedSubview(.view(avatar))
52 userView.addArrangedSubview(.view(avatar))
83
53
84− userView.addArrangedSubview(.spacer(16))
54+ userView.addArrangedSubview(.spacer(8))
85
55
86 let userName = UILabel()
56 let userName = UILabel()
87 let firstName = post?.owner?.firstName ?? ""
57 let firstName = post?.owner?.firstName ?? ""
88 let lastName = post?.owner?.lastName ?? ""
58 let lastName = post?.owner?.lastName ?? ""
89 userName.text = "\(firstName) \(lastName)"
59 userName.text = "\(firstName) \(lastName)"
90 userName.font = UIFont.systemFont(ofSize: 28, weight: UIFontWeightHeavy)
60 userName.font = UIFont.systemFont(ofSize: 28, weight: UIFontWeightHeavy)
91− userName.textColor = UIColor.darkText
92 userName.sizeToFit()
61 userName.sizeToFit()
93 userView.addArrangedSubview(.view(userName))
62 userView.addArrangedSubview(.view(userName))
94−
63+ userView.frame.origin = CGPoint(x: 16, y: 16)
95− userView.layoutIfNeeded()
96
64
97 largeStack.addArrangedSubview(.view(userView))
65 largeStack.addArrangedSubview(.view(userView))
98
66
99− largeStack.addArrangedSubview(.spacer(vPadding1))
67+ largeStack.addArrangedSubview(.spacer(16))
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)
153
68
154 let body = UILabel()
69 let body = UILabel()
155 body.numberOfLines = 0
70 body.numberOfLines = 0
156− let bodyWidth: Double = Double(width)
71+ let bodyWidth: Double = 300
157 body.font = UIFont.systemFont(ofSize: 22, weight: UIFontWeightSemibold)
72 body.font = UIFont.systemFont(ofSize: 22, weight: UIFontWeightSemibold)
158− body.text = post?.body
73+ 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."
159− body.textColor = UIColor.darkText
160 let size = body.textRect(forBounds: CGRect(x: 0, y: 0, width: bodyWidth, height: Double.infinity), limitedToNumberOfLines: 0).size
74 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
75+ body.frame.size = size
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− }
178
76
179 largeStack.addArrangedSubview(.view(body))
77 largeStack.addArrangedSubview(.view(body))
180
78
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−
195 }
79 }
196}
80}
Melk/CollectionView.swift+2−4
@@ -68,7 +68,7 @@ class CollectionView: UIView {
68 var firstStack = true
68 var firstStack = true
69
69
70 for view in arrangedSubviews {
70 for view in arrangedSubviews {
71−// print("new view")
71+ print("new view")
72 if firstView {
72 if firstView {
73 lastStack.addArrangedSubview(.view(view))
73 lastStack.addArrangedSubview(.view(view))
74 firstView = false
74 firstView = false
@@ -94,9 +94,7 @@ class CollectionView: UIView {
94 }
94 }
95 }
95 }
96 lastStack.layoutIfNeeded()
96 lastStack.layoutIfNeeded()
97− if !firstStack {
98− largeStack.addArrangedSubview(.spacer(verticalPadding))
97+ largeStack.addArrangedSubview(.spacer(verticalPadding))
99− }
100 largeStack.addArrangedSubview(.view(lastStack))
98 largeStack.addArrangedSubview(.view(lastStack))
101 largeStack.frame.origin = CGPoint.zero
99 largeStack.frame.origin = CGPoint.zero
102 largeStack.layoutIfNeeded()
100 largeStack.layoutIfNeeded()
Melk/Info.plist−18
@@ -16,26 +16,8 @@
16 <string>APPL</string>
16 <string>APPL</string>
17 <key>CFBundleShortVersionString</key>
17 <key>CFBundleShortVersionString</key>
18 <string>1.0</string>
18 <string>1.0</string>
19− <key>CFBundleURLTypes</key>
20− <array>
21− <dict>
22− <key>CFBundleTypeRole</key>
23− <string>Editor</string>
24− <key>CFBundleURLName</key>
25− <string>com.ilyakooo0.Melk</string>
26− <key>CFBundleURLSchemes</key>
27− <array>
28− <string>vk6097091</string>
29− </array>
30− </dict>
31− </array>
32 <key>CFBundleVersion</key>
19 <key>CFBundleVersion</key>
33 <string>1</string>
20 <string>1</string>
34− <key>LSApplicationQueriesSchemes</key>
35− <array>
36− <string>vkauthorize</string>
37− <string>vk6097091</string>
38− </array>
39 <key>LSRequiresIPhoneOS</key>
21 <key>LSRequiresIPhoneOS</key>
40 <true/>
22 <true/>
41 <key>UILaunchStoryboardName</key>
23 <key>UILaunchStoryboardName</key>
Melk/LocalVKDataTypes.swift+91−137
@@ -11,8 +11,7 @@ import RealmSwift
11import Alamofire
11import Alamofire
12import CoreLocation
12import CoreLocation
13import Nuke
13import Nuke
14−import SwiftyJSON
15−//import SwiftyVK
14+import SwiftyVK
16
15
17
16
18typealias Token = String
17typealias Token = String
@@ -293,25 +292,17 @@ class User: Object {
293 }
292 }
294 }
293 }
295
294
296−// func get(completion: ((User?) -> ())? = nil) {
297−// VK.API.Users.get([VK.Arg.userIDs: "\(id)"]).send(onSuccess: { (response) in
298−// if let json = response.array?.first {
299−// let us = VKData.processUser(json: json)
300−// completion?(us)
301−// } else {
302−// completion?(nil)
303−// }
304−// }, onError: { (error) in
305−// completion?(nil)
306−// })
307−// }
308 func get(completion: ((User?) -> ())? = nil) {
295 func get(completion: ((User?) -> ())? = nil) {
309− VKServer.get(user: self) { (data) in
296+ VK.API.Users.get([VK.Arg.userIDs: "\(id)"]).send(onSuccess: { (response) in
310− if let json = JSON.init(data: data)["response"].array?.first {
297+ if let json = response.array?.first {
311− let user = VKData.processUser(json: json)
298+ let us = VKData.processUser(json: json)
312− completion?(user)
299+ completion?(us)
300+ } else {
301+ completion?(nil)
313 }
302 }
314− }
303+ }, onError: { (error) in
304+ completion?(nil)
305+ })
315 }
306 }
316
307
317
308
@@ -502,19 +493,19 @@ class Message: GenericMessage, Comparable, SortedArrayItem {
502 }
493 }
503 }
494 }
504
495
505−// func get(completion: ((Message?) -> ())? = nil) {
496+ func get(completion: ((Message?) -> ())? = nil) {
506−// VK.API.Messages.getById([VK.Arg.messageIds: String(id)]).send(onSuccess: { (response) in
497+ VK.API.Messages.getById([VK.Arg.messageIds: String(id)]).send(onSuccess: { (response) in
507−// if let json = response.array?.first {
498+ if let json = response.array?.first {
508−// let mes = VKData.processMessage(response)
499+ let mes = VKData.processMessage(response)
509−// completion?(mes)
500+ completion?(mes)
510−// } else {
501+ } else {
511−// completion?(nil)
502+ completion?(nil)
512−// }
503+ }
513−// }, onError: { (error) in
504+ }, onError: { (error) in
514−// completion?(nil)
505+ completion?(nil)
515−// })
506+ })
516−// // TODO: Implement propperly?
507+ // TODO: Implement propperly?
517−// }
508+ }
518
509
519 class func by(id: MessageID) -> Message {
510 class func by(id: MessageID) -> Message {
520 let realm = try! Realm()
511 let realm = try! Realm()
@@ -1248,32 +1239,24 @@ class Photo: Object {
1248 }
1239 }
1249 }
1240 }
1250
1241
1251−// func get(completion: ((Photo?) -> ())? = nil) {
1252−// if let ownerID = owner?.id {
1253−// var ph = "\(ownerID)_\(id)"
1254−// if let key = accessKey {
1255−// ph.append("_\(key)")
1256−// }
1257−// VK.API.Photos.getById([VK.Arg.photos: ph]).send(onSuccess: { (response) in
1258−// if let json = response.array?.first {
1259−// let photo = VKData.processPhoto(json)
1260−// completion?(photo)
1261−// } else {
1262−// completion?(nil)
1263−// }
1264−// }, onError: { (error) in
1265−// completion?(nil)
1266−// })
1267−// } else {
1268−// completion?(nil)
1269−// }
1270−// }
1271 func get(completion: ((Photo?) -> ())? = nil) {
1242 func get(completion: ((Photo?) -> ())? = nil) {
1272− VKServer.get(photo: self) { data in
1243+ if let ownerID = owner?.id {
1273− if let json = JSON.init(data: data)["response"].array?.first {
1244+ var ph = "\(ownerID)_\(id)"
1274− let photo = VKData.processPhoto(json)
1245+ if let key = accessKey {
1275− completion?(photo)
1246+ ph.append("_\(key)")
1276 }
1247 }
1248+ VK.API.Photos.getById([VK.Arg.photos: ph]).send(onSuccess: { (response) in
1249+ if let json = response.array?.first {
1250+ let photo = VKData.processPhoto(json)
1251+ completion?(photo)
1252+ } else {
1253+ completion?(nil)
1254+ }
1255+ }, onError: { (error) in
1256+ completion?(nil)
1257+ })
1258+ } else {
1259+ completion?(nil)
1277 }
1260 }
1278 }
1261 }
1279
1262
@@ -1383,42 +1366,33 @@ class WallPost: Object {
1383 // self.copyOwnerID = copyOwnerID
1366 // self.copyOwnerID = copyOwnerID
1384 // }
1367 // }
1385
1368
1386−// func get(completion: ((WallPost?) -> ())? = nil) {
1387−// if let ownerID = owner?.id {
1388−// var ph = "\(ownerID)_\(id)"
1389−// // if let key = accessKey {
1390−// // ph.append("_\(key)")
1391−// // }
1392−// VK.API.Wall.getById([VK.Arg.posts: ph]).send(onSuccess: { (response) in
1393−// if let json = response.array?.first {
1394−// let photo = VKData.processWallPost(json)
1395−// completion?(photo)
1396−// } else {
1397−// completion?(nil)
1398−// }
1399−// }, onError: { (error) in
1400−// completion?(nil)
1401−// })
1402−// } else {
1403−// completion?(nil)
1404−// }
1405−// }
1406 func get(completion: ((WallPost?) -> ())? = nil) {
1369 func get(completion: ((WallPost?) -> ())? = nil) {
1407− VKServer.get(wallPost: self) { (data) in
1370+ if let ownerID = owner?.id {
1408− if let json = JSON.init(data: data)["response"].array?.first {
1371+ var ph = "\(ownerID)_\(id)"
1372+ // if let key = accessKey {
1373+ // ph.append("_\(key)")
1374+ // }
1375+ VK.API.Wall.getById([VK.Arg.posts: ph]).send(onSuccess: { (response) in
1376+ if let json = response.array?.first {
1409− let post = VKData.processWallPost(json)
1377+ let photo = VKData.processWallPost(json)
1378+ completion?(photo)
1379+ } else {
1380+ completion?(nil)
1381+ }
1382+ }, onError: { (error) in
1410− completion?(post)
1383+ completion?(nil)
1411− }
1384+ })
1385+ } else {
1386+ completion?(nil)
1412 }
1387 }
1413 }
1388 }
1414−
1415
1389
1416
1390
1417 override class func primaryKey() -> String? {
1391 override class func primaryKey() -> String? {
1418 return "id"
1392 return "id"
1419 }
1393 }
1420
1394
1421− class func by(id: WallPostID) -> WallPost {
1395+ class func by(id: UserID) -> WallPost {
1422 let realm = try! Realm()
1396 let realm = try! Realm()
1423 if let us = realm.object(ofType: WallPost.self, forPrimaryKey: id) {
1397 if let us = realm.object(ofType: WallPost.self, forPrimaryKey: id) {
1424 return us
1398 return us
@@ -1458,10 +1432,6 @@ class WallPostReply: Object {
1458 }
1432 }
1459 }
1433 }
1460
1434
1461− func get(completion: (() -> ())) {
1462− // TODO: Get wallPostReply
1463− }
1464−
1465 override class func primaryKey() -> String? {
1435 override class func primaryKey() -> String? {
1466 return "id"
1436 return "id"
1467 }
1437 }
@@ -1742,32 +1712,24 @@ class Video: Object {
1742 }
1712 }
1743 }
1713 }
1744
1714
1745−// func get(completion: ((Video?) -> ())? = nil) {
1746−// if let peerID = owner?.id {
1747−// var vi = "\(peerID)_\(id)"
1748−// if let key = accessKey {
1749−// vi.append("_\(key)")
1750−// }
1751−// VK.API.Video.get([VK.Arg.videos: vi]).send(onSuccess: { (response) in
1752−// if let json = response["items"].array?.first {
1753−// let video = VKData.processVideo(json)
1754−// completion?(video)
1755−// } else {
1756−// completion?(nil)
1757−// }
1758−// }, onError: { (error) in
1759−// completion?(nil)
1760−// })
1761−// } else {
1762−// completion?(nil)
1763−// }
1764−// }
1765 func get(completion: ((Video?) -> ())? = nil) {
1715 func get(completion: ((Video?) -> ())? = nil) {
1766− VKServer.get(video: self) { (data) in
1716+ if let peerID = owner?.id {
1767− if let json = JSON.init(data: data)["response"].array?.first {
1717+ var vi = "\(peerID)_\(id)"
1768− let video = VKData.processVideo(json)
1718+ if let key = accessKey {
1769− completion?(video)
1719+ vi.append("_\(key)")
1770 }
1720 }
1721+ VK.API.Video.get([VK.Arg.videos: vi]).send(onSuccess: { (response) in
1722+ if let json = response["items"].array?.first {
1723+ let video = VKData.processVideo(json)
1724+ completion?(video)
1725+ } else {
1726+ completion?(nil)
1727+ }
1728+ }, onError: { (error) in
1729+ completion?(nil)
1730+ })
1731+ } else {
1732+ completion?(nil)
1771 }
1733 }
1772 }
1734 }
1773
1735
@@ -1874,32 +1836,24 @@ class Document: Object {
1874 }
1836 }
1875 }
1837 }
1876
1838
1877−// func get(completion: ((Document?) -> ())? = nil) {
1878−// if let ownerID = owner?.id {
1879−// var doc = "\(ownerID)_\(id)"
1880−// // if let key = accessKey {
1881−// // doc.append("_\(key)")
1882−// // }
1883−// VK.API.Docs.getById([VK.Arg.docs: doc]).send(onSuccess: { response in
1884−// if let json = response.array?.first {
1885−// let document = VKData.processDocument(json)
1886−// completion?(document)
1887−// } else {
1888−// completion?(nil)
1889−// }
1890−// }, onError: { (error) in
1891−// completion?(nil)
1892−// })
1893−// } else {
1894−// completion?(nil)
1895−// }
1896−// }
1897 func get(completion: ((Document?) -> ())? = nil) {
1839 func get(completion: ((Document?) -> ())? = nil) {
1898− VKServer.get(doc: self) { (data) in
1840+ if let ownerID = owner?.id {
1899− if let json = JSON.init(data: data)["response"].array?.first {
1841+ var doc = "\(ownerID)_\(id)"
1842+ // if let key = accessKey {
1843+ // doc.append("_\(key)")
1844+ // }
1845+ VK.API.Docs.getById([VK.Arg.docs: doc]).send(onSuccess: { response in
1846+ if let json = response.array?.first {
1900− let doc = VKData.processDocument(json)
1847+ let document = VKData.processDocument(json)
1848+ completion?(document)
1849+ } else {
1850+ completion?(nil)
1851+ }
1852+ }, onError: { (error) in
1901− completion?(doc)
1853+ completion?(nil)
1902− }
1854+ })
1855+ } else {
1856+ completion?(nil)
1903 }
1857 }
1904 }
1858 }
1905
1859
@@ -2099,7 +2053,7 @@ class Multichat: Object {
2099 if let us = realm.object(ofType: Multichat.self, forPrimaryKey: id) {
2053 if let us = realm.object(ofType: Multichat.self, forPrimaryKey: id) {
2100 return us
2054 return us
2101 } else {
2055 } else {
2102−// VkServices.getMultichat(for: id)
2056+ VkServices.getMultichat(for: id)
2103 let us = Multichat()
2057 let us = Multichat()
2104 realmWrite { realm in
2058 realmWrite { realm in
2105 us.id = id
2059 us.id = id
Melk/MainCoordinator.swift+1−86
@@ -7,105 +7,20 @@
7//
7//
8
8
9import UIKit
9import UIKit
10−import RealmSwift
11−//import SwiftyVK
12
10
13class MainCoordinator {
11class MainCoordinator {
14 let window: UIWindow
12 let window: UIWindow
15 let mainVC = MainViewController()
13 let mainVC = MainViewController()
16− let loadingVC = UIViewController() // TODO: An actual loading VC
17 let navC: UINavigationController!
14 let navC: UINavigationController!
18 let secondaryCoord = SecondaryCoordinator()
15 let secondaryCoord = SecondaryCoordinator()
19− let stream = StreamingService()
20 init(window: UIWindow) {
16 init(window: UIWindow) {
21 self.window = window
17 self.window = window
22− window.rootViewController = loadingVC
23−
24− Realm.Configuration.defaultConfiguration = Realm.Configuration
25− .init(inMemoryIdentifier: "com.ilyakooo0.Melk.realm",
26− readOnly: false,
27− deleteRealmIfMigrationNeeded: true)
28−
29 navC = UINavigationController(rootViewController: mainVC)
18 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− }
38− updateScreens()
39− stream.handleResult = { result in
40− self.secondaryCoord.add(result: result)
41−// switch result {
42−// case .post(let post):
43−//
44−// }
45− }
46− }
47−
48− func start() {
49−// VK.configure(withAppId: appID, delegate: self)
50−// if VK.state != .authorized {
51−// VK.logIn()
52−// }
53− print("didAuthorize")
54 window.rootViewController = navC
19 window.rootViewController = navC
20+ updateScreens()
55 }
21 }
56
22
57 func updateScreens() {
23 func updateScreens() {
58 secondaryCoord.updateScreens()
24 secondaryCoord.updateScreens()
59 }
25 }
60}
26}
61−/*
62−extension MainCoordinator: VKDelegate {
63− /** ---DEPRECATED. TOKEN NOW STORED IN KEYCHAIN--- Called when SwiftyVK need know where a token is located
64− - returns: Path to save/read token or nil if should save token to UserDefaults*/
65− func vkShouldUseTokenPath() -> String? {
66− return nil
67− }
68−
69− func vkWillAuthorize() -> Set<VK.Scope> {
70− //Called when SwiftyVK need authorization permissions.
71− return permissions
72− }
73−
74− func vkDidAuthorizeWith(parameters: Dictionary<String, String>) {
75− //Called when the user is log in.
76− //Here you can start to send requests to the API.
77− print("authorized")
78− mainSync {
79− self.window.rootViewController = self.navC
80− }
81− authorized()
82− }
83−
84− func vkAutorizationFailedWith(error: AuthError) {
85− //Called when SwiftyVK could not authorize. To let the application know that something went wrong.
86− print("failed auth with error \(error.errorCode): \(error.description)")
87− mainSync {
88− self.window.rootViewController = self.navC
89− }
90− }
91−
92− func vkDidUnauthorize() {
93− print("did unauthorize")
94− mainSync {
95− self.window.rootViewController = self.navC
96− }
97− //Called when user is log out.
98− }
99−
100− func vkWillPresentView() -> UIViewController {
101− //Only for iOS!
102− //Called when need to display a view from SwiftyVK.
103− let authController = UIViewController()
104− mainSync {
105− self.window.rootViewController = authController
106− }
107− return authController //UIViewController that should present authorization view controller
108− }
109−
110−}
111− */
Melk/MainViewController.swift+4−26
@@ -10,9 +10,7 @@ import UIKit
10
10
11class MainViewController: UIViewController {
11class MainViewController: UIViewController {
12
12
13− var present: (([String]) -> ())?
14−
15− private let mainView = MainView()
13+ let mainView = MainView()
16
14
17 init() {
15 init() {
18 super.init(nibName: nil, bundle: nil)
16 super.init(nibName: nil, bundle: nil)
@@ -28,10 +26,8 @@ class MainViewController: UIViewController {
28 fatalError("init(coder:) has not been implemented")
26 fatalError("init(coder:) has not been implemented")
29 }
27 }
30
28
31− @objc private func presentTags() {
29+ func presentTags() {
32− present?(
30+
33− mainView.tags.flatMap({$0}).filter({$0 != ""})
34− )
35 }
31 }
36}
32}
37
33
@@ -47,8 +43,6 @@ class MainView: UIView {
47 tableView.rowHeight = UITableViewAutomaticDimension
43 tableView.rowHeight = UITableViewAutomaticDimension
48 tableView.register(TitleTableViewCell.self, forCellReuseIdentifier: TitleTableViewCell.identifier)
44 tableView.register(TitleTableViewCell.self, forCellReuseIdentifier: TitleTableViewCell.identifier)
49 tableView.register(TagTableViewCell.self, forCellReuseIdentifier: TagTableViewCell.identifier)
45 tableView.register(TagTableViewCell.self, forCellReuseIdentifier: TagTableViewCell.identifier)
50− tableView.separatorStyle = .none
51− tableView.allowsSelection = false
52 setNeedsLayout()
46 setNeedsLayout()
53 }
47 }
54
48
@@ -56,17 +50,6 @@ class MainView: UIView {
56 tableView.frame = bounds
50 tableView.frame = bounds
57 }
51 }
58
52
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−
70 required init?(coder aDecoder: NSCoder) {
53 required init?(coder aDecoder: NSCoder) {
71 fatalError("init(coder:) has not been implemented")
54 fatalError("init(coder:) has not been implemented")
72 }
55 }
@@ -77,18 +60,13 @@ extension MainView: UITableViewDataSource {
77 if let cell = tableView.dequeueReusableCell(withIdentifier: TagTableViewCell.identifier) as? TagTableViewCell {
60 if let cell = tableView.dequeueReusableCell(withIdentifier: TagTableViewCell.identifier) as? TagTableViewCell {
78// cell.titleText = "Testing testing 1 2 3"
61// cell.titleText = "Testing testing 1 2 3"
79 cell.style = indexPath.item == 0 ? .large : .normal
62 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]
85 return cell
63 return cell
86 }
64 }
87 return UITableViewCell()
65 return UITableViewCell()
88 }
66 }
89
67
90 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
68 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
91− return tags.count
69+ return 3
92 }
70 }
93
71
94 func numberOfSections(in tableView: UITableView) -> Int {
72 func numberOfSections(in tableView: UITableView) -> Int {
Melk/PublicCrap.swift−10
@@ -247,13 +247,3 @@ struct DecayingAverage {
247 value = (value * weight + num) / (weight + 1)
247 value = (value * weight + num) / (weight + 1)
248 }
248 }
249}
249}
250−
251−func mainSync(_ code: (() -> ())) {
252− if Thread.isMainThread {
253− code()
254− } else {
255− DispatchQueue.main.sync {
256− code()
257− }
258− }
259−}
Melk/SecondaryCoordinator.swift+1−24
@@ -12,42 +12,19 @@ class SecondaryCoordinator {
12
12
13 var windows: [UIWindow] = []
13 var windows: [UIWindow] = []
14
14
15− private var didStartPresenting = false
16− private var tag: String = ""
17−
18− func add(result: StreamingServiceResult) {
19− for vc in VCs {
20− vc.add(result: result)
21− }
22− }
23−
24− func present(tag newTag: String) {
25− didStartPresenting = true
26− self.tag = newTag
27− VCs.map({ $0.present(tag: newTag) })
28− }
29−
30 init() {
15 init() {
31
16
32 }
17 }
33
18
34− private var VCs: [SecondaryViewController] = []
35−
36 func updateScreens() {
19 func updateScreens() {
37 windows.removeAll()
20 windows.removeAll()
38− VCs.removeAll()
39 for screen in UIScreen.screens.dropFirst() {
21 for screen in UIScreen.screens.dropFirst() {
40 let window = UIWindow(frame: screen.bounds)
22 let window = UIWindow(frame: screen.bounds)
41 window.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
23 window.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
42 window.screen = screen
24 window.screen = screen
43 window.isHidden = false
25 window.isHidden = false
44− let VC = SecondaryViewController()
45− VCs.append(VC)
46− window.rootViewController = VC
26+ window.rootViewController = SecondaryViewController()
47 windows.append(window)
27 windows.append(window)
48− if didStartPresenting {
49− VC.present(tag: tag)
50− }
51 }
28 }
52 }
29 }
53}
30}
Melk/SecondaryViewController.swift+9−125
@@ -9,145 +9,29 @@
9import UIKit
9import UIKit
10
10
11class SecondaryViewController: UIViewController {
11class SecondaryViewController: UIViewController {
12−
13 init() {
12 init() {
14 super.init(nibName: nil, bundle: nil)
13 super.init(nibName: nil, bundle: nil)
15− self.view = sView
14+ self.view = SecondaryView(frame: view.bounds)
16− }
17−
18− func add(result: StreamingServiceResult) {
19− sView.add(result: result)
20− }
21−
22− func present(tag: String) {
23− sView.present(tag: tag)
24 }
15 }
25
16
26 required init?(coder aDecoder: NSCoder) {
17 required init?(coder aDecoder: NSCoder) {
27 fatalError("init(coder:) has not been implemented")
18 fatalError("init(coder:) has not been implemented")
28 }
19 }
29−
30− private let sView = SecondaryView()
31}
20}
32
21
33class SecondaryView: UIView {
22class 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−
61− func add(result: StreamingServiceResult) {
62− switch result {
63− case .post(let post):
64− let card = CardContainer()
65− card.minWidth = min(bounds.width / 2.3, 550)
66− card.height = cardHeight
67− card.post = post
68− cards.addArrangedSubview(.spacer(spacer))
69− cards.addArrangedSubview(.view(card))
70− card.animate()
71− }
72− self.layoutIfNeeded(animated: true)
73−// self.setNeedsLayout(animated: true) // Doesn't work for some reason
74− }
75−
76−// private let card = CardView()
77− private let cards = StackView(axis: .horizontal, alignment: .top)
78−
79 override init(frame: CGRect) {
23 override init(frame: CGRect) {
80 super.init(frame: frame)
24 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
25
129− melkLabel.sizeToFit()
26+ let card = CardView(frame: CGRect(x: 20, y: 20, width: 600, height: 300))
130− melkLabel.center = center
27+ let post = WallPost()
28+ post.owner = User()
29+ post.owner?.firstName = "David"
30+ post.owner?.avatar = RealmPhoto()
31+ post.owner?.avatar?.imageSURL = "https://static.independent.co.uk/s3fs-public/styles/article_small/public/thumbnails/image/2017/04/01/17/twitter-egg.jpg"
32+ card.post = post
33+ addSubview(card)
131
34
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
151 }
35 }
152
36
153 required init?(coder aDecoder: NSCoder) {
37 required init?(coder aDecoder: NSCoder) {
Melk/StackView.swift+1−3
@@ -44,8 +44,6 @@ class StackView: UIView {
44 super.layoutSubviews()
44 super.layoutSubviews()
45 print("laying out subviews")
45 print("laying out subviews")
46
46
47− subviews.map({$0.removeFromSuperview()}) // TODO: There must be a better way!
48−
49 var height: CGFloat = 0
47 var height: CGFloat = 0
50 var width: CGFloat = 0
48 var width: CGFloat = 0
51 switch axis {
49 switch axis {
@@ -64,7 +62,7 @@ class StackView: UIView {
64 height += a
62 height += a
65 }
63 }
66 case .view(let view):
64 case .view(let view):
67− view.layoutIfNeeded()
65+
68 switch axis {
66 switch axis {
69 case .horizontal:
67 case .horizontal:
70 view.frame.origin.x = width
68 view.frame.origin.x = width
Melk/Streaming.swiftdeleted−195
@@ -1,195 +0,0 @@
1−//
2−// Streaming.swift
3−// Melk
4−//
5−// Created by Ilya Kos on 7/9/17.
6−// Copyright © 2017 Ilya Kos. All rights reserved.
7−//
8−
9−import Foundation
10−import SwiftWebSocket
11−import Alamofire
12−import SwiftyJSON
13−
14−class Streaming {
15−
16− let streamingServerSurl = "https://api.vk.com/method/streaming.getServerUrl"
17− let params: [String: String] = [
18− "access_token": accessKey,
19− "v": vkAPIVersion
20− ]
21−
22− private var key: String?
23− private var server: String?
24− let ws = WebSocket()
25−
26− var processItem: ((Any) -> ())?
27−
28− func getServer(completion: (() -> ())? = nil) {
29− Alamofire.request(streamingServerSurl, parameters: params).validate().responseData { (response) in
30− switch response.result {
31− case .success(let data):
32− let json = JSON.init(data: data)["response"]
33− self.key = json["key"].string
34− self.server = json["endpoint"].string
35− case .failure(let error):
36− print(error)
37− }
38− DispatchQueue.main.async {
39− completion?()
40− }
41− }
42− }
43−
44− func add(rule: Rule, completion: (() -> ())? = nil) {
45− if let key = key,
46− let server = server {
47− let url = "https://\(server)/rules?key=\(key)"
48− let request: [String: Any] = [
49− "rule": [
50− "value": rule.rule,
51− "tag": rule.tag
52− ]
53− ]
54− print(try? JSONSerialization.data(withJSONObject: request, options: .prettyPrinted) =>> {String.init(data: $0, encoding: .utf8)})
55− Alamofire.request(url, method: .post, parameters: request, encoding: JSONEncoding.default)
56− .validate().responseData(completionHandler: { (response) in
57− switch response.result {
58− case .success(let data):
59− let json = JSON.init(data: data)
60− print(json) // TODO: Handle error
61− case .failure(let error):
62− print(error)
63− }
64− DispatchQueue.main.async {
65− completion?()
66− }
67− })
68− } else {
69− getServer() {
70− self.add(rule: rule, completion: completion)
71− }
72− }
73− }
74− func add(rules: [Rule], completion: (() -> ())? = nil) {
75− if let server = server,
76− let key = key {
77− var numOfCompletions = rules.count + 1
78− let complete: (() -> ()) = {
79− numOfCompletions -= 1
80− if numOfCompletions == 0 {
81− completion?()
82− }
83− }
84−
85− complete()
86−
87− for rule in rules {
88− add(rule: rule, completion: complete)
89− }
90− } else {
91− getServer() {
92− self.add(rules: rules, completion: completion)
93− }
94− }
95− }
96− func getRules(completion: @escaping (([Rule]?) -> ())) {
97− if let server = server,
98− let key = key {
99− let url = "https://\(server)/rules?key=\(key)"
100− Alamofire.request(url, method: .get).validate().responseData { (response) in
101− switch response.result {
102− case .success(let data):
103− let json = JSON.init(data: data)
104− print(json)
105− if json["code"].int == 200 {
106− var resultRules: [Rule] = []
107− if let rules = json["rules"].array {
108− for rule in rules {
109− if let tag = rule["tag"].string,
110− let value = rule["value"].string {
111− resultRules.append((rule: value, tag: tag))
112− }
113− }
114− }
115− completion(resultRules)
116− } // TODO" Handle errors
117− case .failure(let error):
118− print(error) // TODO: HAndl;e error
119− }
120− }
121− } else {
122− getServer() {
123− self.getRules(completion: completion)
124− }
125− }
126− }
127− func remove(rule: Rule, completion: (() -> ())? = nil) {
128− if let server = server,
129− let key = key {
130− let url = "https://\(server)/rules?key=\(key)"
131− let request: [String: Any] = [
132− "tag": rule.tag
133− ]
134− Alamofire.request(url, method: .delete, parameters: request, encoding: JSONEncoding.default).validate().responseData { response in
135− switch response.result {
136− case .success(let data):
137− let json = JSON.init(data: data)
138− print(json) // TODO: HAndle error
139− completion?()
140− case .failure(let error):
141− print(error) // TODO: HAndl;e error
142− }
143− }
144− } else {
145− getServer() {
146− self.remove(rule: rule, completion: completion)
147− }
148− }
149− }
150− func removeAllRules(completion: (() -> ())? = nil) {
151− getRules { (rules) in
152− if let rules = rules {
153−
154− var numOfCompleted = rules.count + 1
155− let complete : (() -> ()) = {
156− numOfCompleted -= 1
157− if numOfCompleted == 0 {
158− completion?()
159− }
160− }
161−
162− complete()
163−
164− for rule in rules {
165− self.remove(rule: rule, completion: complete)
166− }
167− }
168− }
169− }
170− func connect(completion: (() -> ())? = nil) {
171− if let key = key,
172− let server = server {
173− let surl = "wss://\(server)/stream?key=\(key)"
174− let url = URL(string: surl)!
175− ws.event.message = { message in
176− self.processItem?(message)
177− }
178− let request = NSMutableURLRequest(url: url)
179− request.httpMethod = "GET"
180− request.addValue("upgrade", forHTTPHeaderField: "Connection")
181− request.addValue("websocket", forHTTPHeaderField: "Upgrade")
182− request.addValue("13", forHTTPHeaderField: "Sec-Websocket-Version")
183− ws.open(request: request as URLRequest)
184− DispatchQueue.main.async {
185− completion?()
186− }
187− } else {
188− getServer() {
189− self.connect(completion: completion)
190− }
191− }
192− }
193−}
194−
195−typealias Rule = (rule: String, tag: String)
Melk/StreamingParser.swiftdeleted−80
@@ -1,80 +0,0 @@
1−//
2−// StreamingParser.swift
3−// Melk
4−//
5−// Created by Ilya Kos on 7/12/17.
6−// Copyright © 2017 Ilya Kos. All rights reserved.
7−//
8−
9−import Foundation
10−import Decodable
11−
12−class StreamingParser {
13− static func parse(json: DJSON, completion: @escaping ((StreamingResponse) -> ())) {
14− do {
15− let code: Int = try json => "code"
16− switch code {
17− case 100:
18− let event = try json => "event"
19− let eventType: String = try event => "event_type"
20− let eventID = try event => "event_id"
21− let postID: WallPostID = try eventID => "post_id"
22− let ownerID: UserID = try eventID => "post_owner_id"
23− // let
24− var post: WallPost!
25− var comp = 2
26− realmWrite { _ in
27− post = WallPost.by(id: postID)
28− post.owner = User.by(id: ownerID)
29− switch eventType {
30− case "post":
31− break
32− case "comment":
33− /*
34− if let id: Int = try? eventID => "comment_id" {
35− let comment = WallPostReply.by(id: id)
36− comment.wallPost = post
37− comp += 1
38− comment // TODO: get comment
39− }
40− */
41− print("comment not implemented")
42−
43− case "share":
44− break
45− default:
46− print("error:\n\(json)")
47− }
48− }
49−// print(post.owner)
50− let complete = {
51− comp -= 1
52− if comp == 0 {
53−// print(post.owner)
54− completion(.post(post))
55− }
56− }
57− post.owner?.get(completion: { (_) in
58− complete()
59− })
60− post.get(completion: { (_) in
61− complete()
62− })
63− break // handle event
64− case 300:
65− break // handle service message
66− default:
67− print("Not implemented:\n\(json)\n")
68− }
69− } catch let error {
70− print(error)
71− }
72− }
73−}
74−
75−enum StreamingResponse {
76− case service
77− case post(WallPost)
78−}
79−
80−typealias DJSON = Any
Melk/StreamingService.swiftdeleted−61
@@ -1,61 +0,0 @@
1−//
2−// StreamingService.swift
3−// Melk
4−//
5−// Created by Ilya Kos on 7/12/17.
6−// Copyright © 2017 Ilya Kos. All rights reserved.
7−//
8−
9−import Foundation
10−
11−class StreamingService {
12− init() {
13− streaming.processItem = { item in
14− if let string = item as? String,
15− let data = string.data(using: .utf8),
16− let json = try? JSONSerialization.jsonObject(with: data, options: []) {
17− StreamingParser.parse(json: json, completion: { (result) in
18− switch result {
19− case .post(let post):
20− self.handleResult?(.post(post))
21− case .service:
22− break // TODO: HAndle servoce message
23− }
24− })
25− }
26− }
27− }
28− var rules: [String] = [] {
29− didSet {
30− updateRules()
31− }
32− }
33−
34− func connect() {
35− streaming.connect()
36− }
37−
38− var handleResult: ((StreamingServiceResult) -> ())?
39−
40−
41−
42− private let streaming = Streaming()
43−
44− private func updateRules() {
45− streaming.removeAllRules {
46− var outRules: [Rule] = []
47− var i = 1
48− for rule in self.rules {
49− if i <= 10 {
50− outRules.append((rule: rule, tag: String(i)))
51− i += 1
52− }
53− }
54− self.streaming.add(rules: outRules)
55− }
56− }
57−}
58−
59−enum StreamingServiceResult {
60− case post(WallPost)
61−}
Melk/TableViewCells.swift+3−12
@@ -57,12 +57,6 @@ class TagTableViewCell: UITableViewCell {
57 }
57 }
58 }
58 }
59
59
60− var tagDidChange: ((String?) -> ())?
61−
62− @objc private func textDidChange() {
63− tagDidChange?(tagString)
64− }
65−
66 var style: TagStyle = .normal {
60 var style: TagStyle = .normal {
67 didSet {
61 didSet {
68 updateStyle()
62 updateStyle()
@@ -76,9 +70,6 @@ class TagTableViewCell: UITableViewCell {
76
70
77 textField.borderStyle = .roundedRect
71 textField.borderStyle = .roundedRect
78 textField.adjustsFontSizeToFitWidth = false
72 textField.adjustsFontSizeToFitWidth = false
79− textField.autocapitalizationType = .none
80− textField.autocorrectionType = .no
81− textField.addTarget(self, action: #selector(self.textDidChange), for: .editingChanged)
82
73
83 contentView.addSubview(textField)
74 contentView.addSubview(textField)
84// textField.delegate = self
75// textField.delegate = self
@@ -101,7 +92,7 @@ class TagTableViewCell: UITableViewCell {
101 CGRect.infinite, limitedToNumberOfLines: 1)
92 CGRect.infinite, limitedToNumberOfLines: 1)
102 .height + 2*2
93 .height + 2*2
103
94
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)
105 textField.frame = frame
96 textField.frame = frame
106 print(textField.frame)
97 print(textField.frame)
107 }
98 }
@@ -112,8 +103,8 @@ class TagTableViewCell: UITableViewCell {
112
103
113
104
114 static let identifier = "io.Melk.tagTableViewCell"
105 static let identifier = "io.Melk.tagTableViewCell"
115− static let largeHeight: CGFloat = 37.5 + 16 + 32
106+ static let largeHeight: CGFloat = 37.5 + 8*2
116− static let normalHeight: CGFloat = 28.0 + 4*2
107+ static let normalHeight: CGFloat = 28.0 + 8*2
117}
108}
118
109
119//extension TagTableViewCell: UITextFieldDelegate {
110//extension TagTableViewCell: UITextFieldDelegate {
Melk/VKData.swift+34−34
@@ -7,10 +7,10 @@
7//
7//
8
8
9import Foundation
9import Foundation
10−import SwiftyJSON
10+//import SwiftyJSON
11import CoreLocation
11import CoreLocation
12import RealmSwift
12import RealmSwift
13−//import SwiftyVK
13+import SwiftyVK
14
14
15class VKData {
15class VKData {
16 // var users: [UserID: User] = [:]
16 // var users: [UserID: User] = [:]
@@ -31,7 +31,7 @@ class VKData {
31 // var polls: [PollID: Poll] = [:]
31 // var polls: [PollID: Poll] = [:]
32 // var photoAlbums: [PhotoAlbumID: PhotoAlbum] = [:]
32 // var photoAlbums: [PhotoAlbumID: PhotoAlbum] = [:]
33
33
34− class func processUser(json: JSON) -> User? {
34+ class func processUser(json: SwiftyVK.JSON) -> User? {
35 print("in")
35 print("in")
36 if let id = json["id"].int, let firstName = json["first_name"].string, let lastName = json["last_name"].string {
36 if let id = json["id"].int, let firstName = json["first_name"].string, let lastName = json["last_name"].string {
37 var user: User!
37 var user: User!
@@ -49,7 +49,7 @@ class VKData {
49 }
49 }
50 user.birthday = formatter.date(from: birthday)
50 user.birthday = formatter.date(from: birthday)
51 }
51 }
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)
53 user.photo = RealmPhoto.by(user.photoID, surl: json["photo_max_orig"].string)
53 user.photo = RealmPhoto.by(user.photoID, surl: json["photo_max_orig"].string)
54 if let friendStat = json["friend_status"].int {
54 if let friendStat = json["friend_status"].int {
55 user.friendStatus = FriendStatus(rawValue: friendStat)
55 user.friendStatus = FriendStatus(rawValue: friendStat)
@@ -90,7 +90,7 @@ class VKData {
90 return nil
90 return nil
91 }
91 }
92
92
93− class func processGeolocation(_ json: JSON) -> Geolocation? {
93+ class func processGeolocation(_ json: SwiftyVK.JSON) -> Geolocation? {
94 if let coords = json["coordinates"].string{
94 if let coords = json["coordinates"].string{
95 let nums = coords.characters.split(separator: " ").map({ (n) -> Double? in
95 let nums = coords.characters.split(separator: " ").map({ (n) -> Double? in
96 NumberFormatter().number(from: String(n))?.doubleValue
96 NumberFormatter().number(from: String(n))?.doubleValue
@@ -112,7 +112,7 @@ class VKData {
112 }
112 }
113 }
113 }
114
114
115− class func processMedia(_ json: JSON) -> Media? {
115+ class func processMedia(_ json: SwiftyVK.JSON) -> Media? {
116 if let type = json["type"].string {
116 if let type = json["type"].string {
117 switch type {
117 switch type {
118 case "photo":
118 case "photo":
@@ -174,7 +174,7 @@ class VKData {
174 return nil
174 return nil
175 }
175 }
176
176
177− class func processPhotoAlbum(_ json: JSON) -> PhotoAlbum? {
177+ class func processPhotoAlbum(_ json: SwiftyVK.JSON) -> PhotoAlbum? {
178 if let id = json["id"].int{
178 if let id = json["id"].int{
179 var album: PhotoAlbum!
179 var album: PhotoAlbum!
180 realmWrite { _ in
180 realmWrite { _ in
@@ -209,7 +209,7 @@ class VKData {
209 return nil
209 return nil
210 }
210 }
211
211
212− class func processGift(_ json: JSON) -> Gift? {
212+ class func processGift(_ json: SwiftyVK.JSON) -> Gift? {
213 if let id = json["id"].int {
213 if let id = json["id"].int {
214 var gift: Gift!
214 var gift: Gift!
215 realmWrite({ _ in
215 realmWrite({ _ in
@@ -221,7 +221,7 @@ class VKData {
221 return nil
221 return nil
222 }
222 }
223
223
224− class func processWallPostReply(_ json: JSON) -> WallPostReply? {
224+ class func processWallPostReply(_ json: SwiftyVK.JSON) -> WallPostReply? {
225 let likes = json["likes"]
225 let likes = json["likes"]
226 if let id = json["id"].int {
226 if let id = json["id"].int {
227 var reply: WallPostReply!
227 var reply: WallPostReply!
@@ -248,7 +248,7 @@ class VKData {
248 return nil
248 return nil
249 }
249 }
250
250
251− class func processPollAnswer(_ json: JSON) -> PollAnswer? {
251+ class func processPollAnswer(_ json: SwiftyVK.JSON) -> PollAnswer? {
252 if let id = json["id"].int,
252 if let id = json["id"].int,
253 let body = json["text"].string,
253 let body = json["text"].string,
254 let votes = json["votes"].int,
254 let votes = json["votes"].int,
@@ -258,7 +258,7 @@ class VKData {
258 return nil
258 return nil
259 }
259 }
260
260
261− class func processPoll(_ json: JSON) -> Poll? {
261+ class func processPoll(_ json: SwiftyVK.JSON) -> Poll? {
262 if let id = json["id"].int {
262 if let id = json["id"].int {
263 var poll: Poll!
263 var poll: Poll!
264 realmWrite { _ in
264 realmWrite { _ in
@@ -279,7 +279,7 @@ class VKData {
279 return nil
279 return nil
280 }
280 }
281
281
282− class func processPhoto(_ json: JSON) -> Photo? {
282+ class func processPhoto(_ json: SwiftyVK.JSON) -> Photo? {
283 if let id = json["id"].int {
283 if let id = json["id"].int {
284 var photo: Photo!
284 var photo: Photo!
285 realmWrite { _ in
285 realmWrite { _ in
@@ -289,13 +289,13 @@ class VKData {
289 photo.width.value = json["width"].int
289 photo.width.value = json["width"].int
290 photo.height.value = json["height"].int
290 photo.height.value = json["height"].int
291 var surl: String?
291 var surl: String?
292−// if let imageSurl = json["photo_2560"].string {
292+ if let imageSurl = json["photo_2560"].string {
293−// surl = imageSurl
293+ surl = imageSurl
294−// } else if let imageSurl = json["photo_1280"].string {
294+ } else if let imageSurl = json["photo_1280"].string {
295−// surl = imageSurl
295+ surl = imageSurl
296−// } else if let imageSurl = json["photo_807"].string {
296+ } else if let imageSurl = json["photo_807"].string {
297−// surl = imageSurl
297+ surl = imageSurl
298− /*} else*/ if let imageSurl = json["photo_604"].string {
298+ } else if let imageSurl = json["photo_604"].string {
299 surl = imageSurl
299 surl = imageSurl
300 } else if let imageSurl = json["photo_130"].string {
300 } else if let imageSurl = json["photo_130"].string {
301 surl = imageSurl
301 surl = imageSurl
@@ -312,7 +312,7 @@ class VKData {
312 }
312 }
313 }
313 }
314
314
315− class func processVideo(_ json: JSON) -> Video? {
315+ class func processVideo(_ json: SwiftyVK.JSON) -> Video? {
316 if let id = json["id"].int {
316 if let id = json["id"].int {
317 var video: Video!
317 var video: Video!
318 realmWrite { _ in
318 realmWrite { _ in
@@ -337,7 +337,7 @@ class VKData {
337 }
337 }
338 }
338 }
339
339
340− class func processAudio(_ json: JSON) -> Audio? {
340+ class func processAudio(_ json: SwiftyVK.JSON) -> Audio? {
341 if let id = json["id"].int {
341 if let id = json["id"].int {
342 var audio: Audio!
342 var audio: Audio!
343 realmWrite { _ in
343 realmWrite { _ in
@@ -354,7 +354,7 @@ class VKData {
354 }
354 }
355 }
355 }
356
356
357− class func processDocument(_ json: JSON) -> Document? {
357+ class func processDocument(_ json: SwiftyVK.JSON) -> Document? {
358 if let id = json["id"].int {
358 if let id = json["id"].int {
359 var doc: Document!
359 var doc: Document!
360 realmWrite { _ in
360 realmWrite { _ in
@@ -371,7 +371,7 @@ class VKData {
371 return nil
371 return nil
372 }
372 }
373
373
374− class func processSticker(_ json: JSON) -> Sticker? {
374+ class func processSticker(_ json: SwiftyVK.JSON) -> Sticker? {
375 if let id = json["id"].int,
375 if let id = json["id"].int,
376 let pack = json["product_id"].int {
376 let pack = json["product_id"].int {
377 var sticker: Sticker!
377 var sticker: Sticker!
@@ -387,7 +387,7 @@ class VKData {
387 return nil
387 return nil
388 }
388 }
389
389
390− class func processRating(_ json: JSON) -> Rating? {
390+ class func processRating(_ json: SwiftyVK.JSON) -> Rating? {
391 if let stars = json["stars"].int,
391 if let stars = json["stars"].int,
392 let reviewCount = json["reviews_count"].int {
392 let reviewCount = json["reviews_count"].int {
393 return Rating(stars: stars, reviewCount: reviewCount)
393 return Rating(stars: stars, reviewCount: reviewCount)
@@ -395,7 +395,7 @@ class VKData {
395 return nil
395 return nil
396 }
396 }
397
397
398− class func processButton(_ json: JSON) -> LinkButton? {
398+ class func processButton(_ json: SwiftyVK.JSON) -> LinkButton? {
399 if let title = json["title"].string,
399 if let title = json["title"].string,
400 let surl = json["url"].string,
400 let surl = json["url"].string,
401 let url = URL(string: surl) {
401 let url = URL(string: surl) {
@@ -404,7 +404,7 @@ class VKData {
404 return nil
404 return nil
405 }
405 }
406
406
407− class func processLink(_ json: JSON) -> Link? {
407+ class func processLink(_ json: SwiftyVK.JSON) -> Link? {
408 if let surl = json["url"].string {
408 if let surl = json["url"].string {
409 var link: Link!
409 var link: Link!
410 realmWrite({ (_) in
410 realmWrite({ (_) in
@@ -422,7 +422,7 @@ class VKData {
422 return nil
422 return nil
423 }
423 }
424
424
425− class func processWallPost(_ json: JSON) -> WallPost? {
425+ class func processWallPost(_ json: SwiftyVK.JSON) -> WallPost? {
426 let comments = json["comments"]
426 let comments = json["comments"]
427 let likes = json["likes"]
427 let likes = json["likes"]
428 let reposts = json["reposts"]
428 let reposts = json["reposts"]
@@ -430,7 +430,7 @@ class VKData {
430 var post: WallPost!
430 var post: WallPost!
431 realmWrite { _ in
431 realmWrite { _ in
432 post = WallPost.by(id: id)
432 post = WallPost.by(id: id)
433− post.owner = json["owner_id"].int >>> {User.by(id: $0)}
433+ post.owner = json["to_id"].int >>> {User.by(id: $0)}
434 post.creator = json["from_id"].int >>> {User.by(id: $0)}
434 post.creator = json["from_id"].int >>> {User.by(id: $0)}
435 post.date = json["date"].int >>> {Date.init(timeIntervalSince1970: TimeInterval($0))}
435 post.date = json["date"].int >>> {Date.init(timeIntervalSince1970: TimeInterval($0))}
436 post.body = json["text"].string
436 post.body = json["text"].string
@@ -469,7 +469,7 @@ class VKData {
469 return nil
469 return nil
470 }
470 }
471
471
472− class func prpocessServiceMessageAction(_ json: JSON) -> ServiceMessageAction? {
472+ class func prpocessServiceMessageAction(_ json: SwiftyVK.JSON) -> ServiceMessageAction? {
473 if let sAction = json["action"].string {
473 if let sAction = json["action"].string {
474 switch sAction {
474 switch sAction {
475 case "chat_photo_update":
475 case "chat_photo_update":
@@ -519,7 +519,7 @@ class VKData {
519 return nil
519 return nil
520 }
520 }
521
521
522− class func processMessage(_ json: JSON) -> Message? {
522+ class func processMessage(_ json: SwiftyVK.JSON) -> Message? {
523 if let user = json["user_id"].int >>> {User.by(id: $0)},
523 if let user = json["user_id"].int >>> {User.by(id: $0)},
524 let date = json["date"].int >>> {Date(timeIntervalSince1970: TimeInterval($0))},
524 let date = json["date"].int >>> {Date(timeIntervalSince1970: TimeInterval($0))},
525 let id = json["id"].int {
525 let id = json["id"].int {
@@ -556,7 +556,7 @@ class VKData {
556 }
556 }
557 }
557 }
558
558
559− class func processGenericMessage(_ json: JSON) -> GenericMessage? {
559+ class func processGenericMessage(_ json: SwiftyVK.JSON) -> GenericMessage? {
560 if let user = json["user_id"].int >>> {User.by(id: $0)},
560 if let user = json["user_id"].int >>> {User.by(id: $0)},
561 let date = json["date"].int >>> {Date(timeIntervalSince1970: TimeInterval($0))} {
561 let date = json["date"].int >>> {Date(timeIntervalSince1970: TimeInterval($0))} {
562 let message = GenericMessage()
562 let message = GenericMessage()
@@ -587,7 +587,7 @@ class VKData {
587
587
588
588
589
589
590− class func processNotificationSettings(_ json: JSON) -> ChatNotificationSettings? {
590+ class func processNotificationSettings(_ json: SwiftyVK.JSON) -> ChatNotificationSettings? {
591 if let sound = json["sound"].int,
591 if let sound = json["sound"].int,
592 let date = json["disabled_until"].int {
592 let date = json["disabled_until"].int {
593 if date == -1 {
593 if date == -1 {
@@ -600,7 +600,7 @@ class VKData {
600 }
600 }
601 }
601 }
602
602
603− class func processMultichat(_ json: JSON) -> Multichat? { // from .getChat
603+ class func processMultichat(_ json: SwiftyVK.JSON) -> Multichat? { // from .getChat
604 if let id = json["id"].int {
604 if let id = json["id"].int {
605 var chat: Multichat!
605 var chat: Multichat!
606 realmWrite { _ in
606 realmWrite { _ in
@@ -634,7 +634,7 @@ class VKData {
634 return nil
634 return nil
635 }
635 }
636
636
637− class func processDialog(_ json: JSON) -> Dialog? {
637+ class func processDialog(_ json: SwiftyVK.JSON) -> Dialog? {
638 let message = json["message"]
638 let message = json["message"]
639 if let id = message["chat_id"].int { // Multichat
639 if let id = message["chat_id"].int { // Multichat
640 if let sMessage = processMessage(message) {
640 if let sMessage = processMessage(message) {
Melk/VKPublicCrap.swift+21−24
@@ -6,38 +6,35 @@
6// Copyright © 2016 Ilya Kos. All rights reserved.
6// Copyright © 2016 Ilya Kos. All rights reserved.
7//
7//
8
8
9−//import SwiftyVK
9+import SwiftyVK
10−/*
10+
11let permissions: Set<VK.Scope> = [
11let permissions: Set<VK.Scope> = [
12−// .notify,
12+ .notify,
13−// .friends,
13+ .friends,
14−// .photos,
14+ .photos,
15−// .audio,
15+ .audio,
16−// .video,
16+ .video,
17−// .docs,
17+ .docs,
18−// .notes,
18+ .notes,
19 .pages,
19 .pages,
20−// .status,
20+ .status,
21−// .offers,
21+ .offers,
22−// .questions,
22+ .questions,
23 .wall,
23 .wall,
24 .groups,
24 .groups,
25−// .messages,
25+ .messages,
26−// .email,
26+ .email,
27−// .notifications,
27+ .notifications,
28−// .stats,
28+ .stats,
29−// .ads,
29+ .ads,
30−// .offline,
30+ .offline,
31−// .market,
31+ .market
32]
32]
33− */
34−let vkAPIVersion = "5.67"
33+let vkAPIVersion = "5.60"
35−let appID = "6097091"
34+let appID = "5529752"
36
35
37let multichatchatId = 2000000000
36let multichatchatId = 2000000000
38
37
39enum Methods {
38enum Methods {
40 static let getDialogs = "getDialogs"
39 static let getDialogs = "getDialogs"
41}
40}
42−
43−let accessKey = "363b0ecf363b0ecf363b0ecf9a3666060c3363b363b0ecf6f6cb5bcd453ddb4d0fadf8a"
Melk/VKServer.swiftdeleted−123
@@ -1,123 +0,0 @@
1−//
2−// VKServer.swift
3−// Melk
4−//
5−// Created by Ilya Kos on 7/12/17.
6−// Copyright © 2017 Ilya Kos. All rights reserved.
7−//
8−
9−import Foundation
10−import Alamofire
11−
12−class VKServer {
13− static func get(photo: Photo, completion: @escaping ((Data) -> ())) {
14− func string(`for` photo: Photo) -> String? {
15− if let ownerID = photo.owner?.id {
16− let id = photo.id
17− var out = "\(ownerID)_\(id)"
18− if let accessKey = photo.accessKey {
19− out.append("_\(accessKey)")
20− }
21− return out
22− }
23− return nil
24− }
25− let params: Parameters = [
26− "photos": string(for: photo)!
27− ]
28− Alamofire.request(url(for: "photos.getById"), parameters: params)
29− .validate().responseData { (response) in
30− switch response.result {
31− case .success(let data):
32− completion(data)
33− case .failure(let error):
34− print(error)
35− }
36− }
37− }
38− static func get(video: Video, completion: @escaping ((Data) -> ())) {
39− func string(`for` video: Video) -> String? {
40− if let ownerID = video.owner?.id {
41− let id = video.id
42− var out = "\(ownerID)_\(id)"
43− if let accessKey = video.accessKey {
44− out.append("_\(accessKey)")
45− }
46− return out
47− }
48− return nil
49− }
50− let params: Parameters = [
51− "videos": string(for: video)!
52− ]
53− Alamofire.request(url(for: "videos.get"), parameters: params)
54− .validate().responseData { (response) in
55− switch response.result {
56− case .success(let data):
57− completion(data)
58− case .failure(let error):
59− print(error)
60− }
61− }
62− }
63− static func get(doc: Document, completion: @escaping ((Data) -> ())) {
64− if let userID = doc.owner?.id {
65− let id = doc.id
66− let params: Parameters = [
67− "docs": "\(userID)_\(id)"
68− ]
69− Alamofire.request(url(for: "docs.getById"), parameters: params)
70− .validate().responseData(completionHandler: { (response) in
71− switch response.result {
72− case .success(let data):
73− completion(data)
74− case .failure(let error):
75− print(error)
76− }
77− })
78− }
79− }
80− static func get(user: User, completion: @escaping ((Data) -> ())) {
81− let id = user.id
82− let params: Parameters = [
83− "user_ids": id,
84− "fields": "photo_100"
85− ]
86− Alamofire.request(url(for: "users.get"), parameters: params)
87− .validate().responseData { (response) in
88− switch response.result {
89− case .success(let data):
90− completion(data)
91− case .failure(let error):
92− print(error)
93− }
94− }
95− }
96− static func get(wallPost: WallPost, completion: @escaping ((Data) -> ())) {
97− if let userID = wallPost.owner?.id {
98− let id = wallPost.id
99− let params: Parameters = [
100− "posts": "\(userID)_\(id)"
101− ]
102− Alamofire.request(url(for: "wall.getById"), parameters: params)
103− .validate().responseData(completionHandler: { (response) in
104− switch response.result {
105− case .success(let data):
106− completion(data)
107− case .failure(let error):
108− print(error)
109− }
110− })
111− }
112− }
113−
114− static func get(wallPostReply: WallPostReply, completion: @escaping ((Data) -> ())) {
115− // TODO: Get wallPostReply
116− }
117−
118−}
119−
120−fileprivate func url(`for` method: String) -> URL {
121− let surl = "https://api.vk.com/method/\(method)?access_token=\(accessKey)&v=\(vkAPIVersion)&lang=0"
122− return URL.init(string: surl)!
123−}
Melk/VkServices.swiftnew file+207
@@ -0,0 +1,207 @@
1+//
2+// VkServices.swift
3+// golos
4+//
5+// Created by Ilya Kos on 7/24/16.
6+// Copyright © 2016 Ilya Kos. All rights reserved.
7+//
8+
9+import UIKit
10+import Alamofire
11+import SwiftyVK
12+
13+// let realm = try! Realm()
14+
15+class VkServices {
16+ class func getDialogs(offset: Int = 0, count: Int = 200, completion: (() -> ())? = nil) { // Messages
17+ VK.API.remote(method: Methods.getDialogs, parameters:
18+ [VK.Arg.offset: String(offset),
19+ VK.Arg.count: String(count)])
20+ .send(onSuccess: { (response) in
21+ if let usersJSON = response[1].array,
22+ let chatUsersJSON = response[2].array,
23+ let dialogs = response[0]["items"].array,
24+ let chatUserInvitersJSON = response[3].array,
25+ let multichatsJSON = response[4].array { // TODO: Catch error from vk
26+ userQueue.async {
27+ let _ = usersJSON.map(VKData.processUser)
28+ let _ = chatUsersJSON.map(VKData.processUser)
29+ let _ = chatUserInvitersJSON.flatMap(VKData.processUser)
30+ let _ = multichatsJSON.map(VKData.processMultichat)
31+ let _ = dialogs.map(VKData.processDialog)
32+ print("DONEZO")
33+ DispatchQueue.main.async {
34+ completion?()
35+ }
36+ }
37+ }
38+ }, onError: { error in
39+ print(error)
40+ }) // TODO: Handle error
41+ }
42+
43+
44+ /// - Parameters:
45+ /// - dialog: in the `200000000` and `-` fomat
46+ /// - count: count
47+ /// - offset: offset
48+ /// - completion: completion handler
49+ class func getMessages(forDialog dialog: DialogID, count: Int = 20, offset: Int = 0, completion: (() -> ())? = nil) {
50+ var params: [VK.Arg: String] = [
51+ VK.Arg.peerId: String(dialog),
52+ VK.Arg.offset: String(offset),
53+ VK.Arg.count: String(count)]
54+ var request = VK.API.Messages.getHistory()
55+ request.add(parameters: params)
56+ request.send(onSuccess: { (response) in
57+ userQueue.async {
58+ realmWrite { _ in
59+ let rDialog = RealmDialog.by(peerID: dialog)
60+ var f = rDialog.value
61+ f <- response["items"].array?.flatMap(VKData.processMessage)
62+ f?.lastReadMessageID = max(response["out_read"].intValue, response["in_read"].intValue) // TODO: Probrably should use seperate things for readin and readout
63+ response["count"].int >>> { rDialog.value?.count.value = $0 }
64+ }
65+ }
66+ }, onError: nil) // TODO: Handle error
67+
68+ completion?()
69+ }
70+
71+ class func send(_ message: Message, to dialog: RealmDialog, completion: (() -> ())? = nil) {
72+ let date = Date()
73+ let time = Int(date.timeIntervalSince1970) * 100
74+ var params: [VK.Arg: String] = [:]
75+ if let d = dialog.value {
76+ switch d {
77+ case let chat as Chat:
78+ params[VK.Arg.peerId] = String(chat.userID)
79+ case let mchat as Multichat:
80+ params[VK.Arg.chatId] = String(mchat.id)
81+ default:
82+ break
83+ }
84+ }
85+ if dialog.dateLastSent == date {
86+ realmWrite({ (_) in
87+ dialog.dateSentNumber += 1
88+ })
89+ } else {
90+ realmWrite({ (_) in
91+ dialog.dateSentNumber = 1
92+ dialog.dateLastSent = date
93+ })
94+ }
95+
96+ var i = 0
97+ func photoUploadRequest() {
98+ if i < message.outPhotos.count {
99+ if let data = UIImagePNGRepresentation(message.outPhotos[i]) {
100+ let request = VK.API.Upload.Photo.toMessage(SwiftyVK.Media.init(imageData: data, type: .PNG))
101+ request.send(onSuccess: { (response) in
102+ if let photo = VKData.processPhoto(response) { // TODO: this probrably shouldnt happen on the main queue
103+ message.attachments.append(RealmMedia(value: Media.photo(photo)))
104+ }
105+ i += 1
106+ photoUploadRequest()
107+ }, onError: nil) // TODO: Handle error
108+ } else {
109+ i += 1
110+ photoUploadRequest()
111+ }
112+ }
113+ }
114+
115+
116+
117+ params[VK.Arg.randomId] = String(time + dialog.dateSentNumber)
118+ params[VK.Arg.message] = String(message.body)
119+ message.geolocation?.geoCoordinates?.coordinate.latitude >>> {params[VK.Arg.lat] = String($0)}
120+ message.geolocation?.geoCoordinates?.coordinate.longitude >>> {params[VK.Arg.long] = String($0)}
121+ var att = ""
122+ var stickerID: Int?
123+ for m in message.attachments {
124+ m.string >>> { att.append("\($0),") }
125+ if stickerID == nil {
126+ if let v = m.value {
127+ switch v {
128+ case .sticker(let s):
129+ stickerID = s.id
130+ default:
131+ break
132+ }
133+ }
134+ }
135+ }
136+ params[VK.Arg.attachments] = att
137+ var fm = ""
138+ for m in message.forwardedMessages {
139+ m.id >>> {fm.append("\($0),")}
140+ }
141+ params[VK.Arg.forwardMessages] = fm
142+ stickerID >>> {params[VK.Arg.stickerId] = String($0)}
143+ VK.API.Messages.send(params).send(onSuccess: { (response) in
144+ if let id = response.int {
145+ realmWrite({ (_) in
146+ message.id = id
147+ dialog.value?.messages <~ message // TODO: Uncomment this
148+ })
149+ }
150+ completion?()
151+ }, onError: nil) // TODO: Handle error
152+ }
153+ class func getMultichat(for id: MultichatID) {
154+ let params: [VK.Arg: String] = [
155+ VK.Arg.chatId: String(id),
156+ VK.Arg.fields: "nickname, screen_name, sex, bdate, city, country, timezone, photo_50, photo_100, photo_200_orig, has_mobile, contacts, education, online, counters, relation, last_seen, status, can_write_private_message, can_see_all_posts, can_post, universities",
157+
158+ ]
159+ VK.API.Messages.getChat(params).send(onSuccess: { (response) in
160+ VKData.processMultichat(response)
161+ }, onError: nil) // TODO: Handle error
162+ }
163+
164+}
165+
166+fileprivate extension RealmMedia {
167+ var string: String? {
168+ if let v = value {
169+ switch v {
170+ case .photo(let p):
171+ if let o = p.owner {
172+ var out = "photo\(o.id)_\(p.id)"
173+ p.accessKey >>> {out.append("_\($0)")}
174+ return out
175+ }
176+ case .video(let p):
177+ if let o = p.owner {
178+ var out = "video\(o.id)_\(p.id)"
179+ p.accessKey >>> {out.append("_\($0)")}
180+ return out
181+ }
182+ case .audio(let p):
183+ if let o = p.owner {
184+ return "audio\(o.id)_\(p.id)"
185+ }
186+ case .doc(let p), .graffiti(let p):
187+ if let o = p.owner {
188+ return "doc\(o.id)_\(p.id)"
189+ }
190+ case .wall(let p):
191+ if let o = p.owner {
192+ return "photo\(o.id)_\(p.id)"
193+ }
194+ case .market(let p):
195+ if let o = p.owner {
196+ return "photo\(o.id)_\(p.id)"
197+ }
198+ default: break
199+ }
200+ }
201+ return nil
202+ }
203+}
204+
205+private func URLFor(method: String) -> String {
206+ return "https://api.vk.com/method/" + method
207+}
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”, записи с основным хештегом будут выводиться на любые подключенные к устройству экраны.