Merge lp:~dude-from-by/openlp/my-ios-remote into lp:~danielborges93/openlp/ios-remote
- my-ios-remote
- Merge into ios-remote
Status: | Merged |
---|---|
Approved by: | Daniel Borges |
Approved revision: | no longer in the source branch. |
Merged at revision: | 55 |
Proposed branch: | lp:~dude-from-by/openlp/my-ios-remote |
Merge into: | lp:~danielborges93/openlp/ios-remote |
Diff against target: |
2700 lines (+749/-489) 42 files modified
OLP RemoteTests/APITest.swift (+1/-1) OLP RemoteTests/PollAPITests.swift (+12/-12) OLP RemoteTests/TestUtils.swift (+3/-3) Podfile (+6/-2) Podfile.lock (+44/-35) Remote.xcodeproj/project.pbxproj (+24/-21) Remote/AppDelegate.swift (+44/-11) Remote/Classes/Controller/Alerts/AlertsViewController.swift (+36/-36) Remote/Classes/Controller/Search/SearchResultViewController.swift (+26/-26) Remote/Classes/Controller/Search/SearchViewController.swift (+33/-33) Remote/Classes/Controller/Service/ServiceViewController.swift (+40/-35) Remote/Classes/Controller/Service/ServiceViewController.xib (+13/-9) Remote/Classes/Controller/Service/ServiceViewControllerDelegate.swift (+29/-0) Remote/Classes/Controller/Settings/SettingsControllerPresenter.swift (+3/-3) Remote/Classes/Controller/Settings/SettingsViewController.swift (+14/-24) Remote/Classes/Controller/Slides/SlidesViewController.swift (+54/-44) Remote/Classes/Controller/Slides/SlidesViewController.xib (+12/-8) Remote/Classes/Model/ItemModel.swift (+1/-1) Remote/Classes/Model/LiveModel.swift (+1/-1) Remote/Classes/Model/PollModel.swift (+36/-49) Remote/Classes/Model/ServiceListModel.swift (+2/-2) Remote/Classes/Model/SlideModel.swift (+1/-1) Remote/Classes/Model/SuccessModel.swift (+1/-1) Remote/Classes/Model/UserSettings.swift (+19/-14) Remote/Classes/Network/API.swift (+2/-2) Remote/Classes/Network/AddAPI.swift (+12/-9) Remote/Classes/Network/AlertAPI.swift (+6/-6) Remote/Classes/Network/ControllerAPI.swift (+16/-16) Remote/Classes/Network/DisplayAPI.swift (+4/-4) Remote/Classes/Network/LiveAPI.swift (+12/-9) Remote/Classes/Network/PollAPI.swift (+17/-30) Remote/Classes/Network/SearchAPI.swift (+8/-8) Remote/Classes/Network/Service.swift (+2/-0) Remote/Classes/Network/ServiceAPI.swift (+20/-19) Remote/Classes/Util/ColorUtil.swift (+1/-1) Remote/Classes/Util/DictionaryUtil.swift (+3/-3) Remote/Classes/Util/ErrorUtil.swift (+5/-4) Remote/Classes/Util/TabSwitchingToRightAnimationController.swift (+66/-0) Remote/Classes/Util/ViewControllerUtil.swift (+42/-6) Remote/Classes/View/SlideCell.swift (+44/-0) Remote/Resources/Settings.bundle/Root.inApp.plist (+16/-0) Remote/Resources/Settings.bundle/Root.plist (+18/-0) |
To merge this branch: | bzr merge lp:~dude-from-by/openlp/my-ios-remote |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Borges | Approve | ||
Review via email: mp+315893@code.launchpad.net |
This proposal supersedes a proposal from 2017-01-25.
Commit message
Description of the change
migrated to swift 3
Daniel Borges (danielborges93) wrote : Posted in a previous version of this proposal | # |
Daniel Borges (danielborges93) wrote : Posted in a previous version of this proposal | # |
> - "Use precise slides scroll" is in embedded setting, but not in root settings
> (in Setting.app). As is possible to add to toggle in root setting, add to
> PSToggleSwitchS
And add the String "Use precise slides scroll" in Resources/
andrei (dude-from-by) wrote : Posted in a previous version of this proposal | # |
Fixed issues
Daniel Borges (danielborges93) wrote : Posted in a previous version of this proposal | # |
Now the only thing is that the .string file is missing the character ; at the end os the last 2 lines. The file is not loading because this.
andrei (dude-from-by) wrote : | # |
updated
Daniel Borges (danielborges93) : | # |
- 55. By andrei <email address hidden>
-
Migrated to swift3. Add activity indicator on slide selection, increased polling interval from 0.5 to 2 seconds. And more...
Preview Diff
1 | === modified file 'OLP RemoteTests/APITest.swift' |
2 | --- OLP RemoteTests/APITest.swift 2016-07-03 18:04:32 +0000 |
3 | +++ OLP RemoteTests/APITest.swift 2017-01-30 12:52:52 +0000 |
4 | @@ -40,7 +40,7 @@ |
5 | |
6 | func test_api_base_withHTTPS() { |
7 | let defaults = TestUtils.defaults() |
8 | - defaults.setBool(true, forKey:"server.useHTTPS") |
9 | + defaults.set(true, forKey:"server.useHTTPS") |
10 | let settings = UserSettings(defaults: defaults) |
11 | let api = API(settings: settings) |
12 | XCTAssert(api.base.hasPrefix("https")) |
13 | |
14 | === modified file 'OLP RemoteTests/PollAPITests.swift' |
15 | --- OLP RemoteTests/PollAPITests.swift 2016-07-03 18:04:32 +0000 |
16 | +++ OLP RemoteTests/PollAPITests.swift 2017-01-30 12:52:52 +0000 |
17 | @@ -33,8 +33,8 @@ |
18 | override func setUp() { |
19 | super.setUp() |
20 | |
21 | - stub(isPath("/api/poll")) { _ in |
22 | - guard let path = OHPathForFile("poll_response.json", self.dynamicType) else { |
23 | + stub(condition: isPath("/api/poll")) { _ in |
24 | + guard let path = OHPathForFile("poll_response.json", type(of: self)) else { |
25 | preconditionFailure("Could not find expected file in test bundle") |
26 | } |
27 | |
28 | @@ -44,8 +44,8 @@ |
29 | headers: [ "ContentType": "application/json" ] |
30 | ) |
31 | } |
32 | - stub(isPath("/api/service/list")) { _ in |
33 | - guard let path = OHPathForFile("service_response.json", self.dynamicType) else { |
34 | + stub(condition: isPath("/api/service/list")) { _ in |
35 | + guard let path = OHPathForFile("service_response.json", type(of: self)) else { |
36 | preconditionFailure("Could not find expected file in test bundle") |
37 | } |
38 | |
39 | @@ -68,7 +68,7 @@ |
40 | var selectedItem : String? |
41 | var projectionState: ProjectionState? |
42 | |
43 | - func updateServiceList(items: [ItemModel]) { |
44 | + func updateServiceList(_ items: [ItemModel]) { |
45 | serviceList = items |
46 | } |
47 | |
48 | @@ -76,7 +76,7 @@ |
49 | selectedItem = id |
50 | } |
51 | |
52 | - func updateProjectionState(state: ProjectionState) { |
53 | + func updateProjectionState(_ state: ProjectionState) { |
54 | projectionState = state |
55 | } |
56 | } |
57 | @@ -87,22 +87,22 @@ |
58 | var selectedSlide: Int? |
59 | var projectionState: ProjectionState? |
60 | |
61 | - func updateSlides(slides: [SlideModel]) { |
62 | + func updateSlides(_ slides: [SlideModel]) { |
63 | model = slides |
64 | } |
65 | |
66 | - func updateSelectedSlide(row: Int) { |
67 | + func updateSelectedSlide(_ row: Int) { |
68 | selectedSlide = row |
69 | } |
70 | |
71 | - func updateProjectionState(state: ProjectionState) { |
72 | + func updateProjectionState(_ state: ProjectionState) { |
73 | projectionState = state |
74 | } |
75 | } |
76 | |
77 | - func getPollAPI(serviceDelegate: PollAPIServiceDelegate, slidesDelegate: PollAPISlidesDelegate) -> PollAPI { |
78 | + func getPollAPI(_ serviceDelegate: PollAPIServiceDelegate, slidesDelegate: PollAPISlidesDelegate) -> PollAPI { |
79 | let defaults = TestUtils.defaults() |
80 | - defaults.setBool(true, forKey:"server.useHTTPS") |
81 | + defaults.set(true, forKey:"server.useHTTPS") |
82 | let settings = UserSettings(defaults: defaults) |
83 | let controllerAPI = ControllerAPI(settings: settings) |
84 | let serviceAPI = ServiceAPI(settings: settings) |
85 | @@ -116,7 +116,7 @@ |
86 | let serviceDelegate: PollAPIServiceDelegateMock = PollAPIServiceDelegateMock() |
87 | let slidesDelegate: PollAPISlidesDelegateMock = PollAPISlidesDelegateMock() |
88 | getPollAPI(serviceDelegate, slidesDelegate: slidesDelegate).poll() |
89 | - expect(serviceDelegate.projectionState).toEventually(equal(ProjectionState.Desktop)) |
90 | + expect(serviceDelegate.projectionState).toEventually(equal(ProjectionState.desktop)) |
91 | } |
92 | |
93 | func test_pollSelectedItem() { |
94 | |
95 | === modified file 'OLP RemoteTests/TestUtils.swift' |
96 | --- OLP RemoteTests/TestUtils.swift 2016-07-03 18:04:32 +0000 |
97 | +++ OLP RemoteTests/TestUtils.swift 2017-01-30 12:52:52 +0000 |
98 | @@ -26,11 +26,11 @@ |
99 | |
100 | class TestUtils { |
101 | |
102 | - static func defaults() -> NSUserDefaults { |
103 | - let defaults = NSUserDefaults(suiteName:NSUUID().UUIDString)! |
104 | + static func defaults() -> UserDefaults { |
105 | + let defaults = UserDefaults(suiteName:UUID().uuidString)! |
106 | defaults.setValue("123", forKey: "server.port") |
107 | defaults.setValue("100.200.200.200", forKey:"server.ip") |
108 | return defaults |
109 | } |
110 | |
111 | -} |
112 | \ No newline at end of file |
113 | +} |
114 | |
115 | === modified file 'Podfile' |
116 | --- Podfile 2016-07-03 18:04:32 +0000 |
117 | +++ Podfile 2017-01-30 12:52:52 +0000 |
118 | @@ -8,16 +8,20 @@ |
119 | pod 'AlamofireObjectMapper' |
120 | pod 'TPKeyboardAvoiding' |
121 | pod 'InAppSettingsKit' |
122 | - pod 'BlockLooper' |
123 | pod 'UITextView+Placeholder' |
124 | + pod 'BlockLooper', :git=>'https://github.com/ashender/BlockLooper.git' |
125 | pod 'CWStatusBarNotification' |
126 | end |
127 | |
128 | target 'OLP RemoteTests' do |
129 | pod 'Alamofire' |
130 | - pod 'AlamofireObjectMapper' |
131 | + pod 'InAppSettingsKit' |
132 | + pod 'BlockLooper', :git=>'https://github.com/ashender/BlockLooper.git' |
133 | + pod 'UITextView+Placeholder' |
134 | + pod 'CWStatusBarNotification' |
135 | pod 'OHHTTPStubs' |
136 | pod 'Nimble' |
137 | + pod 'AlamofireObjectMapper' |
138 | pod 'OHHTTPStubs/Swift' |
139 | end |
140 | |
141 | |
142 | === modified file 'Podfile.lock' |
143 | --- Podfile.lock 2016-07-03 18:11:13 +0000 |
144 | +++ Podfile.lock 2017-01-30 12:52:52 +0000 |
145 | @@ -1,35 +1,35 @@ |
146 | PODS: |
147 | - - Alamofire (3.1.3) |
148 | - - AlamofireObjectMapper (2.1.0): |
149 | - - Alamofire (~> 3.1.0) |
150 | - - ObjectMapper (~> 1.0) |
151 | + - Alamofire (4.3.0) |
152 | + - AlamofireObjectMapper (4.0.1): |
153 | + - Alamofire (~> 4.1) |
154 | + - ObjectMapper (~> 2.0) |
155 | - BlockLooper (0.0.3) |
156 | - - CWStatusBarNotification (2.3.3) |
157 | - - InAppSettingsKit (2.6) |
158 | - - Nimble (4.1.0) |
159 | - - ObjectMapper (1.0.1) |
160 | - - OHHTTPStubs (5.1.0): |
161 | - - OHHTTPStubs/Default (= 5.1.0) |
162 | - - OHHTTPStubs/Core (5.1.0) |
163 | - - OHHTTPStubs/Default (5.1.0): |
164 | + - CWStatusBarNotification (2.3.5) |
165 | + - InAppSettingsKit (2.8.1) |
166 | + - Nimble (5.1.1) |
167 | + - ObjectMapper (2.2.2) |
168 | + - OHHTTPStubs (5.2.3): |
169 | + - OHHTTPStubs/Default (= 5.2.3) |
170 | + - OHHTTPStubs/Core (5.2.3) |
171 | + - OHHTTPStubs/Default (5.2.3): |
172 | - OHHTTPStubs/Core |
173 | - OHHTTPStubs/JSON |
174 | - OHHTTPStubs/NSURLSession |
175 | - OHHTTPStubs/OHPathHelpers |
176 | - - OHHTTPStubs/JSON (5.1.0): |
177 | - - OHHTTPStubs/Core |
178 | - - OHHTTPStubs/NSURLSession (5.1.0): |
179 | - - OHHTTPStubs/Core |
180 | - - OHHTTPStubs/OHPathHelpers (5.1.0) |
181 | - - OHHTTPStubs/Swift (5.1.0): |
182 | - - OHHTTPStubs/Core |
183 | - - TPKeyboardAvoiding (1.2.11) |
184 | - - UITextView+Placeholder (1.1.0) |
185 | + - OHHTTPStubs/JSON (5.2.3): |
186 | + - OHHTTPStubs/Core |
187 | + - OHHTTPStubs/NSURLSession (5.2.3): |
188 | + - OHHTTPStubs/Core |
189 | + - OHHTTPStubs/OHPathHelpers (5.2.3) |
190 | + - OHHTTPStubs/Swift (5.2.3): |
191 | + - OHHTTPStubs/Core |
192 | + - TPKeyboardAvoiding (1.3.1) |
193 | + - UITextView+Placeholder (1.2.0) |
194 | |
195 | DEPENDENCIES: |
196 | - Alamofire |
197 | - AlamofireObjectMapper |
198 | - - BlockLooper |
199 | + - BlockLooper (from `https://github.com/ashender/BlockLooper.git`) |
200 | - CWStatusBarNotification |
201 | - InAppSettingsKit |
202 | - Nimble |
203 | @@ -38,18 +38,27 @@ |
204 | - TPKeyboardAvoiding |
205 | - UITextView+Placeholder |
206 | |
207 | +EXTERNAL SOURCES: |
208 | + BlockLooper: |
209 | + :git: https://github.com/ashender/BlockLooper.git |
210 | + |
211 | +CHECKOUT OPTIONS: |
212 | + BlockLooper: |
213 | + :commit: 47b90418b5ee460e3e41013a43d9b9bbd90e0577 |
214 | + :git: https://github.com/ashender/BlockLooper.git |
215 | + |
216 | SPEC CHECKSUMS: |
217 | - Alamofire: 9f93b56389e48def9220dd57d1f44b1927229a5a |
218 | - AlamofireObjectMapper: 24097576202064f8b0a583452dd934064f78dc0e |
219 | + Alamofire: 856a113053a7bc9cbe5d6367a555d773fc5cfef7 |
220 | + AlamofireObjectMapper: 842d2eed43a4d0593ff0110d54ac86a170c4519c |
221 | BlockLooper: 8bba05fef76734e8e52e39412a0212ac3474776c |
222 | - CWStatusBarNotification: 2349142e97c9f16fb8247ed3c00308cd355d334b |
223 | - InAppSettingsKit: cc56d3ec45f11352a16d5b210da8a3fa1b9d05ed |
224 | - Nimble: 97a0a4cae5124c117115634b2d055d8c97d0af19 |
225 | - ObjectMapper: 98524bac0dca46c6b3d5ee02cd410fc700ec6ce2 |
226 | - OHHTTPStubs: 592f74439d2d72615115cf99a954237a3fbe26e5 |
227 | - TPKeyboardAvoiding: e5ce146b313de063957bfa75a13f1e9b0ff18ab7 |
228 | - UITextView+Placeholder: 672ce543356b5b5787f354415bc3b132d47f0362 |
229 | - |
230 | -PODFILE CHECKSUM: b264ee57cf5b5b7fa8f69ff62c6becc3b32d65f4 |
231 | - |
232 | -COCOAPODS: 1.0.1 |
233 | + CWStatusBarNotification: 3d2738b25c3207f60cc50201388d3c96182545ff |
234 | + InAppSettingsKit: 94d2fba3ccd700fc4e32c6d09fabcc0af2426744 |
235 | + Nimble: 415e3aa3267e7bc2c96b05fa814ddea7bb686a29 |
236 | + ObjectMapper: 9e385c2295bcc4e16eabbcfc85db801442bba545 |
237 | + OHHTTPStubs: e238cd5b66d8efa51c861db45895de8fe079f4a7 |
238 | + TPKeyboardAvoiding: 0d6af20e95e2850f4c621841225b59ec7d8dd852 |
239 | + UITextView+Placeholder: 77680995fcdd07c3f52ec92fe1150874a2ac89ff |
240 | + |
241 | +PODFILE CHECKSUM: 33c246100fdb079469ba0c7b05499d31b72d3722 |
242 | + |
243 | +COCOAPODS: 1.1.1 |
244 | |
245 | === modified file 'Remote.xcodeproj/project.pbxproj' |
246 | --- Remote.xcodeproj/project.pbxproj 2016-07-03 18:11:13 +0000 |
247 | +++ Remote.xcodeproj/project.pbxproj 2017-01-30 12:52:52 +0000 |
248 | @@ -48,6 +48,8 @@ |
249 | 750831B91CFF44FC00CA9299 /* poll_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 750831B81CFF44FC00CA9299 /* poll_response.json */; }; |
250 | 750831BB1CFF594400CA9299 /* service_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 750831BA1CFF594400CA9299 /* service_response.json */; }; |
251 | 750831BD1CFF597D00CA9299 /* slides_response.json in Resources */ = {isa = PBXBuildFile; fileRef = 750831BC1CFF597D00CA9299 /* slides_response.json */; }; |
252 | + 75219D021E276111001B6BC8 /* TabSwitchingToRightAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75219D011E276111001B6BC8 /* TabSwitchingToRightAnimationController.swift */; }; |
253 | + 755A61C91E04878F00D035D4 /* ServiceViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755A61C81E04878F00D035D4 /* ServiceViewControllerDelegate.swift */; }; |
254 | 755C78CE1CCE9080001CF70D /* Service.swift in Sources */ = {isa = PBXBuildFile; fileRef = 755C78CD1CCE9080001CF70D /* Service.swift */; }; |
255 | 75667B281CFCA8B1008FDFE0 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4640F2901BE4274A00E2AA61 /* API.swift */; }; |
256 | 75667B291CFCA8C9008FDFE0 /* UserSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46CC0CEC1BE6972300423EB4 /* UserSettings.swift */; }; |
257 | @@ -72,21 +74,12 @@ |
258 | 75667B5D1CFEFF83008FDFE0 /* ColorUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46A612301C78E75D00B61DC8 /* ColorUtil.swift */; }; |
259 | 75667B5E1CFEFF86008FDFE0 /* ErrorUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = 46FD378E1C79867C00DED423 /* ErrorUtil.swift */; }; |
260 | 75667B5F1CFEFFA7008FDFE0 /* DisplayAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4623B6921C078F70007FFE2B /* DisplayAPI.swift */; }; |
261 | + 756FA0FD1E28FF060011AE6F /* SlideCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 756FA0FC1E28FF060011AE6F /* SlideCell.swift */; }; |
262 | 759464A51CEB8493001A56BF /* SettingsControllerPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759464A41CEB8493001A56BF /* SettingsControllerPresenter.swift */; }; |
263 | 759778AE1CF83AC400C2E4B4 /* APITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 759778AD1CF83AC400C2E4B4 /* APITest.swift */; }; |
264 | 863574EB78CF355A8463055D /* Pods_Remote.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3194E32378DD6BB8E273BB47 /* Pods_Remote.framework */; }; |
265 | /* End PBXBuildFile section */ |
266 | |
267 | -/* Begin PBXContainerItemProxy section */ |
268 | - 759778A81CF839C200C2E4B4 /* PBXContainerItemProxy */ = { |
269 | - isa = PBXContainerItemProxy; |
270 | - containerPortal = 462258C11BE29EF300A509C8 /* Project object */; |
271 | - proxyType = 1; |
272 | - remoteGlobalIDString = 462258C81BE29EF300A509C8; |
273 | - remoteInfo = Remote; |
274 | - }; |
275 | -/* End PBXContainerItemProxy section */ |
276 | - |
277 | /* Begin PBXFileReference section */ |
278 | 0BAC8A693E937F5B9F7CF9A6 /* Pods_OLP_RemoteTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OLP_RemoteTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; |
279 | 20B750141C8B3B45881386FA /* Pods-Remote.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Remote.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Remote/Pods-Remote.debug.xcconfig"; sourceTree = "<group>"; }; |
280 | @@ -135,9 +128,12 @@ |
281 | 750831B81CFF44FC00CA9299 /* poll_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = poll_response.json; sourceTree = "<group>"; }; |
282 | 750831BA1CFF594400CA9299 /* service_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = service_response.json; sourceTree = "<group>"; }; |
283 | 750831BC1CFF597D00CA9299 /* slides_response.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = slides_response.json; sourceTree = "<group>"; }; |
284 | + 75219D011E276111001B6BC8 /* TabSwitchingToRightAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabSwitchingToRightAnimationController.swift; sourceTree = "<group>"; }; |
285 | + 755A61C81E04878F00D035D4 /* ServiceViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServiceViewControllerDelegate.swift; sourceTree = "<group>"; }; |
286 | 755C78CD1CCE9080001CF70D /* Service.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Service.swift; sourceTree = "<group>"; }; |
287 | 75667B2A1CFCAE44008FDFE0 /* PollAPITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PollAPITests.swift; sourceTree = "<group>"; }; |
288 | 75667B4B1CFEE85A008FDFE0 /* TestUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = "<group>"; }; |
289 | + 756FA0FC1E28FF060011AE6F /* SlideCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideCell.swift; sourceTree = "<group>"; }; |
290 | 759464A41CEB8493001A56BF /* SettingsControllerPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsControllerPresenter.swift; sourceTree = "<group>"; }; |
291 | 759778A31CF839C200C2E4B4 /* OLP RemoteTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OLP RemoteTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; |
292 | 759778A71CF839C200C2E4B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
293 | @@ -267,6 +263,7 @@ |
294 | 4623BF8E1BE418A2003A04FB /* Util */ = { |
295 | isa = PBXGroup; |
296 | children = ( |
297 | + 75219D011E276111001B6BC8 /* TabSwitchingToRightAnimationController.swift */, |
298 | 462395821BE50C5A00B90146 /* ViewControllerUtil.swift */, |
299 | 463A91841C092E6B00D572E6 /* DictionaryUtil.swift */, |
300 | 46A612301C78E75D00B61DC8 /* ColorUtil.swift */, |
301 | @@ -278,6 +275,7 @@ |
302 | 4623BF8F1BE418A2003A04FB /* View */ = { |
303 | isa = PBXGroup; |
304 | children = ( |
305 | + 756FA0FC1E28FF060011AE6F /* SlideCell.swift */, |
306 | ); |
307 | path = View; |
308 | sourceTree = "<group>"; |
309 | @@ -304,6 +302,7 @@ |
310 | 4623BF981BE419B6003A04FB /* Service */ = { |
311 | isa = PBXGroup; |
312 | children = ( |
313 | + 755A61C81E04878F00D035D4 /* ServiceViewControllerDelegate.swift */, |
314 | 4623BF991BE419FE003A04FB /* ServiceViewController.swift */, |
315 | 4623BF9A1BE419FE003A04FB /* ServiceViewController.xib */, |
316 | ); |
317 | @@ -408,7 +407,6 @@ |
318 | buildRules = ( |
319 | ); |
320 | dependencies = ( |
321 | - 759778A91CF839C200C2E4B4 /* PBXTargetDependency */, |
322 | ); |
323 | name = "OLP RemoteTests"; |
324 | productName = "OLP RemoteTests"; |
325 | @@ -428,9 +426,11 @@ |
326 | TargetAttributes = { |
327 | 462258C81BE29EF300A509C8 = { |
328 | CreatedOnToolsVersion = 7.1; |
329 | + LastSwiftMigration = 0810; |
330 | }; |
331 | 759778A21CF839C200C2E4B4 = { |
332 | CreatedOnToolsVersion = 7.3.1; |
333 | + LastSwiftMigration = 0810; |
334 | }; |
335 | }; |
336 | }; |
337 | @@ -538,7 +538,7 @@ |
338 | ); |
339 | runOnlyForDeploymentPostprocessing = 0; |
340 | shellPath = /bin/sh; |
341 | - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; |
342 | + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; |
343 | showEnvVarsInLog = 0; |
344 | }; |
345 | BCF6BCAAAC1529152D882FC6 /* [CP] Check Pods Manifest.lock */ = { |
346 | @@ -553,7 +553,7 @@ |
347 | ); |
348 | runOnlyForDeploymentPostprocessing = 0; |
349 | shellPath = /bin/sh; |
350 | - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; |
351 | + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; |
352 | showEnvVarsInLog = 0; |
353 | }; |
354 | F0EA71C50D6F72431C9A5B4E /* [CP] Embed Pods Frameworks */ = { |
355 | @@ -589,10 +589,12 @@ |
356 | 46FD37891C796C9B00DED423 /* SearchResultViewController.swift in Sources */, |
357 | 463A918D1C093DD500D572E6 /* AlertsViewController.swift in Sources */, |
358 | 4640F2951BE42B6E00E2AA61 /* PollModel.swift in Sources */, |
359 | + 75219D021E276111001B6BC8 /* TabSwitchingToRightAnimationController.swift in Sources */, |
360 | 46A9EED61BFD85FF00E8D520 /* ItemModel.swift in Sources */, |
361 | 755C78CE1CCE9080001CF70D /* Service.swift in Sources */, |
362 | 46A9EEDC1BFD8FEE00E8D520 /* SuccessModel.swift in Sources */, |
363 | 4640F2911BE4274A00E2AA61 /* API.swift in Sources */, |
364 | + 756FA0FD1E28FF060011AE6F /* SlideCell.swift in Sources */, |
365 | 4623BF9B1BE419FE003A04FB /* ServiceViewController.swift in Sources */, |
366 | 463A91891C093AE100D572E6 /* ServiceListModel.swift in Sources */, |
367 | 463A91871C093A2300D572E6 /* LiveModel.swift in Sources */, |
368 | @@ -608,6 +610,7 @@ |
369 | 46FD378F1C79867C00DED423 /* ErrorUtil.swift in Sources */, |
370 | 46A612351C79572600B61DC8 /* PluginModel.swift in Sources */, |
371 | 759464A51CEB8493001A56BF /* SettingsControllerPresenter.swift in Sources */, |
372 | + 755A61C91E04878F00D035D4 /* ServiceViewControllerDelegate.swift in Sources */, |
373 | ); |
374 | runOnlyForDeploymentPostprocessing = 0; |
375 | }; |
376 | @@ -644,14 +647,6 @@ |
377 | }; |
378 | /* End PBXSourcesBuildPhase section */ |
379 | |
380 | -/* Begin PBXTargetDependency section */ |
381 | - 759778A91CF839C200C2E4B4 /* PBXTargetDependency */ = { |
382 | - isa = PBXTargetDependency; |
383 | - target = 462258C81BE29EF300A509C8 /* Remote */; |
384 | - targetProxy = 759778A81CF839C200C2E4B4 /* PBXContainerItemProxy */; |
385 | - }; |
386 | -/* End PBXTargetDependency section */ |
387 | - |
388 | /* Begin PBXVariantGroup section */ |
389 | 4623BFA11BE42390003A04FB /* Localizable.strings */ = { |
390 | isa = PBXVariantGroup; |
391 | @@ -705,6 +700,7 @@ |
392 | ONLY_ACTIVE_ARCH = YES; |
393 | SDKROOT = iphoneos; |
394 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; |
395 | + SWIFT_VERSION = ""; |
396 | }; |
397 | name = Debug; |
398 | }; |
399 | @@ -741,6 +737,7 @@ |
400 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; |
401 | MTL_ENABLE_DEBUG_INFO = NO; |
402 | SDKROOT = iphoneos; |
403 | + SWIFT_VERSION = ""; |
404 | VALIDATE_PRODUCT = YES; |
405 | }; |
406 | name = Release; |
407 | @@ -753,11 +750,13 @@ |
408 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; |
409 | CODE_SIGN_IDENTITY = "iPhone Developer"; |
410 | DEFINES_MODULE = NO; |
411 | + DEVELOPMENT_TEAM = ""; |
412 | INFOPLIST_FILE = "Remote/Supporting files/Info.plist"; |
413 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; |
414 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; |
415 | PRODUCT_BUNDLE_IDENTIFIER = org.openlp.Remote; |
416 | PRODUCT_NAME = "$(TARGET_NAME)"; |
417 | + SWIFT_VERSION = 3.0; |
418 | }; |
419 | name = Debug; |
420 | }; |
421 | @@ -769,11 +768,13 @@ |
422 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; |
423 | CODE_SIGN_IDENTITY = "iPhone Developer"; |
424 | DEFINES_MODULE = NO; |
425 | + DEVELOPMENT_TEAM = ""; |
426 | INFOPLIST_FILE = "Remote/Supporting files/Info.plist"; |
427 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; |
428 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; |
429 | PRODUCT_BUNDLE_IDENTIFIER = org.openlp.Remote; |
430 | PRODUCT_NAME = "$(TARGET_NAME)"; |
431 | + SWIFT_VERSION = 3.0; |
432 | }; |
433 | name = Release; |
434 | }; |
435 | @@ -787,6 +788,7 @@ |
436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; |
437 | PRODUCT_BUNDLE_IDENTIFIER = "com.openlp.OLP-RemoteTests"; |
438 | PRODUCT_NAME = "$(TARGET_NAME)"; |
439 | + SWIFT_VERSION = 3.0; |
440 | }; |
441 | name = Debug; |
442 | }; |
443 | @@ -800,6 +802,7 @@ |
444 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; |
445 | PRODUCT_BUNDLE_IDENTIFIER = "com.openlp.OLP-RemoteTests"; |
446 | PRODUCT_NAME = "$(TARGET_NAME)"; |
447 | + SWIFT_VERSION = 3.0; |
448 | }; |
449 | name = Release; |
450 | }; |
451 | |
452 | === modified file 'Remote/AppDelegate.swift' |
453 | --- Remote/AppDelegate.swift 2016-07-03 18:04:32 +0000 |
454 | +++ Remote/AppDelegate.swift 2017-01-30 12:52:52 +0000 |
455 | @@ -26,23 +26,31 @@ |
456 | import BlockLooper |
457 | |
458 | @UIApplicationMain |
459 | -class AppDelegate: UIResponder, UIApplicationDelegate { |
460 | +class AppDelegate: UIResponder, UIApplicationDelegate, UITabBarControllerDelegate, ServiceViewControllerDelegate { |
461 | |
462 | var window: UIWindow? |
463 | var service: Service! |
464 | var settings: UserSettings! |
465 | - |
466 | - |
467 | - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { |
468 | - |
469 | - settings = UserSettings(defaults: NSUserDefaults.standardUserDefaults()) |
470 | + var tabBarController: UITabBarController! |
471 | + var useAnimator: Bool = false |
472 | + |
473 | + enum OpenLPTab: Int { |
474 | + case serviceTab |
475 | + case slidesTab |
476 | + case alertsTab |
477 | + case searchTab |
478 | + } |
479 | + |
480 | + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { |
481 | + |
482 | + settings = UserSettings(defaults: UserDefaults.standard) |
483 | settings.registerDefaults() |
484 | service = Service(settings: settings) |
485 | |
486 | var rootViewControllers = [UINavigationController]() |
487 | var navigationController: UINavigationController |
488 | |
489 | - let serviceViewController = ServiceViewController(settings: settings, service: service) |
490 | + let serviceViewController = ServiceViewController(settings: settings, service: service, delegate: self) |
491 | navigationController = UINavigationController(rootViewController: serviceViewController) |
492 | rootViewControllers.append(navigationController) |
493 | |
494 | @@ -63,22 +71,47 @@ |
495 | |
496 | let tabBarController = UITabBarController() |
497 | tabBarController.viewControllers = rootViewControllers |
498 | + |
499 | + self.tabBarController = tabBarController |
500 | + tabBarController.delegate = self |
501 | |
502 | - self.window = UIWindow(frame: UIScreen.mainScreen().bounds) |
503 | + self.window = UIWindow(frame: UIScreen.main.bounds) |
504 | self.window?.rootViewController = tabBarController |
505 | self.window?.makeKeyAndVisible() |
506 | |
507 | settings.resetDefaultsIfNeeded() |
508 | |
509 | - BlockLooper.executeBlockWithRate(0.5) { |
510 | + BlockLooper.executeBlockWithRate(2.0) { |
511 | if self.settings.validateURL() { |
512 | - self.service.pollAPI.poll() |
513 | + if self.service.pauseLoopPolling == false { |
514 | + self.service.pollAPI.poll() |
515 | + } |
516 | } |
517 | return false |
518 | } |
519 | |
520 | return true |
521 | } |
522 | - |
523 | + |
524 | + |
525 | + func withAnimator(_ block:()-> Void) -> Void { |
526 | + useAnimator = true |
527 | + block() |
528 | + useAnimator = false |
529 | + } |
530 | + |
531 | + |
532 | + // MARK: - ServiceViewControllerDelegate |
533 | + func serviceViewControllerDidSelectItem(_ item: ItemModel) { |
534 | + withAnimator { |
535 | + self.tabBarController.selectedIndex = OpenLPTab.slidesTab.rawValue |
536 | + } |
537 | + } |
538 | + |
539 | + |
540 | + // MARK: - TabBarControllerDelegate |
541 | + func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { |
542 | + return useAnimator ? TabSwitchingToRightAnimationController(tabBarController: self.tabBarController) : nil |
543 | + } |
544 | } |
545 | |
546 | |
547 | === modified file 'Remote/Classes/Controller/Alerts/AlertsViewController.swift' |
548 | --- Remote/Classes/Controller/Alerts/AlertsViewController.swift 2016-07-03 18:04:32 +0000 |
549 | +++ Remote/Classes/Controller/Alerts/AlertsViewController.swift 2017-01-30 12:52:52 +0000 |
550 | @@ -33,9 +33,9 @@ |
551 | @IBOutlet weak var btShow: UIButton! |
552 | @IBOutlet weak var btShowBottomConstraint: NSLayoutConstraint! |
553 | |
554 | - private var btCancel: UIBarButtonItem! |
555 | - private let service: Service! |
556 | - private let settingsPresenter: SettingsControllerPresenter! |
557 | + fileprivate var btCancel: UIBarButtonItem! |
558 | + fileprivate let service: Service! |
559 | + fileprivate let settingsPresenter: SettingsControllerPresenter! |
560 | |
561 | // MARK: Init |
562 | |
563 | @@ -62,57 +62,57 @@ |
564 | |
565 | // MARK: Setup |
566 | |
567 | - private func setupNavigationBar() { |
568 | + fileprivate func setupNavigationBar() { |
569 | self.navigationItem.leftBarButtonItem = settingsPresenter.settingsBarButton(self) |
570 | |
571 | self.navigationItem.title = NSLocalizedString("Alerts", comment: "") |
572 | |
573 | let strCancel = NSLocalizedString("Cancel", comment: "") |
574 | - self.btCancel = UIBarButtonItem(title: strCancel, style: .Plain, target: self, action: #selector(AlertsViewController.clear)) |
575 | - self.btCancel.enabled = false |
576 | + self.btCancel = UIBarButtonItem(title: strCancel, style: .plain, target: self, action: #selector(AlertsViewController.clear)) |
577 | + self.btCancel.isEnabled = false |
578 | self.navigationItem.rightBarButtonItem = self.btCancel |
579 | } |
580 | |
581 | - private func setupAlertTextView() { |
582 | + fileprivate func setupAlertTextView() { |
583 | self.textAlert.placeholder = NSLocalizedString("Type here...", comment: "") |
584 | } |
585 | |
586 | - private func setupShowButton() { |
587 | + fileprivate func setupShowButton() { |
588 | let strShow = NSLocalizedString("Show", comment: "") |
589 | - self.btShow.setTitle(strShow, forState: .Normal) |
590 | - self.btShow.enabled = false |
591 | + self.btShow.setTitle(strShow, for: UIControlState()) |
592 | + self.btShow.isEnabled = false |
593 | } |
594 | |
595 | - private func setupTabBar() { |
596 | + fileprivate func setupTabBar() { |
597 | self.tabBarItem.title = NSLocalizedString("Alerts", comment: "") |
598 | self.tabBarItem.image = UIImage(named: "ic_alerts") |
599 | } |
600 | |
601 | - private func setupObservers() { |
602 | - NSNotificationCenter.defaultCenter().addObserver(self, |
603 | + fileprivate func setupObservers() { |
604 | + NotificationCenter.default.addObserver(self, |
605 | selector: #selector(AlertsViewController.keyboardWillAppear(_:)), |
606 | - name: UIKeyboardWillShowNotification, |
607 | + name: NSNotification.Name.UIKeyboardWillShow, |
608 | object: nil) |
609 | - NSNotificationCenter.defaultCenter().addObserver(self, |
610 | + NotificationCenter.default.addObserver(self, |
611 | selector: #selector(AlertsViewController.keyboardWillDisappear(_:)), |
612 | - name: UIKeyboardWillHideNotification, |
613 | + name: NSNotification.Name.UIKeyboardWillHide, |
614 | object: nil) |
615 | } |
616 | |
617 | // MARK: My methods |
618 | |
619 | - @objc private func clear() { |
620 | + @objc fileprivate func clear() { |
621 | self.textAlert.resignFirstResponder() |
622 | self.textAlert.text = "" |
623 | } |
624 | |
625 | @IBAction func showAlert() { |
626 | self.service.alertAPI.alert(self.textAlert.text) { success, error in |
627 | - if let error = error, message = verifyError(error) { |
628 | - self.displayNotification(message: message, isError: true) |
629 | + if let error = error, let message = verifyError(error as NSError) { |
630 | + self.displayNotification(message, isError: true) |
631 | } else { |
632 | let strNotification = NSLocalizedString("Alert showed!", comment: "") |
633 | - self.displayNotification(message: strNotification) |
634 | + self.displayNotification(strNotification) |
635 | self.clear() |
636 | } |
637 | } |
638 | @@ -120,25 +120,25 @@ |
639 | |
640 | // MARK: Keyboard |
641 | |
642 | - @objc func keyboardWillAppear(notification: NSNotification) { |
643 | - self.btCancel.enabled = true |
644 | + @objc func keyboardWillAppear(_ notification: Notification) { |
645 | + self.btCancel.isEnabled = true |
646 | |
647 | - let keyboardRect = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue() |
648 | + let keyboardRect = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue |
649 | let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double |
650 | self.btShowBottomConstraint.constant = keyboardRect.size.height + 8 |
651 | - UIView.animateWithDuration(animationDuration) { |
652 | + UIView.animate(withDuration: animationDuration, animations: { |
653 | self.view.layoutIfNeeded() |
654 | - } |
655 | + }) |
656 | } |
657 | |
658 | - @objc func keyboardWillDisappear(notification: NSNotification) { |
659 | - self.btCancel.enabled = false |
660 | + @objc func keyboardWillDisappear(_ notification: Notification) { |
661 | + self.btCancel.isEnabled = false |
662 | |
663 | let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double |
664 | self.btShowBottomConstraint.constant = 57 |
665 | - UIView.animateWithDuration(animationDuration) { |
666 | + UIView.animate(withDuration: animationDuration, animations: { |
667 | self.view.layoutIfNeeded() |
668 | - } |
669 | + }) |
670 | } |
671 | |
672 | } |
673 | @@ -147,19 +147,19 @@ |
674 | |
675 | extension AlertsViewController: UITextViewDelegate { |
676 | |
677 | - func textViewDidChange(textView: UITextView) { |
678 | + func textViewDidChange(_ textView: UITextView) { |
679 | if textView.text == "" { |
680 | - self.btShow.enabled = false |
681 | + self.btShow.isEnabled = false |
682 | } else { |
683 | - self.btShow.enabled = true |
684 | + self.btShow.isEnabled = true |
685 | } |
686 | } |
687 | |
688 | - func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool { |
689 | + func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { |
690 | |
691 | - if text.containsString("\n") { |
692 | - let newText = text.stringByReplacingOccurrencesOfString("\n", withString: " ") |
693 | - let fullText = (textView.text as NSString).stringByReplacingCharactersInRange(range, withString: newText) |
694 | + if text.contains("\n") { |
695 | + let newText = text.replacingOccurrences(of: "\n", with: " ") |
696 | + let fullText = (textView.text as NSString).replacingCharacters(in: range, with: newText) |
697 | textView.text = fullText |
698 | return false |
699 | } |
700 | |
701 | === modified file 'Remote/Classes/Controller/Search/SearchResultViewController.swift' |
702 | --- Remote/Classes/Controller/Search/SearchResultViewController.swift 2016-07-03 18:04:32 +0000 |
703 | +++ Remote/Classes/Controller/Search/SearchResultViewController.swift 2017-01-30 12:52:52 +0000 |
704 | @@ -26,13 +26,13 @@ |
705 | |
706 | class SearchResultViewController: UITableViewController { |
707 | |
708 | - private var items: [ItemModel]! |
709 | - private let service: Service! |
710 | + fileprivate var items: [ItemModel]! |
711 | + fileprivate let service: Service! |
712 | |
713 | init(items: [ItemModel], service: Service) { |
714 | self.items = items |
715 | self.service = service |
716 | - super.init(style: .Plain) |
717 | + super.init(style: .plain) |
718 | } |
719 | |
720 | required init?(coder aDecoder: NSCoder) { |
721 | @@ -48,25 +48,25 @@ |
722 | |
723 | // MARK: Setup |
724 | |
725 | - private func setupNavigationBar() { |
726 | + fileprivate func setupNavigationBar() { |
727 | self.navigationItem.title = NSLocalizedString("Results", comment: "") |
728 | } |
729 | |
730 | - private func setupTableView() { |
731 | + fileprivate func setupTableView() { |
732 | self.tableView.estimatedRowHeight = 44 |
733 | self.tableView.rowHeight = UITableViewAutomaticDimension |
734 | } |
735 | |
736 | // MARK: Table view data source |
737 | |
738 | - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
739 | + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
740 | return self.items.count |
741 | } |
742 | |
743 | - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
744 | - var cell = tableView.dequeueReusableCellWithIdentifier("Cell") |
745 | + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
746 | + var cell = tableView.dequeueReusableCell(withIdentifier: "Cell") |
747 | if cell == nil { |
748 | - cell = UITableViewCell(style: .Default, reuseIdentifier: "Cell") |
749 | + cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") |
750 | cell!.textLabel?.numberOfLines = 0 |
751 | } |
752 | let item = self.items[indexPath.row] |
753 | @@ -76,60 +76,60 @@ |
754 | |
755 | // MARK: Table view delegate |
756 | |
757 | - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { |
758 | - func showErrorNotification(error: NSError) { |
759 | + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { |
760 | + func showErrorNotification(_ error: NSError) { |
761 | if let message = verifyError(error) { |
762 | - self.displayNotification(message: message, isError: true) |
763 | + self.displayNotification(message, isError: true) |
764 | } |
765 | } |
766 | func itemAddedNotification() { |
767 | let message = NSLocalizedString("Item added.", comment: "") |
768 | - self.displayNotification(message: message) |
769 | + self.displayNotification(message) |
770 | } |
771 | let item = self.items[indexPath.row] |
772 | - let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) |
773 | + let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) |
774 | let goLiveStr = NSLocalizedString("Go Live", comment: "") |
775 | - let goLiveAction = UIAlertAction(title: goLiveStr, style: .Default) { _ in |
776 | - tableView.deselectRowAtIndexPath(indexPath, animated: true) |
777 | + let goLiveAction = UIAlertAction(title: goLiveStr, style: .default) { _ in |
778 | + tableView.deselectRow(at: indexPath, animated: true) |
779 | self.service.liveAPI.goItemToLive(item, plugin: Plugin(rawValue: item.plugin!)!) { error in |
780 | if let error = error { |
781 | - showErrorNotification(error) |
782 | + showErrorNotification(error as NSError) |
783 | return |
784 | } |
785 | self.tabBarController?.selectedIndex = 1 |
786 | } |
787 | } |
788 | let addStr = NSLocalizedString("Add to Service", comment: "") |
789 | - let addAction = UIAlertAction(title: addStr, style: .Default) { _ in |
790 | - tableView.deselectRowAtIndexPath(indexPath, animated: true) |
791 | + let addAction = UIAlertAction(title: addStr, style: .default) { _ in |
792 | + tableView.deselectRow(at: indexPath, animated: true) |
793 | self.service.addAPI.addItem(item, plugin: Plugin(rawValue: item.plugin!)!) { error in |
794 | if let error = error { |
795 | - showErrorNotification(error) |
796 | + showErrorNotification(error as NSError) |
797 | } else { |
798 | itemAddedNotification() |
799 | } |
800 | } |
801 | } |
802 | let addAndGoStr = NSLocalizedString("Add & Go to Service", comment: "") |
803 | - let addAndGoAction = UIAlertAction(title: addAndGoStr, style: .Default) { _ in |
804 | - tableView.deselectRowAtIndexPath(indexPath, animated: true) |
805 | + let addAndGoAction = UIAlertAction(title: addAndGoStr, style: .default) { _ in |
806 | + tableView.deselectRow(at: indexPath, animated: true) |
807 | self.service.addAPI.addItem(item, plugin: Plugin(rawValue: item.plugin!)!) { error in |
808 | if let error = error { |
809 | - showErrorNotification(error) |
810 | + showErrorNotification(error as NSError) |
811 | return |
812 | } |
813 | self.tabBarController?.selectedIndex = 0 |
814 | } |
815 | } |
816 | let cancelStr = NSLocalizedString("Cancel", comment: "") |
817 | - let cancelAction = UIAlertAction(title: cancelStr, style: .Cancel) { _ in |
818 | - tableView.deselectRowAtIndexPath(indexPath, animated: true) |
819 | + let cancelAction = UIAlertAction(title: cancelStr, style: .cancel) { _ in |
820 | + tableView.deselectRow(at: indexPath, animated: true) |
821 | } |
822 | alertController.addAction(goLiveAction) |
823 | alertController.addAction(addAction) |
824 | alertController.addAction(addAndGoAction) |
825 | alertController.addAction(cancelAction) |
826 | - self.presentViewController(alertController, animated: true, completion: nil) |
827 | + self.present(alertController, animated: true, completion: nil) |
828 | } |
829 | |
830 | } |
831 | |
832 | === modified file 'Remote/Classes/Controller/Search/SearchViewController.swift' |
833 | --- Remote/Classes/Controller/Search/SearchViewController.swift 2016-07-03 18:04:32 +0000 |
834 | +++ Remote/Classes/Controller/Search/SearchViewController.swift 2017-01-30 12:52:52 +0000 |
835 | @@ -32,11 +32,11 @@ |
836 | @IBOutlet weak var lbTitle: UILabel! |
837 | @IBOutlet weak var pickerView: UIPickerView! |
838 | |
839 | - private var notifications: CWStatusBarNotification! |
840 | - private var textField: UITextField! |
841 | - private var plugins: [Plugin]! |
842 | - private let service: Service! |
843 | - private var settingsPresenter: SettingsControllerPresenter! |
844 | + fileprivate var notifications: CWStatusBarNotification! |
845 | + fileprivate var textField: UITextField! |
846 | + fileprivate var plugins: [Plugin]! |
847 | + fileprivate let service: Service! |
848 | + fileprivate var settingsPresenter: SettingsControllerPresenter! |
849 | |
850 | // MARK: Init |
851 | |
852 | @@ -64,32 +64,32 @@ |
853 | |
854 | // MARK: Setup |
855 | |
856 | - private func setupNavigationBar() { |
857 | + fileprivate func setupNavigationBar() { |
858 | self.navigationItem.leftBarButtonItem = settingsPresenter.settingsBarButton(self) |
859 | |
860 | self.textField = UITextField(frame: CGRect(x: 0, y: 0, width: 300, height: 30)) |
861 | - self.textField.backgroundColor = UIColor.whiteColor() |
862 | - self.textField.textAlignment = .Center |
863 | - self.textField.clearButtonMode = .WhileEditing |
864 | + self.textField.backgroundColor = UIColor.white |
865 | + self.textField.textAlignment = .center |
866 | + self.textField.clearButtonMode = .whileEditing |
867 | self.textField.placeholder = NSLocalizedString("Type here...", comment: "") |
868 | self.textField.layer.borderWidth = 0.7 |
869 | - self.textField.layer.borderColor = kGreyColor.CGColor |
870 | + self.textField.layer.borderColor = kGreyColor.cgColor |
871 | self.textField.layer.cornerRadius = 5 |
872 | - self.textField.returnKeyType = .Search |
873 | + self.textField.returnKeyType = .search |
874 | self.textField.delegate = self |
875 | self.navigationItem.titleView = self.textField |
876 | |
877 | - let btSearch = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: #selector(SearchViewController.search)) |
878 | + let btSearch = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(SearchViewController.search)) |
879 | self.navigationItem.rightBarButtonItem = btSearch |
880 | } |
881 | |
882 | - private func setupPickerView() { |
883 | + fileprivate func setupPickerView() { |
884 | self.lbTitle.text = NSLocalizedString("Search for", comment: "") |
885 | - self.pickerView.layer.borderColor = kGreyColor.CGColor |
886 | + self.pickerView.layer.borderColor = kGreyColor.cgColor |
887 | self.pickerView.layer.borderWidth = 0.7 |
888 | } |
889 | |
890 | - private func setupOptions() { |
891 | + fileprivate func setupOptions() { |
892 | self.plugins = [ |
893 | .Songs, |
894 | .Bibles, |
895 | @@ -100,7 +100,7 @@ |
896 | ] |
897 | } |
898 | |
899 | - private func setupGestures() { |
900 | + fileprivate func setupGestures() { |
901 | var gesture: UIGestureRecognizer |
902 | gesture = UITapGestureRecognizer(target: self, action: #selector(SearchViewController.dismissKeyboard)) |
903 | gesture.delegate = self |
904 | @@ -109,35 +109,35 @@ |
905 | self.pickerView.addGestureRecognizer(gesture) |
906 | } |
907 | |
908 | - private func setupTabBar() { |
909 | - self.tabBarItem = UITabBarItem(tabBarSystemItem: .Search, tag: 0) |
910 | + fileprivate func setupTabBar() { |
911 | + self.tabBarItem = UITabBarItem(tabBarSystemItem: .search, tag: 0) |
912 | self.tabBarItem.title = NSLocalizedString("Search", comment: "") |
913 | } |
914 | |
915 | - private func setupNotifications() { |
916 | + fileprivate func setupNotifications() { |
917 | self.notifications = CWStatusBarNotification() |
918 | - self.notifications.notificationLabelTextColor = UIColor.whiteColor() |
919 | - self.notifications.notificationAnimationInStyle = .Top |
920 | - self.notifications.notificationAnimationOutStyle = .Top |
921 | + self.notifications.notificationLabelTextColor = UIColor.white |
922 | + self.notifications.notificationAnimationInStyle = .top |
923 | + self.notifications.notificationAnimationOutStyle = .top |
924 | } |
925 | |
926 | // MARK: My functions |
927 | |
928 | - @objc private func search() { |
929 | + @objc fileprivate func search() { |
930 | self.dismissKeyboard() |
931 | - let plugin = self.plugins[self.pickerView.selectedRowInComponent(0)] |
932 | + let plugin = self.plugins[self.pickerView.selectedRow(inComponent: 0)] |
933 | let text = self.textField.text! |
934 | service.searchAPI.search(plugin: plugin, text: text) { items, error in |
935 | if let error = error { |
936 | let message = NSLocalizedString("An error occurred. Try again...", comment: "") |
937 | self.notifications.notificationLabelBackgroundColor = kRedColor |
938 | - self.notifications.displayNotificationWithMessage(message, forDuration: 3) |
939 | + self.notifications.display(withMessage: message, forDuration: 3) |
940 | print(error) |
941 | return |
942 | } else if items?.count == 0 { |
943 | let message = NSLocalizedString("No results found", comment: "") |
944 | self.notifications.notificationLabelBackgroundColor = kBlueColor |
945 | - self.notifications.displayNotificationWithMessage(message, forDuration: 3) |
946 | + self.notifications.display(withMessage: message, forDuration: 3) |
947 | return |
948 | } |
949 | let resultsViewController = SearchResultViewController(items: items!, service: self.service) |
950 | @@ -145,7 +145,7 @@ |
951 | } |
952 | } |
953 | |
954 | - @objc private func dismissKeyboard() { |
955 | + @objc fileprivate func dismissKeyboard() { |
956 | self.textField.resignFirstResponder() |
957 | } |
958 | |
959 | @@ -155,11 +155,11 @@ |
960 | |
961 | extension SearchViewController: UIPickerViewDataSource { |
962 | |
963 | - func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { |
964 | + func numberOfComponents(in pickerView: UIPickerView) -> Int { |
965 | return 1 |
966 | } |
967 | |
968 | - func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { |
969 | + func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { |
970 | return self.plugins.count |
971 | } |
972 | |
973 | @@ -169,7 +169,7 @@ |
974 | |
975 | extension SearchViewController: UIPickerViewDelegate { |
976 | |
977 | - func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { |
978 | + func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { |
979 | let option = self.plugins[row] |
980 | return option.name() |
981 | } |
982 | @@ -180,8 +180,8 @@ |
983 | |
984 | extension SearchViewController: UIGestureRecognizerDelegate { |
985 | |
986 | - func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, |
987 | - shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool { |
988 | + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, |
989 | + shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { |
990 | return true |
991 | } |
992 | |
993 | @@ -191,7 +191,7 @@ |
994 | |
995 | extension SearchViewController: UITextFieldDelegate { |
996 | |
997 | - func textFieldShouldReturn(textField: UITextField) -> Bool { |
998 | + func textFieldShouldReturn(_ textField: UITextField) -> Bool { |
999 | self.search() |
1000 | return true |
1001 | } |
1002 | |
1003 | === modified file 'Remote/Classes/Controller/Service/ServiceViewController.swift' |
1004 | --- Remote/Classes/Controller/Service/ServiceViewController.swift 2016-07-03 18:04:32 +0000 |
1005 | +++ Remote/Classes/Controller/Service/ServiceViewController.swift 2017-01-30 12:52:52 +0000 |
1006 | @@ -31,16 +31,18 @@ |
1007 | @IBOutlet weak var tableView: UITableView! |
1008 | @IBOutlet weak var segProjectionState: UISegmentedControl! |
1009 | |
1010 | - private var items = [ItemModel]() |
1011 | - private var dicItemRow = [String: Int]() |
1012 | - private let service: Service! |
1013 | - private var settingsPresenter: SettingsControllerPresenter! |
1014 | + fileprivate var items = [ItemModel]() |
1015 | + fileprivate var dicItemRow = [String: Int]() |
1016 | + fileprivate let service: Service! |
1017 | + fileprivate var settingsPresenter: SettingsControllerPresenter! |
1018 | + fileprivate let delegate: ServiceViewControllerDelegate! |
1019 | |
1020 | // MARK: Init |
1021 | |
1022 | - init(settings: UserSettings, service: Service) { |
1023 | + init(settings: UserSettings, service: Service, delegate: ServiceViewControllerDelegate) { |
1024 | self.service = service |
1025 | self.settingsPresenter = SettingsControllerPresenter(settings: settings, pollAPI: service.pollAPI) |
1026 | + self.delegate = delegate |
1027 | super.init(nibName: "ServiceViewController", bundle: nil) |
1028 | self.setupNavigationBar() |
1029 | self.setupTabBar() |
1030 | @@ -48,6 +50,7 @@ |
1031 | |
1032 | required init?(coder aDecoder: NSCoder) { |
1033 | self.service = nil |
1034 | + self.delegate = nil |
1035 | super.init(coder: aDecoder) |
1036 | } |
1037 | |
1038 | @@ -59,8 +62,8 @@ |
1039 | |
1040 | // MARK: Setup |
1041 | |
1042 | - private func setupNavigationBar() { |
1043 | - let btAdd = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(ServiceViewController.goToSearchViewController)) |
1044 | + fileprivate func setupNavigationBar() { |
1045 | + let btAdd = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(ServiceViewController.goToSearchViewController)) |
1046 | self.navigationItem.leftBarButtonItems = [ |
1047 | settingsPresenter.settingsBarButton(self), |
1048 | btAdd |
1049 | @@ -69,58 +72,59 @@ |
1050 | self.navigationItem.title = NSLocalizedString("Service", comment: "") |
1051 | |
1052 | let imagePrevious = UIImage(named: "ic_arrow-up") |
1053 | - let btPrevious = UIBarButtonItem(image: imagePrevious, style: .Plain, target: self, action: #selector(ServiceViewController.previousItem)) |
1054 | + let btPrevious = UIBarButtonItem(image: imagePrevious, style: .plain, target: self, action: #selector(ServiceViewController.previousItem)) |
1055 | let imageNext = UIImage(named: "ic_arrow-down") |
1056 | - let btNext = UIBarButtonItem(image: imageNext, style: .Plain, target: self, action: #selector(ServiceViewController.nextItem)) |
1057 | + let btNext = UIBarButtonItem(image: imageNext, style: .plain, target: self, action: #selector(ServiceViewController.nextItem)) |
1058 | self.navigationItem.rightBarButtonItems = [ |
1059 | btNext, |
1060 | btPrevious |
1061 | ] |
1062 | } |
1063 | |
1064 | - private func setupTabBar() { |
1065 | + fileprivate func setupTabBar() { |
1066 | self.tabBarItem.title = NSLocalizedString("Service", comment: "") |
1067 | self.tabBarItem.image = UIImage(named: "ic_service") |
1068 | } |
1069 | |
1070 | - private func setupTableView() { |
1071 | + fileprivate func setupTableView() { |
1072 | self.tableView.rowHeight = UITableViewAutomaticDimension |
1073 | self.tableView.estimatedRowHeight = 44 |
1074 | + self.tableView?.decelerationRate = UIScrollViewDecelerationRateFast |
1075 | } |
1076 | |
1077 | - private func setupSegmentedControl() { |
1078 | + fileprivate func setupSegmentedControl() { |
1079 | self.segProjectionState.selectedSegmentIndex = -1 |
1080 | } |
1081 | |
1082 | // MARK: My methods |
1083 | |
1084 | - @IBAction func segmentedControlValueChanged() { |
1085 | + @IBAction func sementedControlValueChanged() { |
1086 | let index = self.segProjectionState.selectedSegmentIndex |
1087 | if let state = ProjectionState(rawValue: index) { |
1088 | self.service.displayAPI.projectionState(state) { _, error in |
1089 | - if let error = error, message = verifyError(error) { |
1090 | - self.displayNotification(message: message, isError: true) |
1091 | + if let error = error, let message = verifyError(error as NSError) { |
1092 | + self.displayNotification(message, isError: true) |
1093 | } |
1094 | } |
1095 | } |
1096 | } |
1097 | |
1098 | - @objc private func goToSearchViewController() { |
1099 | + @objc fileprivate func goToSearchViewController() { |
1100 | self.tabBarController?.selectedIndex = 3 |
1101 | } |
1102 | |
1103 | - @objc private func previousItem() { |
1104 | + @objc fileprivate func previousItem() { |
1105 | self.service.serviceAPI.previous() { _, error in |
1106 | - if let error = error, message = verifyError(error) { |
1107 | - self.displayNotification(message: message, isError: true) |
1108 | + if let error = error, let message = verifyError(error as NSError) { |
1109 | + self.displayNotification(message, isError: true) |
1110 | } |
1111 | } |
1112 | } |
1113 | |
1114 | - @objc private func nextItem() { |
1115 | + @objc fileprivate func nextItem() { |
1116 | self.service.serviceAPI.next() { _, error in |
1117 | - if let error = error, message = verifyError(error) { |
1118 | - self.displayNotification(message: message, isError: true) |
1119 | + if let error = error, let message = verifyError(error as NSError) { |
1120 | + self.displayNotification(message, isError: true) |
1121 | } |
1122 | } |
1123 | } |
1124 | @@ -131,15 +135,15 @@ |
1125 | |
1126 | extension ServiceViewController: UITableViewDataSource { |
1127 | |
1128 | - func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
1129 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
1130 | return self.items.count |
1131 | } |
1132 | |
1133 | - func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
1134 | - var cell = tableView.dequeueReusableCellWithIdentifier("Cell") |
1135 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
1136 | + var cell = tableView.dequeueReusableCell(withIdentifier: "Cell") |
1137 | |
1138 | if cell == nil { |
1139 | - cell = UITableViewCell(style: .Default, reuseIdentifier: "Cell") |
1140 | + cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") |
1141 | cell!.textLabel?.numberOfLines = 0 |
1142 | } |
1143 | |
1144 | @@ -155,22 +159,23 @@ |
1145 | |
1146 | extension ServiceViewController: UITableViewDelegate { |
1147 | |
1148 | - func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { |
1149 | + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { |
1150 | self.service.serviceAPI.set(row: indexPath.row) { success, error in |
1151 | - if let error = error, message = verifyError(error) { |
1152 | - self.displayNotification(message: message, isError: true) |
1153 | - tableView.deselectRowAtIndexPath(indexPath, animated: true) |
1154 | + if let error = error, let message = verifyError(error as NSError) { |
1155 | + self.displayNotification(message, isError: true) |
1156 | + tableView.deselectRow(at: indexPath, animated: true) |
1157 | + } else if success { |
1158 | + self.delegate.serviceViewControllerDidSelectItem(self.items[indexPath.row]) |
1159 | } |
1160 | } |
1161 | } |
1162 | - |
1163 | } |
1164 | |
1165 | // MARK: - PollAPIServiceDelegate |
1166 | |
1167 | extension ServiceViewController: PollAPIServiceDelegate { |
1168 | |
1169 | - func updateServiceList(items: [ItemModel]) { |
1170 | + func updateServiceList(_ items: [ItemModel]) { |
1171 | self.items = items |
1172 | self.tableView.reloadData() |
1173 | |
1174 | @@ -185,13 +190,13 @@ |
1175 | func updateSelectedItem(itemId id: String) { |
1176 | if let selectedRow = self.dicItemRow[id] { |
1177 | if selectedRow < self.items.count { |
1178 | - let indexPath = NSIndexPath(forRow: selectedRow, inSection: 0) |
1179 | - self.tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .None) |
1180 | + let indexPath = IndexPath(row: selectedRow, section: 0) |
1181 | + self.tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none) |
1182 | } |
1183 | } |
1184 | } |
1185 | |
1186 | - func updateProjectionState(state: ProjectionState) { |
1187 | + func updateProjectionState(_ state: ProjectionState) { |
1188 | self.segProjectionState.selectedSegmentIndex = state.rawValue |
1189 | } |
1190 | |
1191 | |
1192 | === modified file 'Remote/Classes/Controller/Service/ServiceViewController.xib' |
1193 | --- Remote/Classes/Controller/Service/ServiceViewController.xib 2016-07-03 18:04:32 +0000 |
1194 | +++ Remote/Classes/Controller/Service/ServiceViewController.xib 2017-01-30 12:52:52 +0000 |
1195 | @@ -1,8 +1,12 @@ |
1196 | -<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
1197 | -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="14F1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES"> |
1198 | +<?xml version="1.0" encoding="UTF-8"?> |
1199 | +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11542" systemVersion="16D17a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> |
1200 | + <device id="retina4_0" orientation="portrait"> |
1201 | + <adaptation id="fullscreen"/> |
1202 | + </device> |
1203 | <dependencies> |
1204 | <deployment identifier="iOS"/> |
1205 | - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/> |
1206 | + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/> |
1207 | + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
1208 | </dependencies> |
1209 | <objects> |
1210 | <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ServiceViewController" customModule="Remote" customModuleProvider="target"> |
1211 | @@ -14,18 +18,18 @@ |
1212 | </placeholder> |
1213 | <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
1214 | <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> |
1215 | - <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> |
1216 | + <rect key="frame" x="0.0" y="0.0" width="320" height="568"/> |
1217 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
1218 | <subviews> |
1219 | - <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="A9d-va-PLe"> |
1220 | + <tableView clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="A9d-va-PLe"> |
1221 | <rect key="frame" x="0.0" y="0.0" width="600" height="556"/> |
1222 | - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
1223 | + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
1224 | <connections> |
1225 | <outlet property="dataSource" destination="-1" id="5bH-k5-YRz"/> |
1226 | <outlet property="delegate" destination="-1" id="hnH-to-FEe"/> |
1227 | </connections> |
1228 | </tableView> |
1229 | - <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bfe-Nb-Utk"> |
1230 | + <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bfe-Nb-Utk"> |
1231 | <rect key="frame" x="0.0" y="507" width="600" height="44"/> |
1232 | <constraints> |
1233 | <constraint firstAttribute="height" constant="44" id="IBR-6A-7Oo"/> |
1234 | @@ -43,7 +47,7 @@ |
1235 | <segment title="Show"/> |
1236 | </segments> |
1237 | <connections> |
1238 | - <action selector="segmentedControlValueChanged" destination="-1" eventType="valueChanged" id="43O-Kb-ivs"/> |
1239 | + <action selector="sementedControlValueChanged" destination="-1" eventType="valueChanged" id="YOp-zI-OuN"/> |
1240 | </connections> |
1241 | </segmentedControl> |
1242 | </barButtonItem> |
1243 | @@ -51,7 +55,7 @@ |
1244 | </items> |
1245 | </toolbar> |
1246 | </subviews> |
1247 | - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> |
1248 | + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
1249 | <constraints> |
1250 | <constraint firstItem="A9d-va-PLe" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="0X6-ik-XVD"/> |
1251 | <constraint firstAttribute="bottom" secondItem="A9d-va-PLe" secondAttribute="bottom" constant="44" id="OCH-8f-c0t"/> |
1252 | |
1253 | === added file 'Remote/Classes/Controller/Service/ServiceViewControllerDelegate.swift' |
1254 | --- Remote/Classes/Controller/Service/ServiceViewControllerDelegate.swift 1970-01-01 00:00:00 +0000 |
1255 | +++ Remote/Classes/Controller/Service/ServiceViewControllerDelegate.swift 2017-01-30 12:52:52 +0000 |
1256 | @@ -0,0 +1,29 @@ |
1257 | +/****************************************************************************** |
1258 | + * OpenLP iOS Remote * |
1259 | + * --------------------------------------------------------------------------- * |
1260 | + * Copyright (c) 2008-2016 OpenLP Developers * |
1261 | + * --------------------------------------------------------------------------- * |
1262 | + * Permission is hereby granted, free of charge, to any person obtaining a * |
1263 | + * copy of this software and associated documentation files (the "Software"), * |
1264 | + * to deal in the Software without restriction, including without limitation * |
1265 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * |
1266 | + * and/or sell copies of the Software, and to permit persons to whom the * |
1267 | + * Software is furnished to do so, subject to the following conditions: * |
1268 | + * * |
1269 | + * The above copyright notice and this permission notice shall be included in * |
1270 | + * all copies or substantial portions of the Software. * |
1271 | + * * |
1272 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * |
1273 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * |
1274 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * |
1275 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * |
1276 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * |
1277 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * |
1278 | + * DEALINGS IN THE SOFTWARE. * |
1279 | + ******************************************************************************/ |
1280 | + |
1281 | +import Foundation |
1282 | + |
1283 | +protocol ServiceViewControllerDelegate { |
1284 | + func serviceViewControllerDidSelectItem(_ item: ItemModel) |
1285 | +} |
1286 | |
1287 | === modified file 'Remote/Classes/Controller/Settings/SettingsControllerPresenter.swift' |
1288 | --- Remote/Classes/Controller/Settings/SettingsControllerPresenter.swift 2016-07-03 18:04:32 +0000 |
1289 | +++ Remote/Classes/Controller/Settings/SettingsControllerPresenter.swift 2017-01-30 12:52:52 +0000 |
1290 | @@ -37,10 +37,10 @@ |
1291 | super.init() |
1292 | } |
1293 | |
1294 | - func settingsBarButton(fromController: UIViewController) -> UIBarButtonItem { |
1295 | + func settingsBarButton(_ fromController: UIViewController) -> UIBarButtonItem { |
1296 | self.fromController = fromController |
1297 | let imageSettings = UIImage(named: "ic_gear") |
1298 | - let btSettings = UIBarButtonItem(image: imageSettings, style: .Plain, target: self, action: #selector(SettingsControllerPresenter.presentSettingViewController)) |
1299 | + let btSettings = UIBarButtonItem(image: imageSettings, style: .plain, target: self, action: #selector(SettingsControllerPresenter.presentSettingViewController)) |
1300 | return btSettings |
1301 | } |
1302 | |
1303 | @@ -48,6 +48,6 @@ |
1304 | func presentSettingViewController() { |
1305 | let settingsController = SettingsViewController(settings:settings, pollAPI: pollAPI) |
1306 | let navigationController = UINavigationController(rootViewController: settingsController) |
1307 | - fromController!.showViewController(navigationController, sender: nil) |
1308 | + fromController!.show(navigationController, sender: nil) |
1309 | } |
1310 | } |
1311 | |
1312 | === modified file 'Remote/Classes/Controller/Settings/SettingsViewController.swift' |
1313 | --- Remote/Classes/Controller/Settings/SettingsViewController.swift 2016-07-03 18:04:32 +0000 |
1314 | +++ Remote/Classes/Controller/Settings/SettingsViewController.swift 2017-01-30 12:52:52 +0000 |
1315 | @@ -27,14 +27,14 @@ |
1316 | |
1317 | class SettingsViewController: IASKAppSettingsViewController { |
1318 | |
1319 | - private let hiddenSettingsKeys = ["auth.userID", "auth.password"] as Set<NSObject> |
1320 | - private let pollAPI: PollAPI! |
1321 | - private let settings: UserSettings! |
1322 | + fileprivate let hiddenSettingsKeys = ["auth.userID" as NSObject, "auth.password" as NSObject] as Set<NSObject> |
1323 | + fileprivate let pollAPI: PollAPI! |
1324 | + fileprivate let settings: UserSettings! |
1325 | |
1326 | init(settings: UserSettings, pollAPI: PollAPI) { |
1327 | self.pollAPI = pollAPI |
1328 | self.settings = settings |
1329 | - super.init(style: .Grouped) |
1330 | + super.init(style: .grouped) |
1331 | self.setupSettingViewController() |
1332 | self.setupNavigationBar() |
1333 | } |
1334 | @@ -47,7 +47,7 @@ |
1335 | |
1336 | // MARK: My methods |
1337 | |
1338 | - private func setupSettingViewController() { |
1339 | + fileprivate func setupSettingViewController() { |
1340 | self.showDoneButton = false |
1341 | self.showCreditsFooter = false |
1342 | self.delegate = self |
1343 | @@ -55,12 +55,12 @@ |
1344 | let needsAuth = settings.needsAuth |
1345 | self.hiddenKeys = needsAuth ? [] : self.hiddenSettingsKeys |
1346 | |
1347 | - NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(SettingsViewController.settingsDidChange(_:)), name: kIASKAppSettingChanged, object: nil) |
1348 | + NotificationCenter.default.addObserver(self, selector: #selector(SettingsViewController.settingsDidChange(_:)), name: NSNotification.Name(rawValue: kIASKAppSettingChanged), object: nil) |
1349 | } |
1350 | |
1351 | - @objc private func settingsDidChange(notification: NSNotification) { |
1352 | - if let object = notification.object { |
1353 | - if object.isEqual("auth.needsAuth") { |
1354 | + @objc fileprivate func settingsDidChange(_ notification: Notification) { |
1355 | + if let object = notification.userInfo { |
1356 | + if object["auth.needsAuth"] != nil { |
1357 | let enabled = settings.needsAuth |
1358 | let hiddenKeys = enabled ? [] : self.hiddenSettingsKeys |
1359 | self.setHiddenKeys(hiddenKeys, animated: true) |
1360 | @@ -68,15 +68,15 @@ |
1361 | } |
1362 | } |
1363 | |
1364 | - private func setupNavigationBar() { |
1365 | + fileprivate func setupNavigationBar() { |
1366 | self.navigationItem.title = NSLocalizedString("Settings", comment: "") |
1367 | |
1368 | let strSave = NSLocalizedString("OK", comment: "") |
1369 | - let btSave = UIBarButtonItem(title: strSave, style: .Done, target: self, action: #selector(SettingsViewController.dismissViewController)) |
1370 | + let btSave = UIBarButtonItem(title: strSave, style: .done, target: self, action: #selector(SettingsViewController.dismissViewController)) |
1371 | self.navigationItem.rightBarButtonItem = btSave |
1372 | } |
1373 | |
1374 | - @objc private func dismissViewController() { |
1375 | + @objc fileprivate func dismissViewController() { |
1376 | if !settings.validateServerIP() { |
1377 | let title = NSLocalizedString("Error", comment: "") |
1378 | let message = NSLocalizedString("Please, verify if the server IP is valid.", comment: "") |
1379 | @@ -89,7 +89,7 @@ |
1380 | .show() |
1381 | } else { |
1382 | self.synchronizeSettings() |
1383 | - self.dismissViewControllerAnimated(true, completion: nil) |
1384 | + self.dismiss(animated: true, completion: nil) |
1385 | } |
1386 | } |
1387 | |
1388 | @@ -99,17 +99,7 @@ |
1389 | |
1390 | extension SettingsViewController: IASKSettingsDelegate { |
1391 | |
1392 | - func settingsViewControllerDidEnd(sender: IASKAppSettingsViewController!) { |
1393 | + func settingsViewControllerDidEnd(_ sender: IASKAppSettingsViewController!) { |
1394 | // This is required... |
1395 | } |
1396 | - |
1397 | - func settingsViewController(sender: IASKAppSettingsViewController!, buttonTappedForSpecifier specifier: IASKSpecifier!) { |
1398 | - if specifier.key() == "server.testConnection" { |
1399 | - pollAPI.testConnection { success in |
1400 | - print("Success: \(success)") |
1401 | - } |
1402 | - } |
1403 | - self.synchronizeSettings() |
1404 | - } |
1405 | - |
1406 | } |
1407 | |
1408 | === modified file 'Remote/Classes/Controller/Slides/SlidesViewController.swift' |
1409 | --- Remote/Classes/Controller/Slides/SlidesViewController.swift 2016-07-03 18:04:32 +0000 |
1410 | +++ Remote/Classes/Controller/Slides/SlidesViewController.swift 2017-01-30 12:52:52 +0000 |
1411 | @@ -31,15 +31,19 @@ |
1412 | @IBOutlet weak var tableView: UITableView? |
1413 | @IBOutlet weak var segProjectionState: UISegmentedControl? |
1414 | |
1415 | - private var slides = [SlideModel]() |
1416 | - private let service: Service! |
1417 | - private var settingsPresenter: SettingsControllerPresenter! |
1418 | + fileprivate var slides = [SlideModel]() |
1419 | + fileprivate let service: Service! |
1420 | + fileprivate var settingsPresenter: SettingsControllerPresenter! |
1421 | + fileprivate let settings: UserSettings! |
1422 | + |
1423 | + fileprivate let cellIdentifier = "cell_id" |
1424 | |
1425 | // MARK: Init |
1426 | |
1427 | init(settings: UserSettings, service: Service) { |
1428 | self.service = service |
1429 | self.settingsPresenter = SettingsControllerPresenter(settings: settings, pollAPI: service.pollAPI) |
1430 | + self.settings = settings |
1431 | super.init(nibName: "SlidesViewController", bundle: nil) |
1432 | self.setupTabBar() |
1433 | self.setupNavigationBar() |
1434 | @@ -48,43 +52,50 @@ |
1435 | required init?(coder aDecoder: NSCoder) { |
1436 | self.service = nil |
1437 | self.settingsPresenter = nil |
1438 | + self.settings = nil |
1439 | super.init(coder: aDecoder) |
1440 | } |
1441 | |
1442 | override func viewDidLoad() { |
1443 | super.viewDidLoad() |
1444 | - self.setupTableView() |
1445 | - self.setupSegmentedControl() |
1446 | - } |
1447 | - |
1448 | + setupTableView() |
1449 | + setupSegmentedControl() |
1450 | + } |
1451 | + |
1452 | + override func viewWillAppear(_ animated: Bool) { |
1453 | + self.tableView?.decelerationRate = settings.preciseSlidesScroll ? UIScrollViewDecelerationRateFast : UIScrollViewDecelerationRateNormal |
1454 | + self.tableView?.bounces = !settings.preciseSlidesScroll |
1455 | + } |
1456 | + |
1457 | // MARK: Setup |
1458 | |
1459 | - private func setupTabBar() { |
1460 | + fileprivate func setupTabBar() { |
1461 | self.tabBarItem.title = NSLocalizedString("Slides", comment: "") |
1462 | self.tabBarItem.image = UIImage(named: "ic_slides") |
1463 | } |
1464 | |
1465 | - private func setupNavigationBar() { |
1466 | + fileprivate func setupNavigationBar() { |
1467 | self.navigationItem.leftBarButtonItem = settingsPresenter.settingsBarButton(self) |
1468 | |
1469 | self.navigationItem.title = NSLocalizedString("Slides", comment: "") |
1470 | |
1471 | let imagePrevious = UIImage(named: "ic_arrow-up") |
1472 | - let btPrevious = UIBarButtonItem(image: imagePrevious, style: .Plain, target: self, action: #selector(SlidesViewController.previousSlide)) |
1473 | + let btPrevious = UIBarButtonItem(image: imagePrevious, style: .plain, target: self, action: #selector(SlidesViewController.previousSlide)) |
1474 | let imageNext = UIImage(named: "ic_arrow-down") |
1475 | - let btNext = UIBarButtonItem(image: imageNext, style: .Plain, target: self, action: #selector(SlidesViewController.nextSlide)) |
1476 | + let btNext = UIBarButtonItem(image: imageNext, style: .plain, target: self, action: #selector(SlidesViewController.nextSlide)) |
1477 | self.navigationItem.rightBarButtonItems = [ |
1478 | btNext, |
1479 | btPrevious |
1480 | ] |
1481 | } |
1482 | |
1483 | - private func setupTableView() { |
1484 | + fileprivate func setupTableView() { |
1485 | self.tableView?.rowHeight = UITableViewAutomaticDimension |
1486 | self.tableView?.estimatedRowHeight = 44 |
1487 | + self.tableView?.register(SlideCell.self, forCellReuseIdentifier: cellIdentifier) |
1488 | } |
1489 | |
1490 | - private func setupSegmentedControl() { |
1491 | + fileprivate func setupSegmentedControl() { |
1492 | self.segProjectionState?.selectedSegmentIndex = -1 |
1493 | } |
1494 | |
1495 | @@ -94,25 +105,25 @@ |
1496 | let index = self.segProjectionState?.selectedSegmentIndex |
1497 | if let state = ProjectionState(rawValue: index!) { |
1498 | self.service.displayAPI.projectionState(state) { _, error in |
1499 | - if let error = error, message = verifyError(error) { |
1500 | - self.displayNotification(message: message, isError: true) |
1501 | + if let error = error, let message = verifyError(error as NSError) { |
1502 | + self.displayNotification(message, isError: true) |
1503 | } |
1504 | } |
1505 | } |
1506 | } |
1507 | |
1508 | - @objc private func previousSlide() { |
1509 | + @objc fileprivate func previousSlide() { |
1510 | self.service.controllerAPI.livePrevious() { _, error in |
1511 | - if let error = error, message = verifyError(error) { |
1512 | - self.displayNotification(message: message, isError: true) |
1513 | + if let error = error, let message = verifyError(error) { |
1514 | + self.displayNotification(message, isError: true) |
1515 | } |
1516 | } |
1517 | } |
1518 | |
1519 | - @objc private func nextSlide() { |
1520 | + @objc fileprivate func nextSlide() { |
1521 | self.service.controllerAPI.liveNext() { _, error in |
1522 | - if let error = error, message = verifyError(error) { |
1523 | - self.displayNotification(message: message, isError: true) |
1524 | + if let error = error, let message = verifyError(error) { |
1525 | + self.displayNotification(message, isError: true) |
1526 | } |
1527 | } |
1528 | } |
1529 | @@ -124,58 +135,57 @@ |
1530 | |
1531 | extension SlidesViewController: UITableViewDataSource { |
1532 | |
1533 | - func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
1534 | + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { |
1535 | return self.slides.count |
1536 | } |
1537 | |
1538 | - func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { |
1539 | - var cell = tableView.dequeueReusableCellWithIdentifier("Cell") |
1540 | - |
1541 | - if cell == nil { |
1542 | - cell = UITableViewCell(style: .Default, reuseIdentifier: "Cell") |
1543 | - cell!.textLabel?.numberOfLines = 0 |
1544 | - } |
1545 | - |
1546 | + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { |
1547 | + let cell: SlideCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! SlideCell |
1548 | let slide = self.slides[indexPath.row] |
1549 | - cell!.textLabel?.text = slide.text |
1550 | - |
1551 | - return cell! |
1552 | + cell.textLabel?.text = slide.text |
1553 | + return cell |
1554 | } |
1555 | - |
1556 | } |
1557 | |
1558 | + |
1559 | // MARK: - UITableViewDelegate |
1560 | |
1561 | extension SlidesViewController: UITableViewDelegate { |
1562 | |
1563 | - func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { |
1564 | + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { |
1565 | + let cell = tableView.cellForRow(at: indexPath) as! SlideCell |
1566 | + cell.spinner.startAnimating() |
1567 | + service.pauseLoopPolling = true |
1568 | self.service.controllerAPI.liveSet(row: indexPath.row) { _, error in |
1569 | - if let error = error, message = verifyError(error) { |
1570 | - self.displayNotification(message: message, isError: true) |
1571 | - tableView.deselectRowAtIndexPath(indexPath, animated: true) |
1572 | + self.service.pauseLoopPolling = false |
1573 | + cell.spinner.stopAnimating() |
1574 | + if let error = error, let message = verifyError(error as NSError) { |
1575 | + self.displayNotification(message, isError: true) |
1576 | + tableView.deselectRow(at: indexPath, animated: true) |
1577 | } |
1578 | } |
1579 | } |
1580 | - |
1581 | } |
1582 | |
1583 | + |
1584 | // MARK: - PollAPISlidesDelegate |
1585 | |
1586 | extension SlidesViewController: PollAPISlidesDelegate { |
1587 | |
1588 | - func updateSlides(slides: [SlideModel]) { |
1589 | + func updateSlides(_ slides: [SlideModel]) { |
1590 | self.slides = slides |
1591 | self.tableView?.reloadData() |
1592 | + self.tableView?.scrollToRow(at: IndexPath(row: 0, section: 0), at: UITableViewScrollPosition.top, animated: true) |
1593 | } |
1594 | |
1595 | - func updateSelectedSlide(row: Int) { |
1596 | + func updateSelectedSlide(_ row: Int) { |
1597 | if self.slides.count > 0 { |
1598 | - let indexPath = NSIndexPath(forRow: row, inSection: 0) |
1599 | - self.tableView?.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .None) |
1600 | + let indexPath = IndexPath(row: row, section: 0) |
1601 | + self.tableView?.selectRow(at: indexPath, animated: true, scrollPosition: .none) |
1602 | } |
1603 | } |
1604 | |
1605 | - func updateProjectionState(state: ProjectionState) { |
1606 | + func updateProjectionState(_ state: ProjectionState) { |
1607 | self.segProjectionState?.selectedSegmentIndex = state.rawValue |
1608 | } |
1609 | |
1610 | |
1611 | === modified file 'Remote/Classes/Controller/Slides/SlidesViewController.xib' |
1612 | --- Remote/Classes/Controller/Slides/SlidesViewController.xib 2016-07-03 18:04:32 +0000 |
1613 | +++ Remote/Classes/Controller/Slides/SlidesViewController.xib 2017-01-30 12:52:52 +0000 |
1614 | @@ -1,8 +1,12 @@ |
1615 | -<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
1616 | -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="14F1021" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES"> |
1617 | +<?xml version="1.0" encoding="UTF-8"?> |
1618 | +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11542" systemVersion="16D17a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES"> |
1619 | + <device id="retina4_0" orientation="portrait"> |
1620 | + <adaptation id="fullscreen"/> |
1621 | + </device> |
1622 | <dependencies> |
1623 | <deployment identifier="iOS"/> |
1624 | - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/> |
1625 | + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/> |
1626 | + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
1627 | </dependencies> |
1628 | <objects> |
1629 | <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SlidesViewController" customModule="Remote" customModuleProvider="target"> |
1630 | @@ -14,18 +18,18 @@ |
1631 | </placeholder> |
1632 | <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> |
1633 | <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT"> |
1634 | - <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> |
1635 | + <rect key="frame" x="0.0" y="0.0" width="320" height="568"/> |
1636 | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
1637 | <subviews> |
1638 | - <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="yep-A9-X97"> |
1639 | + <tableView clipsSubviews="YES" contentMode="scaleToFill" misplaced="YES" alwaysBounceVertical="YES" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="yep-A9-X97"> |
1640 | <rect key="frame" x="0.0" y="0.0" width="600" height="556"/> |
1641 | - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> |
1642 | + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
1643 | <connections> |
1644 | <outlet property="dataSource" destination="-1" id="IUL-yU-aAA"/> |
1645 | <outlet property="delegate" destination="-1" id="yTW-CE-U9j"/> |
1646 | </connections> |
1647 | </tableView> |
1648 | - <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bd2-0o-H00"> |
1649 | + <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bd2-0o-H00"> |
1650 | <rect key="frame" x="0.0" y="507" width="600" height="44"/> |
1651 | <constraints> |
1652 | <constraint firstAttribute="height" constant="44" id="nTo-A6-Fmk"/> |
1653 | @@ -51,7 +55,7 @@ |
1654 | </items> |
1655 | </toolbar> |
1656 | </subviews> |
1657 | - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> |
1658 | + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
1659 | <constraints> |
1660 | <constraint firstItem="bd2-0o-H00" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" id="9Nx-QJ-WEy"/> |
1661 | <constraint firstAttribute="bottom" secondItem="yep-A9-X97" secondAttribute="bottom" constant="44" id="K91-G1-wno"/> |
1662 | |
1663 | === modified file 'Remote/Classes/Model/ItemModel.swift' |
1664 | --- Remote/Classes/Model/ItemModel.swift 2016-07-03 18:04:32 +0000 |
1665 | +++ Remote/Classes/Model/ItemModel.swift 2017-01-30 12:52:52 +0000 |
1666 | @@ -36,7 +36,7 @@ |
1667 | |
1668 | init() {} |
1669 | |
1670 | - required init?(_ map: Map) {} |
1671 | + required init?(map: Map) {} |
1672 | |
1673 | func mapping(map: Map) { |
1674 | self.id <- map["id"] |
1675 | |
1676 | === modified file 'Remote/Classes/Model/LiveModel.swift' |
1677 | --- Remote/Classes/Model/LiveModel.swift 2016-07-03 18:04:32 +0000 |
1678 | +++ Remote/Classes/Model/LiveModel.swift 2017-01-30 12:52:52 +0000 |
1679 | @@ -30,7 +30,7 @@ |
1680 | var item: String! |
1681 | var slides: [SlideModel]! |
1682 | |
1683 | - required init?(_ map: Map) {} |
1684 | + required init?(map: Map) {} |
1685 | |
1686 | func mapping(map: Map) { |
1687 | self.item <- map["results.item"] |
1688 | |
1689 | === modified file 'Remote/Classes/Model/PollModel.swift' |
1690 | --- Remote/Classes/Model/PollModel.swift 2016-07-03 18:04:32 +0000 |
1691 | +++ Remote/Classes/Model/PollModel.swift 2017-01-30 12:52:52 +0000 |
1692 | @@ -26,20 +26,20 @@ |
1693 | import ObjectMapper |
1694 | |
1695 | enum ProjectionState: Int { |
1696 | - case Blank = 0 |
1697 | - case Theme = 1 |
1698 | - case Desktop = 2 |
1699 | - case Show = 3 |
1700 | + case blank = 0 |
1701 | + case theme = 1 |
1702 | + case desktop = 2 |
1703 | + case show = 3 |
1704 | |
1705 | func string() -> String { |
1706 | switch self { |
1707 | - case .Blank: |
1708 | + case .blank: |
1709 | return "blank" |
1710 | - case .Theme: |
1711 | + case .theme: |
1712 | return "theme" |
1713 | - case .Desktop: |
1714 | + case .desktop: |
1715 | return "desktop" |
1716 | - case .Show: |
1717 | + case .show: |
1718 | return "show" |
1719 | } |
1720 | } |
1721 | @@ -47,48 +47,39 @@ |
1722 | |
1723 | class PollModel: Mappable { |
1724 | |
1725 | - var item: String! |
1726 | - var version: Int! |
1727 | - var isSecure: Bool! |
1728 | - var isAuthorised: Bool! |
1729 | - private var blank: Bool! |
1730 | - private var display: Bool! |
1731 | - private var theme: Bool! |
1732 | - var twelve: Bool! |
1733 | - var slide: Int! |
1734 | - var service: Int! |
1735 | + var item: String = "" |
1736 | + var version: Int = 0 |
1737 | + var isSecure: Bool = false |
1738 | + var isAuthorised: Bool = false |
1739 | + fileprivate var blank: Bool = false |
1740 | + fileprivate var display: Bool = false |
1741 | + fileprivate var theme: Bool = false |
1742 | + var twelve: Bool = false |
1743 | + var slide: Int = 0 |
1744 | + var service: Int = 0 |
1745 | var projectionState: ProjectionState { |
1746 | - if blank.boolValue || display.boolValue || theme.boolValue { |
1747 | - if (blank.boolValue) { |
1748 | - return .Blank |
1749 | - } |
1750 | - else if display.boolValue { |
1751 | - return .Desktop |
1752 | + get { |
1753 | + if blank || display || theme { |
1754 | + if (blank) { |
1755 | + return .blank |
1756 | + } |
1757 | + else if display { |
1758 | + return .desktop |
1759 | + } |
1760 | + else { |
1761 | + return .theme |
1762 | + } |
1763 | } |
1764 | else { |
1765 | - return .Theme |
1766 | + return .show |
1767 | } |
1768 | } |
1769 | - else { |
1770 | - return .Show |
1771 | - } |
1772 | - } |
1773 | - |
1774 | - init() { |
1775 | - self.item = "" |
1776 | - self.version = 0 |
1777 | - self.isSecure = false |
1778 | - self.isAuthorised = false |
1779 | - self.blank = false |
1780 | - self.display = false |
1781 | - self.theme = false |
1782 | - self.twelve = false |
1783 | - self.slide = 0 |
1784 | - self.service = 0 |
1785 | - } |
1786 | - |
1787 | - required init?(_ map: Map) {} |
1788 | - |
1789 | + } |
1790 | + |
1791 | + init() {} |
1792 | + |
1793 | + required init?(map: Map) {} |
1794 | + |
1795 | func mapping(map: Map) { |
1796 | self.item <- map["results.item"] |
1797 | self.version <- map["results.version"] |
1798 | @@ -101,8 +92,4 @@ |
1799 | self.slide <- map["results.slide"] |
1800 | self.service <- map["results.service"] |
1801 | } |
1802 | - |
1803 | - |
1804 | - |
1805 | - |
1806 | } |
1807 | |
1808 | === modified file 'Remote/Classes/Model/ServiceListModel.swift' |
1809 | --- Remote/Classes/Model/ServiceListModel.swift 2016-07-03 18:04:32 +0000 |
1810 | +++ Remote/Classes/Model/ServiceListModel.swift 2017-01-30 12:52:52 +0000 |
1811 | @@ -27,12 +27,12 @@ |
1812 | |
1813 | class ServiceListModel: Mappable { |
1814 | |
1815 | - private var intern: Dictionary<String, [ItemModel]>! |
1816 | + fileprivate var intern: Dictionary<String, [ItemModel]>! |
1817 | var results: [ItemModel] { |
1818 | return intern["items"]! |
1819 | } |
1820 | |
1821 | - required init?(_ map: Map) {} |
1822 | + required init?(map: Map) {} |
1823 | |
1824 | func mapping(map: Map) { |
1825 | self.intern <- map["results"] |
1826 | |
1827 | === modified file 'Remote/Classes/Model/SlideModel.swift' |
1828 | --- Remote/Classes/Model/SlideModel.swift 2016-07-03 18:04:32 +0000 |
1829 | +++ Remote/Classes/Model/SlideModel.swift 2017-01-30 12:52:52 +0000 |
1830 | @@ -32,7 +32,7 @@ |
1831 | var text: String! |
1832 | var selected: Bool! |
1833 | |
1834 | - required init?(_ map: Map) {} |
1835 | + required init?(map: Map) {} |
1836 | |
1837 | func mapping(map: Map) { |
1838 | self.tag <- map["tag"] |
1839 | |
1840 | === modified file 'Remote/Classes/Model/SuccessModel.swift' |
1841 | --- Remote/Classes/Model/SuccessModel.swift 2016-07-03 18:04:32 +0000 |
1842 | +++ Remote/Classes/Model/SuccessModel.swift 2017-01-30 12:52:52 +0000 |
1843 | @@ -29,7 +29,7 @@ |
1844 | |
1845 | var success: Bool! |
1846 | |
1847 | - required init?(_ map: Map) {} |
1848 | + required init?(map: Map) {} |
1849 | |
1850 | func mapping(map: Map) { |
1851 | self.success <- map["results.success"] |
1852 | |
1853 | === modified file 'Remote/Classes/Model/UserSettings.swift' |
1854 | --- Remote/Classes/Model/UserSettings.swift 2016-07-03 18:04:32 +0000 |
1855 | +++ Remote/Classes/Model/UserSettings.swift 2017-01-30 12:52:52 +0000 |
1856 | @@ -26,57 +26,62 @@ |
1857 | |
1858 | struct UserSettings { |
1859 | |
1860 | - private let userDefaults: NSUserDefaults |
1861 | + fileprivate let userDefaults: UserDefaults |
1862 | |
1863 | - init(defaults: NSUserDefaults) { |
1864 | + init(defaults: UserDefaults) { |
1865 | userDefaults = defaults |
1866 | } |
1867 | |
1868 | var serverIP: String { |
1869 | - return userDefaults.valueForKey("server.ip") as! String |
1870 | + return userDefaults.value(forKey: "server.ip") as! String |
1871 | } |
1872 | |
1873 | var serverPort: String { |
1874 | - return userDefaults.valueForKey("server.port") as! String |
1875 | + return userDefaults.value(forKey: "server.port") as! String |
1876 | } |
1877 | |
1878 | var useHTTPS: Bool { |
1879 | - return userDefaults.boolForKey("server.useHTTPS") |
1880 | + return userDefaults.bool(forKey: "server.useHTTPS") |
1881 | } |
1882 | |
1883 | var needsAuth: Bool { |
1884 | - return userDefaults.boolForKey("auth.needsAuth") |
1885 | + return userDefaults.bool(forKey: "auth.needsAuth") |
1886 | } |
1887 | |
1888 | var userID: String { |
1889 | - return userDefaults.valueForKey("auth.userID") as! String |
1890 | + return userDefaults.value(forKey: "auth.userID") as! String |
1891 | } |
1892 | |
1893 | var password: String { |
1894 | - return userDefaults.valueForKey("auth.password") as! String |
1895 | + return userDefaults.value(forKey: "auth.password") as! String |
1896 | + } |
1897 | + |
1898 | + var preciseSlidesScroll: Bool { |
1899 | + return userDefaults.bool(forKey: "ui.preciseScroll") |
1900 | } |
1901 | |
1902 | func registerDefaults() { |
1903 | - userDefaults.registerDefaults([ |
1904 | + userDefaults.register(defaults: [ |
1905 | "server.ip": "", |
1906 | "server.port": "4316", |
1907 | "server.useHTTPS": false, |
1908 | "auth.needsAuth": false, |
1909 | "auth.userID": "", |
1910 | - "auth.password": "" |
1911 | + "auth.password": "", |
1912 | + "ui.preciseScroll": false |
1913 | ]) |
1914 | } |
1915 | |
1916 | func resetDefaultsIfNeeded() { |
1917 | - guard let _ = NSURL(string: serverIP + ":" + serverPort) else { |
1918 | - userDefaults.removeObjectForKey("server.ip") |
1919 | - userDefaults.removeObjectForKey("server.port") |
1920 | + guard let _ = URL(string: serverIP + ":" + serverPort) else { |
1921 | + userDefaults.removeObject(forKey: "server.ip") |
1922 | + userDefaults.removeObject(forKey: "server.port") |
1923 | return |
1924 | } |
1925 | } |
1926 | |
1927 | func validateServerIP() -> Bool { |
1928 | - guard let _ = NSURL(string: serverIP) else { |
1929 | + guard let _ = URL(string: serverIP) else { |
1930 | return false |
1931 | } |
1932 | return true |
1933 | |
1934 | === modified file 'Remote/Classes/Network/API.swift' |
1935 | --- Remote/Classes/Network/API.swift 2016-07-03 18:04:32 +0000 |
1936 | +++ Remote/Classes/Network/API.swift 2017-01-30 12:52:52 +0000 |
1937 | @@ -43,7 +43,7 @@ |
1938 | scheme += "s" |
1939 | } |
1940 | |
1941 | - let components: NSURLComponents = NSURLComponents() |
1942 | + var components: URLComponents = URLComponents() |
1943 | components.scheme = scheme |
1944 | components.host = serverIP |
1945 | components.port = Int(serverPort) |
1946 | @@ -51,4 +51,4 @@ |
1947 | |
1948 | return components.string!//strUrl |
1949 | } |
1950 | -} |
1951 | \ No newline at end of file |
1952 | +} |
1953 | |
1954 | === modified file 'Remote/Classes/Network/AddAPI.swift' |
1955 | --- Remote/Classes/Network/AddAPI.swift 2016-07-03 18:04:32 +0000 |
1956 | +++ Remote/Classes/Network/AddAPI.swift 2017-01-30 12:52:52 +0000 |
1957 | @@ -27,22 +27,25 @@ |
1958 | |
1959 | class AddAPI: API { |
1960 | |
1961 | - func addItem(item: ItemModel, plugin: Plugin, completion: (NSError?) -> Void) { |
1962 | + func addItem(_ item: ItemModel, plugin: Plugin, completion: @escaping (Error?) -> Void) { |
1963 | let url = self.base + "/" + plugin.rawValue + "/add" |
1964 | - var params: [String: AnyObject] = [ |
1965 | + var params: [String: Any] = [ |
1966 | "request": [ |
1967 | "id": (item.id == nil ? String(item.idInt!) : item.id!) |
1968 | ] |
1969 | ] |
1970 | if let jsonString = jsonString(fromDictionary: params) { |
1971 | - params = ["data": jsonString] |
1972 | - let request = Alamofire.request(.GET, url, parameters: params).validate(statusCode: 200...200) |
1973 | + params = ["data": jsonString as Any] |
1974 | + let request = Alamofire.request(url, parameters: params).validate(statusCode: 200...200) |
1975 | if settings.needsAuth { |
1976 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
1977 | - } |
1978 | - request.response { _, _, _, error in |
1979 | - completion(error) |
1980 | - } |
1981 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
1982 | + } |
1983 | + |
1984 | + let responseHandler: (Alamofire.DefaultDataResponse) -> Swift.Void = { response in |
1985 | + completion(response.error) |
1986 | + } |
1987 | + |
1988 | + request.response(completionHandler: responseHandler) |
1989 | } |
1990 | } |
1991 | |
1992 | |
1993 | === modified file 'Remote/Classes/Network/AlertAPI.swift' |
1994 | --- Remote/Classes/Network/AlertAPI.swift 2016-07-03 18:04:32 +0000 |
1995 | +++ Remote/Classes/Network/AlertAPI.swift 2017-01-30 12:52:52 +0000 |
1996 | @@ -28,21 +28,21 @@ |
1997 | |
1998 | class AlertAPI: API { |
1999 | |
2000 | - func alert(text: String, completion: ((Bool, NSError?) -> Void)? = nil) { |
2001 | + func alert(_ text: String, completion: ((Bool, Error?) -> Void)? = nil) { |
2002 | let url = self.base + "/alert" |
2003 | - var params: [String: AnyObject] = [ |
2004 | + var params: [String: Any] = [ |
2005 | "request": [ |
2006 | "text": text |
2007 | ] |
2008 | ] |
2009 | |
2010 | if let jsonString = jsonString(fromDictionary: params) { |
2011 | - params = ["data": jsonString] |
2012 | - let request = Alamofire.request(.GET, url, parameters: params).validate(statusCode: 200...200) |
2013 | + params = ["data": jsonString as Any] |
2014 | + let request = Alamofire.request(url, parameters: params).validate(statusCode: 200...200) |
2015 | if settings.needsAuth { |
2016 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2017 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2018 | } |
2019 | - request.responseObject { (response: Response<SuccessModel, NSError>) in |
2020 | + request.responseObject { (response: DataResponse<SuccessModel>) in |
2021 | let error = response.result.error |
2022 | var success = response.result.value?.success |
2023 | if success == nil { |
2024 | |
2025 | === modified file 'Remote/Classes/Network/ControllerAPI.swift' |
2026 | --- Remote/Classes/Network/ControllerAPI.swift 2016-07-03 18:04:32 +0000 |
2027 | +++ Remote/Classes/Network/ControllerAPI.swift 2017-01-30 12:52:52 +0000 |
2028 | @@ -28,26 +28,26 @@ |
2029 | |
2030 | class ControllerAPI: API { |
2031 | |
2032 | - func liveText(completion: ([SlideModel]?, NSError?) -> Void) { |
2033 | + func liveText(_ completion: @escaping ([SlideModel]?, Error?) -> Void) { |
2034 | let url = self.base + "/controller/live/text" |
2035 | - let request = Alamofire.request(.GET, url).validate(statusCode: 200...200) |
2036 | + let request = Alamofire.request(url).validate(statusCode: 200...200) |
2037 | if settings.needsAuth { |
2038 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2039 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2040 | } |
2041 | - request.responseObject { (response: Response<LiveModel, NSError>) -> Void in |
2042 | + request.responseObject { (response: DataResponse<LiveModel>) -> Void in |
2043 | let error = response.result.error |
2044 | let slides = response.result.value?.slides |
2045 | completion(slides, error) |
2046 | } |
2047 | } |
2048 | |
2049 | - private func action(action: String, completion: ((Bool, NSError?) -> Void)?) { |
2050 | + fileprivate func action(_ action: String, completion: ((Bool, Error?) -> Void)?) { |
2051 | let url = self.base + "/controller/live/" + action |
2052 | - let request = Alamofire.request(.GET, url).validate(statusCode: 200...200) |
2053 | + let request = Alamofire.request(url).validate(statusCode: 200...200) |
2054 | if settings.needsAuth { |
2055 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2056 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2057 | } |
2058 | - request.responseObject { (response: Response<SuccessModel, NSError>) -> Void in |
2059 | + request.responseObject { (response: DataResponse<SuccessModel>) -> Void in |
2060 | let error = response.result.error |
2061 | var success = response.result.value?.success |
2062 | if success == nil { |
2063 | @@ -60,29 +60,29 @@ |
2064 | } |
2065 | } |
2066 | |
2067 | - func livePrevious(completion: ((Bool, NSError?) -> Void)? = nil) { |
2068 | + func livePrevious(_ completion: ((Bool, Error?) -> Void)? = nil) { |
2069 | self.action("previous", completion: completion) |
2070 | } |
2071 | |
2072 | - func liveNext(completion: ((Bool, NSError?) -> Void)? = nil) { |
2073 | + func liveNext(_ completion: ((Bool, Error?) -> Void)? = nil) { |
2074 | self.action("next", completion: completion) |
2075 | } |
2076 | |
2077 | - func liveSet(row row: Int, completion: ((Bool, NSError?) -> Void)? = nil) { |
2078 | + func liveSet(row: Int, completion: ((Bool, Error?) -> Void)? = nil) { |
2079 | let url = self.base + "/controller/live/set" |
2080 | - var params: [String: AnyObject] = [ |
2081 | + var params: [String: Any] = [ |
2082 | "request": [ |
2083 | "id": "+\(row)" |
2084 | ] |
2085 | ] |
2086 | |
2087 | if let jsonString = jsonString(fromDictionary: params) { |
2088 | - params = ["data": jsonString] |
2089 | - let request = Alamofire.request(.GET, url, parameters: params).validate(statusCode: 200...200) |
2090 | + params = ["data": jsonString as Any] |
2091 | + let request = Alamofire.request(url, parameters: params).validate(statusCode: 200...200) |
2092 | if settings.needsAuth { |
2093 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2094 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2095 | } |
2096 | - request.responseObject { (response: Response<SuccessModel, NSError>) in |
2097 | + request.responseObject { (response: DataResponse<SuccessModel>) in |
2098 | let error = response.result.error |
2099 | var success = response.result.value?.success |
2100 | if success == nil { |
2101 | |
2102 | === modified file 'Remote/Classes/Network/DisplayAPI.swift' |
2103 | --- Remote/Classes/Network/DisplayAPI.swift 2016-07-03 18:04:32 +0000 |
2104 | +++ Remote/Classes/Network/DisplayAPI.swift 2017-01-30 12:52:52 +0000 |
2105 | @@ -28,13 +28,13 @@ |
2106 | |
2107 | class DisplayAPI: API { |
2108 | |
2109 | - func projectionState(state: ProjectionState, completion: ((Bool, NSError?) -> Void)? = nil) { |
2110 | + func projectionState(_ state: ProjectionState, completion: ((Bool, Error?) -> Void)? = nil) { |
2111 | let url = self.base + "/display/" + state.string() |
2112 | - let request = Alamofire.request(.GET, url).validate(statusCode: 200...200) |
2113 | + let request = Alamofire.request(url).validate(statusCode: 200...200) |
2114 | if settings.needsAuth { |
2115 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2116 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2117 | } |
2118 | - request.responseObject { (response: Response<SuccessModel, NSError>) in |
2119 | + request.responseObject { (response: DataResponse<SuccessModel>) in |
2120 | let error = response.result.error |
2121 | var success = response.result.value?.success |
2122 | if success == nil { |
2123 | |
2124 | === modified file 'Remote/Classes/Network/LiveAPI.swift' |
2125 | --- Remote/Classes/Network/LiveAPI.swift 2016-07-03 18:04:32 +0000 |
2126 | +++ Remote/Classes/Network/LiveAPI.swift 2017-01-30 12:52:52 +0000 |
2127 | @@ -27,22 +27,25 @@ |
2128 | |
2129 | class LiveAPI: API { |
2130 | |
2131 | - func goItemToLive(item: ItemModel, plugin: Plugin, completion: (NSError?) -> Void) { |
2132 | + func goItemToLive(_ item: ItemModel, plugin: Plugin, completion: @escaping (Error?) -> Void) { |
2133 | let url = self.base + "/" + plugin.rawValue + "/live" |
2134 | - var params: [String: AnyObject] = [ |
2135 | + var params: [String: Any] = [ |
2136 | "request": [ |
2137 | "id": (item.id == nil ? String(item.idInt!) : item.id!) |
2138 | ] |
2139 | ] |
2140 | if let jsonString = jsonString(fromDictionary: params) { |
2141 | - params = ["data": jsonString] |
2142 | - let request = Alamofire.request(.GET, url, parameters: params).validate(statusCode: 200...200) |
2143 | + params = ["data": jsonString as Any] |
2144 | + let request = Alamofire.request(url, parameters: params).validate(statusCode: 200...200) |
2145 | if settings.needsAuth { |
2146 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2147 | - } |
2148 | - request.response { _, _, _, error in |
2149 | - completion(error) |
2150 | - } |
2151 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2152 | + } |
2153 | + |
2154 | + let responseHandler: (Alamofire.DefaultDataResponse) -> Swift.Void = { response in |
2155 | + completion(response.error) |
2156 | + } |
2157 | + |
2158 | + request.response(completionHandler: responseHandler) |
2159 | } |
2160 | } |
2161 | |
2162 | |
2163 | === modified file 'Remote/Classes/Network/PollAPI.swift' |
2164 | --- Remote/Classes/Network/PollAPI.swift 2016-07-03 18:04:32 +0000 |
2165 | +++ Remote/Classes/Network/PollAPI.swift 2017-01-30 12:52:52 +0000 |
2166 | @@ -27,24 +27,24 @@ |
2167 | import AlamofireObjectMapper |
2168 | |
2169 | protocol PollAPIServiceDelegate { |
2170 | - func updateServiceList(items: [ItemModel]) |
2171 | + func updateServiceList(_ items: [ItemModel]) |
2172 | func updateSelectedItem(itemId id: String) |
2173 | - func updateProjectionState(state: ProjectionState) |
2174 | + func updateProjectionState(_ state: ProjectionState) |
2175 | } |
2176 | |
2177 | protocol PollAPISlidesDelegate { |
2178 | - func updateSlides(slides: [SlideModel]) |
2179 | - func updateSelectedSlide(row: Int) |
2180 | - func updateProjectionState(state: ProjectionState) |
2181 | + func updateSlides(_ slides: [SlideModel]) |
2182 | + func updateSelectedSlide(_ row: Int) |
2183 | + func updateProjectionState(_ state: ProjectionState) |
2184 | } |
2185 | |
2186 | class PollAPI: API { |
2187 | |
2188 | - private var poll: PollModel = PollModel() |
2189 | + fileprivate var poll: PollModel = PollModel() |
2190 | var serviceDelegate: PollAPIServiceDelegate? |
2191 | var slidesDelegate: PollAPISlidesDelegate? |
2192 | - private let controllerAPI: ControllerAPI |
2193 | - private let serviceAPI: ServiceAPI |
2194 | + fileprivate let controllerAPI: ControllerAPI |
2195 | + fileprivate let serviceAPI: ServiceAPI |
2196 | |
2197 | init(settings: UserSettings, controllerAPI: ControllerAPI, serviceAPI: ServiceAPI) { |
2198 | self.controllerAPI = controllerAPI |
2199 | @@ -52,13 +52,13 @@ |
2200 | super.init(settings: settings) |
2201 | } |
2202 | |
2203 | - func poll(completion: ((PollModel?, NSError?) -> Void)? = nil) { |
2204 | + func poll(_ completion: ((PollModel?, Error?) -> Void)? = nil) { |
2205 | let url = self.base + "/poll" |
2206 | - let request = Alamofire.request(.GET, url).validate(statusCode: 200...200) |
2207 | + let request = Alamofire.request(url).validate(statusCode: 200...200) |
2208 | if settings.needsAuth { |
2209 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2210 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2211 | } |
2212 | - request.responseObject { (response: Response<PollModel, NSError>) in |
2213 | + request.responseObject { (response: DataResponse<PollModel>) in |
2214 | let error = response.result.error |
2215 | let poll = response.result.value |
2216 | |
2217 | @@ -71,7 +71,7 @@ |
2218 | } |
2219 | |
2220 | |
2221 | - private func updateService(completion: ((Void) -> Void)? = nil) { |
2222 | + fileprivate func updateService(_ completion: ((Void) -> Void)? = nil) { |
2223 | self.serviceAPI.list { items, error in |
2224 | if let items = items { |
2225 | self.serviceDelegate?.updateServiceList(items) |
2226 | @@ -84,7 +84,7 @@ |
2227 | } |
2228 | |
2229 | |
2230 | - private func updateSlides(completion: ((Void) -> Void)? = nil) { |
2231 | + fileprivate func updateSlides(_ completion: ((Void) -> Void)? = nil) { |
2232 | self.controllerAPI.liveText { slides, error in |
2233 | if let slides = slides { |
2234 | self.slidesDelegate?.updateSlides(slides) |
2235 | @@ -97,13 +97,13 @@ |
2236 | } |
2237 | |
2238 | |
2239 | - private func updateProjectionState(projectionState: ProjectionState) { |
2240 | + fileprivate func updateProjectionState(_ projectionState: ProjectionState) { |
2241 | self.serviceDelegate?.updateProjectionState(projectionState) |
2242 | self.slidesDelegate?.updateProjectionState(projectionState) |
2243 | } |
2244 | |
2245 | |
2246 | - private func handlePollResponse(poll: PollModel?) { |
2247 | + fileprivate func handlePollResponse(_ poll: PollModel?) { |
2248 | if let poll = poll { |
2249 | if self.poll.service != poll.service { |
2250 | self.updateService({ |
2251 | @@ -129,17 +129,4 @@ |
2252 | } |
2253 | } |
2254 | |
2255 | - |
2256 | - func testConnection(completion: (Bool) -> Void) { |
2257 | - self.poll { poll, error in |
2258 | - if let _ = error { |
2259 | - completion(false) |
2260 | - } else if let _ = poll { |
2261 | - completion(true) |
2262 | - } else { |
2263 | - completion(false) |
2264 | - } |
2265 | - } |
2266 | - } |
2267 | - |
2268 | -} |
2269 | \ No newline at end of file |
2270 | +} |
2271 | |
2272 | === modified file 'Remote/Classes/Network/SearchAPI.swift' |
2273 | --- Remote/Classes/Network/SearchAPI.swift 2016-07-03 18:04:32 +0000 |
2274 | +++ Remote/Classes/Network/SearchAPI.swift 2017-01-30 12:52:52 +0000 |
2275 | @@ -27,24 +27,24 @@ |
2276 | |
2277 | class SearchAPI: API { |
2278 | |
2279 | - func search(plugin plugin: Plugin, text: String, completion: ([ItemModel]?, NSError?) -> Void) { |
2280 | + func search(plugin: Plugin, text: String, completion: @escaping ([ItemModel]?, Error?) -> Void) { |
2281 | let url = self.base + "/" + plugin.rawValue + "/search" |
2282 | - var params: [String: AnyObject] = [ |
2283 | + var params: [String: Any] = [ |
2284 | "request": [ |
2285 | "text": text |
2286 | ] |
2287 | ] |
2288 | if let jsonString = jsonString(fromDictionary: params) { |
2289 | - params = ["data": jsonString] |
2290 | - let request = Alamofire.request(.GET, url, parameters: params).validate(statusCode: 200...200) |
2291 | + params = ["data": jsonString as Any] |
2292 | + let request = Alamofire.request(url, parameters: params).validate(statusCode: 200...200) |
2293 | if settings.needsAuth { |
2294 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2295 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2296 | } |
2297 | - request.responseJSON { (response: Response<AnyObject, NSError>) in |
2298 | + request.responseJSON { (response: DataResponse<Any>) in |
2299 | var result = [ItemModel]() |
2300 | if let value = response.result.value as? NSDictionary, |
2301 | - results = value["results"] as? NSDictionary, |
2302 | - items = results["items"] as? NSArray { |
2303 | + let results = value["results"] as? NSDictionary, |
2304 | + let items = results["items"] as? NSArray { |
2305 | for item in items { |
2306 | let item = item as! NSArray |
2307 | let i = ItemModel() |
2308 | |
2309 | === modified file 'Remote/Classes/Network/Service.swift' |
2310 | --- Remote/Classes/Network/Service.swift 2016-07-03 18:04:32 +0000 |
2311 | +++ Remote/Classes/Network/Service.swift 2017-01-30 12:52:52 +0000 |
2312 | @@ -33,6 +33,8 @@ |
2313 | let searchAPI: SearchAPI |
2314 | let liveAPI: LiveAPI |
2315 | let addAPI: AddAPI |
2316 | + var pauseLoopPolling = false |
2317 | + |
2318 | init(settings: UserSettings) { |
2319 | serviceAPI = ServiceAPI(settings: settings) |
2320 | controllerAPI = ControllerAPI(settings :settings) |
2321 | |
2322 | === modified file 'Remote/Classes/Network/ServiceAPI.swift' |
2323 | --- Remote/Classes/Network/ServiceAPI.swift 2016-07-03 18:04:32 +0000 |
2324 | +++ Remote/Classes/Network/ServiceAPI.swift 2017-01-30 12:52:52 +0000 |
2325 | @@ -28,34 +28,35 @@ |
2326 | |
2327 | class ServiceAPI: API { |
2328 | |
2329 | - func list(completion: ([ItemModel]?, NSError?) -> Void) { |
2330 | + func list(_ completion: @escaping ([ItemModel]?, Error?) -> Void) { |
2331 | let url = self.base + "/service/list" |
2332 | - let request = Alamofire.request(.GET, url).validate(statusCode: 200...200) |
2333 | + let request = Alamofire.request(url).validate(statusCode: 200...200) |
2334 | if settings.needsAuth { |
2335 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2336 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2337 | } |
2338 | - request.responseObject { (response: Response<ServiceListModel, NSError>) in |
2339 | + request.responseObject { (response: DataResponse<ServiceListModel>) in |
2340 | let error = response.result.error |
2341 | let items = response.result.value?.results |
2342 | completion(items, error) |
2343 | } |
2344 | } |
2345 | |
2346 | - func set(row row: Int, completion: ((Bool, NSError?) -> Void)? = nil) { |
2347 | + func set(row: Int, completion: ((Bool, Error?) -> Void)? = nil) { |
2348 | let url = self.base + "/service/set" |
2349 | - var params: [String: AnyObject] = [ |
2350 | - "request": [ |
2351 | - "id": "+\(row)" |
2352 | - ] |
2353 | + let literal: [String: Any] = [ |
2354 | + "id": "+\(row)" |
2355 | + ] |
2356 | + var params: [String: Any] = [ |
2357 | + "request": literal |
2358 | ] |
2359 | |
2360 | if let jsonString = jsonString(fromDictionary: params) { |
2361 | - params = ["data": jsonString] |
2362 | - let request = Alamofire.request(.GET, url, parameters: params).validate(statusCode: 200...200) |
2363 | + params = ["data": jsonString as AnyObject] |
2364 | + let request = Alamofire.request(url, parameters: params).validate(statusCode: 200...200) |
2365 | if settings.needsAuth { |
2366 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2367 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2368 | } |
2369 | - request.responseObject { (response: Response<SuccessModel, NSError>) in |
2370 | + request.responseObject { (response: DataResponse<SuccessModel>) in |
2371 | let error = response.result.error |
2372 | var success = response.result.value?.success |
2373 | if success == nil { |
2374 | @@ -71,13 +72,13 @@ |
2375 | } |
2376 | } |
2377 | |
2378 | - private func nextPrevious(action: String, completion: ((Bool, NSError?) -> Void)? = nil) { |
2379 | + fileprivate func nextPrevious(_ action: String, completion: ((Bool, Error?) -> Void)? = nil) { |
2380 | let url = self.base + "/service/" + action |
2381 | - let request = Alamofire.request(.GET, url).validate(statusCode: 200...200) |
2382 | + let request = Alamofire.request(url).validate(statusCode: 200...200) |
2383 | if settings.needsAuth { |
2384 | - request.authenticate(user: settings.userID, password: settings.password, persistence: .None) |
2385 | + request.authenticate(user: settings.userID, password: settings.password, persistence: .none) |
2386 | } |
2387 | - request.responseObject { (response: Response<SuccessModel, NSError>) in |
2388 | + request.responseObject { (response: DataResponse<SuccessModel>) in |
2389 | let error = response.result.error |
2390 | var success = response.result.value?.success |
2391 | if success == nil { |
2392 | @@ -90,11 +91,11 @@ |
2393 | } |
2394 | } |
2395 | |
2396 | - func previous(completion: ((Bool, NSError?) -> Void)? = nil) { |
2397 | + func previous(_ completion: ((Bool, Error?) -> Void)? = nil) { |
2398 | self.nextPrevious("previous", completion: completion) |
2399 | } |
2400 | |
2401 | - func next(completion: ((Bool, NSError?) -> Void)? = nil) { |
2402 | + func next(_ completion: ((Bool, Error?) -> Void)? = nil) { |
2403 | self.nextPrevious("next", completion: completion) |
2404 | } |
2405 | |
2406 | |
2407 | === modified file 'Remote/Classes/Util/ColorUtil.swift' |
2408 | --- Remote/Classes/Util/ColorUtil.swift 2016-07-03 18:04:32 +0000 |
2409 | +++ Remote/Classes/Util/ColorUtil.swift 2017-01-30 12:52:52 +0000 |
2410 | @@ -26,4 +26,4 @@ |
2411 | |
2412 | let kGreyColor = UIColor(red: 207/255, green: 207/255, blue: 207/255, alpha: 1) |
2413 | let kBlueColor = UIColor(red: 0, green: 122/255, blue: 255/255, alpha: 1) |
2414 | -let kRedColor = UIColor.redColor() |
2415 | +let kRedColor = UIColor.red |
2416 | |
2417 | === modified file 'Remote/Classes/Util/DictionaryUtil.swift' |
2418 | --- Remote/Classes/Util/DictionaryUtil.swift 2016-07-03 18:04:32 +0000 |
2419 | +++ Remote/Classes/Util/DictionaryUtil.swift 2017-01-30 12:52:52 +0000 |
2420 | @@ -24,10 +24,10 @@ |
2421 | |
2422 | import Foundation |
2423 | |
2424 | -func jsonString(fromDictionary dictionary: [String: AnyObject]) -> String? { |
2425 | +func jsonString(fromDictionary dictionary: [String: Any]) -> String? { |
2426 | do { |
2427 | - let jsonData = try NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions(rawValue: 0)) |
2428 | - let jsonString = String(data: jsonData, encoding: NSUTF8StringEncoding)! |
2429 | + let jsonData = try JSONSerialization.data(withJSONObject: dictionary, options: JSONSerialization.WritingOptions(rawValue: 0)) |
2430 | + let jsonString = String(data: jsonData, encoding: String.Encoding.utf8)! |
2431 | return jsonString |
2432 | } catch { |
2433 | return nil |
2434 | |
2435 | === modified file 'Remote/Classes/Util/ErrorUtil.swift' |
2436 | --- Remote/Classes/Util/ErrorUtil.swift 2016-07-03 18:04:32 +0000 |
2437 | +++ Remote/Classes/Util/ErrorUtil.swift 2017-01-30 12:52:52 +0000 |
2438 | @@ -24,12 +24,13 @@ |
2439 | |
2440 | import UIKit |
2441 | |
2442 | -func verifyError(error: NSError) -> String? { |
2443 | - if error.code == -6003 { |
2444 | +func verifyError(_ error: Error) -> String? { |
2445 | + let castedError = error as NSError |
2446 | + if castedError.code == -6003 { |
2447 | return NSLocalizedString("User not authenticated.", comment: "") |
2448 | - } else if error.code == -999 { |
2449 | + } else if castedError.code == -999 { |
2450 | return NSLocalizedString("Verify your credentials of authentication.", comment: "") |
2451 | - } else if error.code == -6004 { |
2452 | + } else if castedError.code == -6004 { |
2453 | return nil |
2454 | } |
2455 | return NSLocalizedString("An error occurred. Try again...", comment: "") |
2456 | |
2457 | === added file 'Remote/Classes/Util/TabSwitchingToRightAnimationController.swift' |
2458 | --- Remote/Classes/Util/TabSwitchingToRightAnimationController.swift 1970-01-01 00:00:00 +0000 |
2459 | +++ Remote/Classes/Util/TabSwitchingToRightAnimationController.swift 2017-01-30 12:52:52 +0000 |
2460 | @@ -0,0 +1,66 @@ |
2461 | +/****************************************************************************** |
2462 | + * OpenLP iOS Remote * |
2463 | + * --------------------------------------------------------------------------- * |
2464 | + * Copyright (c) 2008-2016 OpenLP Developers * |
2465 | + * --------------------------------------------------------------------------- * |
2466 | + * Permission is hereby granted, free of charge, to any person obtaining a * |
2467 | + * copy of this software and associated documentation files (the "Software"), * |
2468 | + * to deal in the Software without restriction, including without limitation * |
2469 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * |
2470 | + * and/or sell copies of the Software, and to permit persons to whom the * |
2471 | + * Software is furnished to do so, subject to the following conditions: * |
2472 | + * * |
2473 | + * The above copyright notice and this permission notice shall be included in * |
2474 | + * all copies or substantial portions of the Software. * |
2475 | + * * |
2476 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * |
2477 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * |
2478 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * |
2479 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * |
2480 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * |
2481 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * |
2482 | + * DEALINGS IN THE SOFTWARE. * |
2483 | + ******************************************************************************/ |
2484 | + |
2485 | +import UIKit |
2486 | + |
2487 | +class TabSwitchingToRightAnimationController: NSObject, UIViewControllerAnimatedTransitioning { |
2488 | + let tabBarController: UITabBarController |
2489 | + |
2490 | + init(tabBarController: UITabBarController) { |
2491 | + self.tabBarController = tabBarController |
2492 | + } |
2493 | + |
2494 | + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { |
2495 | + return 0.5 |
2496 | + } |
2497 | + |
2498 | + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { |
2499 | + if let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), |
2500 | + let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) { |
2501 | + let fromView = fromVC.view |
2502 | + let toView: UIView = toVC.view |
2503 | + |
2504 | + let containerView = transitionContext.containerView |
2505 | + containerView.addSubview(toView) |
2506 | + |
2507 | + var fromViewEndFrame = fromView?.frame |
2508 | + fromViewEndFrame?.origin.x -= containerView.frame.width |
2509 | + |
2510 | + let toViewEndFrame = transitionContext.finalFrame(for: toVC) |
2511 | + let toViewStartFrame = CGRect(x: toViewEndFrame.origin.x + toViewEndFrame.size.width, y: toViewEndFrame.origin.y, width: toViewEndFrame.size.width, height: toViewEndFrame.size.height) |
2512 | + |
2513 | + toView.frame = toViewStartFrame |
2514 | + |
2515 | + containerView.backgroundColor = UIColor.white |
2516 | + |
2517 | + UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(), animations: { () -> Void in |
2518 | + toView.frame = toViewEndFrame |
2519 | + fromView?.frame = fromViewEndFrame! |
2520 | + |
2521 | + }, completion: { (completed) -> Void in |
2522 | + transitionContext.completeTransition(completed) |
2523 | + }) |
2524 | + } |
2525 | + } |
2526 | +} |
2527 | |
2528 | === modified file 'Remote/Classes/Util/ViewControllerUtil.swift' |
2529 | --- Remote/Classes/Util/ViewControllerUtil.swift 2016-07-03 18:04:32 +0000 |
2530 | +++ Remote/Classes/Util/ViewControllerUtil.swift 2017-01-30 12:52:52 +0000 |
2531 | @@ -27,19 +27,55 @@ |
2532 | |
2533 | |
2534 | extension UIViewController { |
2535 | - func wrapedInNavigationController(controller: UIViewController) -> UINavigationController { |
2536 | + func wrapedInNavigationController(_ controller: UIViewController) -> UINavigationController { |
2537 | let navigationController = UINavigationController(rootViewController: controller) |
2538 | return navigationController |
2539 | } |
2540 | |
2541 | |
2542 | - func displayNotification(message message: String, isError: Bool = false) { |
2543 | + func displayNotification(_ message: String, isError: Bool = false) { |
2544 | let notifications = CWStatusBarNotification() |
2545 | - notifications.notificationLabelTextColor = UIColor.whiteColor() |
2546 | + notifications.notificationLabelTextColor = UIColor.white |
2547 | notifications.notificationLabelBackgroundColor = isError ? kRedColor : kBlueColor |
2548 | - notifications.notificationAnimationInStyle = .Top |
2549 | - notifications.notificationAnimationOutStyle = .Top |
2550 | - notifications.displayNotificationWithMessage(message, forDuration: 3) |
2551 | + notifications.notificationAnimationInStyle = .top |
2552 | + notifications.notificationAnimationOutStyle = .top |
2553 | + notifications.display(withMessage: message, forDuration: 3) |
2554 | + } |
2555 | + |
2556 | + |
2557 | + func animateRightBetweenTabViews(_ fromViewController: UIViewController, toViewController: UIViewController, completion:@escaping ()->Void) { |
2558 | + |
2559 | + let toView = toViewController.view |
2560 | + let fromView = fromViewController.view |
2561 | + |
2562 | + |
2563 | + |
2564 | + // Add the toView to the tab bar view |
2565 | + fromView?.superview!.addSubview(toView!) |
2566 | + |
2567 | + |
2568 | + // Position toView off screen (to the left/right of fromView) |
2569 | + let screenWidth = UIScreen.main.bounds.size.width; |
2570 | + |
2571 | + let offset = screenWidth; |
2572 | + toView?.center = CGPoint(x: (fromView?.center.x)! + offset, y: (toView?.center.y)!) |
2573 | + |
2574 | + // Disable interaction during animation |
2575 | + view.isUserInteractionEnabled = false |
2576 | + |
2577 | + UIView.animate(withDuration: 0.5, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 0, options: UIViewAnimationOptions.curveEaseOut, animations: { |
2578 | + |
2579 | + // Slide the views by -offset |
2580 | + fromView?.center = CGPoint(x: (fromView?.center.x)! - offset, y: (fromView?.center.y)!); |
2581 | + toView?.center = CGPoint(x: (toView?.center.x)! - offset, y: (toView?.center.y)!); |
2582 | + |
2583 | + }, completion: { finished in |
2584 | + |
2585 | + // Remove the old view from the tabbar view. |
2586 | + fromView?.removeFromSuperview() |
2587 | + self.view.isUserInteractionEnabled = true |
2588 | + completion() |
2589 | + }) |
2590 | } |
2591 | |
2592 | } |
2593 | |
2594 | === added file 'Remote/Classes/View/SlideCell.swift' |
2595 | --- Remote/Classes/View/SlideCell.swift 1970-01-01 00:00:00 +0000 |
2596 | +++ Remote/Classes/View/SlideCell.swift 2017-01-30 12:52:52 +0000 |
2597 | @@ -0,0 +1,44 @@ |
2598 | +/****************************************************************************** |
2599 | + * OpenLP iOS Remote * |
2600 | + * --------------------------------------------------------------------------- * |
2601 | + * Copyright (c) 2008-2016 OpenLP Developers * |
2602 | + * --------------------------------------------------------------------------- * |
2603 | + * Permission is hereby granted, free of charge, to any person obtaining a * |
2604 | + * copy of this software and associated documentation files (the "Software"), * |
2605 | + * to deal in the Software without restriction, including without limitation * |
2606 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * |
2607 | + * and/or sell copies of the Software, and to permit persons to whom the * |
2608 | + * Software is furnished to do so, subject to the following conditions: * |
2609 | + * * |
2610 | + * The above copyright notice and this permission notice shall be included in * |
2611 | + * all copies or substantial portions of the Software. * |
2612 | + * * |
2613 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * |
2614 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * |
2615 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * |
2616 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * |
2617 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * |
2618 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * |
2619 | + * DEALINGS IN THE SOFTWARE. * |
2620 | + ******************************************************************************/ |
2621 | + |
2622 | +import UIKit |
2623 | + |
2624 | +class SlideCell: UITableViewCell { |
2625 | + |
2626 | + let spinner: UIActivityIndicatorView |
2627 | + |
2628 | + override init(style: UITableViewCellStyle, reuseIdentifier: String?) { |
2629 | + spinner = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.gray) |
2630 | + spinner.hidesWhenStopped = true |
2631 | + super.init(style: style, reuseIdentifier: reuseIdentifier) |
2632 | + accessoryView = spinner |
2633 | + textLabel?.numberOfLines = 0 |
2634 | + textLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping |
2635 | + } |
2636 | + |
2637 | + required init?(coder aDecoder: NSCoder) { |
2638 | + fatalError("init(coder:) has not been implemented") |
2639 | + } |
2640 | + |
2641 | +} |
2642 | |
2643 | === modified file 'Remote/Resources/Settings.bundle/Root.inApp.plist' |
2644 | --- Remote/Resources/Settings.bundle/Root.inApp.plist 2016-07-03 18:04:32 +0000 |
2645 | +++ Remote/Resources/Settings.bundle/Root.inApp.plist 2017-01-30 12:52:52 +0000 |
2646 | @@ -95,6 +95,22 @@ |
2647 | <string>PSGroupSpecifier</string> |
2648 | <key>Title</key> |
2649 | <string></string> |
2650 | + <key>FooterText</key> |
2651 | + <string>This switch forces slides tab scroll to decelerate faster and disables bouncing. This enables faster and more precise slide selection.</string> |
2652 | + </dict> |
2653 | + <dict> |
2654 | + <key>Type</key> |
2655 | + <string>PSToggleSwitchSpecifier</string> |
2656 | + <key>Title</key> |
2657 | + <string>Use precise slides scroll</string> |
2658 | + <key>Key</key> |
2659 | + <string>ui.preciseScroll</string> |
2660 | + </dict> |
2661 | + <dict> |
2662 | + <key>Type</key> |
2663 | + <string>PSGroupSpecifier</string> |
2664 | + <key>Title</key> |
2665 | + <string></string> |
2666 | </dict> |
2667 | <dict> |
2668 | <key>DefaultValue</key> |
2669 | |
2670 | === modified file 'Remote/Resources/Settings.bundle/Root.plist' |
2671 | --- Remote/Resources/Settings.bundle/Root.plist 2016-07-03 18:04:32 +0000 |
2672 | +++ Remote/Resources/Settings.bundle/Root.plist 2017-01-30 12:52:52 +0000 |
2673 | @@ -90,6 +90,24 @@ |
2674 | <key>Key</key> |
2675 | <string>auth.password</string> |
2676 | </dict> |
2677 | + <dict> |
2678 | + <key>Type</key> |
2679 | + <string>PSGroupSpecifier</string> |
2680 | + <key>Title</key> |
2681 | + <string></string> |
2682 | + <key>FooterText</key> |
2683 | + <string>This switch forces slides tab scroll to decelerate faster and disables bouncing. This enables faster and more precise slide selection.</string> |
2684 | + </dict> |
2685 | + <dict> |
2686 | + <key>Type</key> |
2687 | + <string>PSToggleSwitchSpecifier</string> |
2688 | + <key>Title</key> |
2689 | + <string>Use precise slides scroll</string> |
2690 | + <key>Key</key> |
2691 | + <string>ui.preciseScroll</string> |
2692 | + <key>DefaultValue</key> |
2693 | + <false/> |
2694 | + </dict> |
2695 | </array> |
2696 | </dict> |
2697 | </plist> |
2698 | |
2699 | === modified file 'Remote/Resources/Settings.bundle/en.lproj/Root.strings' |
2700 | Binary files Remote/Resources/Settings.bundle/en.lproj/Root.strings 2016-07-03 18:04:32 +0000 and Remote/Resources/Settings.bundle/en.lproj/Root.strings 2017-01-30 12:52:52 +0000 differ |
Follows some observations:
1) The link of the pod BlockLooper is incorrect. I think you only have access to the current :git link. Replacing to "https:/ /github. com/ashender/ BlockLooper. git" works well for me; oller) are breaking the app; ller): "slide selection error: nil", please remove it; roller when I (dis)able Needs Auth the fields do not hide or show; pecifier into Root.plist; Mapper pod into test target, but I'm getting errors about swift version. It is only with me?
2) The arrow to next and previous slide (in SlidesViewContr
- There is a log message when I select a slide (in SlideViewContro
- In SettingViewCont
- "Use precise slides scroll" is in embedded setting, but not in root settings (in Setting.app). As is possible to add to toggle in root setting, add to PSToggleSwitchS
- The tests here are quite crazy. I had to add the AlamofireObject
If possible, add a footer text after "Use precise slides scroll" explaining what is it. For this, add the key "FooterText" as a String in the dictionary of its GroupSpecifier.