Skip to content

Commit 5387f3a

Browse files
committed
Settings page
1 parent b97e6ef commit 5387f3a

File tree

7 files changed

+177
-17
lines changed

7 files changed

+177
-17
lines changed

ShoppingList.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
D7A20F861F744F7F001CE337 /* ShoppingListManageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A20F851F744F7F001CE337 /* ShoppingListManageViewController.swift */; };
2424
D7A20F881F748AC6001CE337 /* ShoppingListManageTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A20F871F748AC6001CE337 /* ShoppingListManageTableCell.swift */; };
2525
D7A20F8A1F74AD3F001CE337 /* SyncManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7A20F891F74AD3F001CE337 /* SyncManager.swift */; };
26+
D7F79D7B1F7D79ED0022F43E /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7F79D7A1F7D79ED0022F43E /* SettingsViewController.swift */; };
2627
/* End PBXBuildFile section */
2728

2829
/* Begin PBXFileReference section */
@@ -44,6 +45,7 @@
4445
D7A20F851F744F7F001CE337 /* ShoppingListManageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShoppingListManageViewController.swift; sourceTree = "<group>"; };
4546
D7A20F871F748AC6001CE337 /* ShoppingListManageTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShoppingListManageTableCell.swift; sourceTree = "<group>"; };
4647
D7A20F891F74AD3F001CE337 /* SyncManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncManager.swift; sourceTree = "<group>"; };
48+
D7F79D7A1F7D79ED0022F43E /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
4749
D9DB28B1B20A6F4272DAF4D5 /* Pods-ShoppingList.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShoppingList.release.xcconfig"; path = "Pods/Target Support Files/Pods-ShoppingList/Pods-ShoppingList.release.xcconfig"; sourceTree = "<group>"; };
4850
FCE0928FBEC2083B1D4FCB5B /* Pods-ShoppingList.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShoppingList.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShoppingList/Pods-ShoppingList.debug.xcconfig"; sourceTree = "<group>"; };
4951
/* End PBXFileReference section */
@@ -125,6 +127,7 @@
125127
D7A20F8B1F75A61E001CE337 /* View */ = {
126128
isa = PBXGroup;
127129
children = (
130+
D7F79D7A1F7D79ED0022F43E /* SettingsViewController.swift */,
128131
D7A20F7F1F7435DB001CE337 /* ShoppingListAddViewController.swift */,
129132
D7A20F871F748AC6001CE337 /* ShoppingListManageTableCell.swift */,
130133
D7A20F851F744F7F001CE337 /* ShoppingListManageViewController.swift */,
@@ -277,6 +280,7 @@
277280
D71D20431F74124E00E53E3D /* AppDelegate.swift in Sources */,
278281
D71D20551F74140700E53E3D /* Datastore.swift in Sources */,
279282
D71D205A1F741D9800E53E3D /* ShoppingListFactory.swift in Sources */,
283+
D7F79D7B1F7D79ED0022F43E /* SettingsViewController.swift in Sources */,
280284
D71D205C1F741E2500E53E3D /* ShoppingListRepository.swift in Sources */,
281285
D7A20F861F744F7F001CE337 /* ShoppingListManageViewController.swift in Sources */,
282286
);

ShoppingList/AppDelegate.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
3636

3737
func applicationDidBecomeActive(_ application: UIApplication) {
3838
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
39-
SyncManager.startSync()
39+
SyncManager.startSync(settingsDatastore: StateManager.datastore.settingsDB)
4040
}
4141

4242
func applicationWillTerminate(_ application: UIApplication) {

ShoppingList/Base.lproj/Main.storyboard

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@
9999
</constraints>
100100
</view>
101101
<navigationItem key="navigationItem" title="Shopping Lists" id="E4b-ds-FYU">
102+
<barButtonItem key="leftBarButtonItem" title="Settings" id="rsw-9y-ZpW">
103+
<connections>
104+
<segue destination="UwB-iO-cfC" kind="show" id="C4a-Yn-5Kc"/>
105+
</connections>
106+
</barButtonItem>
102107
<barButtonItem key="rightBarButtonItem" systemItem="add" id="C5m-We-A4i">
103108
<connections>
104109
<segue destination="J1G-F2-wPT" kind="show" id="yuC-et-SeQ"/>
@@ -150,7 +155,7 @@
150155
</viewController>
151156
<placeholder placeholderIdentifier="IBFirstResponder" id="E7h-jF-WkQ" userLabel="First Responder" sceneMemberID="firstResponder"/>
152157
</objects>
153-
<point key="canvasLocation" x="1233" y="-412"/>
158+
<point key="canvasLocation" x="1233" y="-54"/>
154159
</scene>
155160
<!--Shopping List-->
156161
<scene sceneID="dsA-58-uTk">
@@ -226,7 +231,7 @@
226231
</viewController>
227232
<placeholder placeholderIdentifier="IBFirstResponder" id="YOe-8j-AvK" userLabel="First Responder" sceneMemberID="firstResponder"/>
228233
</objects>
229-
<point key="canvasLocation" x="1232.8" y="323.38830584707648"/>
234+
<point key="canvasLocation" x="1233" y="709"/>
230235
</scene>
231236
<!--Navigation Controller-->
232237
<scene sceneID="xte-ca-9Ck">
@@ -246,5 +251,58 @@
246251
</objects>
247252
<point key="canvasLocation" x="-780" y="-54"/>
248253
</scene>
254+
<!--Settings-->
255+
<scene sceneID="csN-Pa-pCg">
256+
<objects>
257+
<viewController id="UwB-iO-cfC" userLabel="Settings" customClass="SettingsViewController" customModule="ShoppingList" customModuleProvider="target" sceneMemberID="viewController">
258+
<layoutGuides>
259+
<viewControllerLayoutGuide type="top" id="MLA-vK-0Sh"/>
260+
<viewControllerLayoutGuide type="bottom" id="KKm-40-GmE"/>
261+
</layoutGuides>
262+
<view key="view" contentMode="scaleToFill" id="bZP-vh-Hp3">
263+
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
264+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
265+
<subviews>
266+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sync URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LCr-z0-GaB">
267+
<rect key="frame" x="16" y="72" width="75" height="21"/>
268+
<constraints>
269+
<constraint firstAttribute="height" constant="21" id="ZKB-BV-V36"/>
270+
</constraints>
271+
<fontDescription key="fontDescription" type="system" pointSize="17"/>
272+
<nil key="textColor"/>
273+
<nil key="highlightedColor"/>
274+
</label>
275+
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="6Sh-Z2-snh">
276+
<rect key="frame" x="16" y="101" width="343" height="30"/>
277+
<constraints>
278+
<constraint firstAttribute="height" constant="30" id="AZx-e4-n5H"/>
279+
</constraints>
280+
<nil key="textColor"/>
281+
<fontDescription key="fontDescription" type="system" pointSize="14"/>
282+
<textInputTraits key="textInputTraits"/>
283+
</textField>
284+
</subviews>
285+
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
286+
<constraints>
287+
<constraint firstItem="LCr-z0-GaB" firstAttribute="leading" secondItem="bZP-vh-Hp3" secondAttribute="leadingMargin" id="EOG-4k-iKG"/>
288+
<constraint firstItem="6Sh-Z2-snh" firstAttribute="trailing" secondItem="bZP-vh-Hp3" secondAttribute="trailingMargin" id="NLc-Hu-5D6"/>
289+
<constraint firstItem="6Sh-Z2-snh" firstAttribute="top" secondItem="LCr-z0-GaB" secondAttribute="bottom" constant="8" id="OoP-J9-iOv"/>
290+
<constraint firstItem="6Sh-Z2-snh" firstAttribute="leading" secondItem="bZP-vh-Hp3" secondAttribute="leadingMargin" id="d2T-4w-99j"/>
291+
<constraint firstItem="LCr-z0-GaB" firstAttribute="top" secondItem="MLA-vK-0Sh" secondAttribute="bottom" constant="8" id="i8Q-la-db6"/>
292+
</constraints>
293+
</view>
294+
<navigationItem key="navigationItem" title="Settings" id="9cl-IV-C0c">
295+
<barButtonItem key="backBarButtonItem" title="Back" id="a4t-fA-t08"/>
296+
<barButtonItem key="rightBarButtonItem" title="Done" id="dGV-ra-aKo"/>
297+
</navigationItem>
298+
<connections>
299+
<outlet property="doneButton" destination="dGV-ra-aKo" id="Ztw-z4-fT5"/>
300+
<outlet property="textField" destination="6Sh-Z2-snh" id="F0f-5R-7gU"/>
301+
</connections>
302+
</viewController>
303+
<placeholder placeholderIdentifier="IBFirstResponder" id="MGR-vQ-SaP" userLabel="First Responder" sceneMemberID="firstResponder"/>
304+
</objects>
305+
<point key="canvasLocation" x="1232.8" y="-772.26386806596713"/>
306+
</scene>
249307
</scenes>
250308
</document>

ShoppingList/Datastore.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import UIKit
1111

1212
class Datastore {
1313

14-
let datastore: CDTDatastore
14+
let settingsDB: CDTDatastore
15+
let shoppingListDB: CDTDatastore
1516
let shoppingListRepository: ShoppingListRepository
1617

1718
init?() {
@@ -21,8 +22,9 @@ class Datastore {
2122
let path = storeURL.path
2223
do {
2324
let manager = try CDTDatastoreManager(directory: path)
24-
self.datastore = try manager.datastoreNamed("shopping-list")
25-
self.shoppingListRepository = ShoppingListRepository(datastore: self.datastore)
25+
self.settingsDB = try manager.datastoreNamed("settings")
26+
self.shoppingListDB = try manager.datastoreNamed("shopping-list")
27+
self.shoppingListRepository = ShoppingListRepository(datastore: self.shoppingListDB)
2628
} catch {
2729
print("Encountered an error: \(error)")
2830
return nil
@@ -54,7 +56,7 @@ class Datastore {
5456
}
5557

5658
func loadItems(list: CDTDocumentRevision) -> [CDTDocumentRevision] {
57-
let result = self.datastore.find(["type": "item", "list": list.docId!])
59+
let result = self.shoppingListDB.find(["type": "item", "list": list.docId!])
5860
var items = [CDTDocumentRevision]()
5961
result?.enumerateObjects { rev, idx, stop in
6062
items.append(rev)
@@ -84,9 +86,9 @@ class Datastore {
8486
}
8587

8688
func deleteAllDocs() throws {
87-
let allDocs = self.datastore.getAllDocuments()
89+
let allDocs = self.shoppingListDB.getAllDocuments()
8890
for doc in allDocs {
89-
try self.datastore.deleteDocument(from: doc)
91+
try self.shoppingListDB.deleteDocument(from: doc)
9092
}
9193
}
9294

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// ShoppingListAddViewController.swift
3+
// ShoppingList
4+
//
5+
// Created by Mark Watson on 9/21/17.
6+
// Copyright © 2017 IBM Watson Data Lab. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
class SettingsViewController: UIViewController {
12+
13+
@IBOutlet var doneButton: UIBarButtonItem!
14+
@IBOutlet var textField: UITextField!
15+
16+
override func viewDidLoad() {
17+
super.viewDidLoad()
18+
self.doneButton.action = #selector(SettingsViewController.save)
19+
}
20+
21+
override func viewWillAppear(_ animated: Bool) {
22+
super.viewWillAppear(animated)
23+
self.textField.text = SyncManager.activeSyncUrl
24+
}
25+
26+
override func viewDidDisappear(_ animated: Bool) {
27+
super.viewDidDisappear(animated)
28+
self.textField.text = ""
29+
}
30+
31+
func save() {
32+
SyncManager.updateSyncUrl(syncUrl: self.textField!.text)
33+
_ = self.navigationController?.popViewController(animated: true)
34+
}
35+
36+
}
37+

ShoppingList/ShoppingListRepository.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class ShoppingListRepository {
1818
}
1919
}
2020

21-
static let iso8601: DateFormatter = {
21+
private static let iso8601: DateFormatter = {
2222
let formatter = DateFormatter()
2323
formatter.calendar = Calendar(identifier: .iso8601)
2424
formatter.locale = Locale(identifier: "en_US_POSIX")
@@ -29,14 +29,17 @@ class ShoppingListRepository {
2929

3030
let datastore: CDTDatastore
3131
let replicationListener = ReplicationListener()
32+
var syncUrl: String? = nil
3233

3334
init(datastore: CDTDatastore) {
3435
self.datastore = datastore
3536
}
3637

3738
func sync() {
38-
//let remote = URL(string: "http://admin:[email protected]:35984/shopping-list")!
39-
let remote = URL(string: "http://admin:[email protected]:35984/shopping-list")!
39+
if (self.syncUrl == nil) {
40+
return
41+
}
42+
let remote = URL(string: self.syncUrl!)!
4043
self.datastore.push(to: remote) { error in
4144
if let error = error {
4245
print("Error performing push replication: \(error)")

ShoppingList/SyncManager.swift

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// Copyright © 2017 IBM Watson Data Lab. All rights reserved.
77
//
88

9+
import CDTDatastore
910
import Foundation
1011

1112
protocol SyncListener {
@@ -15,26 +16,81 @@ protocol SyncListener {
1516
class SyncManager {
1617

1718
static var syncListener: SyncListener? = nil
19+
static var activeSyncUrl : String? = nil
20+
private static var settingsDatastore: CDTDatastore? = nil
21+
private static var settingsDoc: CDTDocumentRevision? = nil
1822
private static var running = false
1923

20-
static func startSync() {
21-
running = true
24+
static func startSync(settingsDatastore: CDTDatastore) {
25+
SyncManager.activeSyncUrl = nil
26+
SyncManager.settingsDatastore = settingsDatastore
27+
do {
28+
SyncManager.settingsDoc = try SyncManager.settingsDatastore?.getDocumentWithId("settings")
29+
SyncManager.applySyncUrl(syncUrl: SyncManager.settingsDoc?.body["syncUrl"] as? String, updateDB: false)
30+
}
31+
catch {
32+
// ignore
33+
}
34+
}
35+
36+
private static func start() {
37+
guard let syncUrl = StateManager.datastore.shoppingListRepository.syncUrl, !syncUrl.isEmpty else {
38+
SyncManager.running = false
39+
return // or break, continue, throw
40+
}
41+
SyncManager.running = true
2242
let queue = DispatchQueue(label: "com.ibm.shoppinglist.sync", qos: DispatchQoS.userInteractive)
2343
queue.async {
24-
while running {
44+
while SyncManager.running {
2545
StateManager.datastore.shoppingListRepository.sync()
2646
sleep(2)
2747
}
2848
}
2949
}
3050

3151
static func stopSync() {
32-
running = false
52+
SyncManager.running = false
3353
}
3454

3555
static func onSyncComplete() {
3656
DispatchQueue.main.sync {
37-
syncListener?.onSyncComplete()
57+
SyncManager.syncListener?.onSyncComplete()
58+
}
59+
}
60+
61+
static func updateSyncUrl(syncUrl: String?) {
62+
SyncManager.applySyncUrl(syncUrl: syncUrl, updateDB: true)
63+
}
64+
65+
private static func applySyncUrl(syncUrl: String?, updateDB: Bool) {
66+
print(syncUrl)
67+
if (syncUrl != SyncManager.activeSyncUrl) {
68+
if (updateDB) {
69+
if (SyncManager.settingsDoc == nil) {
70+
SyncManager.settingsDoc = CDTDocumentRevision(docId: "settings")
71+
SyncManager.settingsDoc!.body = ["syncUrl": syncUrl ?? ""]
72+
do {
73+
SyncManager.settingsDoc = try SyncManager.settingsDatastore!.createDocument(from: SyncManager.settingsDoc!)
74+
}
75+
catch {
76+
// TODO
77+
}
78+
}
79+
else {
80+
SyncManager.settingsDoc!.body = ["syncUrl": syncUrl ?? ""]
81+
do {
82+
SyncManager.settingsDoc = try SyncManager.settingsDatastore!.updateDocument(from: SyncManager.settingsDoc!)
83+
}
84+
catch {
85+
// TODO
86+
}
87+
}
88+
}
89+
SyncManager.activeSyncUrl = syncUrl
90+
StateManager.datastore.shoppingListRepository.syncUrl = syncUrl
91+
if (!SyncManager.running) {
92+
SyncManager.start()
93+
}
3894
}
3995
}
4096

0 commit comments

Comments
 (0)