瀏覽代碼

Add couchbase lab.

James Montemagno 10 年之前
父節點
當前提交
73a50381b8
共有 92 個文件被更改,包括 2773 次插入0 次删除
  1. 22 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/LICENSE
  2. 163 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/README.md
  3. 166 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/README_jp.md
  4. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/architecture.png
  5. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/cellaccessory.png
  6. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/detail.png
  7. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/solutionpad.png
  8. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/storyboard.png
  9. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/taskdone_xap.png
  10. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/tasky_xap.png
  11. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/taskysim.png
  12. 39 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSync.sln
  13. 21 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSync.userprefs
  14. 19 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Assets/AboutAssets.txt
  15. 80 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/KitchenSyncAndroid.csproj
  16. 45 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/KitchenSyncListAdapter.cs
  17. 109 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/MainActivity.cs
  18. 6 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Properties/AndroidManifest.xml
  19. 28 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Properties/AssemblyInfo.cs
  20. 44 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/AboutResources.txt
  21. 131 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/Resource.designer.cs
  22. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/drawable/icon.png
  23. 17 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/layout/list_item.xml
  24. 15 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/layout/main.xml
  25. 6 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/values/Strings.xml
  26. 7 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/packages.config
  27. 11 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/KitchenSyncShared.shproj
  28. 51 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/Task.cs
  29. 89 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/TaskManager.cs
  30. 15 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/TaskyShared.projitems
  31. 11 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/AppDelegate.cs
  32. 95 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/HomeScreen.storyboard
  33. 125 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/HomeScreenController.cs
  34. 37 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/HomeScreenController.designer.cs
  35. 35 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Info.plist
  36. 119 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/KitchenSyncIos.csproj
  37. 13 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Main.cs
  38. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Default-568h@2x.png
  39. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Default.png
  40. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Default@2x.png
  41. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-60@2x.png
  42. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-Small-40@2x.png
  43. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-Small.png
  44. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-Small@2x.png
  45. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon.png
  46. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon@2x.png
  47. 16 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/ViewController.cs
  48. 45 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/ViewController.designer.cs
  49. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/iTunesArtwork
  50. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/iTunesArtwork@2x
  51. 7 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/packages.config
  52. 39 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSync.sln
  53. 21 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSync.userprefs
  54. 19 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Assets/AboutAssets.txt
  55. 80 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/KitchenSyncAndroid.csproj
  56. 45 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/KitchenSyncListAdapter.cs
  57. 97 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/MainActivity.cs
  58. 6 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Properties/AndroidManifest.xml
  59. 28 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Properties/AssemblyInfo.cs
  60. 44 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/AboutResources.txt
  61. 131 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/Resource.designer.cs
  62. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/drawable/Icon.png
  63. 17 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/layout/list_item.xml
  64. 15 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/layout/main.xml
  65. 6 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/values/Strings.xml
  66. 7 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/packages.config
  67. 11 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/KitchenSyncShared.shproj
  68. 51 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/Task.cs
  69. 43 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/TaskManager.cs
  70. 15 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/TaskyShared.projitems
  71. 11 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/AppDelegate.cs
  72. 95 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/HomeScreen.storyboard
  73. 118 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/HomeScreenController.cs
  74. 37 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/HomeScreenController.designer.cs
  75. 35 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Info.plist
  76. 119 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/KitchenSyncIos.csproj
  77. 13 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Main.cs
  78. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Default-568h@2x.png
  79. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Default.png
  80. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Default@2x.png
  81. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-60@2x.png
  82. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-Small-40@2x.png
  83. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-Small.png
  84. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-Small@2x.png
  85. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon.png
  86. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon@2x.png
  87. 16 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/ViewController.cs
  88. 45 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/ViewController.designer.cs
  89. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/iTunesArtwork
  90. 二進制
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/iTunesArtwork@2x
  91. 7 0
      3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/packages.config
  92. 15 0
      3 - Advanced - Couchbase Mobile/README.md

+ 22 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/LICENSE

@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Mike Bluestein
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+

+ 163 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/README.md

@@ -0,0 +1,163 @@
+Kitchen Sync
+============
+
+### Goal
+
+Build your first Couchbase Mobile app in just a few minutes! Take an existing Xamarin application and add data persistence along with offline support!
+
+![Application Architecture](https://raw.githubusercontent.com/couchbaselabs/mini-hacks/master/kitchen-sync/topology.png "Typical Couchbase Mobile Architecture")
+
+
+### Understanding the Architecture
+
+The architecture and project structure of the KitchenSync application is shown in the following diagram:
+
+![architecture](https://raw.githubusercontent.com/couchbaselabs/mini-hacks/master/kitchen-sync/xamarin/project/images/architecture.png)
+
+- User Interface - The screens, controls and data presentation code. In Xamarin.iOS these classes are wrappers around the iOS CocoaTouch frameworks. The user interface that you build looks, feels and performs like a native Objective-C application.
+- App Layer - Custom classes to bind the business layer to the user interface, typically requiring platform specific features.
+- Business Layer - Business object classes and business logic.
+- Data Access Layer - Abstraction layer between the business logic and the data layer.
+- Data Layer - Low-level data persistence and retrieval; the KitchenSync sample uses Couchbase Lite. 
+
+### Tutorial
+
+The tutorial will create the shared logic, as well as the iOS and Android specific portions.  Each step has a corresponding comment in the workshop_start project (For per-platform items they are labeled as [step-number]A (for Android) and [step-number]B (for iOS) Otherwise, items are for shared logic)  To begin, git clone the repository and load the 'KitchenSync.sln' file found from 'mini_hack_projects ▸ mini-hacks ▸ kitchen-sync ▸ xamarin ▸ project ▸ src ▸ workshop_start' path.
+
+From within Xamarin Studio:
+
+- (1) We need to get a reference to our database object. To do that, add the below to the `TaskManager` constructor in the 'TaskManager.cs' file:
+```c#
+_db = Manager.SharedInstance.GetDatabase("kitchen-sync");
+```
+- (2) Next, we create an index to allow for fast queries. Couchbase Lite uses MapReduce queries, which let us create our queries using plain-old C# functions. We can also do powerful transformations of documents, compute aggregates, etc. In this project, however, we're going to keep things simple and just index our documents by date.
+```c#
+View view = _db.GetView("viewItemsByDate");
+view.SetMap((doc, emit) => {
+    if(doc.ContainsKey("created_at") && doc["created_at"] is DateTime) {
+        emit(doc["created_at"], null);
+    }
+}, "1");
+```
+- (3) Next, we start our `LiveQuery`. Like a regular `Query`, LiveQuery gives us the ability to filter and order the index we created in step 2. However, 'LiveQuery' also can send us results that appear later--even after we have already iterated through the results! We also need to make sure that the UI layer is informed of this, and gets a callback with already instantiated Task objects.  Let's add the following:
+```c#
+ _query = view.CreateQuery().ToLiveQuery();
+ _query.Descending = true;
+ _query.Changed += (sender, e) => {
+    if(TasksUpdated != null) {
+        var tasks = from row in e.Rows
+                    select Task.FromDictionary(row.Document.Properties);
+        TasksUpdated(this, tasks.ToList());
+     }
+ };
+
+ _query.Start();
+```
+- (4) We need a way to save Tasks as they are added or updated from the UI layer.  While the logic is similar in both, for new documents the `PutProperties` method needs to be called and for updating the Tasks, the `Update` method needs to be called.  New `Task` objects will not have their `ID` property set initially, so we can distinguish between the two cases by using that fact.  Add the following as the body of the `SaveTask` method.
+```c#
+ if (item.ID == null) {
+     Document doc = _db.CreateDocument ();
+     doc.PutProperties (item.ToDictionary ());
+     item.ID = doc.Id;
+ } else {
+     Document doc = _db.GetDocument (item.ID);
+     doc.Update (newRevision => {
+          newRevision.SetUserProperties(item.ToDictionary());
+          return true;
+     });
+ }
+```
+- (5) On the other hand, we also need a way to delete documents.  This is simple; get an existing document and if it is not `null` then call its `Delete` method.  Add the following as the body of the `DeleteTask` method.
+```c#
+ var doc = _db.GetExistingDocument (task.ID);
+ if(doc != null) {
+     doc.Delete();
+ }
+```
+- (6A) Getting the data is great, but we need to inform the UI about how to use it.  On Android, this involves setting the `Adapter` property on the `ListView` that displays the data.  The `KitchenSyncListAdapter` class is responsible for this.  It is already set up, you just need to create it.  Add the following as the body of the `InitItemListAdapter` method in `MainActivity`:
+```c#
+ _listAdapter = new KitchenSyncListAdapter(ApplicationContext, Resource.Layout.list_item, Resource.Id.label, new List<Task>());
+
+ _itemListView.Adapter = _listAdapter;
+```
+- (6B) The process on iOS is similar, just replace `KitchenSyncListAdapter` with `DataSource` in the above explanation.  The `DataSource` class is located in `HomeScreenController` and only needs a small modification to get it working (it needs to reload the table view .  Add this to its constructor:
+```c#
+ taskMgr.TasksUpdated += (sender, e) => {
+     _rows = e;
+     controller.tableView.ReloadData();
+ };
+```
+- (7A) We want to provide a way for users to toggle the checkbox on an item.  The most natural way to do this is to do it when the user taps on a row in the `ListView`.  Add the following as the body of the `OnItemClick` method:
+```c#
+ Task task = _listAdapter.GetItem(position);
+ task.Checked = !task.Checked;
+ _taskMgr.SaveTask(task);
+```
+- (7B) We will use tapping in iOS as well to signal checkbox toggling.  Add the following to the `RowSelected` method of `TableViewDelegate`:
+```c#
+ var task = _source.Tasks[indexPath.Row];
+ task.Checked = !task.Checked;
+ var manager = new TaskManager();
+ manager.SaveTask(task);
+```
+- (8A) As for deletion, long pressing feels the most natural to Android users and so we will implement the following in the `OnItemLongClick` method:
+```c#
+ Task task = _listAdapter.GetItem(position);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ AlertDialog alert = builder.SetTitle("Delete Item?").
+ SetMessage("Are you sure you want to delete \"" + task.Text + "\"?").
+ SetPositiveButton("Yes", (sender, e) => _taskMgr.DeleteTask(task)).
+ SetNegativeButton("No", (sender, e) => {}).Create();
+
+ alert.Show();
+```
+- (8B) However, on iOS users are used to swiping for the option to delete a row in a table view.  Add the following to the `CommitEditingStyle` method of `DataSource`:
+```c#
+ if (editingStyle == UITableViewCellEditingStyle.Delete) {
+     taskMgr.DeleteTask (_rows[indexPath.Row]);
+ }
+```
+- Your app now has a database and local persistence!  It is a great time to build and run the application on device or emulator. You should see all of your new list items saved locally.
+
+- (9A) Let's add sync! First, we need to provide a URL for our Couchbase Sync Gateway. If you are doing this tutorial on a Mac and deploying to a real device, then enter the IP address of your Wifi interface (i.e. don't use localhost).  If you are deploying to an emulator, you will need to use `10.0.2.2` if you want to use localhost.  Add the following member to `MainActivity`:
+```c#
+private const string SYNC_URL = "http://<YOUR_WIFI_OR_ETHERNET_IP>:4984/kitchen-sync";
+```
+- (9B) Let's add sync! First, we need to provide a URL for our Couchbase Sync Gateway. If you are doing this tutorial on a Mac and deploying to a real device, then enter the IP address of your Wifi interface (i.e. don't use localhost).  If you are deploying to the simulator, you can use localhost.  Add the following Member to `HomeScreenController`:
+```c#
+private const string SYNC_URL = "http://<YOUR_WIFI_OR_ETHERNET_IP>:4984/kitchen-sync";
+```
+- (10) That's the hardest part! Now we need to add our `StartSync` method which, in this case, will continuously sync all local and remote changes.  Add the StartSync logic to the 'TaskManager.cs' file located under 'KitchenSyncShared'
+```c#
+Uri uri;
+ try {
+     uri = new Uri(syncUrl);
+ } catch(UriFormatException) {
+     Log.E("TaskManager", "Invalid URL {0}", syncUrl);
+     return;
+ }
+
+ if(_pull == null) {
+     _pull = _db.CreatePullReplication(uri);
+     _pull.Continuous = true;
+     _pull.Start();
+ }
+
+ if(_push == null) {
+     _push = _db.CreatePushReplication(uri);
+     _push.Continuous = true;
+     _push.Start();
+ }
+```
+- (11A) All that's left is to call this method at the appropriate time.  Add the following to the `OnCreate` method of `MainActivity`:
+```c#
+ _taskMgr.StartSync(SYNC_URL);
+```
+- (11B) And add the it to the `ViewDidLoad` method of `HomeScreenController` as well:
+```c#
+ _taskMgr.StartSync(SYNC_URL);
+```
+- Build and run time! Shortly after launching, you should see lots of sync activity scrolling by in the console for your device. Make sure that you have some list items for Couchbase Lite to sync.
+
+- Let's go see the results of sync in the Sync Gateway Admin Console. Open your browser to [http://localhost:4985/_admin/](http://localhost:4985/_admin/), and click on the [kitchen-sync](http://localhost:4985/_admin/db/kitchen-sync) link. You will land on the **Documents** page, which will list all documents found. Clicking on a document id will reveal the contents of the document.

+ 166 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/README_jp.md

@@ -0,0 +1,166 @@
+Kitchen Sync
+============
+
+## 目的
+
+短時間で初めてのCouchbase Mobileアプリを開発しましょう!既存のアプリを改善させ、保存と同期を入れましょう!
+
+
+![Application Architecture](https://raw.githubusercontent.com/couchbaselabs/mini-hacks/master/kitchen-sync/topology.png "Typical Couchbase Mobile Architecture")
+
+## 準備
+
+Xamarinのインストールなどに関しては[こちら](http://dev.classmethod.jp/smartphone/xamarin-start/)をご参考にしてください。
+
+### アーキテクチャーの説明
+
+The architecture and project structure of the KitchenSync application is shown in the following diagram:
+
+![architecture](https://raw.githubusercontent.com/couchbaselabs/mini-hacks/master/kitchen-sync/xamarin/project/images/architecture.png)
+
+- User Interface - 画面、コントロール、表示などの部分になります。それぞれのプラットフォームのネイティブUIライブラリーをラッピングしますのでネイティブアプリと同様に動作します。
+- App Layer - Business LayerとUser Interfaceをつなげるロジックです。多くはプラットフォーム固有の機能を使います。
+- Business Layer - データモデルや共通ロジック
+- Data Access Layer - Data LayerとBusiness Layerをつなげるロジックです。
+- Data Layer - データの保存と取得です。KitchenSyncはCouchbase Liteを使います。
+
+### チュートリアル
+
+このチュートリアルで共通部分並びにiOS・Android専用ロジックと実装します。各手順はworkshop_startプロジェクトにコメントがあります(プラットフォーム固有の部分は[番号]A (Android)と[番号]B (iOS)になっています)。
+
+- (1) データベースを取得します。. `TaskManager`初期化にこれを追加しましょう。
+```c#
+_db = Manager.SharedInstance.GetDatabase("kitchen-sync");
+```
+- (2) これから速いクエリを作るためにインデックスを作成します。Couchbase LiteはC#関数でクエリを作ることができるMapReduceクエリを使います。それにドキュメントの変換や集計の計算などもできますが、こちらの場合は単純に日付によってのインデックスを作ります。
+```c#
+View view = _db.GetView("viewItemsByDate");
+view.SetMap((doc, emit) => {
+    if(doc.ContainsKey("created_at") && doc["created_at"] is DateTime) {
+        emit(doc["created_at"], null);
+    }
+}, "1");
+```
+- (3) 次にLiveQueryを開始します。普通のQueryのように2番で作ったインデックスをフィルターやソートをかけることができます。しかしその上にクエリが終わった後のデータについても通知されます。そしてTaskオブジェクトを作成してUIに通知する必要があります。
+```c#
+ _query = view.CreateQuery().ToLiveQuery();
+ _query.Descending = true;
+ _query.Changed += (sender, e) => {
+    if(TasksUpdated != null) {
+        var tasks = from row in e.Rows
+                    select Task.FromDictionary(row.Document.Properties);
+        TasksUpdated(this, tasks.ToList());
+     }
+ };
+
+ _query.Start();
+```
+- (4) これからUIの作成と更新によって`Task`を保存する機能を入れます。作成と更新のロジックは似ていますが作成は`PutProperties`関数を使い、更新は`Update`関数を使います。新規`Task`のIDはまだ入っていないのでそれで区別できます。以下のソースを`SaveTask`に入れましょう。
+```c#
+ if (item.ID == null) {
+     Document doc = _db.CreateDocument ();
+     doc.PutProperties (item.ToDictionary ());
+     item.ID = doc.Id;
+ } else {
+     Document doc = _db.GetDocument (item.ID);
+     doc.Update (newRevision => {
+          newRevision.SetUserProperties(item.ToDictionary());
+          return true;
+     });
+ }
+```
+- (5) 保存があれば削除も必要です。既存のドキュメントを求めてnullでない場合は`Delete`関数を呼ぶ簡単な行動です。以下を`DeleteTask`に入れましょう。
+```c#
+ var doc = _db.GetExistingDocument (task.ID);
+ if(doc != null) {
+     doc.Delete();
+ }
+```
+- (6A) UIに通知しなければデータの取得は無意味でしょう。Androidの場合はデータを表示する`ListView`の`Adapter`プロパティを指定することによって行います。このプロジェクトの`KitchenSyncListAdapter`クラスがその役割をします。すでに作ってありますので、作成さえすればよいです。`MainActivity`の`InitItemListAdapter`に以下を追加しましょう。
+```c#
+ _listAdapter = new KitchenSyncListAdapter(ApplicationContext, Resource.Layout.list_item, Resource.Id.label, new List<Task>());
+
+ _itemListView.Adapter = _listAdapter;
+```
+- (6B) iOSの場合は似ています。Androidは`KitchenSyncListAdapter`と言えばiOSは`DataSource`クラスを使います。`DataSource`は`HomeScreenController`にあり、小さい変更で準備ができます(データが変わる際にテーブルビューを更新します)。`DataSource`の初期化にこれを入れましょう。
+```c#
+ taskMgr.TasksUpdated += (sender, e) => {
+     _rows = e;
+     controller.tableView.ReloadData();
+ };
+```
+- (7A) チェックボックスをトグルする方法を入れましょう。最も自然なやり方は`ListView`のタップで行うことでしょう。`OnItemClick`に以下を追加しましょう。
+```c#
+ Task task = _listAdapter.GetItem(position);
+ task.Checked = !task.Checked;
+ _taskMgr.SaveTask(task);
+```
+- (7B) iOSの方もタップでトグル処理をします。`TableViewDelegate`の`RowSelected`に以下を追加しましょう。  
+```c#
+ var task = _source.Tasks[indexPath.Row];
+ task.Checked = !task.Checked;
+ var manager = new TaskManager();
+ manager.SaveTask(task);
+```
+- (8A) 削除に関してはAndroidの場合は長押しが一番自然でしょう。`OnItemLongClick`に以下を追加しましょう。
+```c#
+ Task task = _listAdapter.GetItem(position);
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ AlertDialog alert = builder.SetTitle("Delete Item?").
+ SetMessage("Are you sure you want to delete \"" + task.Text + "\"?").
+ SetPositiveButton("Yes", (sender, e) => _taskMgr.DeleteTask(task)).
+ SetNegativeButton("No", (sender, e) => {}).Create();
+
+ alert.Show();
+```
+- (8B) しかしiOSに関してはユーザーはスワイプで削除処理を行うように慣れているでしょう。`DataSource`の`CommitEditingStyle`に以下を追加しましょう。
+```c#
+ if (editingStyle == UITableViewCellEditingStyle.Delete) {
+     taskMgr.DeleteTask (_rows[indexPath.Row]);
+ }
+```
+- 端末で実行してみましょう。リストの項目が保存されるはずです。
+- (9A) 同期を追加しましょう!MainActivityの上側に同期のURLを定義しま す。端末で行っている場合はパソコンのWi-Fi IPアドレスを使います(つまりlocalhost>ではない)。エミュレーターを使っている場合はlocalhostが10.0.2.2になります。以下を`MainActivity`に追加しましょう。
+```c#
+private const string SYNC_URL = "http://<YOUR_WIFI_OR_ETHERNET_IP>:4984/kitchen-sync";
+```
+- (9B) 同期を追加しましょう!一旦AppDelegate.mに戻って、上側に同期のURLを定義します。端末で行っている場合はパソコンのWi-Fi IPアドレスを使います(つまりlocalhostではない)。シミュレーターを使っている場合はlocalhostでも大丈夫です。以下を`HomeScreenController`に追加しましょう。
+```c#
+private const string SYNC_URL = "http://<YOUR_WIFI_OR_ETHERNET_IP>:4984/kitchen-sync";
+```
+- (10) 一番難しいところが無事に済みました。継続的にローカルとリモートの変更を同期するStartSync関数を入れましょう
+```c#
+Uri uri;
+ try {
+     uri = new Uri(syncUrl);
+ } catch(UriFormatException) {
+     Log.E("TaskManager", "Invalid URL {0}", syncUrl);
+     return;
+ }
+
+ if(_pull == null) {
+     _pull = _db.CreatePullReplication(uri);
+     _pull.Continuous = true;
+     _pull.Start();
+ }
+
+ if(_push == null) {
+     _push = _db.CreatePushReplication(uri);
+     _push.Continuous = true;
+     _push.Start();
+ }
+```
+- (11A) 後は呼び出すだけです。`MainActivity`の`OnCreate`に以下を追加しましょう。
+```c#
+ _taskMgr.StartSync(SYNC_URL);
+```
+- (11B) そして`HomeScreenController`の`ViewDidLoad`にも。
+```c#
+ _taskMgr.StartSync(SYNC_URL);
+```
+- (12) 実行しましょう!アイテムを追加するか、チェックボックスを変更する際にコンソールにログが見れるはずです。アイテムがリストに追加されていることを確認しましょう。
+- (13) Sync Gateway管理者コンソールで結果を見てみましょう。ブラウザーで[http://localhost:4985/_admin/](http://localhost:4985/_admin/)を開いて[kitchen-sync](http://localhost:4985/_admin/db/kitchen-sync)リンクを押します。**Documents**ページが出>てきて、全てのドキュメントをリストアップします。ドキュメントのIDを押すとそのドキ
+ュメントの詳細を見ることができます。
+- (14) 最後に、皆さんのご意見をお伺いしたいです。 [アンケートにご協力をお願いします
+](http://goo.gl/forms/AH8sIlFOiO)!

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/architecture.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/cellaccessory.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/detail.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/solutionpad.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/storyboard.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/taskdone_xap.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/tasky_xap.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/images/taskysim.png


+ 39 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSync.sln

@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "KitchenSyncShared", "KitchenSyncShared\KitchenSyncShared.shproj", "{93C9720C-7E4C-4A75-AD01-4F50CA100E25}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitchenSyncAndroid", "KitchenSyncAndroid\KitchenSyncAndroid.csproj", "{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitchenSyncIos", "KitchenSynciOS\KitchenSyncIos.csproj", "{08FAE550-E302-4022-A871-17E0462E99F3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Debug|iPhone = Debug|iPhone
+		Release|iPhone = Release|iPhone
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhone.ActiveCfg = Debug|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhone.Build.0 = Debug|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|iPhone.ActiveCfg = Release|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|iPhone.Build.0 = Release|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+	EndGlobalSection
+EndGlobal

+ 21 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSync.userprefs

@@ -0,0 +1,21 @@
+<Properties StartupItem="KitchenSyncAndroid/KitchenSyncAndroid.csproj">
+  <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" PreferredExecutionTarget="Android.Lollipop" />
+  <MonoDevelop.Ide.Workbench ActiveDocument="KitchenSynciOS/packages.config">
+    <Files>
+      <File FileName="KitchenSynciOS/packages.config" Line="1" Column="1" />
+    </Files>
+    <Pads>
+      <Pad Id="ProjectPad">
+        <State name="__root__">
+          <Node name="KitchenSync" expanded="True">
+            <Node name="KitchenSyncAndroid" selected="True" />
+          </Node>
+        </State>
+      </Pad>
+    </Pads>
+  </MonoDevelop.Ide.Workbench>
+  <MonoDevelop.Ide.DebuggingService.Breakpoints>
+    <BreakpointStore />
+  </MonoDevelop.Ide.DebuggingService.Breakpoints>
+  <MonoDevelop.Ide.DebuggingService.PinnedWatches />
+</Properties>

+ 19 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Assets/AboutAssets.txt

@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with your package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+	protected override void OnCreate (Bundle bundle)
+	{
+		base.OnCreate (bundle);
+
+		InputStream input = Assets.Open ("my_asset.txt");
+	}
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");

+ 80 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/KitchenSyncAndroid.csproj

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>KitchenSyncAndroid</RootNamespace>
+    <MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
+    <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
+    <AndroidResgenClass>Resource</AndroidResgenClass>
+    <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
+    <AndroidApplication>True</AndroidApplication>
+    <AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
+    <AssemblyName>TaskyAndroid</AssemblyName>
+    <TargetFrameworkVersion>v4.4</TargetFrameworkVersion>
+    <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidLinkMode>None</AndroidLinkMode>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="Mono.Android" />
+    <Reference Include="SQLitePCL.raw">
+      <HintPath>..\packages\SQLitePCL.raw_basic.0.7.1\lib\MonoAndroid\SQLitePCL.raw.dll</HintPath>
+    </Reference>
+    <Reference Include="SQLitePCL.ugly">
+      <HintPath>..\packages\SQLitePCL.ugly.0.7.1\lib\portable-net45+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCL.ugly.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Couchbase.Lite">
+      <HintPath>..\packages\Couchbase.Lite.1.0.4.1\lib\MonoAndroid\Couchbase.Lite.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Resources\Resource.designer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="MainActivity.cs" />
+    <Compile Include="KitchenSyncListAdapter.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\AboutResources.txt" />
+    <None Include="Assets\AboutAssets.txt" />
+    <None Include="Properties\AndroidManifest.xml" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\values\Strings.xml" />
+    <AndroidResource Include="Resources\drawable\Icon.png" />
+    <AndroidResource Include="Resources\layout\main.xml" />
+    <AndroidResource Include="Resources\layout\list_item.xml" />
+  </ItemGroup>
+  <Import Project="..\KitchenSyncShared\TaskyShared.projitems" Label="Shared" Condition="Exists('..\KitchenSyncShared\TaskyShared.projitems')" />
+  <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
+</Project>

+ 45 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/KitchenSyncListAdapter.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+
+using Android.Content;
+using Android.Graphics;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+
+using KitchenSyncShared;
+
+namespace KitchenSyncAndroid {
+    public class KitchenSyncListAdapter : ArrayAdapter<Task> {
+		public KitchenSyncListAdapter (Context context, int resource, int textViewResourceId, IList<Task> tasks) :
+        base(context, resource, textViewResourceId, tasks)
+		{
+		}
+		
+		public override View GetView (int position, View convertView, ViewGroup parent)
+		{
+            if(convertView == null) {
+                LayoutInflater vi = (LayoutInflater)parent.Context.GetSystemService(Android.Content.Context.LayoutInflaterService);
+                convertView = vi.Inflate(Resource.Layout.list_item, null);
+            }
+
+            Task task;
+            try {
+                TextView label = convertView.FindViewById<TextView>(Resource.Id.label);
+                task = GetItem(position);
+                if(task == null) {
+                    return convertView;
+                }
+
+                label.Text = task.Text;
+                label.SetTextColor(Color.White);
+                CheckBox checkbox = convertView.FindViewById<CheckBox>(Resource.Id.item_checked);
+                checkbox.Checked = task.Checked;
+            } catch(Exception e) {
+                Log.Error("KitchenSyncListAdapter", "Error {0}", e);
+            }
+			
+            return convertView;
+		}
+	}
+}

+ 109 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/MainActivity.cs

@@ -0,0 +1,109 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using Android.App;
+using Android.OS;
+using Android.Views;
+using Android.Widget;
+
+using KitchenSyncShared;
+
+namespace KitchenSyncAndroid {
+   
+	[Activity (Label = "KitchenSync", MainLauncher = true, Icon="@drawable/icon")]			
+    public class MainActivity : Activity, View.IOnKeyListener, AdapterView.IOnItemClickListener, 
+            AdapterView.IOnItemLongClickListener {
+        
+		private KitchenSyncListAdapter _listAdapter;
+		private ListView _itemListView;
+        private EditText _addItemEditText;
+        private readonly TaskManager _taskMgr = new TaskManager ();
+        private const string SYNC_URL = "http://192.168.11.2:4984/kitchen-sync";
+
+        private void InitItemListAdapter()
+        {
+            _listAdapter = new KitchenSyncListAdapter(ApplicationContext, Resource.Layout.list_item, 
+                Resource.Id.label, new List<Task>());
+
+            _itemListView.Adapter = _listAdapter;
+        }
+
+        private Task CreateNewListItem(string text)
+        {
+            var task = new Task() { 
+                Text = text, 
+                Checked = false, 
+                CreationDate = DateTime.UtcNow 
+            };
+
+            var taskManager = new TaskManager();
+            taskManager.SaveTask(task);
+
+            return task;
+        }
+
+		protected override void OnCreate (Bundle savedInstanceState)
+		{
+			base.OnCreate (savedInstanceState);
+            SetContentView(Resource.Layout.main);
+
+            _itemListView = FindViewById<ListView>(Resource.Id.itemListView);
+            _itemListView.OnItemClickListener = this;
+            _itemListView.OnItemLongClickListener = this;
+
+            _addItemEditText = FindViewById<EditText>(Resource.Id.newItemText);
+            _addItemEditText.SetOnKeyListener(this);
+            _addItemEditText.RequestFocus();
+
+            InitItemListAdapter();
+            _taskMgr.TasksUpdated += (sender, e) => {
+                _listAdapter.Clear();
+                _listAdapter.AddAll((ICollection)e);
+                _listAdapter.NotifyDataSetChanged();
+            };
+
+            _taskMgr.StartSync(SYNC_URL);
+		}
+
+        public bool OnKey(View v, Keycode keyCode, KeyEvent e)
+        {
+            if(e.Action == KeyEventActions.Down && keyCode == Keycode.Enter) {
+                if(_addItemEditText.Text.Length == 0) {
+                    return true;
+                }
+
+                string inputText = _addItemEditText.Text;
+                CreateNewListItem(inputText);
+                Toast.MakeText(ApplicationContext, "Created new list item!", ToastLength.Long);
+                _addItemEditText.Text = "";
+
+                return true;
+            }
+
+            return false;
+        }
+
+        public void OnItemClick(AdapterView parent, View view, int position, long id)
+        {
+            Task task = _listAdapter.GetItem(position);
+            task.Checked = !task.Checked;
+            _taskMgr.SaveTask(task);
+        }
+
+        public bool OnItemLongClick(AdapterView parent, View view, int position, long id)
+        {
+            Task task = _listAdapter.GetItem(position);
+
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            AlertDialog alert = builder.SetTitle("Delete Item?").
+                SetMessage("Are you sure you want to delete \"" + task.Text + "\"?").
+                SetPositiveButton("Yes", (sender, e) => _taskMgr.DeleteTask(task)).
+                SetNegativeButton("No", (sender, e) => {}).Create();
+
+            alert.Show();
+
+            return true;
+        }
+	}
+}

+ 6 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Properties/AndroidManifest.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="TaskyAndroid.TaskyAndroid">
+	<uses-sdk />
+	<application android:label="TaskyAndroid">
+	</application>
+</manifest>

+ 28 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Properties/AssemblyInfo.cs

@@ -0,0 +1,28 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Android.App;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle ("TaskyAndroid")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("")]
+[assembly: AssemblyCopyright ("mike_bluestein")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion ("1.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+

+ 44 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/AboutResources.txt

@@ -0,0 +1,44 @@
+Images, layout descriptions, binary blobs and string dictionaries can be included 
+in your application as resource files.  Various Android APIs are designed to 
+operate on the resource IDs instead of dealing with images, strings or binary blobs 
+directly.
+
+For example, a sample Android app that contains a user interface layout (main.axml),
+an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 
+would keep its resources in the "Resources" directory of the application:
+
+Resources/
+    drawable/
+        icon.png
+
+    layout/
+        main.axml
+
+    values/
+        strings.xml
+
+In order to get the build system to recognize Android resources, set the build action to
+"AndroidResource".  The native Android APIs do not operate directly with filenames, but 
+instead operate on resource IDs.  When you compile an Android application that uses resources, 
+the build system will package the resources for distribution and generate a class called "R" 
+(this is an Android convention) that contains the tokens for each one of the resources 
+included. For example, for the above Resources layout, this is what the R class would expose:
+
+public class R {
+    public class drawable {
+        public const int icon = 0x123;
+    }
+
+    public class layout {
+        public const int main = 0x456;
+    }
+
+    public class strings {
+        public const int first_string = 0xabc;
+        public const int second_string = 0xbcd;
+    }
+}
+
+You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 
+to reference the layout/main.axml file, or R.strings.first_string to reference the first 
+string in the dictionary file values/strings.xml.

+ 131 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/Resource.designer.cs

@@ -0,0 +1,131 @@
+#pragma warning disable 1591
+// ------------------------------------------------------------------------------
+//  <autogenerated>
+//      This code was generated by a tool.
+//      Mono Runtime Version: 4.0.30319.17020
+// 
+//      Changes to this file may cause incorrect behavior and will be lost if 
+//      the code is regenerated.
+//  </autogenerated>
+// ------------------------------------------------------------------------------
+
+[assembly: Android.Runtime.ResourceDesignerAttribute("KitchenSyncAndroid.Resource", IsApplication=true)]
+
+namespace KitchenSyncAndroid
+{
+	
+	
+	[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
+	public partial class Resource
+	{
+		
+		static Resource()
+		{
+			global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+		}
+		
+		public static void UpdateIdValues()
+		{
+			global::Couchbase.Lite.Android.Resource.String.library_name = global::KitchenSyncAndroid.Resource.String.library_name;
+		}
+		
+		public partial class Attribute
+		{
+			
+			static Attribute()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Attribute()
+			{
+			}
+		}
+		
+		public partial class Drawable
+		{
+			
+			// aapt resource value: 0x7f020000
+			public const int Icon = 2130837504;
+			
+			static Drawable()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Drawable()
+			{
+			}
+		}
+		
+		public partial class Id
+		{
+			
+			// aapt resource value: 0x7f050003
+			public const int itemListView = 2131034115;
+			
+			// aapt resource value: 0x7f050000
+			public const int item_checked = 2131034112;
+			
+			// aapt resource value: 0x7f050001
+			public const int label = 2131034113;
+			
+			// aapt resource value: 0x7f050002
+			public const int newItemText = 2131034114;
+			
+			static Id()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Id()
+			{
+			}
+		}
+		
+		public partial class Layout
+		{
+			
+			// aapt resource value: 0x7f030000
+			public const int list_item = 2130903040;
+			
+			// aapt resource value: 0x7f030001
+			public const int main = 2130903041;
+			
+			static Layout()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Layout()
+			{
+			}
+		}
+		
+		public partial class String
+		{
+			
+			// aapt resource value: 0x7f040003
+			public const int action_settings = 2130968579;
+			
+			// aapt resource value: 0x7f040002
+			public const int add_item_hint = 2130968578;
+			
+			// aapt resource value: 0x7f040001
+			public const int app_name = 2130968577;
+			
+			// aapt resource value: 0x7f040000
+			public const int library_name = 2130968576;
+			
+			static String()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private String()
+			{
+			}
+		}
+	}
+}
+#pragma warning restore 1591

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/drawable/icon.png


+ 17 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/layout/list_item.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
+
+        <CheckBox android:focusable="false"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginTop="15dp" android:layout_marginBottom="15dp"
+            android:id="@+id/item_checked"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent" android:id="@+id/label"
+            android:layout_marginLeft="5dp"
+            android:textSize="15dp" android:gravity="center_vertical" android:textColor="#000000" android:singleLine="true"
+            />
+
+</LinearLayout>

+ 15 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/layout/main.xml

@@ -0,0 +1,15 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
+    android:paddingTop="16dp"
+    android:paddingBottom="0dp"
+    android:orientation="vertical"
+    tools:context=".ListActivity">
+
+    <EditText android:id="@+id/newItemText" android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_margin="10dp" android:maxLines="1" android:hint="@string/add_item_hint" android:textSize="15dp" android:inputType="text" />
+    <ListView android:id="@+id/itemListView" android:layout_width="fill_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:listSelector="#00000000" android:cacheColorHint="#00000000"></ListView>
+
+</LinearLayout>

+ 6 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/Resources/values/Strings.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+	<string name="app_name">KitchenSync</string>
+  <string name="add_item_hint">Enter new item.</string>
+  <string name="action_settings">Settings</string>
+</resources>

+ 7 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncAndroid/packages.config

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Couchbase.Lite" version="1.0.4.1" targetFramework="MonoAndroid44" />
+  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="MonoAndroid44" />
+  <package id="SQLitePCL.raw_basic" version="0.7.1" targetFramework="MonoAndroid44" />
+  <package id="SQLitePCL.ugly" version="0.7.1" targetFramework="MonoAndroid44" />
+</packages>

+ 11 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/KitchenSyncShared.shproj

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectGuid>{93C9720C-7E4C-4A75-AD01-4F50CA100E25}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <Import Project="TaskyShared.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 51 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/Task.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+
+using Couchbase.Lite.Util;
+
+namespace KitchenSyncShared
+{
+    public class Task
+    {
+        private const string TAG = "Task";
+
+        public string ID { get; set; }
+
+        public string Text { get; set; }
+
+        public bool Checked { get; set; }
+
+        public DateTime CreationDate { get; set; }
+
+        public static Task FromDictionary(IDictionary<string, object> properties)
+        {
+            Task t = new Task();
+            try {
+                t.ID = properties["_id"] as string;
+                t.Text = properties["text"] as string;
+                t.Checked = (bool)properties["checked"];
+                t.CreationDate = (DateTime)properties["created_at"];
+            } catch(KeyNotFoundException) {
+                Log.E(TAG, "Invalid dictionary passed to FromDictionary");
+                return null;
+            } catch(InvalidCastException) {
+                Log.E(TAG, "Dictionary contains invalid value(s)");
+                return null;
+            }
+
+            return t;
+        }
+
+        public Dictionary<string, object> ToDictionary()
+        {
+            var d = new Dictionary<string, object>
+            {
+                {"text", Text},
+                {"created_at", CreationDate},
+                {"checked", Checked},
+            };
+
+            return d;
+        }
+    }
+}

+ 89 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/TaskManager.cs

@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Couchbase.Lite;
+using Couchbase.Lite.Util;
+
+namespace KitchenSyncShared
+{
+    public class TaskManager
+    {
+        private readonly Database _db;
+        private readonly LiveQuery _query;
+        private Replication _pull;
+        private Replication _push;
+
+        public event EventHandler<IList<Task>> TasksUpdated;
+
+        public TaskManager ()
+        {
+            _db = Manager.SharedInstance.GetDatabase("kitchen-sync");
+            View view = _db.GetView("viewItemsByDate");
+            view.SetMap((doc, emit) => {
+                if(doc.ContainsKey("created_at") && doc["created_at"] is DateTime) {
+                    emit(doc["created_at"], null);
+                }
+            }, "1");
+
+            _query = view.CreateQuery().ToLiveQuery();
+            _query.Descending = true;
+            _query.Changed += (sender, e) => {
+                if(TasksUpdated != null) {
+                    var tasks = from row in e.Rows
+                        select Task.FromDictionary(row.Document.Properties);
+                    TasksUpdated(this, tasks.ToList());
+                }
+            };
+
+            _query.Start();
+        }
+
+        public void StartSync(string syncUrl)
+        {
+            Uri uri;
+            try {
+                uri = new Uri(syncUrl);
+            } catch(UriFormatException) {
+                Log.E("TaskManager", "Invalid URL {0}", syncUrl);
+                return;
+            }
+
+            if(_pull == null) {
+                _pull = _db.CreatePullReplication(uri);
+                _pull.Continuous = true;
+                _pull.Start();
+            }
+
+            if(_push == null) {
+                _push = _db.CreatePushReplication(uri);
+                _push.Continuous = true;
+                _push.Start();
+            }
+        }
+
+        public void SaveTask (Task item)
+        {
+            if (item.ID == null) {
+                Document doc = _db.CreateDocument ();
+                doc.PutProperties (item.ToDictionary ());
+                item.ID = doc.Id;
+            } else {
+                Document doc = _db.GetDocument (item.ID);
+                doc.Update (newRevision => {
+                    newRevision.SetUserProperties(item.ToDictionary());
+                    return true;
+                });
+            }
+        }
+
+        public void DeleteTask (Task task)
+        {
+            var doc = _db.GetExistingDocument (task.ID);
+            if(doc != null) {
+                doc.Delete();
+            }
+        }
+
+    }
+}

+ 15 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSyncShared/TaskyShared.projitems

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>{93C9720C-7E4C-4A75-AD01-4F50CA100E25}</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>KitchenSyncShared</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Task.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TaskManager.cs" />
+  </ItemGroup>
+</Project>

+ 11 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/AppDelegate.cs

@@ -0,0 +1,11 @@
+using Foundation;
+using UIKit;
+
+namespace KitchenSyncIos {
+
+    [Register ("AppDelegate")]
+    public partial class AppDelegate : UIApplicationDelegate
+    {
+        public override UIWindow Window { get; set; }
+    }
+}

+ 95 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/HomeScreen.storyboard

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C1510" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="oSP-RS-uRz">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+    </dependencies>
+    <scenes>
+        <!--Kitchen Sync-->
+        <scene sceneID="ufC-wZ-h7g">
+            <objects>
+                <viewController id="vXZ-lx-hvc" customClass="HomeScreenController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
+                        <viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <subviews>
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="7WH-uJ-7lN">
+                                <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="600" id="22"/>
+                                    <constraint firstAttribute="height" constant="600" id="23"/>
+                                </constraints>
+                                <view key="tableHeaderView" contentMode="scaleToFill" id="3rr-Gp-MjW">
+                                    <rect key="frame" x="0.0" y="0.0" width="600" height="64"/>
+                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                    <subviews>
+                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="New Item" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="70f-1n-86l">
+                                            <rect key="frame" x="10" y="17" width="580" height="30"/>
+                                            <constraints>
+                                                <constraint firstAttribute="height" constant="30" id="g3Z-Kr-7af"/>
+                                            </constraints>
+                                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                            <textInputTraits key="textInputTraits"/>
+                                            <connections>
+                                                <outlet property="delegate" destination="vXZ-lx-hvc" id="UfV-ju-cGf"/>
+                                            </connections>
+                                        </textField>
+                                    </subviews>
+                                    <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+                                    <constraints>
+                                        <constraint firstItem="70f-1n-86l" firstAttribute="leading" secondItem="3rr-Gp-MjW" secondAttribute="leading" constant="10" id="9m9-E7-0dM"/>
+                                        <constraint firstAttribute="centerY" secondItem="70f-1n-86l" secondAttribute="centerY" id="cFB-Q1-M4z"/>
+                                        <constraint firstAttribute="trailing" secondItem="70f-1n-86l" secondAttribute="trailing" constant="10" id="emt-sT-309"/>
+                                    </constraints>
+                                </view>
+                                <variation key="default">
+                                    <mask key="constraints">
+                                        <exclude reference="22"/>
+                                        <exclude reference="23"/>
+                                    </mask>
+                                </variation>
+                            </tableView>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" secondItem="7WH-uJ-7lN" secondAttribute="trailing" id="24"/>
+                            <constraint firstAttribute="bottom" secondItem="7WH-uJ-7lN" secondAttribute="bottom" id="25"/>
+                            <constraint firstItem="7WH-uJ-7lN" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" constant="-64" id="9W2-Yn-9Uv"/>
+                            <constraint firstItem="7WH-uJ-7lN" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="eCW-fR-KjE"/>
+                            <constraint firstAttribute="trailing" secondItem="7WH-uJ-7lN" secondAttribute="trailing" id="yz1-LD-9tL"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="Kitchen Sync" id="i0N-DT-gP2"/>
+                    <connections>
+                        <outlet property="tableView" destination="7WH-uJ-7lN" id="name-outlet-7WH-uJ-7lN"/>
+                        <outlet property="textField" destination="70f-1n-86l" id="y9t-7H-tpU"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1094" y="1090"/>
+        </scene>
+        <!--Navigation Controller-->
+        <scene sceneID="6xC-sL-E1W">
+            <objects>
+                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="oSP-RS-uRz" sceneMemberID="viewController">
+                    <toolbarItems/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="Dvh-er-WzT">
+                        <rect key="frame" x="0.0" y="20" width="600" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="vXZ-lx-hvc" kind="relationship" relationship="rootViewController" id="gDM-an-5Bh"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Wxo-cX-hOJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="202" y="1090"/>
+        </scene>
+    </scenes>
+</document>

+ 125 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/HomeScreenController.cs

@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+
+using Foundation;
+using UIKit;
+
+using KitchenSyncShared;
+
+namespace KitchenSyncIos
+{
+    partial class HomeScreenController : UIViewController
+    {
+        private DataSource _source;
+        private readonly TaskManager _taskMgr = new TaskManager();
+        private const string SYNC_URL = "http://localhost:4984/kitchen-sync";
+
+        public HomeScreenController (IntPtr handle) : base (handle)
+        {
+        }
+
+        public override void ViewDidLoad ()
+        {
+            base.ViewDidLoad();
+
+            Title = "KitchenSync";
+
+            tableView.Source = _source = new DataSource(this);
+            textField.Delegate = new TextFieldDelegate();
+            tableView.Delegate = new TableViewDelegate(_source);
+
+            _taskMgr.StartSync(SYNC_URL);
+        }
+
+        class TableViewDelegate : UITableViewDelegate 
+        {
+            private readonly DataSource _source;
+
+            public TableViewDelegate(DataSource dataSource)
+            {
+                _source = dataSource;
+            }
+
+            public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
+            {
+                var task = _source.Tasks[indexPath.Row];
+                task.Checked = !task.Checked;
+                var manager = new TaskManager();
+                manager.SaveTask(task);
+            }
+        }
+            
+        class TextFieldDelegate : UITextFieldDelegate
+        {
+            public override bool ShouldReturn(UITextField textField)
+            {
+                textField.ResignFirstResponder();
+                return textField.Text.Length > 0;
+            }
+
+            public override void EditingEnded(UITextField textField)
+            {
+                if(textField.Text.Length == 0) {
+                    return;
+                }
+
+                var task = new Task() { 
+                    Text = textField.Text, 
+                    Checked = false, 
+                    CreationDate = DateTime.UtcNow 
+                };
+
+                var taskManager = new TaskManager();
+                taskManager.SaveTask(task);
+            }
+        }
+
+        class DataSource : UITableViewSource
+        {
+            static readonly NSString CellIdentifier = new NSString ("TaskCell");
+            private readonly HomeScreenController controller;
+            private IList<Task> _rows;
+            private readonly TaskManager taskMgr = new TaskManager ();
+
+            public IList<Task> Tasks
+            {
+                get { return _rows; }
+            }
+
+            public DataSource (HomeScreenController controller)
+            {
+                this.controller = controller;
+                taskMgr.TasksUpdated += (sender, e) => {
+                    _rows = e;
+                    controller.tableView.ReloadData();
+                };
+            }
+
+            public override nint RowsInSection (UITableView tableview, nint section)
+            {
+                return _rows == null ? 0 : _rows.Count;
+            }
+
+            public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
+            {
+                var cell = tableView.DequeueReusableCell (CellIdentifier);
+                if(cell == null) {
+                    cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
+                }
+                var task = _rows[indexPath.Row];
+                cell.TextLabel.Text = task.Text;
+                cell.Accessory = task.Checked ? UITableViewCellAccessory.Checkmark : UITableViewCellAccessory.None;
+
+                return cell;
+            }
+
+            public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath)
+            {
+                if (editingStyle == UITableViewCellEditingStyle.Delete) {
+                    taskMgr.DeleteTask (_rows[indexPath.Row]);
+                }
+            }
+        }
+            
+    }
+}

+ 37 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/HomeScreenController.designer.cs

@@ -0,0 +1,37 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio from the outlets and
+// actions declared in your storyboard file.
+// Manual changes to this file will not be maintained.
+//
+using Foundation;
+using UIKit;
+using System;
+using System.CodeDom.Compiler;
+
+namespace KitchenSyncIos
+{
+	[Register ("HomeScreenController")]
+	partial class HomeScreenController
+	{
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITableView tableView { get; set; }
+
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITextField textField { get; set; }
+
+		void ReleaseDesignerOutlets ()
+		{
+			if (tableView != null) {
+				tableView.Dispose ();
+				tableView = null;
+			}
+			if (textField != null) {
+				textField.Dispose ();
+				textField = null;
+			}
+		}
+	}
+}

+ 35 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Info.plist

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDisplayName</key>
+	<string>Tasky</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>Icon-60@2x</string>
+		<string>Icon-Small-40@2x</string>
+		<string>Icon@2x</string>
+		<string>Icon</string>
+		<string>Icon-Small</string>
+		<string>Icon-Small@2x</string>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>UIDeviceFamily</key>
+	<array>
+		<integer>1</integer>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>com.xamarin.tasky</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>MinimumOSVersion</key>
+	<string>8.1</string>
+	<key>UIMainStoryboardFile</key>
+	<string>HomeScreen</string>
+</dict>
+</plist>

+ 119 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/KitchenSyncIos.csproj

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{08FAE550-E302-4022-A871-17E0462E99F3}</ProjectGuid>
+    <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>KitchenSyncIos</RootNamespace>
+    <AssemblyName>Tasky</AssemblyName>
+    <TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
+    <TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+    <MtouchDebug>True</MtouchDebug>
+    <MtouchI18n>
+    </MtouchI18n>
+    <MtouchArch>i386</MtouchArch>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+    <DebugType>none</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhone\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchDebug>True</MtouchDebug>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <IpaPackageName>
+    </IpaPackageName>
+    <MtouchArch>ARMv7</MtouchArch>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhone\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <MtouchArch>ARMv7, ARM64</MtouchArch>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="Xamarin.iOS" />
+    <Reference Include="SQLitePCL.raw">
+      <HintPath>..\packages\SQLitePCL.raw_basic.0.7.1\lib\Xamarin.iOS10\SQLitePCL.raw.dll</HintPath>
+    </Reference>
+    <Reference Include="SQLitePCL.ugly">
+      <HintPath>..\packages\SQLitePCL.ugly.0.7.1\lib\portable-net45+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCL.ugly.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Couchbase.Lite">
+      <HintPath>..\packages\Couchbase.Lite.1.0.4.1\lib\xamarinios10\Couchbase.Lite.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="AppDelegate.cs" />
+    <Compile Include="HomeScreenController.cs" />
+    <Compile Include="HomeScreenController.designer.cs">
+      <DependentUpon>HomeScreenController.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <Import Project="..\KitchenSyncShared\TaskyShared.projitems" Label="Shared" Condition="Exists('..\KitchenSyncShared\TaskyShared.projitems')" />
+  <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+  <ItemGroup>
+    <Folder Include="Resources\" />
+  </ItemGroup>
+  <ItemGroup>
+    <BundleResource Include="Resources\Icon-60%402x.png" />
+    <BundleResource Include="Resources\Icon-Small-40%402x.png" />
+    <BundleResource Include="Resources\Default-568h%402x.png" />
+    <BundleResource Include="Resources\Default%402x.png" />
+    <BundleResource Include="Resources\Icon%402x.png" />
+    <BundleResource Include="Resources\Icon.png" />
+    <BundleResource Include="Resources\Icon-Small.png" />
+    <BundleResource Include="Resources\Icon-Small%402x.png" />
+    <BundleResource Include="Resources\Default.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <ITunesArtwork Include="iTunesArtwork%402x" />
+    <ITunesArtwork Include="iTunesArtwork" />
+  </ItemGroup>
+  <ItemGroup>
+    <InterfaceDefinition Include="HomeScreen.storyboard" />
+  </ItemGroup>
+</Project>

+ 13 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Main.cs

@@ -0,0 +1,13 @@
+using UIKit;
+
+namespace KitchenSyncIos {
+	public class Application {
+		// This is the main entry point of the application.
+		static void Main (string[] args)
+		{
+			// if you want to use a different Application Delegate class from "AppDelegate"
+			// you can specify it here.
+			UIApplication.Main (args, null, "AppDelegate");
+		}
+	}
+}

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Default-568h@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Default.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Default@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-60@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-Small-40@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-Small.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon-Small@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/Resources/Icon@2x.png


+ 16 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/ViewController.cs

@@ -0,0 +1,16 @@
+// This file has been autogenerated from a class added in the UI designer.
+
+using System;
+
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+
+namespace Tasky
+{
+	public partial class ViewController : UIViewController
+	{
+		public ViewController (IntPtr handle) : base (handle)
+		{
+		}
+	}
+}

+ 45 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/ViewController.designer.cs

@@ -0,0 +1,45 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio from the outlets and
+// actions declared in your storyboard file.
+// Manual changes to this file will not be maintained.
+//
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+using System;
+using System.CodeDom.Compiler;
+
+namespace Tasky
+{
+	[Register ("ViewController")]
+	partial class ViewController
+	{
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITableView tableView { get; set; }
+
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITextField textField { get; set; }
+
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UIView textField { get; set; }
+
+		void ReleaseDesignerOutlets ()
+		{
+			if (tableView != null) {
+				tableView.Dispose ();
+				tableView = null;
+			}
+			if (textField != null) {
+				textField.Dispose ();
+				textField = null;
+			}
+			if (textField != null) {
+				textField.Dispose ();
+				textField = null;
+			}
+		}
+	}
+}

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/iTunesArtwork


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/iTunesArtwork@2x


+ 7 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/complete/KitchenSynciOS/packages.config

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Couchbase.Lite" version="1.0.4.1" targetFramework="xamarinios10" />
+  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="xamarinios10" />
+  <package id="SQLitePCL.raw_basic" version="0.7.1" targetFramework="xamarinios10" />
+  <package id="SQLitePCL.ugly" version="0.7.1" targetFramework="xamarinios10" />
+</packages>

+ 39 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSync.sln

@@ -0,0 +1,39 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "KitchenSyncShared", "KitchenSyncShared\KitchenSyncShared.shproj", "{93C9720C-7E4C-4A75-AD01-4F50CA100E25}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitchenSyncAndroid", "KitchenSyncAndroid\KitchenSyncAndroid.csproj", "{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KitchenSyncIos", "KitchenSynciOS\KitchenSyncIos.csproj", "{08FAE550-E302-4022-A871-17E0462E99F3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Debug|iPhone = Debug|iPhone
+		Release|iPhone = Release|iPhone
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhone.ActiveCfg = Debug|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhone.Build.0 = Debug|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|iPhone.ActiveCfg = Release|iPhone
+		{08FAE550-E302-4022-A871-17E0462E99F3}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|iPhone.Build.0 = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+	EndGlobalSection
+EndGlobal

+ 21 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSync.userprefs

@@ -0,0 +1,21 @@
+<Properties StartupItem="KitchenSyncAndroid/KitchenSyncAndroid.csproj">
+  <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" PreferredExecutionTarget="Android.Lollipop" />
+  <MonoDevelop.Ide.Workbench ActiveDocument="KitchenSyncAndroid/packages.config">
+    <Files>
+      <File FileName="KitchenSyncAndroid/packages.config" Line="1" Column="1" />
+    </Files>
+    <Pads>
+      <Pad Id="ProjectPad">
+        <State name="__root__">
+          <Node name="KitchenSync" expanded="True">
+            <Node name="KitchenSyncIos" selected="True" />
+          </Node>
+        </State>
+      </Pad>
+    </Pads>
+  </MonoDevelop.Ide.Workbench>
+  <MonoDevelop.Ide.DebuggingService.Breakpoints>
+    <BreakpointStore />
+  </MonoDevelop.Ide.DebuggingService.Breakpoints>
+  <MonoDevelop.Ide.DebuggingService.PinnedWatches />
+</Properties>

+ 19 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Assets/AboutAssets.txt

@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with your package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+	protected override void OnCreate (Bundle bundle)
+	{
+		base.OnCreate (bundle);
+
+		InputStream input = Assets.Open ("my_asset.txt");
+	}
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");

+ 80 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/KitchenSyncAndroid.csproj

@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{9CAFBA9D-40F7-464A-8E2A-1DAE969B3C3C}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>KitchenSyncAndroid</RootNamespace>
+    <MonoAndroidAssetsPrefix>Assets</MonoAndroidAssetsPrefix>
+    <MonoAndroidResourcePrefix>Resources</MonoAndroidResourcePrefix>
+    <AndroidResgenClass>Resource</AndroidResgenClass>
+    <AndroidResgenFile>Resources\Resource.designer.cs</AndroidResgenFile>
+    <AndroidApplication>True</AndroidApplication>
+    <AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
+    <AssemblyName>TaskyAndroid</AssemblyName>
+    <TargetFrameworkVersion>v4.4</TargetFrameworkVersion>
+    <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidLinkMode>None</AndroidLinkMode>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="Mono.Android" />
+    <Reference Include="SQLitePCL.raw">
+      <HintPath>..\packages\SQLitePCL.raw_basic.0.7.1\lib\MonoAndroid\SQLitePCL.raw.dll</HintPath>
+    </Reference>
+    <Reference Include="SQLitePCL.ugly">
+      <HintPath>..\packages\SQLitePCL.ugly.0.7.1\lib\portable-net45+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCL.ugly.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Couchbase.Lite">
+      <HintPath>..\packages\Couchbase.Lite.1.0.4.1\lib\MonoAndroid\Couchbase.Lite.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Resources\Resource.designer.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="MainActivity.cs" />
+    <Compile Include="KitchenSyncListAdapter.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\AboutResources.txt" />
+    <None Include="Assets\AboutAssets.txt" />
+    <None Include="Properties\AndroidManifest.xml" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <AndroidResource Include="Resources\values\Strings.xml" />
+    <AndroidResource Include="Resources\drawable\Icon.png" />
+    <AndroidResource Include="Resources\layout\main.xml" />
+    <AndroidResource Include="Resources\layout\list_item.xml" />
+  </ItemGroup>
+  <Import Project="..\KitchenSyncShared\TaskyShared.projitems" Label="Shared" Condition="Exists('..\KitchenSyncShared\TaskyShared.projitems')" />
+  <Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
+</Project>

+ 45 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/KitchenSyncListAdapter.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+
+using Android.Content;
+using Android.Graphics;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+
+using KitchenSyncShared;
+
+namespace KitchenSyncAndroid {
+    public class KitchenSyncListAdapter : ArrayAdapter<Task> {
+		public KitchenSyncListAdapter (Context context, int resource, int textViewResourceId, IList<Task> tasks) :
+        base(context, resource, textViewResourceId, tasks)
+		{
+		}
+		
+		public override View GetView (int position, View convertView, ViewGroup parent)
+		{
+            if(convertView == null) {
+                LayoutInflater vi = (LayoutInflater)parent.Context.GetSystemService(Android.Content.Context.LayoutInflaterService);
+                convertView = vi.Inflate(Resource.Layout.list_item, null);
+            }
+
+            Task task;
+            try {
+                TextView label = convertView.FindViewById<TextView>(Resource.Id.label);
+                task = GetItem(position);
+                if(task == null) {
+                    return convertView;
+                }
+
+                label.Text = task.Text;
+                label.SetTextColor(Color.White);
+                CheckBox checkbox = convertView.FindViewById<CheckBox>(Resource.Id.item_checked);
+                checkbox.Checked = task.Checked;
+            } catch(Exception e) {
+                Log.Error("KitchenSyncListAdapter", "Error {0}", e);
+            }
+			
+            return convertView;
+		}
+	}
+}

+ 97 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/MainActivity.cs

@@ -0,0 +1,97 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+using Android.App;
+using Android.OS;
+using Android.Views;
+using Android.Widget;
+
+using KitchenSyncShared;
+
+namespace KitchenSyncAndroid {
+   
+	[Activity (Label = "KitchenSync", MainLauncher = true, Icon="@drawable/icon")]			
+    public class MainActivity : Activity, View.IOnKeyListener, AdapterView.IOnItemClickListener, 
+            AdapterView.IOnItemLongClickListener {
+        
+		private KitchenSyncListAdapter _listAdapter;
+		private ListView _itemListView;
+        private EditText _addItemEditText;
+        private readonly TaskManager _taskMgr = new TaskManager ();
+
+        //Step 9A - Add sync URL
+
+        private void InitItemListAdapter()
+        {
+            //Step 6A - Setup data source for Android UI
+        }
+
+        private Task CreateNewListItem(string text)
+        {
+            var task = new Task() { 
+                Text = text, 
+                Checked = false, 
+                CreationDate = DateTime.UtcNow 
+            };
+
+            var taskManager = new TaskManager();
+            taskManager.SaveTask(task);
+
+            return task;
+        }
+
+		protected override void OnCreate (Bundle savedInstanceState)
+		{
+			base.OnCreate (savedInstanceState);
+            SetContentView(Resource.Layout.main);
+
+            _itemListView = FindViewById<ListView>(Resource.Id.itemListView);
+            _itemListView.OnItemClickListener = this;
+            _itemListView.OnItemLongClickListener = this;
+
+            _addItemEditText = FindViewById<EditText>(Resource.Id.newItemText);
+            _addItemEditText.SetOnKeyListener(this);
+            _addItemEditText.RequestFocus();
+
+            InitItemListAdapter();
+            _taskMgr.TasksUpdated += (sender, e) => {
+                _listAdapter.Clear();
+                _listAdapter.AddAll((ICollection)e);
+                _listAdapter.NotifyDataSetChanged();
+            };
+
+            //Step 11A - Start sync
+		}
+
+        public bool OnKey(View v, Keycode keyCode, KeyEvent e)
+        {
+            if(e.Action == KeyEventActions.Down && keyCode == Keycode.Enter) {
+                if(_addItemEditText.Text.Length == 0) {
+                    return true;
+                }
+
+                string inputText = _addItemEditText.Text;
+                CreateNewListItem(inputText);
+                Toast.MakeText(ApplicationContext, "Created new list item!", ToastLength.Long);
+                _addItemEditText.Text = "";
+
+                return true;
+            }
+
+            return false;
+        }
+
+        public void OnItemClick(AdapterView parent, View view, int position, long id)
+        {
+            //Step 7A - Handle checkbox toggling
+        }
+
+        public bool OnItemLongClick(AdapterView parent, View view, int position, long id)
+        {
+            //Step 8A - Handle UI long press (deletion)
+
+            return true;
+        }
+	}
+}

+ 6 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Properties/AndroidManifest.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="TaskyAndroid.TaskyAndroid">
+	<uses-sdk />
+	<application android:label="TaskyAndroid">
+	</application>
+</manifest>

+ 28 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Properties/AssemblyInfo.cs

@@ -0,0 +1,28 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Android.App;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle ("TaskyAndroid")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("")]
+[assembly: AssemblyCopyright ("mike_bluestein")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion ("1.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+

+ 44 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/AboutResources.txt

@@ -0,0 +1,44 @@
+Images, layout descriptions, binary blobs and string dictionaries can be included 
+in your application as resource files.  Various Android APIs are designed to 
+operate on the resource IDs instead of dealing with images, strings or binary blobs 
+directly.
+
+For example, a sample Android app that contains a user interface layout (main.axml),
+an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 
+would keep its resources in the "Resources" directory of the application:
+
+Resources/
+    drawable/
+        icon.png
+
+    layout/
+        main.axml
+
+    values/
+        strings.xml
+
+In order to get the build system to recognize Android resources, set the build action to
+"AndroidResource".  The native Android APIs do not operate directly with filenames, but 
+instead operate on resource IDs.  When you compile an Android application that uses resources, 
+the build system will package the resources for distribution and generate a class called "R" 
+(this is an Android convention) that contains the tokens for each one of the resources 
+included. For example, for the above Resources layout, this is what the R class would expose:
+
+public class R {
+    public class drawable {
+        public const int icon = 0x123;
+    }
+
+    public class layout {
+        public const int main = 0x456;
+    }
+
+    public class strings {
+        public const int first_string = 0xabc;
+        public const int second_string = 0xbcd;
+    }
+}
+
+You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 
+to reference the layout/main.axml file, or R.strings.first_string to reference the first 
+string in the dictionary file values/strings.xml.

+ 131 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/Resource.designer.cs

@@ -0,0 +1,131 @@
+#pragma warning disable 1591
+// ------------------------------------------------------------------------------
+//  <autogenerated>
+//      This code was generated by a tool.
+//      Mono Runtime Version: 4.0.30319.17020
+// 
+//      Changes to this file may cause incorrect behavior and will be lost if 
+//      the code is regenerated.
+//  </autogenerated>
+// ------------------------------------------------------------------------------
+
+[assembly: Android.Runtime.ResourceDesignerAttribute("KitchenSyncAndroid.Resource", IsApplication=true)]
+
+namespace KitchenSyncAndroid
+{
+	
+	
+	[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
+	public partial class Resource
+	{
+		
+		static Resource()
+		{
+			global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+		}
+		
+		public static void UpdateIdValues()
+		{
+			global::Couchbase.Lite.Android.Resource.String.library_name = global::KitchenSyncAndroid.Resource.String.library_name;
+		}
+		
+		public partial class Attribute
+		{
+			
+			static Attribute()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Attribute()
+			{
+			}
+		}
+		
+		public partial class Drawable
+		{
+			
+			// aapt resource value: 0x7f020000
+			public const int Icon = 2130837504;
+			
+			static Drawable()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Drawable()
+			{
+			}
+		}
+		
+		public partial class Id
+		{
+			
+			// aapt resource value: 0x7f050003
+			public const int itemListView = 2131034115;
+			
+			// aapt resource value: 0x7f050000
+			public const int item_checked = 2131034112;
+			
+			// aapt resource value: 0x7f050001
+			public const int label = 2131034113;
+			
+			// aapt resource value: 0x7f050002
+			public const int newItemText = 2131034114;
+			
+			static Id()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Id()
+			{
+			}
+		}
+		
+		public partial class Layout
+		{
+			
+			// aapt resource value: 0x7f030000
+			public const int list_item = 2130903040;
+			
+			// aapt resource value: 0x7f030001
+			public const int main = 2130903041;
+			
+			static Layout()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private Layout()
+			{
+			}
+		}
+		
+		public partial class String
+		{
+			
+			// aapt resource value: 0x7f040003
+			public const int action_settings = 2130968579;
+			
+			// aapt resource value: 0x7f040002
+			public const int add_item_hint = 2130968578;
+			
+			// aapt resource value: 0x7f040001
+			public const int app_name = 2130968577;
+			
+			// aapt resource value: 0x7f040000
+			public const int library_name = 2130968576;
+			
+			static String()
+			{
+				global::Android.Runtime.ResourceIdManager.UpdateIdValues();
+			}
+			
+			private String()
+			{
+			}
+		}
+	}
+}
+#pragma warning restore 1591

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/drawable/Icon.png


+ 17 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/layout/list_item.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal">
+
+        <CheckBox android:focusable="false"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginTop="15dp" android:layout_marginBottom="15dp"
+            android:id="@+id/item_checked"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent" android:id="@+id/label"
+            android:layout_marginLeft="5dp"
+            android:textSize="15dp" android:gravity="center_vertical" android:textColor="#000000" android:singleLine="true"
+            />
+
+</LinearLayout>

+ 15 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/layout/main.xml

@@ -0,0 +1,15 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="16dp"
+    android:paddingRight="16dp"
+    android:paddingTop="16dp"
+    android:paddingBottom="0dp"
+    android:orientation="vertical"
+    tools:context=".ListActivity">
+
+    <EditText android:id="@+id/newItemText" android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_margin="10dp" android:maxLines="1" android:hint="@string/add_item_hint" android:textSize="15dp" android:inputType="text" />
+    <ListView android:id="@+id/itemListView" android:layout_width="fill_parent" android:layout_height="match_parent" android:layout_margin="10dp" android:listSelector="#00000000" android:cacheColorHint="#00000000"></ListView>
+
+</LinearLayout>

+ 6 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/Resources/values/Strings.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+	<string name="app_name">KitchenSync</string>
+  <string name="add_item_hint">Enter new item.</string>
+  <string name="action_settings">Settings</string>
+</resources>

+ 7 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncAndroid/packages.config

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Couchbase.Lite" version="1.0.4.1" targetFramework="MonoAndroid44" />
+  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="MonoAndroid44" />
+  <package id="SQLitePCL.raw_basic" version="0.7.1" targetFramework="MonoAndroid44" />
+  <package id="SQLitePCL.ugly" version="0.7.1" targetFramework="MonoAndroid44" />
+</packages>

+ 11 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/KitchenSyncShared.shproj

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectGuid>{93C9720C-7E4C-4A75-AD01-4F50CA100E25}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <Import Project="TaskyShared.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>

+ 51 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/Task.cs

@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+
+using Couchbase.Lite.Util;
+
+namespace KitchenSyncShared
+{
+    public class Task
+    {
+        private const string TAG = "Task";
+
+        public string ID { get; set; }
+
+        public string Text { get; set; }
+
+        public bool Checked { get; set; }
+
+        public DateTime CreationDate { get; set; }
+
+        public static Task FromDictionary(IDictionary<string, object> properties)
+        {
+            Task t = new Task();
+            try {
+                t.ID = properties["_id"] as string;
+                t.Text = properties["text"] as string;
+                t.Checked = (bool)properties["checked"];
+                t.CreationDate = (DateTime)properties["created_at"];
+            } catch(KeyNotFoundException) {
+                Log.E(TAG, "Invalid dictionary passed to FromDictionary");
+                return null;
+            } catch(InvalidCastException) {
+                Log.E(TAG, "Dictionary contains invalid value(s)");
+                return null;
+            }
+
+            return t;
+        }
+
+        public Dictionary<string, object> ToDictionary()
+        {
+            var d = new Dictionary<string, object>
+            {
+                {"text", Text},
+                {"created_at", CreationDate},
+                {"checked", Checked},
+            };
+
+            return d;
+        }
+    }
+}

+ 43 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/TaskManager.cs

@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+
+using Couchbase.Lite;
+using Couchbase.Lite.Util;
+
+namespace KitchenSyncShared
+{
+    public class TaskManager
+    {
+        private readonly Database _db;
+        private readonly LiveQuery _query;
+        private Replication _pull;
+        private Replication _push;
+
+        public event EventHandler<IList<Task>> TasksUpdated;
+
+        public TaskManager ()
+        {
+            //Step 1 - Get reference to the database
+
+            //Step 2 - Setup view for querying
+
+            //Step 3 - Setup live query
+        }
+
+        public void StartSync(string syncUrl)
+        {
+            //Step 10 - Create sync objects
+        }
+            
+        public void SaveTask (Task item)
+        {
+            //Step 4 - Create save logic
+        }
+
+        public void DeleteTask (Task task)
+        {
+            //Step 5 - Create delete logic
+        }
+            
+    }
+}

+ 15 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSyncShared/TaskyShared.projitems

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>{93C9720C-7E4C-4A75-AD01-4F50CA100E25}</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>KitchenSyncShared</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)Task.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)TaskManager.cs" />
+  </ItemGroup>
+</Project>

+ 11 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/AppDelegate.cs

@@ -0,0 +1,11 @@
+using Foundation;
+using UIKit;
+
+namespace KitchenSyncIos {
+
+    [Register ("AppDelegate")]
+    public partial class AppDelegate : UIApplicationDelegate
+    {
+        
+    }
+}

+ 95 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/HomeScreen.storyboard

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C1510" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="oSP-RS-uRz">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+    </dependencies>
+    <scenes>
+        <!--Kitchen Sync-->
+        <scene sceneID="ufC-wZ-h7g">
+            <objects>
+                <viewController id="vXZ-lx-hvc" customClass="HomeScreenController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="jyV-Pf-zRb"/>
+                        <viewControllerLayoutGuide type="bottom" id="2fi-mo-0CV"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="kh9-bI-dsS">
+                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                        <subviews>
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="7WH-uJ-7lN">
+                                <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="600" id="22"/>
+                                    <constraint firstAttribute="height" constant="600" id="23"/>
+                                </constraints>
+                                <view key="tableHeaderView" contentMode="scaleToFill" id="3rr-Gp-MjW">
+                                    <rect key="frame" x="0.0" y="0.0" width="600" height="64"/>
+                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                    <subviews>
+                                        <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="New Item" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="70f-1n-86l">
+                                            <rect key="frame" x="10" y="17" width="580" height="30"/>
+                                            <constraints>
+                                                <constraint firstAttribute="height" constant="30" id="g3Z-Kr-7af"/>
+                                            </constraints>
+                                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                            <textInputTraits key="textInputTraits"/>
+                                            <connections>
+                                                <outlet property="delegate" destination="vXZ-lx-hvc" id="UfV-ju-cGf"/>
+                                            </connections>
+                                        </textField>
+                                    </subviews>
+                                    <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+                                    <constraints>
+                                        <constraint firstItem="70f-1n-86l" firstAttribute="leading" secondItem="3rr-Gp-MjW" secondAttribute="leading" constant="10" id="9m9-E7-0dM"/>
+                                        <constraint firstAttribute="centerY" secondItem="70f-1n-86l" secondAttribute="centerY" id="cFB-Q1-M4z"/>
+                                        <constraint firstAttribute="trailing" secondItem="70f-1n-86l" secondAttribute="trailing" constant="10" id="emt-sT-309"/>
+                                    </constraints>
+                                </view>
+                                <variation key="default">
+                                    <mask key="constraints">
+                                        <exclude reference="22"/>
+                                        <exclude reference="23"/>
+                                    </mask>
+                                </variation>
+                            </tableView>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" secondItem="7WH-uJ-7lN" secondAttribute="trailing" id="24"/>
+                            <constraint firstAttribute="bottom" secondItem="7WH-uJ-7lN" secondAttribute="bottom" id="25"/>
+                            <constraint firstItem="7WH-uJ-7lN" firstAttribute="top" secondItem="jyV-Pf-zRb" secondAttribute="bottom" constant="-64" id="9W2-Yn-9Uv"/>
+                            <constraint firstItem="7WH-uJ-7lN" firstAttribute="leading" secondItem="kh9-bI-dsS" secondAttribute="leading" id="eCW-fR-KjE"/>
+                            <constraint firstAttribute="trailing" secondItem="7WH-uJ-7lN" secondAttribute="trailing" id="yz1-LD-9tL"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="Kitchen Sync" id="i0N-DT-gP2"/>
+                    <connections>
+                        <outlet property="tableView" destination="7WH-uJ-7lN" id="name-outlet-7WH-uJ-7lN"/>
+                        <outlet property="textField" destination="70f-1n-86l" id="y9t-7H-tpU"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="x5A-6p-PRh" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1094" y="1090"/>
+        </scene>
+        <!--Navigation Controller-->
+        <scene sceneID="6xC-sL-E1W">
+            <objects>
+                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="oSP-RS-uRz" sceneMemberID="viewController">
+                    <toolbarItems/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="Dvh-er-WzT">
+                        <rect key="frame" x="0.0" y="20" width="600" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="vXZ-lx-hvc" kind="relationship" relationship="rootViewController" id="gDM-an-5Bh"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Wxo-cX-hOJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="202" y="1090"/>
+        </scene>
+    </scenes>
+</document>

+ 118 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/HomeScreenController.cs

@@ -0,0 +1,118 @@
+using System;
+using System.Collections.Generic;
+
+using Foundation;
+using UIKit;
+
+using KitchenSyncShared;
+
+namespace KitchenSyncIos
+{
+    partial class HomeScreenController : UIViewController
+    {
+        private DataSource _source;
+        private readonly TaskManager _taskMgr = new TaskManager();
+
+        //Step 9B - Add sync URL
+
+        public HomeScreenController (IntPtr handle) : base (handle)
+        {
+        }
+
+        public override void ViewDidLoad ()
+        {
+            base.ViewDidLoad();
+
+            Title = "KitchenSync";
+
+            tableView.Source = _source = new DataSource(this);
+            textField.Delegate = new TextFieldDelegate();
+            tableView.Delegate = new TableViewDelegate(_source);
+
+            //Step 11B - Start sync
+        }
+
+        class TableViewDelegate : UITableViewDelegate 
+        {
+            private readonly DataSource _source;
+
+            public TableViewDelegate(DataSource dataSource)
+            {
+                _source = dataSource;
+            }
+
+            public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
+            {
+                //Step 7B - Handle checkbox toggling
+            }
+        }
+            
+        class TextFieldDelegate : UITextFieldDelegate
+        {
+            public override bool ShouldReturn(UITextField textField)
+            {
+                textField.ResignFirstResponder();
+                return textField.Text.Length > 0;
+            }
+
+            public override void EditingEnded(UITextField textField)
+            {
+                if(textField.Text.Length == 0) {
+                    return;
+                }
+
+                var task = new Task() { 
+                    Text = textField.Text, 
+                    Checked = false, 
+                    CreationDate = DateTime.UtcNow 
+                };
+
+                var taskManager = new TaskManager();
+                taskManager.SaveTask(task);
+            }
+        }
+
+        class DataSource : UITableViewSource
+        {
+            static readonly NSString CellIdentifier = new NSString ("TaskCell");
+            private readonly HomeScreenController controller;
+            private IList<Task> _rows;
+            private readonly TaskManager taskMgr = new TaskManager ();
+
+            public IList<Task> Tasks
+            {
+                get { return _rows; }
+            }
+
+            public DataSource (HomeScreenController controller)
+            {
+                this.controller = controller;
+                //Step 6B - Setup data source for UI
+            }
+
+            public override nint RowsInSection (UITableView tableview, nint section)
+            {
+                return _rows == null ? 0 : _rows.Count;
+            }
+
+            public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
+            {
+                var cell = tableView.DequeueReusableCell (CellIdentifier);
+                if(cell == null) {
+                    cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
+                }
+                var task = _rows[indexPath.Row];
+                cell.TextLabel.Text = task.Text;
+                cell.Accessory = task.Checked ? UITableViewCellAccessory.Checkmark : UITableViewCellAccessory.None;
+
+                return cell;
+            }
+
+            public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath)
+            {
+                //Step 8B - Handle UI deletion
+            }
+        }
+            
+    }
+}

+ 37 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/HomeScreenController.designer.cs

@@ -0,0 +1,37 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio from the outlets and
+// actions declared in your storyboard file.
+// Manual changes to this file will not be maintained.
+//
+using Foundation;
+using UIKit;
+using System;
+using System.CodeDom.Compiler;
+
+namespace KitchenSyncIos
+{
+	[Register ("HomeScreenController")]
+	partial class HomeScreenController
+	{
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITableView tableView { get; set; }
+
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITextField textField { get; set; }
+
+		void ReleaseDesignerOutlets ()
+		{
+			if (tableView != null) {
+				tableView.Dispose ();
+				tableView = null;
+			}
+			if (textField != null) {
+				textField.Dispose ();
+				textField = null;
+			}
+		}
+	}
+}

+ 35 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Info.plist

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDisplayName</key>
+	<string>Tasky</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>Icon-60@2x</string>
+		<string>Icon-Small-40@2x</string>
+		<string>Icon@2x</string>
+		<string>Icon</string>
+		<string>Icon-Small</string>
+		<string>Icon-Small@2x</string>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>UIDeviceFamily</key>
+	<array>
+		<integer>1</integer>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>com.xamarin.tasky</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>MinimumOSVersion</key>
+	<string>8.1</string>
+	<key>UIMainStoryboardFile</key>
+	<string>HomeScreen</string>
+</dict>
+</plist>

+ 119 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/KitchenSyncIos.csproj

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{08FAE550-E302-4022-A871-17E0462E99F3}</ProjectGuid>
+    <ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>KitchenSyncIos</RootNamespace>
+    <AssemblyName>Tasky</AssemblyName>
+    <TargetFrameworkIdentifier>Xamarin.iOS</TargetFrameworkIdentifier>
+    <TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+    <MtouchDebug>True</MtouchDebug>
+    <MtouchI18n>
+    </MtouchI18n>
+    <MtouchArch>i386</MtouchArch>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+    <DebugType>none</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhone\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchDebug>True</MtouchDebug>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <IpaPackageName>
+    </IpaPackageName>
+    <MtouchArch>ARMv7</MtouchArch>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhone\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <MtouchArch>ARMv7, ARM64</MtouchArch>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="Xamarin.iOS" />
+    <Reference Include="SQLitePCL.raw">
+      <HintPath>..\packages\SQLitePCL.raw_basic.0.7.1\lib\Xamarin.iOS10\SQLitePCL.raw.dll</HintPath>
+    </Reference>
+    <Reference Include="SQLitePCL.ugly">
+      <HintPath>..\packages\SQLitePCL.ugly.0.7.1\lib\portable-net45+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCL.ugly.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\portable-net45+wp80+win8+wpa81\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="Couchbase.Lite">
+      <HintPath>..\packages\Couchbase.Lite.1.0.4.1\lib\xamarinios10\Couchbase.Lite.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+    <None Include="packages.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="AppDelegate.cs" />
+    <Compile Include="HomeScreenController.cs" />
+    <Compile Include="HomeScreenController.designer.cs">
+      <DependentUpon>HomeScreenController.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <Import Project="..\KitchenSyncShared\TaskyShared.projitems" Label="Shared" Condition="Exists('..\KitchenSyncShared\TaskyShared.projitems')" />
+  <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
+  <ItemGroup>
+    <Folder Include="Resources\" />
+  </ItemGroup>
+  <ItemGroup>
+    <BundleResource Include="Resources\Icon-60%402x.png" />
+    <BundleResource Include="Resources\Icon-Small-40%402x.png" />
+    <BundleResource Include="Resources\Default-568h%402x.png" />
+    <BundleResource Include="Resources\Default%402x.png" />
+    <BundleResource Include="Resources\Icon%402x.png" />
+    <BundleResource Include="Resources\Icon.png" />
+    <BundleResource Include="Resources\Icon-Small.png" />
+    <BundleResource Include="Resources\Icon-Small%402x.png" />
+    <BundleResource Include="Resources\Default.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <ITunesArtwork Include="iTunesArtwork%402x" />
+    <ITunesArtwork Include="iTunesArtwork" />
+  </ItemGroup>
+  <ItemGroup>
+    <InterfaceDefinition Include="HomeScreen.storyboard" />
+  </ItemGroup>
+</Project>

+ 13 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Main.cs

@@ -0,0 +1,13 @@
+using UIKit;
+
+namespace KitchenSyncIos {
+	public class Application {
+		// This is the main entry point of the application.
+		static void Main (string[] args)
+		{
+			// if you want to use a different Application Delegate class from "AppDelegate"
+			// you can specify it here.
+			UIApplication.Main (args, null, "AppDelegate");
+		}
+	}
+}

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Default-568h@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Default.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Default@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-60@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-Small-40@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-Small.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon-Small@2x.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon.png


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/Resources/Icon@2x.png


+ 16 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/ViewController.cs

@@ -0,0 +1,16 @@
+// This file has been autogenerated from a class added in the UI designer.
+
+using System;
+
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+
+namespace Tasky
+{
+	public partial class ViewController : UIViewController
+	{
+		public ViewController (IntPtr handle) : base (handle)
+		{
+		}
+	}
+}

+ 45 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/ViewController.designer.cs

@@ -0,0 +1,45 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio from the outlets and
+// actions declared in your storyboard file.
+// Manual changes to this file will not be maintained.
+//
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+using System;
+using System.CodeDom.Compiler;
+
+namespace Tasky
+{
+	[Register ("ViewController")]
+	partial class ViewController
+	{
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITableView tableView { get; set; }
+
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UITextField textField { get; set; }
+
+		[Outlet]
+		[GeneratedCode ("iOS Designer", "1.0")]
+		UIView textField { get; set; }
+
+		void ReleaseDesignerOutlets ()
+		{
+			if (tableView != null) {
+				tableView.Dispose ();
+				tableView = null;
+			}
+			if (textField != null) {
+				textField.Dispose ();
+				textField = null;
+			}
+			if (textField != null) {
+				textField.Dispose ();
+				textField = null;
+			}
+		}
+	}
+}

二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/iTunesArtwork


二進制
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/iTunesArtwork@2x


+ 7 - 0
3 - Advanced - Couchbase Mobile/Kitchen-Sync/src/workshop_start/KitchenSynciOS/packages.config

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Couchbase.Lite" version="1.0.4.1" targetFramework="xamarinios10" />
+  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="xamarinios10" />
+  <package id="SQLitePCL.raw_basic" version="0.7.1" targetFramework="xamarinios10" />
+  <package id="SQLitePCL.ugly" version="0.7.1" targetFramework="xamarinios10" />
+</packages>

+ 15 - 0
3 - Advanced - Couchbase Mobile/README.md

@@ -0,0 +1,15 @@
+Couchbase Labs
+==========
+
+Labs are fun and quick challenges to discover the beauty of using Couchbase Mobile in real apps.
+
+#### Available Labs
+
+* [Kitchen Sync](Kitchen-Sync) - Build a todo list that syncs!
+
+#### Development Resources
+* [Developer Portal](http://developer.couchbase.com/mobile/)
+* [Developer Forum](http://forums.couchbase.com/c/mobile)
+
+#### Feedback for Couchbase
+[Tell us what you think!](https://docs.google.com/forms/d/1Qs9svNccKCC5iji6NXC35uCvdmtFzB0dopz57iApSnY/viewform)