├── .classpath ├── .gitignore ├── .gitmodules ├── .project ├── CONTRIBUTING.md ├── GrocerySync-Android ├── build.gradle ├── libs │ └── td_collator_so.jar └── src │ └── main │ ├── AndroidManifest.xml │ ├── ic_launcher-web.png │ ├── java │ └── com │ │ └── couchbase │ │ └── grocerysync │ │ ├── GrocerySyncArrayAdapter.java │ │ ├── GrocerySyncPreferencesActivity.java │ │ ├── MainActivity.java │ │ └── SplashScreenDialog.java │ └── res │ ├── drawable-hdpi │ └── ic_launcher.png │ ├── drawable-mdpi │ ├── ic_launcher.png │ └── splash.png │ ├── drawable-xhdpi │ └── ic_launcher.png │ ├── drawable-xxhdpi │ └── ic_launcher.png │ ├── drawable │ ├── .DS_Store │ ├── add_item_edittext_rounded_corners.xml │ ├── couchbase_progress.xml │ ├── couchbase_red_gradient.xml │ ├── item_background.png │ ├── item_left_background.png │ ├── item_right_background.png │ ├── list_area___checkbox___checked.png │ ├── list_area___checkbox___unchecked.png │ └── rounded_corners.xml │ ├── layout │ ├── activity_main.xml │ ├── grocery_list_item.xml │ └── splashscreen.xml │ ├── menu │ └── main.xml │ ├── values-sw600dp │ └── dimens.xml │ ├── values-sw720dp-land │ └── dimens.xml │ ├── values-v11 │ └── styles.xml │ ├── values-v14 │ └── styles.xml │ ├── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ └── preferences.xml ├── README.md ├── build.gradle ├── docs ├── GrocerySync.graffle ├── GrocerySync.png └── sync_gw_config.json ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── local.properties.example └── settings.gradle /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.apk 2 | *.ap_ 3 | *.dex 4 | *.class 5 | /bin/ 6 | /gen/ 7 | local.properties 8 | build.properties 9 | /GrocerySync-Android/build/ 10 | /GrocerySync-Android/src/main/res/.DS_Store 11 | /.gradle/ 12 | /.idea/ 13 | /.DS_Store 14 | /GrocerySync-Android/.DS_Store 15 | /GrocerySync-Android/GrocerySync-Android-GrocerySync-Android.iml 16 | /.idea/misc.xml 17 | /GrocerySync-Android.iml 18 | *.iml 19 | \#* 20 | *~ 21 | .#* 22 | \#*\# 23 | *.class 24 | /.DS_Store 25 | build -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/.gitmodules -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AndroidGrocerySync 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We hate bugs, but we love bug reports! And we're grateful to our developers who exercise Couchbase Lite and the Couchbase Sync Gateway in new and unexpected ways and help us work out the kinks. 2 | 3 | We also want to hear about your ideas for new features and improvements. You can file those in the issue trackers too. 4 | 5 | And while we welcome questions, **we prefer to answer questions on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/mobile-couchbase)** rather than in Github issues. 6 | 7 | # 1. Is This A Duplicate? 8 | 9 | It's great if you can scan the open issues to see if your problem/idea has been reported already. If so, feel free to add any new details or just a note that you hit this too. But if you're in a hurry, go ahead and skip this step -- we'd rather get duplicate reports than miss an issue! 10 | 11 | # 2. Describe The Bug 12 | 13 | ## Version 14 | 15 | Please indicate **what version of the software** you're using. If you compiled it yourself from source, it helps if you give the Git commit ID, or at least the branch name and date ("I last pulled from master on 6/30.") 16 | 17 | If the bug involves replication, also indicate what software and version is on the other end of the line, i.e. "Couchbase Lite Android 1.0" or "Sync Gateway 1.0" or "Sync Gateway commit f3d3229c" or "CouchDB 1.6". 18 | 19 | ## Include Steps To Reproduce 20 | 21 | The most **important information** to provide with a bug report is a clear set of steps to reproduce the problem. Include as much information as possible that you think may be related to the bug. An example would be: 22 | 23 | * Install & run Sync Gateway 1.0.3 on Mac running OS X 10.10.1 24 | * Install app on iPhone 6 running iOS 8.1.1 25 | * Login with Facebook 26 | * Turn off WiFi 27 | * Add a new document 28 | * Turn on WiFi 29 | * Saw no new documents on Sync Gateway (expected: there should have been some documents) 30 | 31 | ## Include Actual vs. Expected 32 | 33 | As mentioned above, the last thing in your steps to reproduce is the "actual vs expected" behavior. The reason this is important is because you may have misunderstood what is supposed to happen. If you give a clear description of what actually happened as well as what you were expecting to happen, it will make the bug a lot easier to figure out. 34 | 35 | ## General Formatting 36 | 37 | Please **format source code or program output (including logs or backtraces) as code**. This makes it easier to read and prevents Github from interpreting any of it as Markdown formatting or bug numbers. To do this, put a line of just three back-quotes ("```") before and after it. (For inline code snippets, just put a single back-quote before and after.) 38 | 39 | **If you need to post a block of code/output that is longer than 1/2 a page, please don't paste it into the bug report** -- it's annoying to scroll past. Instead, create a [gist](https://gist.github.com) (or something similar) and just post a link to it. 40 | 41 | ## Crashes / Exceptions 42 | 43 | If the bug causes a crash or an uncaught exception, include a crash log or backtrace. **Please don't add this as a screenshot of the IDE** if you have any alternative. (In Xcode, use the `bt` command in the debugger console to dump a backtrace that you can copy.) 44 | 45 | If the log/backtrace is long, don't paste it in directly (see the previous section.) 46 | -------------------------------------------------------------------------------- /GrocerySync-Android/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | 4 | Build script for Grocery-Sync Android, an example application based on Couchbase Lite 5 | 6 | This project depends on Couchbase Lite via Maven artifacts by default. Instructions 7 | below are included to depend on the source code directly via submodules. If you are 8 | using the Maven artifacts, the submodules are not needed. 9 | 10 | Warning: this may be pointed to an out-of-date release of Couchbase Lite, 11 | See https://github.com/couchbase/couchbase-lite-android#latest-maven-release 12 | for instructions on getting the latest release version. 13 | 14 | */ 15 | 16 | apply plugin: 'android' 17 | 18 | 19 | android { 20 | compileSdkVersion 22 21 | buildToolsVersion "22.0.1" 22 | 23 | defaultConfig { 24 | minSdkVersion 9 25 | targetSdkVersion 22 26 | } 27 | 28 | // workaround for "duplicate files during packaging of APK" issue 29 | // see https://groups.google.com/d/msg/adt-dev/bl5Rc4Szpzg/wC8cylTWuIEJ 30 | packagingOptions { 31 | exclude 'META-INF/ASL2.0' 32 | exclude 'META-INF/LICENSE' 33 | exclude 'META-INF/NOTICE' 34 | } 35 | } 36 | 37 | dependencies { 38 | compile 'com.android.support:appcompat-v7:22.0.0' 39 | 40 | // By default, this depends on couchbase lite via the maven artifact 41 | compile 'com.couchbase.lite:couchbase-lite-android:0.0.0-679' 42 | } 43 | 44 | 45 | task sourcesJar(type: Jar) { 46 | classifier = 'sources' 47 | from android.sourceSets.main.java.srcDirs 48 | } 49 | 50 | task generateJavadocs(type: Javadoc) { 51 | source = android.sourceSets.main.java.srcDirs 52 | } 53 | -------------------------------------------------------------------------------- /GrocerySync-Android/libs/td_collator_so.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/libs/td_collator_so.jar -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/java/com/couchbase/grocerysync/GrocerySyncArrayAdapter.java: -------------------------------------------------------------------------------- 1 | package com.couchbase.grocerysync; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ArrayAdapter; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.couchbase.lite.QueryRow; 12 | import com.couchbase.lite.SavedRevision; 13 | 14 | import java.util.List; 15 | 16 | 17 | public class GrocerySyncArrayAdapter extends ArrayAdapter { 18 | 19 | private List list; 20 | private final Context context; 21 | 22 | public GrocerySyncArrayAdapter(Context context, int resource, int textViewResourceId, List objects) { 23 | super(context, resource, textViewResourceId, objects); 24 | this.context = context; 25 | } 26 | 27 | private static class ViewHolder { 28 | ImageView icon; 29 | TextView label; 30 | } 31 | 32 | @Override 33 | public View getView(int position, View itemView, ViewGroup parent) { 34 | 35 | if (itemView == null) { 36 | LayoutInflater vi = (LayoutInflater)parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 37 | itemView = vi.inflate(R.layout.grocery_list_item, null); 38 | ViewHolder vh = new ViewHolder(); 39 | vh.label = (TextView) itemView.findViewById(R.id.label); 40 | vh.icon = (ImageView) itemView.findViewById(R.id.icon); 41 | itemView.setTag(vh); 42 | } 43 | 44 | try { 45 | TextView label = ((ViewHolder)itemView.getTag()).label; 46 | QueryRow row = getItem(position); 47 | SavedRevision currentRevision = row.getDocument().getCurrentRevision(); 48 | Object check = (Object) currentRevision.getProperty("check"); 49 | boolean isGroceryItemChecked = false; 50 | if (check != null && check instanceof Boolean) { 51 | isGroceryItemChecked = ((Boolean)check).booleanValue(); 52 | } 53 | String groceryItemText = (String) currentRevision.getProperty("text"); 54 | label.setText(groceryItemText); 55 | 56 | ImageView icon = ((ViewHolder)itemView.getTag()).icon; 57 | if(isGroceryItemChecked) { 58 | icon.setImageResource(R.drawable.list_area___checkbox___checked); 59 | } 60 | else { 61 | icon.setImageResource(R.drawable.list_area___checkbox___unchecked); 62 | } 63 | } catch (Exception e) { 64 | e.printStackTrace(); 65 | } 66 | 67 | return itemView; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/java/com/couchbase/grocerysync/GrocerySyncPreferencesActivity.java: -------------------------------------------------------------------------------- 1 | package com.couchbase.grocerysync; 2 | 3 | import android.os.Bundle; 4 | import android.preference.PreferenceActivity; 5 | 6 | public class GrocerySyncPreferencesActivity extends PreferenceActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | addPreferencesFromResource(R.xml.preferences); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/java/com/couchbase/grocerysync/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.couchbase.grocerysync; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.app.ProgressDialog; 6 | import android.content.DialogInterface; 7 | import android.content.Intent; 8 | import android.os.Bundle; 9 | import android.view.KeyEvent; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | import android.view.View; 13 | import android.view.View.OnKeyListener; 14 | import android.widget.AdapterView; 15 | import android.widget.AdapterView.OnItemClickListener; 16 | import android.widget.AdapterView.OnItemLongClickListener; 17 | import android.widget.EditText; 18 | import android.widget.ListView; 19 | import android.widget.Toast; 20 | 21 | import com.couchbase.lite.Database; 22 | import com.couchbase.lite.DatabaseOptions; 23 | import com.couchbase.lite.Document; 24 | import com.couchbase.lite.Emitter; 25 | import com.couchbase.lite.LiveQuery; 26 | import com.couchbase.lite.Manager; 27 | import com.couchbase.lite.Mapper; 28 | import com.couchbase.lite.QueryRow; 29 | import com.couchbase.lite.android.AndroidContext; 30 | import com.couchbase.lite.replicator.Replication; 31 | import com.couchbase.lite.util.Log; 32 | 33 | import java.net.MalformedURLException; 34 | import java.net.URL; 35 | import java.text.SimpleDateFormat; 36 | import java.util.ArrayList; 37 | import java.util.Calendar; 38 | import java.util.GregorianCalendar; 39 | import java.util.HashMap; 40 | import java.util.Iterator; 41 | import java.util.Map; 42 | import java.util.StringTokenizer; 43 | import java.util.UUID; 44 | 45 | public class MainActivity extends Activity implements Replication.ChangeListener, 46 | OnItemClickListener, OnItemLongClickListener, OnKeyListener { 47 | 48 | public static String TAG = "GrocerySync"; 49 | 50 | //constants 51 | public static final String DATABASE_NAME = "grocery-sync"; 52 | public static final String designDocName = "grocery-local"; 53 | public static final String byDateViewName = "byDate"; 54 | 55 | // By default, use the sync gateway running on the Couchbase demo server. 56 | // Warning: this will have "random data" entered by other users. 57 | // If you want to limit this to your own data, please install and run your own 58 | // Sync Gateway and point it to that URL instead. 59 | public static final String SYNC_URL = "http://10.0.2.2:4984/grocery-sync"; 60 | 61 | //splash screen 62 | protected SplashScreenDialog splashDialog; 63 | 64 | //main screen 65 | protected EditText addItemEditText; 66 | protected ListView itemListView; 67 | protected GrocerySyncArrayAdapter grocerySyncArrayAdapter; 68 | 69 | //couch internals 70 | protected static Manager manager; 71 | private Database database; 72 | private LiveQuery liveQuery; 73 | 74 | 75 | public void onCreate(Bundle savedInstanceState) { 76 | 77 | super.onCreate(savedInstanceState); 78 | 79 | setContentView(R.layout.activity_main); 80 | 81 | //connect items from layout 82 | addItemEditText = (EditText)findViewById(R.id.addItemEditText); 83 | itemListView = (ListView)findViewById(R.id.itemListView); 84 | 85 | //connect listeners 86 | addItemEditText.setOnKeyListener(this); 87 | 88 | //show splash and start couch 89 | showSplashScreen(); 90 | removeSplashScreen(); 91 | 92 | try { 93 | startCBLite(); 94 | } catch (Exception e) { 95 | Toast.makeText(getApplicationContext(), "Error Initializing CBLIte, see logs for details", Toast.LENGTH_LONG).show(); 96 | Log.e(TAG, "Error initializing CBLite", e); 97 | } 98 | 99 | } 100 | 101 | 102 | protected void onDestroy() { 103 | if(manager != null) { 104 | manager.close(); 105 | } 106 | super.onDestroy(); 107 | } 108 | 109 | protected void startCBLite() throws Exception { 110 | 111 | Manager.enableLogging(TAG, Log.VERBOSE); 112 | Manager.enableLogging(Log.TAG, Log.VERBOSE); 113 | Manager.enableLogging(Log.TAG_SYNC_ASYNC_TASK, Log.VERBOSE); 114 | Manager.enableLogging(Log.TAG_SYNC, Log.VERBOSE); 115 | Manager.enableLogging(Log.TAG_QUERY, Log.VERBOSE); 116 | Manager.enableLogging(Log.TAG_VIEW, Log.VERBOSE); 117 | Manager.enableLogging(Log.TAG_DATABASE, Log.VERBOSE); 118 | 119 | manager = new Manager(new AndroidContext(getApplicationContext()), Manager.DEFAULT_OPTIONS); 120 | 121 | //install a view definition needed by the application 122 | DatabaseOptions options = new DatabaseOptions(); 123 | options.setCreate(true); 124 | database = manager.openDatabase(DATABASE_NAME, options); 125 | com.couchbase.lite.View viewItemsByDate = database.getView(String.format("%s/%s", designDocName, byDateViewName)); 126 | viewItemsByDate.setMap(new Mapper() { 127 | @Override 128 | public void map(Map document, Emitter emitter) { 129 | Object createdAt = document.get("created_at"); 130 | if (createdAt != null) { 131 | emitter.emit(createdAt.toString(), null); 132 | } 133 | } 134 | }, "1.0"); 135 | 136 | initItemListAdapter(); 137 | 138 | startLiveQuery(viewItemsByDate); 139 | 140 | startSync(); 141 | 142 | } 143 | 144 | private void startSync() { 145 | 146 | URL syncUrl; 147 | try { 148 | syncUrl = new URL(SYNC_URL); 149 | } catch (MalformedURLException e) { 150 | throw new RuntimeException(e); 151 | } 152 | 153 | Replication pullReplication = database.createPullReplication(syncUrl); 154 | pullReplication.setContinuous(true); 155 | 156 | Replication pushReplication = database.createPushReplication(syncUrl); 157 | pushReplication.setContinuous(true); 158 | 159 | pullReplication.start(); 160 | pushReplication.start(); 161 | 162 | pullReplication.addChangeListener(this); 163 | pushReplication.addChangeListener(this); 164 | 165 | } 166 | 167 | private void startLiveQuery(com.couchbase.lite.View view) throws Exception { 168 | 169 | final ProgressDialog progressDialog = showLoadingSpinner(); 170 | 171 | if (liveQuery == null) { 172 | 173 | liveQuery = view.createQuery().toLiveQuery(); 174 | 175 | liveQuery.addChangeListener(new LiveQuery.ChangeListener() { 176 | public void changed(final LiveQuery.ChangeEvent event) { 177 | runOnUiThread(new Runnable() { 178 | public void run() { 179 | grocerySyncArrayAdapter.clear(); 180 | for (Iterator it = event.getRows(); it.hasNext();) { 181 | grocerySyncArrayAdapter.add(it.next()); 182 | } 183 | grocerySyncArrayAdapter.notifyDataSetChanged(); 184 | progressDialog.dismiss(); 185 | } 186 | }); 187 | } 188 | }); 189 | 190 | liveQuery.start(); 191 | 192 | } 193 | 194 | } 195 | 196 | private void initItemListAdapter() { 197 | grocerySyncArrayAdapter = new GrocerySyncArrayAdapter( 198 | getApplicationContext(), 199 | R.layout.grocery_list_item, 200 | R.id.label, 201 | new ArrayList() 202 | ); 203 | itemListView.setAdapter(grocerySyncArrayAdapter); 204 | itemListView.setOnItemClickListener(MainActivity.this); 205 | itemListView.setOnItemLongClickListener(MainActivity.this); 206 | } 207 | 208 | 209 | private ProgressDialog showLoadingSpinner() { 210 | ProgressDialog progress = new ProgressDialog(this); 211 | progress.setTitle("Loading"); 212 | progress.setMessage("Wait while loading..."); 213 | progress.show(); 214 | return progress; 215 | } 216 | 217 | 218 | /** 219 | * Handle typing item text 220 | */ 221 | public boolean onKey(View v, int keyCode, KeyEvent event) { 222 | if ((event.getAction() == KeyEvent.ACTION_DOWN) 223 | && (keyCode == KeyEvent.KEYCODE_ENTER)) { 224 | 225 | String inputText = addItemEditText.getText().toString(); 226 | if(!inputText.equals("")) { 227 | try { 228 | 229 | if (inputText.contains(":")) { // hack to create multiple items 230 | int numCreated = createMultipleGrocerySyncItems(inputText); 231 | String msg = String.format("Created %d new grocery items!", numCreated); 232 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show(); 233 | } 234 | else { 235 | createGroceryItem(inputText); 236 | Toast.makeText(getApplicationContext(), "Created new grocery item!", Toast.LENGTH_LONG).show(); 237 | } 238 | 239 | } catch (Exception e) { 240 | Toast.makeText(getApplicationContext(), "Error creating document, see logs for details", Toast.LENGTH_LONG).show(); 241 | Log.e(TAG, "Error creating document.", e); 242 | } 243 | } 244 | addItemEditText.setText(""); 245 | return true; 246 | } 247 | return false; 248 | } 249 | 250 | 251 | /** 252 | * Handle click on item in list 253 | */ 254 | public void onItemClick(AdapterView adapterView, View view, int position, long id) { 255 | 256 | QueryRow row = (QueryRow) adapterView.getItemAtPosition(position); 257 | Document document = row.getDocument(); 258 | Map newProperties = new HashMap(document.getProperties()); 259 | 260 | boolean checked = ((Boolean) newProperties.get("check")).booleanValue(); 261 | newProperties.put("check", !checked); 262 | 263 | try { 264 | document.putProperties(newProperties); 265 | grocerySyncArrayAdapter.notifyDataSetChanged(); 266 | } catch (Exception e) { 267 | Toast.makeText(getApplicationContext(), "Error updating database, see logs for details", Toast.LENGTH_LONG).show(); 268 | Log.e(TAG, "Error updating database", e); 269 | } 270 | 271 | } 272 | 273 | /** 274 | * Handle long-click on item in list 275 | */ 276 | public boolean onItemLongClick(AdapterView adapterView, View view, int position, long id) { 277 | 278 | QueryRow row = (QueryRow) adapterView.getItemAtPosition(position); 279 | final Document clickedDocument = row.getDocument(); 280 | String itemText = (String) clickedDocument.getCurrentRevision().getProperty("text"); 281 | 282 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 283 | AlertDialog alert = builder.setTitle("Delete Item?") 284 | .setMessage("Are you sure you want to delete \"" + itemText + "\"?") 285 | .setPositiveButton("Yes", new DialogInterface.OnClickListener() { 286 | public void onClick(DialogInterface dialog, int id) { 287 | try { 288 | clickedDocument.delete(); 289 | } catch (Exception e) { 290 | Toast.makeText(getApplicationContext(), "Error deleting document, see logs for details", Toast.LENGTH_LONG).show(); 291 | Log.e(TAG, "Error deleting document", e); 292 | } 293 | } 294 | }) 295 | .setNegativeButton("No", new DialogInterface.OnClickListener() { 296 | public void onClick(DialogInterface dialog, int id) { 297 | // Handle Cancel 298 | } 299 | }) 300 | .create(); 301 | 302 | alert.show(); 303 | 304 | return true; 305 | } 306 | 307 | 308 | /** 309 | * Removes the Dialog that displays the splash screen 310 | */ 311 | protected void removeSplashScreen() { 312 | if (splashDialog != null) { 313 | splashDialog.dismiss(); 314 | splashDialog = null; 315 | } 316 | } 317 | 318 | /** 319 | * Shows the splash screen over the full Activity 320 | */ 321 | private void showSplashScreen() { 322 | splashDialog = new SplashScreenDialog(this); 323 | splashDialog.show(); 324 | } 325 | 326 | /** 327 | * Add settings item to the menu 328 | */ 329 | public boolean onCreateOptionsMenu(Menu menu) { 330 | menu.add(Menu.NONE, 0, 0, "Settings"); 331 | return super.onCreateOptionsMenu(menu); 332 | } 333 | 334 | /** 335 | * Launch the settings activity 336 | */ 337 | public boolean onOptionsItemSelected(MenuItem item) { 338 | switch (item.getItemId()) { 339 | case 0: 340 | startActivity(new Intent(this, GrocerySyncPreferencesActivity.class)); 341 | return true; 342 | } 343 | return false; 344 | } 345 | 346 | private Document createGroceryItem(String text) throws Exception { 347 | 348 | SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 349 | 350 | UUID uuid = UUID.randomUUID(); 351 | Calendar calendar = GregorianCalendar.getInstance(); 352 | long currentTime = calendar.getTimeInMillis(); 353 | String currentTimeString = dateFormatter.format(calendar.getTime()); 354 | 355 | String id = currentTime + "-" + uuid.toString(); 356 | 357 | Document document = database.createDocument(); 358 | 359 | Map properties = new HashMap(); 360 | properties.put("_id", id); 361 | properties.put("text", text); 362 | properties.put("check", Boolean.FALSE); 363 | properties.put("created_at", currentTimeString); 364 | document.putProperties(properties); 365 | 366 | Log.d(TAG, "Created new grocery item with id: %s", document.getId()); 367 | 368 | return document; 369 | } 370 | 371 | private int createMultipleGrocerySyncItems(String text) throws Exception { 372 | StringTokenizer st = new StringTokenizer(text, ":"); 373 | String itemText = st.nextToken(); 374 | String numItemsString = st.nextToken(); 375 | int numItems = Integer.parseInt(numItemsString); 376 | for (int i = 0; i < numItems; i++) { 377 | String curItemText = String.format("%s-%d", itemText, i); 378 | createGroceryItem(curItemText); 379 | } 380 | return numItems; 381 | } 382 | 383 | @Override 384 | public void changed(Replication.ChangeEvent event) { 385 | 386 | Replication replication = event.getSource(); 387 | Log.d(TAG, "Replication : " + replication + " changed."); 388 | if (!replication.isRunning()) { 389 | String msg = String.format("Replicator %s not running", replication); 390 | Log.d(TAG, msg); 391 | } 392 | else { 393 | int processed = replication.getCompletedChangesCount(); 394 | int total = replication.getChangesCount(); 395 | String msg = String.format("Replicator processed %d / %d", processed, total); 396 | Log.d(TAG, msg); 397 | } 398 | 399 | if (event.getError() != null) { 400 | showError("Sync error", event.getError()); 401 | } 402 | 403 | } 404 | 405 | public void showError(final String errorMessage, final Throwable throwable) { 406 | 407 | runOnUiThread(new Runnable() { 408 | @Override 409 | public void run() { 410 | String msg = String.format("%s: %s", errorMessage, throwable); 411 | Log.e(TAG, msg, throwable); 412 | Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show(); 413 | } 414 | }); 415 | 416 | } 417 | 418 | } 419 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/java/com/couchbase/grocerysync/SplashScreenDialog.java: -------------------------------------------------------------------------------- 1 | package com.couchbase.grocerysync; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.widget.ProgressBar; 6 | import android.widget.TextView; 7 | 8 | public class SplashScreenDialog extends Dialog { 9 | 10 | protected ProgressBar splashProgressBar; 11 | protected TextView splashProgressMessage; 12 | 13 | public SplashScreenDialog(Context context) { 14 | super(context, R.style.SplashScreenStyle); 15 | 16 | setContentView(R.layout.splashscreen); 17 | setCancelable(false); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable-mdpi/splash.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable/.DS_Store -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/add_item_edittext_rounded_corners.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/couchbase_progress.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/couchbase_red_gradient.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/item_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable/item_background.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/item_left_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable/item_left_background.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/item_right_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable/item_right_background.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/list_area___checkbox___checked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable/list_area___checkbox___checked.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/list_area___checkbox___unchecked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/GrocerySync-Android/src/main/res/drawable/list_area___checkbox___unchecked.png -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/drawable/rounded_corners.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/layout/grocery_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/layout/splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values-sw600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values-sw720dp-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 128dp 5 | 6 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values-v11/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values-v14/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Grocery Sync 4 | Starting Couchbase Mobile 5 | Add Item 6 | Couchbase Error 7 | Exit 8 | Action Settings 9 | 10 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #efeee9 4 | #efeee9 5 | #9e0c0c 6 | #c96565 7 | 12 | 13 | 17 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /GrocerySync-Android/src/main/res/xml/preferences.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ⚠️ This repo is obsolete. It was built against a version of Couchbase Lite that reached end of life years ago. 2 | 3 | ## Grocery Sync for Couchbase Lite Android 4 | 5 | An example app that uses the [Couchbase Lite Android](https://github.com/couchbase/couchbase-lite-android) mobile database framework. 6 | 7 | This example code corresopnds to the master branch of Couchbase Lite Android. 8 | 9 | ![](http://cl.ly/image/1H11131G2c3d/Screen%20Shot%202013-05-14%20at%204.44.48%20PM.png) 10 | 11 | ## Architecture 12 | 13 | ![](http://cl.ly/image/3c1k113o182b/GrocerySync.png) 14 | 15 | If Couchbase Lite is configured to sync it's changes with a Sync Gateway, then all changes will automatically background sync bi-directionally such that any changes on either device will propagate to the other. 16 | 17 | ## Install Android Studio 18 | 19 | * [Android Studio](http://developer.android.com/sdk/installing/studio.html) -- see the [Android Studio Compatibility Table](https://github.com/couchbase/couchbase-lite-android/blob/master/README.md#building-couchbase-lite-via-android-studio) to make sure the version you are using is supported. 20 | 21 | ## Screencasts 22 | 23 | The following screencasts walk you through getting GrocerySync up and running: 24 | 25 | * [GrocerySync - Couchbase Lite Android demo app: Part I](https://www.youtube.com/watch?v=9rWY2CrnFHw) -- get up and running (4m 35s) 26 | * [GrocerySync - Couchbase Lite Android demo app: Part II](https://www.youtube.com/watch?v=rX9IPMBl780) -- run a local Sync Gateway (5m 47s) 27 | 28 | The screencasts follow the instructions in the remainder of this document. 29 | 30 | ## Getting the code 31 | 32 | ``` 33 | $ git clone https://github.com/couchbaselabs/GrocerySync-Android.git 34 | $ git submodule update --init 35 | ``` 36 | 37 | ## Import the project in Android Studio 38 | 39 | Follow the same instructions as importing [Couchbase Lite](https://github.com/couchbase/couchbase-lite-android#importing-project-into-android-studio) 40 | 41 | ## Run the app via Android Studio 42 | 43 | * Run it using the "play" or "debug" buttons in the UI 44 | 45 | Congratulations! If you got this far and see [this UI](http://cl.ly/image/1H11131G2c3d/Screen%20Shot%202013-05-14%20at%204.44.48%20PM.png), you have your first Couchbase Lite Android app up and running. 46 | 47 | ## Install Sync Gateway 48 | 49 | 1. Download and install Sync Gateway (see the [installation page](http://developer.couchbase.com/documentation/mobile/current/installation/sync-gateway/index.html) for details). 50 | 2. Start Sync Gateway with the configuration file in the root of this project. 51 | 52 | ```bash 53 | ~/Downloads/couchbase-sync-gateway/bin/sync_gateway sync-gateway-config.json 54 | ``` 55 | 56 | 3. Open **MainActivity.java** and update the `SYNC_URL` constant to point to your Sync Gateway instance. 57 | 58 | ```java 59 | public static final String SYNC_URL = "http://10.0.2.2:4984/grocery-sync"; 60 | ``` 61 | 62 | - If you are using the Genymotion emulator: `http://10.0.3.2:4984/grocery-sync` 63 | - If you are using the standard android emulator: `http://10.0.2.2:4984/grocery-sync` 64 | - If you are running on a device: `http://:4984/grocery-sync` 65 | 66 | 4. Build and run the app. 67 | 5. Add items and they should be visible on the Sync Gateway Admin UI at [http://localhost:4985/_admin/] 68 | (http://localhost:4985/_admin/). 69 | 70 | ## Change the dependency from Maven -> Direct code dependency (optional) 71 | 72 | By default, this project depends on the Couchbase Lite maven artifacts. However, it can also depend on the CBLite code directly, which is useful if you need to modify the Couchbase Lite code. (Note: if you are using maven artifacts, since we ship the source code artifacts, you should already be able to browse the code and debug) 73 | 74 | See the build.gradle and settings.gradle files for instructions on how to do this. 75 | 76 | ## Run via Gradle (optional) 77 | 78 | If you would rather run the project via the command line, you can do the following: 79 | 80 | * Run the android emulator 81 | * Run `./gradlew clean && ./gradlew installDebug` 82 | * Switch to the emulator and you should have a new app called GrocerySync-Android 83 | * Tap it to open the app 84 | 85 | ## Compile with submodules (Couchbase Lite from source code) (optional) 86 | 87 | If you would rather compile the project with couchbase lite source codes, you can do the following: 88 | 89 | * Open `sttings.gradle`, remove `/*` and `*/`. 90 | * Open `build.gradle` in `GrocerySync-Android` folder, comment out `compile 'com.couchbase.lite:couchbase-lite-android:1.1.0'` and remove `//` for `compile project(':libraries:couchbase-lite-android')`, `compile project(':libraries:couchbase-lite-java-core')`, and `compile project(':libraries:couchbase-lite-java-native:sqlite-default')`. 91 | 92 | 93 | # Additional Information 94 | 95 | ## Where to go from here: creating your own Couchbase-Lite app 96 | 97 | See the [Getting Started Guide](http://developer.couchbase.com/mobile/develop/training/build-first-android-app/index.html). 98 | 99 | ## Support 100 | 101 | See [Getting Help](https://github.com/couchbase/couchbase-lite-android#getting-help) 102 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | 4 | buildscript { 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:1.3.0' 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | jcenter() 16 | maven { 17 | url "http://files.couchbase.com/maven2/" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/GrocerySync.graffle: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ActiveLayerIndex 6 | 0 7 | ApplicationVersion 8 | 9 | com.omnigroup.OmniGrafflePro 10 | 138.33.0.157554 11 | 12 | AutoAdjust 13 | 14 | BackgroundGraphic 15 | 16 | Bounds 17 | {{0, 0}, {576, 733}} 18 | Class 19 | SolidGraphic 20 | ID 21 | 2 22 | Style 23 | 24 | shadow 25 | 26 | Draws 27 | NO 28 | 29 | stroke 30 | 31 | Draws 32 | NO 33 | 34 | 35 | 36 | CanvasOrigin 37 | {0, 0} 38 | ColumnAlign 39 | 1 40 | ColumnSpacing 41 | 36 42 | CreationDate 43 | 2013-10-23 16:32:23 +0000 44 | Creator 45 | Traun Leyden 46 | DisplayScale 47 | 1 0/72 in = 1.0000 in 48 | GraphDocumentVersion 49 | 8 50 | GraphicsList 51 | 52 | 53 | Class 54 | LineGraphic 55 | ControlPoints 56 | 57 | {0.3977356, 1.5163574} 58 | {399.84146, -166.70648} 59 | 60 | Head 61 | 62 | ID 63 | 56 64 | 65 | ID 66 | 60 67 | Points 68 | 69 | {273.21545, 250.46275} 70 | {375.20959, 499.69824} 71 | 72 | Style 73 | 74 | stroke 75 | 76 | Bezier 77 | 78 | HeadArrow 79 | FilledArrow 80 | LineType 81 | 1 82 | TailArrow 83 | FilledArrow 84 | 85 | 86 | Tail 87 | 88 | ID 89 | 10 90 | 91 | 92 | 93 | Class 94 | Group 95 | Graphics 96 | 97 | 98 | Bounds 99 | {{336.47504, 453.05316}, {95, 24}} 100 | Class 101 | ShapedGraphic 102 | FitText 103 | YES 104 | Flow 105 | Resize 106 | FontInfo 107 | 108 | Color 109 | 110 | w 111 | 0 112 | 113 | Font 114 | Helvetica 115 | Size 116 | 12 117 | 118 | ID 119 | 54 120 | Line 121 | 122 | ID 123 | 55 124 | Position 125 | 0.52040815353393555 126 | RotationType 127 | 0 128 | 129 | Shape 130 | Rectangle 131 | Style 132 | 133 | shadow 134 | 135 | Draws 136 | NO 137 | 138 | stroke 139 | 140 | Draws 141 | NO 142 | 143 | 144 | Text 145 | 146 | Text 147 | {\rtf1\ansi\ansicpg1252\cocoartf1265 148 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 149 | {\colortbl;\red255\green255\blue255;} 150 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 151 | 152 | \f0\fs24 \cf0 Native Java API} 153 | 154 | Wrap 155 | NO 156 | 157 | 158 | Class 159 | LineGraphic 160 | Head 161 | 162 | ID 163 | 56 164 | 165 | ID 166 | 55 167 | Points 168 | 169 | {383.99237, 427.5} 170 | {383.95905, 499.66095} 171 | 172 | Style 173 | 174 | stroke 175 | 176 | HeadArrow 177 | StickArrow 178 | TailArrow 179 | StickArrow 180 | 181 | 182 | Tail 183 | 184 | ID 185 | 57 186 | 187 | 188 | 189 | Bounds 190 | {{315, 500.16095}, {138, 42}} 191 | Class 192 | ShapedGraphic 193 | ID 194 | 56 195 | Shape 196 | Rectangle 197 | Text 198 | 199 | Text 200 | {\rtf1\ansi\ansicpg1252\cocoartf1265 201 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 202 | {\colortbl;\red255\green255\blue255;} 203 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 204 | 205 | \f0\fs24 \cf0 Couchbase Lite} 206 | 207 | 208 | 209 | Bounds 210 | {{315, 395}, {138, 32}} 211 | Class 212 | ShapedGraphic 213 | ID 214 | 57 215 | Shape 216 | Rectangle 217 | Text 218 | 219 | Text 220 | {\rtf1\ansi\ansicpg1252\cocoartf1265 221 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 222 | {\colortbl;\red255\green255\blue255;} 223 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 224 | 225 | \f0\fs24 \cf0 Application Code} 226 | 227 | 228 | 229 | Bounds 230 | {{294, 343}, {182, 214}} 231 | Class 232 | ShapedGraphic 233 | ID 234 | 58 235 | Shape 236 | Rectangle 237 | Style 238 | 239 | Text 240 | 241 | Text 242 | {\rtf1\ansi\ansicpg1252\cocoartf1265 243 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 244 | {\colortbl;\red255\green255\blue255;} 245 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 246 | 247 | \f0\fs24 \cf0 Grocery Sync\ 248 | Client #2} 249 | 250 | TextPlacement 251 | 0 252 | 253 | 254 | ID 255 | 53 256 | 257 | 258 | Bounds 259 | {{419, 274}, {77, 14}} 260 | Class 261 | ShapedGraphic 262 | FitText 263 | YES 264 | Flow 265 | Resize 266 | ID 267 | 29 268 | Shape 269 | Rectangle 270 | Style 271 | 272 | fill 273 | 274 | Draws 275 | NO 276 | 277 | shadow 278 | 279 | Draws 280 | NO 281 | 282 | stroke 283 | 284 | Draws 285 | NO 286 | 287 | 288 | Text 289 | 290 | Pad 291 | 0 292 | RTFD 293 | 294 | BAtzdHJlYW10eXBlZIHoA4QBQISEhBJOU0F0dHJpYnV0 295 | ZWRTdHJpbmcAhIQITlNPYmplY3QAhZKEhIQITlNTdHJp 296 | bmcBlIQBKwPvv7yGhAJpSQEBkoSEhAxOU0RpY3Rpb25h 297 | cnkAlIQBaQGShJaWDE5TQXR0YWNobWVudIaShISEEE5T 298 | VGV4dEF0dGFjaG1lbnQAlIQCY0AAhISEDU5TRmlsZVdy 299 | YXBwZXIulJKEhIQNTlNNdXRhYmxlRGF0YQCEhAZOU0Rh 300 | dGEAlJmB9y6ECFsxMjAyM2NdcnRmZAAAAAADAAAABAAA 301 | AAIAAAAuLhcAAABfX0BVVEY4UHJlZmVycmVkTmFtZUBf 302 | XxMAAABfX0BQcmVmZXJyZWROYW1lQF9fAQAAAC5ALgAA 303 | GgAAABoAAAAmAAAAAQAAAAAAAICdHgAAkw8AAAAAAAAA 304 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 305 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 306 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 307 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 308 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 309 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 310 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 311 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 312 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 313 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 314 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 315 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 316 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 317 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 318 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 319 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 320 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 321 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 322 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 323 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 324 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 325 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 326 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 327 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 328 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 329 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 330 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 331 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 332 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 333 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 334 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 335 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 336 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 337 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 338 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 339 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 340 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 341 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 342 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 343 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 344 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 345 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 346 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 347 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 348 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 349 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 350 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 351 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 352 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 353 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 354 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 355 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 356 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 357 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 358 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 359 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 360 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 361 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 362 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 363 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 364 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 365 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 366 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 367 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 368 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 369 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 370 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 371 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 372 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 373 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 374 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 375 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 376 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 377 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 378 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 379 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 380 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 381 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 382 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 383 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 384 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 385 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 386 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 387 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 388 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 389 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 390 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 391 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 392 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 393 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 394 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 395 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 396 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 397 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 398 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 399 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 400 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 401 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 402 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 403 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 404 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 405 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 406 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 407 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 408 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 409 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 410 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 411 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 412 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 413 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 414 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 415 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 416 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 417 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 418 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 419 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 420 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 421 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 422 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 423 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 424 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAACVQREYtMS4zCiXE 425 | 5fLl66fzoNDExgo0IDAgb2JqCjw8IC9MZW5ndGggNSAw 426 | IFIgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4Kc3RyZWFt 427 | CngBVY6xCsJAEAX7fMWUl+Jyt2ei0TJBECuD24nVgV2K 428 | cP8PLngprN7sPB7sxsJGmIuQC5GS7RSDiBcOYzdwIq9M 429 | iqSqE96KKMMx0aMrQVUaQT+8cLcWH7uE05a/fIQqnlS4 430 | 1Oz3yfkHjRt3Y9UbvXNVe3T5AlXiIngKZW5kc3RyZWFt 431 | CmVuZG9iago1IDAgb2JqCjEyMQplbmRvYmoKMiAwIG9i 432 | ago8PCAvVHlwZSAvUGFnZSAvUGFyZW50IDMgMCBSIC9S 433 | ZXNvdXJjZXMgNiAwIFIgL0NvbnRlbnRzIDQgMCBSIC9N 434 | ZWRpYUJveCBbMCAwIDc3IDE0XQo+PgplbmRvYmoKNiAw 435 | IG9iago8PCAvUHJvY1NldCBbIC9QREYgL1RleHQgXSAv 436 | Q29sb3JTcGFjZSA8PCAvQ3MxIDcgMCBSID4+IC9Gb250 437 | IDw8IC9UVDEgOCAwIFIKPj4gPj4KZW5kb2JqCjkgMCBv 438 | YmoKPDwgL0xlbmd0aCAxMCAwIFIgL04gMSAvQWx0ZXJu 439 | YXRlIC9EZXZpY2VHcmF5IC9GaWx0ZXIgL0ZsYXRlRGVj 440 | b2RlID4+CnN0cmVhbQp4AYVVXWgcVRQ+uzM7eYlDEW1L 441 | K3XwryGkYVKtJha12026u03YrpuNNlWq09nZ7nQnM+Od 442 | 2bQJfQqCb1oQxFdFfBItiNBqxOTFvrRUqIkUiyAotFhB 443 | EPogCn5ndrI7G5HMcGe+Ofc7557z3XsYor5lw/edtEY0 444 | 54YiX8nOHp89ofV9R2lSqZ9wGWbgZ8vlKcau51r87r3u 445 | rVOKLTf2cazeuS2/MjUrMMFawfBqgTlHlNKJlGHTFyFR 446 | 3+uwj54NfcbvAz/QrFZywJ8Aq7EvID2Yt1xL2KaWF8aC 447 | VhZe3XaSuW41zzG2vOacFufK1x6M/qA5PYn3IHI+VzPG 448 | GT8F/KFpTEwDDwGv++HhSpuTTreaM9m2PT1UF0dmYvvx 449 | RqvAeJgovbTYqL4MvA34onuqdCzmr5hB7gTwY7DfbVhF 450 | 3g+NSNpmh8UqMHwlXXgV5oMjnaxZ4xPAzwIvNb1JzmEn 451 | 8HIwP8125n+/2MiVgLGWnD5jHC0Dbwe+33LyzEccecAP 452 | yxxzFHjKdUq8LuqV37SCqMYB4E/DRrUQ89dDUWXfR2D/ 453 | q24fKQJDh8xDDVFgO/LJFHwnOk9PAy+JVoVrfwL4kiEm 454 | 8sCImfnJcmdYQ2BFoZdSBlnk0Sk8TXLpH9QekE3zEfJJ 455 | YK6Ob4fyYLgYAsMB6zTQrxRinq3sH1ATNvZlRoBnGUPE 456 | /hrV8NX2szHLiCPejnzMTdwc4ri0SAZ47ZXvxDxP3iHr 457 | 8pMYB+Up+Tl5VB4jTX5BPiQ/L4/DOiYfjHwEfBcQtVsB 458 | r3gHUduR3qBWTz6ryDmEj0M/g+NFGQbI4G9EaEbMhBoX 459 | drUGfP+9t5fEa7Z5/Z0/Eupwbc24zq4+CV86llQ70r+2 460 | We3ML5nbmTU8b2ZuJarRMj9mbuG+2VOXF69moz4bmW8o 461 | y9rb2FWvh72xA5tZWVTuRHsyh2pZfd5RVp+VbAGHeNZh 462 | dWlfMuKV88s7O7wF0tbkS6/e6L9y/n81YX1YZ4sSqtTd 463 | C7t8/+THrKb1VuleiZaG9Iv6Xf0j/Qf9d31N/wDoN+ld 464 | 6Qvpa+my9KV0lTRpRVqVvpG+lT6TvsLX57CuSpeRW/LU 465 | tU9Z5/Qg0/Y5NOMTxvXwKQ6IFWA218/WDaXOYK6bKZ/t 466 | zSuwzt0T3VlLPazuVh9Vx9WH1cfVKXVQPaAeUneo+zFG 467 | 1IK6FzO7OypxT7HWNt5lvDf6zqbZSKv2jnBWDagnkKWB 468 | u5sX96jdiYY4qfugM0frcniNdnfbiKLF3euhYw2aQcU2 469 | nY20C/Dt4Bu7+R9v7klkl3oFJ8uW98gjcjHuwax8AF04 470 | 2dOPo9ylyoQyrmRJUwaVMWVEOco4qpU7VFP2YnYMz4lk 471 | 9oie4PQogr9PaJ3Df4so5/kLwj7dCLX9uv6MlsVv0tKK 472 | rjk8pBmOo0VTgSaswBLzVm2Y+B/MfkR/vhj9W1Pbr5ot 473 | Md+2USp1jehf+rqHewplbmRzdHJlYW0KZW5kb2JqCjEw 474 | IDAgb2JqCjEwODgKZW5kb2JqCjcgMCBvYmoKWyAvSUND 475 | QmFzZWQgOSAwIFIgXQplbmRvYmoKMyAwIG9iago8PCAv 476 | VHlwZSAvUGFnZXMgL01lZGlhQm94IFswIDAgNzcgMTRd 477 | IC9Db3VudCAxIC9LaWRzIFsgMiAwIFIgXSA+PgplbmRv 478 | YmoKMTEgMCBvYmoKPDwgL1R5cGUgL0NhdGFsb2cgL1Bh 479 | Z2VzIDMgMCBSID4+CmVuZG9iago4IDAgb2JqCjw8IC9U 480 | eXBlIC9Gb250IC9TdWJ0eXBlIC9UcnVlVHlwZSAvQmFz 481 | ZUZvbnQgL1ZKV1hURStIZWx2ZXRpY2EgL0ZvbnREZXNj 482 | cmlwdG9yCjEyIDAgUiAvRW5jb2RpbmcgL01hY1JvbWFu 483 | RW5jb2RpbmcgL0ZpcnN0Q2hhciAzMiAvTGFzdENoYXIg 484 | ODQgL1dpZHRocyBbIDI3OAowIDAgMCAwIDAgMCAwIDAg 485 | MCAwIDAgMCAwIDAgMjc4IDAgMCAwIDAgNTU2IDAgMCAw 486 | IDU1NiA1NTYgMjc4IDAgMCAwIDAgMCAwCjAgMCAwIDAg 487 | MCAwIDAgNzIyIDAgMCAwIDAgMCAwIDAgNjY3IDAgMCA2 488 | NjcgNjExIF0gPj4KZW5kb2JqCjEyIDAgb2JqCjw8IC9U 489 | eXBlIC9Gb250RGVzY3JpcHRvciAvRm9udE5hbWUgL1ZK 490 | V1hURStIZWx2ZXRpY2EgL0ZsYWdzIDMyIC9Gb250QkJv 491 | eCBbLTk1MSAtNDgxIDE0NDUgMTEyMl0KL0l0YWxpY0Fu 492 | Z2xlIDAgL0FzY2VudCA3NzAgL0Rlc2NlbnQgLTIzMCAv 493 | Q2FwSGVpZ2h0IDcxNyAvU3RlbVYgOTggL1hIZWlnaHQK 494 | NTIzIC9TdGVtSCA4NSAvQXZnV2lkdGggLTQ0MSAvTWF4 495 | V2lkdGggMTUwMCAvRm9udEZpbGUyIDEzIDAgUiA+Pgpl 496 | bmRvYmoKMTMgMCBvYmoKPDwgL0xlbmd0aCAxNCAwIFIg 497 | L0xlbmd0aDEgNzE2OCAvRmlsdGVyIC9GbGF0ZURlY29k 498 | ZSA+PgpzdHJlYW0KeAG9WXt4U1W2X3ufc5KTpI8kfSXp 499 | I0nTpGnTd5vS0l4bSlJaoFgoYlIpJKWpbYWxF2oFFKai 500 | IJTKqAjDgKPgaxRUDgU1hQ8GHRxkvCLq+GK8V734unOn 501 | 6swFPxWb3HVOSqX91I8//Dyna6+19tqPtX977b1zdnuX 502 | 3xSEWOgHBppaAj0dID2pJmQfLFkW6Inq2g+Qr1vS12uK 503 | 6pwdgFna0XP9sqjO3wegTL9+6aqx+gm3AsjrO4OB9qgd 504 | vkNe3okZUZ2UIc/qXNa7MqprDyHPW3rjkjF7glhPtyyw 505 | cqx/eA91068Cy4LR8gaxvayeG1f0juknkFf0LA+OlSde 506 | 9O9VIJirgntBATeAHCio8W1Fzz5TpgOLVtGOT9Hpv/1x 507 | cXz1BdDwkr648TcSf2X48HNfB7/LVt3Df4MZikvlRS7L 508 | CecAxBC0j6juGbdI9TBRhaDZEYIGpBokJ5LDMU0H/eQx 509 | uBtpNxIDXWQzrELahPQ7JHZcegK1YbJ5iOVdh8kqMJCZ 510 | LhVrnJ+oN+qUKuPrISI79IDxXd25I0SPs/ch0Q/FgmKa 511 | kuwmD0I7GMmjYCWroR7sZOfBnKVGP5qegB6kfiRGSgl5 512 | YiijxHiM5IGVJVjHBhksedb4aXG+8ePiECVDxheyQyyy 513 | 5zNQc8Ubj6c/YPxj+vXGY0j7oqa9OVjiWeMT6UuNWzNC 514 | ZOeQ8d70EME690TZTelY9VnjspztxvZiyT57e4juGzJW 515 | on2BS2UsrzAbnekfGQuzQzxBPT99tjG3+BVjFlbEYiZs 516 | 1OrSGNPStxqnoikj3ZM9FekI2Ut2QS7ZNWSdaTyMIg73 517 | YENOxfYQueVgvb3YGiKrXeX19u059dnWnNlGa05ddjbK 518 | C16S3yG/Tj5NXiJ3yO1ym9wsT5Un8lpezcfxMbyS53l5 519 | iDw5VGOUHSH7oAZh2XeQl/FciDyNmewR8pSU+dRzPMtT 520 | HvjEUOQDDF4CiSGy75BalFB4ViZJshB56mA06ymXkRUl 521 | VjKoqShjgilQwlOYCQK5KySD9cl9Nboa7VWayjr3jyV+ 522 | yXIpdfz4oyPpwvZZzV5hb7pPKBGFSLrvUnHdJeFHee9N 523 | aArWOhyz5q062NfT3eEJWjx+iyeI5Bc293XqhP42k+lA 524 | d49oMAmMzd+2pFPkgaDQYwm6hW6L23SgT6o3ydwhmvss 525 | 7gPQ4ZnvPdDhCrqH+lx9HkvA7TvYVru8dUJfm8b7Wl77 526 | A33Vio0tF/tqk+pN6qtVNLeJfbWKfbWKfbW52qS+xMF7 527 | upprV/RidJo8XbNMgr1ZaJjb4hVMAZ87RB7DTPdNwB0H 528 | NXcU7Fw/GNhCMAJE3kU6K/LwNZFPuJOgDi+L/JOpwkkd 529 | FomGa6rhONwFu2A/yOBxlO2wCHbAKdKNa3shHIK3SAYU 530 | QD+u+xDMhv8gkchr0AGPYPleeAG2wQGIwTrLIAmtW4g1 531 | shp1F8ptcEfkIciCCtgAR6ESW90CI5EnIgfROg+ugb2w 532 | D+u/TCz0AJsQeTryEfAwF9u8Ay2vRWZH9oMW8qAWmjD3 533 | DjhGrMzZSCfooAq9ux8ehD3wPPyDrCOHIp2RvsiZyIcY 534 | qjpIg2Z815BD5ENmP7shcn/k75EwImGHXOzVD1vhYWx/ 535 | P77HcWv1kBtIL9lKtlEXXUcPseu5lPAo4pADM/Cthxth 536 | IyIwDCfgX/AN+YLqGDXTy7wYcUb+D/fsWThKcSRB6MP3 537 | Tny34JiOEBkpItNJE1lD7iPbyBs0l15DvfRmupJ+wsxh 538 | FjKrmDfYFewQN8jtkKnCFyJHIicjb0IKpMN1sBzW4uhe 539 | gDNwHr4lDLaVRqykitSSRfj2k110mOwhw7SJHCdn6F7y 540 | PjlHviAXKUdjaBJ10F66le6jL9DTTBezjfkd8z5zgb2K 541 | o9we7mOZVf63cFt4U/h0pCryYeRr3GJ5MOPM1MIcWAwB 542 | HG0PlMGvcRRP4bsfZ+0EvAinpPccSYMR+BpRAKIlBlJC 543 | GvGdQ64mHaSLPEAO43tM8uUrihNBFVRDU2gabaZtdBnt 544 | p2/SfiaVyWVmMi3MfnxfYt5iLjIXWY5NYJPYGWwDDLLL 545 | 2J34PsY+zg6xr3KV3FXcHG4B189t4gaZJdxr3FuytbIt 546 | siHZF7IvcVucLb9RPoizcwpj9nmM5e8flmSh9yXwK1hC 547 | 3KQNtuNs7CEBGMDoaicbEa8esEdambXMDFqE0XAMbsFo 548 | 3QlrYBOzEPZE3mH2wtsYKUuxyX74A1sL6dxvcXbWQRFG 549 | 0djrysnNsWfbrFmWTLMJt/y0VINel5KclJig1ahjY1RK 550 | BS+XcSxDCeR5LHV+k2DzC6zNUl+fL+qWAGYELsvw41I2 551 | CXUTywgmsV4ATRNKurBkx6SSrmhJ13hJojZVQ3V+nslj 552 | MQmvuC2mEGmZ60X5LrfFZxJGJLlRku+W5FiUzWasYPLo 553 | Ot0mgfhNHqGur3PA43fn55FhF8KhzM8TNw4XqMSGBZge 554 | WIMbLEwXS3gEg8XtEfQWlNHGWD2BdqFprtfjTjWbfZiH 555 | WfO82Ed+XpeAfsLmmHZL++aQC9r8ohRY6BWYgE+gfrEt 556 | jUNIsbiFlNUf675XL0mewcuMArXWBYIDdYLLvxnBFVW/ 557 | qAUGUZvVbMJm6XqfVyDrx5wQfexGT0V3o2eC1d9tEhSW 558 | WkvnQLcfwYV53iGDyyBtvgI0eYf0Lr2k5OcN69ZWmXH0 559 | w/nT8qeJvMqsWxvln94ezX/9uMh1a098gHzWvHEAiIiA 560 | pQH9FExLpE4s6GyFmAQrYGBJBeKEj4/gMLvQn+kCxZhh 561 | rAJnbQgI/c2X3Oh0R53zd7uHFHqDdAjV+rC8f0A9FWcK 562 | y6stpoELeFr7LSP/mJgTGMuRWdUXQDSKEz0eKwIJXJL7 563 | xMPSiqPu1Fk6xfntk+YUdYvOc1kG6iI0os9CIh7gTV6z 564 | YPJhBv6azJsVAkWT9wAhW3whElkfAnf6MP5GZRYvQnOe 565 | GGpdbuwflfw8zMg1o1SQZ6rDnuvEWDENmAYa2gdMdaZO 566 | DCbWKnE0BAd8hYhgsxdxgvnYo8uXOi4Gfb6p2E6h2A5W 567 | weIDPmyhe6wF5FJW4SgWKsrDw5SxNXnneoV+d6rgcvtw 568 | FjB8jzd5heMYuT4flioe9xQ9XtOlG/O5BH0uzkV7abQV 569 | /O3Sj034BgbENpu9FrNwfGAgdUBcb1E9RGByhmssIwRi 570 | ERHyEOlvwrrILOZUaQ7MFjO65RMxLcOQvhRR+Jv9pxEu 571 | H/cba05Bb8slhCt+JoQrrwThqVeEcNW4pxMQrkafq0SE 572 | /+2XQ/iqCQjX/DTCrnG/0clp6K1LQrj2Z0J4+pUg7L4i 573 | hD3jnk5AuA599ogIz/jlEK6fgHDDTyM8c9xvdHIWejtT 574 | Qnj2z4Rw45UgPOeKEL563NMJCDehz1eLCM/95RCeNwHh 575 | 5p9GeP643+jkNejtfAnhBT8TwtdeCcLeK0LYN+7pBIRb 576 | 0GefiPB14wi7UgW4fB/un7Ttws++MS+8DHL8pcRpoZZW 577 | 4oczErsCypBqkRpQP4ffYXu4BbAfyc+ew9/g4ic2fmTj 578 | E4NfH+J9kQmcYzlS9g8kdDyPGZNY4LD2jz/ySaboRZIC 579 | lGP55VAOLfA4aSFf4i/3+XQv08c8gj/ma3EEZ/C7ksH7 580 | qenROyO+MAQsEq8OAZxBEnWUmfdQRi5HziBXvAeHsRbA 581 | AsdhbIlDXlRcqjFrspFq2S2h7/6bO/rt9BDbeBHvIKIj 582 | pt1SXw5XipykkN/iRxClaVqGAcooxfsIRl+o+yvUVNdU 583 | c3cWONaoT5BWUkos5PUd4YIdYmsIOn7HoH/c/SjFwkJX 584 | poIq+Vhs55hWJpNTGeHkPH5byZX0JhX3BRMjZ5kQSXmG 585 | bI/ln1SGiPcgFz8jTt13QvfXC+erRz+Cmhpk1ZrKSqLR 586 | VuJfJXbMrlG/GF9cRDQKojE7SammNMmioY+GneT06CC9 587 | e8cbb+Bn2abRm8McWSQwW75b/PvwQyLQDNRG3mYN6JsK 588 | v/lK4GXXjAXkWkVLvC+hnQQVN8R3JdxsVTSob9H3WZZb 589 | V2TfWnxryUb9naY7szcWbCzeoY+dwZfw1jhqLVE5NZo8 590 | zpnBpTjzYmkF/mDY8FxcRc6NhXxFKsrPJFYUls0olYYx 591 | cn5EfQETqBmpGdFWFo5Eh6KtLC6avsrlzC1IM2mTmdjk 592 | /EQ7xDji7ESp5e0gS8eENVI7SSpIsUNsLibyNM5OGBMm 593 | eFnocBAxcdyGD2nFa8tyZ5nNkilLSkwu1V4mQ7bNWVZe 594 | WoKfR3KZPFn8TKKWzCzMm0If2dB/+7re7R0bH927/raH 595 | t90ffib36s/ePP13t63JV7o4/Nlr4fdvXc241i9s2rCh 596 | Jbh8tOrODZvv3rqu52G629HUv/uTd+/Z0FyYn+Ns3300 597 | /M25d349XCzOf0PkHVbD7YRUyIZ9rgI95+DsyfUyL9fJ 598 | bdJvNOwwKOp4uTk726lU6sxONcc6U0/qYuW0Wp5RjLdk 599 | 17hUsZCTeltWRWzODPv3EI5Wrpk1b+XqQh0COYYkhoME 600 | YpnRpjeoEgijtVJbZnyWHUyaDIRKj3cPNhWqljiznRgT 601 | MCEG1g7WmGz7ZRCOYUgQnNKS8oQ4YsmkzjJtqSkhOUkt 602 | p+ZMm/NydImav2GK57ZnbdUHOl795+efkcqba6++PXzy 603 | 9bO05MCDt9yxa+M20rKtMuNt0rC4kdCX/0Ts4U92/U/4 604 | m5fDT7/3GLHdJTyw68B9g4+KWJ3DhXeINUvru8Rl4HLl 605 | TC7g4lCkpBg40s6Cnle0m1feipdxc8434kKY4wm6P8FF 606 | 0TiiHikuShADH+nca/iw5rOjW/HCSVzLe3AXLMS1rIIa 607 | l5lXZDCUsoQq5Twrt8o4QyxRWlWgj4mJ3W3u68HG1XPO 608 | Vzdi6+qvRCat8MpC7E7sAreLUo0FU8ueU/S7U6dG2VPc 609 | 0dE9dPG30+n+0bnYH8VvfmC/xv6UkAgBl7Mrpku7Kma1 610 | lq1P9CZ2Jq5OZOV8hkatVpK4+AzcSJQ8lWljWEViYjFr 611 | SI5XWEGflBwiqoPmbZuiQ5V8aRzVaFMqcbToiRqXDjLS 612 | WlzUmmAWw1lmQZcwvJGZS8qd++m2E1++9V/hkpNM/8ra 613 | FeFeMrjhD9zR/3zpycjoVnZ4qjHMLL9b9NUfeZP9ivsY 614 | CvFOIexalBOfbbHZyuOc5hm2NtvquJuzFDfwurgUK/XF 615 | dcbtzWSUcVMzszKVDJum25BYWOhIm5rIsFMdiiKqjOM1 616 | WZlGe1GRRmdNaeCtdkOJ0appAGuhvrhkt7l7bDC4+hHZ 617 | RmQ4CC3uZSLhsKJhrB4RR1kwWtr671I0N9oLNEbgqY3a 618 | 8q0yq8HG5IED8gskxuXyDpKeYHRAapLOQfQ6ks86QJGt 619 | chCrihSgLM/BJEObhsZkTKQ4V6txu1BXi/tFNJX2DWiN 620 | hvwU3C6ybYXEJm4VWaUlbJIFRWkvSUk2imWSElmLKds2 621 | hZAMedmSb3sWDs2a/dDJP80dJNqLn5LpR+KLrzsr7Gyp 622 | OnN629zB8O//N/z5rl0MbSRn18y513TV7pWlJdb8POfC 623 | 5/4cfv9CX82K+9qWlpiKCjOrrj9x/vXBzZ+zKjFm8SwW 624 | IwvPrDKXgcgyQE5ZXlwIcJEyVo69KNPzg4t0jjnq843i 625 | mXD+0loQQxZPgyQMBzwO2FNhzV/CGu7o/m//xcVhYIpz 626 | Lj2RIN4X/tCD3eMK1OKZkIq3mOmIdimex1Mwl2Bu9NeB 627 | DP83BAtmXuud73HUB5f2BXu7lgSkEpdaxHMPXEhNSH6k 628 | HqR+JAw62I0kIB1HOhMZe1CGcZmAaZJeOEkX27+8fMUk 629 | HX/tTLBPnaTXT9JFPy9vr3mSPl/U/x9RDog1CmVuZHN0 630 | cmVhbQplbmRvYmoKMTQgMCBvYmoKNDMzOAplbmRvYmoK 631 | MTUgMCBvYmoKKE1hYyBPUyBYIDEwLjkgUXVhcnR6IFBE 632 | RkNvbnRleHQpCmVuZG9iagoxNiAwIG9iagooRDoyMDE0 633 | MDEyOTE2MzMwNFowMCcwMCcpCmVuZG9iagoxIDAgb2Jq 634 | Cjw8IC9Qcm9kdWNlciAxNSAwIFIgL0NyZWF0aW9uRGF0 635 | ZSAxNiAwIFIgL01vZERhdGUgMTYgMCBSID4+CmVuZG9i 636 | agp4cmVmCjAgMTcKMDAwMDAwMDAwMCA2NTUzNSBmIAow 637 | MDAwMDA2OTAxIDAwMDAwIG4gCjAwMDAwMDAyMzYgMDAw 638 | MDAgbiAKMDAwMDAwMTY4MiAwMDAwMCBuIAowMDAwMDAw 639 | MDIyIDAwMDAwIG4gCjAwMDAwMDAyMTcgMDAwMDAgbiAK 640 | MDAwMDAwMDMzOCAwMDAwMCBuIAowMDAwMDAxNjQ3IDAw 641 | MDAwIG4gCjAwMDAwMDE4MTMgMDAwMDAgbiAKMDAwMDAw 642 | MDQzNSAwMDAwMCBuIAowMDAwMDAxNjI2IDAwMDAwIG4g 643 | CjAwMDAwMDE3NjMgMDAwMDAgbiAKMDAwMDAwMjEwOSAw 644 | MDAwMCBuIAowMDAwMDAyMzYwIDAwMDAwIG4gCjAwMDAw 645 | MDY3ODggMDAwMDAgbiAKMDAwMDAwNjgwOSAwMDAwMCBu 646 | IAowMDAwMDA2ODU5IDAwMDAwIG4gCnRyYWlsZXIKPDwg 647 | L1NpemUgMTcgL1Jvb3QgMTEgMCBSIC9JbmZvIDEgMCBS 648 | IC9JRCBbIDw3NjNjYjUyNjkxODg2MmVjOWUwZmUyYTIy 649 | ZGMzOGJmYz4KPDc2M2NiNTI2OTE4ODYyZWM5ZTBmZTJh 650 | MjJkYzM4YmZjPiBdID4+CnN0YXJ0eHJlZgo2OTc2CiUl 651 | RU9GCjEgMCBvYmoKPDwvQXV0aG9yIChUcmF1biBMZXlk 652 | ZW4pL0NyZWF0aW9uRGF0ZSAoRDoyMDEzMTAyMzE2MzIw 653 | MFopL0NyZWF0b3IgKE9tbmlHcmFmZmxlIFByb2Zlc3Np 654 | b25hbCA1LjMuNikvTW9kRGF0ZSAoRDoyMDE0MDEyOTE2 655 | MzMwMFopL1Byb2R1Y2VyIDE1IDAgUiAvVGl0bGUgKEdy 656 | b2NlcnlTeW5jKT4+CmVuZG9iagp4cmVmCjEgMQowMDAw 657 | MDA3NDczIDAwMDAwIG4gCnRyYWlsZXIKPDwvSUQgWzw3 658 | NjNjYjUyNjkxODg2MmVjOWUwZmUyYTIyZGMzOGJmYz4g 659 | PDc2M2NiNTI2OTE4ODYyZWM5ZTBmZTJhMjJkYzM4YmZj 660 | Pl0gL0luZm8gMSAwIFIgL1ByZXYgNjk3NiAvUm9vdCAx 661 | MSAwIFIgL1NpemUgMTc+PgpzdGFydHhyZWYKNzY1NAol 662 | JUVPRgoBAAAAEgAAAFBhc3RlZCBHcmFwaGljLnBkZgEA 663 | AAASAAAAUGFzdGVkIEdyYXBoaWMucGRmAQAAAB4AAAAB 664 | AAAAAgAAAC4uEAAAAAAAAAC2AQAAAgAAAAEAAACGhoaG 665 | hg== 666 | 667 | VerticalPad 668 | 0 669 | 670 | Wrap 671 | NO 672 | 673 | 674 | Bounds 675 | {{132, 53}, {268, 28}} 676 | Class 677 | ShapedGraphic 678 | FitText 679 | YES 680 | Flow 681 | Resize 682 | ID 683 | 28 684 | Shape 685 | Rectangle 686 | Style 687 | 688 | fill 689 | 690 | Draws 691 | NO 692 | 693 | shadow 694 | 695 | Draws 696 | NO 697 | 698 | stroke 699 | 700 | Draws 701 | NO 702 | 703 | 704 | Text 705 | 706 | Pad 707 | 0 708 | Text 709 | {\rtf1\ansi\ansicpg1252\cocoartf1265 710 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 711 | {\colortbl;\red255\green255\blue255;} 712 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 713 | 714 | \f0\fs46 \cf0 Grocery Sync Architecture} 715 | VerticalPad 716 | 0 717 | 718 | Wrap 719 | NO 720 | 721 | 722 | Class 723 | LineGraphic 724 | Head 725 | 726 | ID 727 | 10 728 | 729 | ID 730 | 26 731 | Points 732 | 733 | {263, 168} 734 | {263, 200.5} 735 | 736 | Style 737 | 738 | stroke 739 | 740 | HeadArrow 741 | StickArrow 742 | TailArrow 743 | StickArrow 744 | 745 | 746 | Tail 747 | 748 | ID 749 | 3 750 | 751 | 752 | 753 | Bounds 754 | {{45, 274}, {77, 14}} 755 | Class 756 | ShapedGraphic 757 | FitText 758 | YES 759 | Flow 760 | Resize 761 | ID 762 | 22 763 | Shape 764 | Rectangle 765 | Style 766 | 767 | fill 768 | 769 | Draws 770 | NO 771 | 772 | shadow 773 | 774 | Draws 775 | NO 776 | 777 | stroke 778 | 779 | Draws 780 | NO 781 | 782 | 783 | Text 784 | 785 | Pad 786 | 0 787 | Text 788 | {\rtf1\ansi\ansicpg1252\cocoartf1265 789 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 790 | {\colortbl;\red255\green255\blue255;} 791 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 792 | 793 | \f0\fs24 \cf0 HTTP/S :4984} 794 | VerticalPad 795 | 0 796 | 797 | Wrap 798 | NO 799 | 800 | 801 | Class 802 | LineGraphic 803 | ControlPoints 804 | 805 | {-53, -9.5} 806 | {-411.75626, 102.51122} 807 | 808 | Head 809 | 810 | ID 811 | 10 812 | 813 | ID 814 | 33 815 | Points 816 | 817 | {169.33502, 499.68781} 818 | {254.46448, 250.47313} 819 | 820 | Style 821 | 822 | stroke 823 | 824 | Bezier 825 | 826 | HeadArrow 827 | FilledArrow 828 | LineType 829 | 1 830 | TailArrow 831 | FilledArrow 832 | 833 | 834 | Tail 835 | 836 | ID 837 | 50 838 | 839 | 840 | 841 | Bounds 842 | {{150, 201}, {226, 49}} 843 | Class 844 | ShapedGraphic 845 | ID 846 | 10 847 | Shape 848 | Rectangle 849 | Text 850 | 851 | Text 852 | {\rtf1\ansi\ansicpg1252\cocoartf1265 853 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 854 | {\colortbl;\red255\green255\blue255;} 855 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 856 | 857 | \f0\fs24 \cf0 Sync Gateway} 858 | 859 | 860 | 861 | Bounds 862 | {{150, 114.5}, {226, 53}} 863 | Class 864 | ShapedGraphic 865 | ID 866 | 3 867 | Shape 868 | Rectangle 869 | Text 870 | 871 | Text 872 | {\rtf1\ansi\ansicpg1252\cocoartf1265 873 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 874 | {\colortbl;\red255\green255\blue255;} 875 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 876 | 877 | \f0\fs24 \cf0 Couchbase \ 878 | Server} 879 | 880 | 881 | 882 | Class 883 | Group 884 | Graphics 885 | 886 | 887 | Bounds 888 | {{114.5, 453.05316}, {95, 24}} 889 | Class 890 | ShapedGraphic 891 | FitText 892 | YES 893 | Flow 894 | Resize 895 | FontInfo 896 | 897 | Color 898 | 899 | w 900 | 0 901 | 902 | Font 903 | Helvetica 904 | Size 905 | 12 906 | 907 | ID 908 | 48 909 | Line 910 | 911 | ID 912 | 49 913 | Position 914 | 0.52040815353393555 915 | RotationType 916 | 0 917 | 918 | Shape 919 | Rectangle 920 | Style 921 | 922 | shadow 923 | 924 | Draws 925 | NO 926 | 927 | stroke 928 | 929 | Draws 930 | NO 931 | 932 | 933 | Text 934 | 935 | Text 936 | {\rtf1\ansi\ansicpg1252\cocoartf1265 937 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 938 | {\colortbl;\red255\green255\blue255;} 939 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 940 | 941 | \f0\fs24 \cf0 Native Java API} 942 | 943 | Wrap 944 | NO 945 | 946 | 947 | Class 948 | LineGraphic 949 | Head 950 | 951 | ID 952 | 50 953 | 954 | ID 955 | 49 956 | Points 957 | 958 | {162, 427.5} 959 | {162, 499.66095} 960 | 961 | Style 962 | 963 | stroke 964 | 965 | HeadArrow 966 | StickArrow 967 | TailArrow 968 | StickArrow 969 | 970 | 971 | Tail 972 | 973 | ID 974 | 51 975 | 976 | 977 | 978 | Bounds 979 | {{93, 500.16095}, {138, 42}} 980 | Class 981 | ShapedGraphic 982 | ID 983 | 50 984 | Shape 985 | Rectangle 986 | Text 987 | 988 | Text 989 | {\rtf1\ansi\ansicpg1252\cocoartf1265 990 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 991 | {\colortbl;\red255\green255\blue255;} 992 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 993 | 994 | \f0\fs24 \cf0 Couchbase Lite} 995 | 996 | 997 | 998 | Bounds 999 | {{93, 395}, {138, 32}} 1000 | Class 1001 | ShapedGraphic 1002 | ID 1003 | 51 1004 | Shape 1005 | Rectangle 1006 | Text 1007 | 1008 | Text 1009 | {\rtf1\ansi\ansicpg1252\cocoartf1265 1010 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1011 | {\colortbl;\red255\green255\blue255;} 1012 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1013 | 1014 | \f0\fs24 \cf0 Application Code} 1015 | 1016 | 1017 | 1018 | Bounds 1019 | {{72, 343}, {182, 214}} 1020 | Class 1021 | ShapedGraphic 1022 | ID 1023 | 52 1024 | Shape 1025 | Rectangle 1026 | Style 1027 | 1028 | Text 1029 | 1030 | Text 1031 | {\rtf1\ansi\ansicpg1252\cocoartf1265 1032 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 1033 | {\colortbl;\red255\green255\blue255;} 1034 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc 1035 | 1036 | \f0\fs24 \cf0 Grocery Sync\ 1037 | Client #1} 1038 | 1039 | TextPlacement 1040 | 0 1041 | 1042 | 1043 | ID 1044 | 47 1045 | 1046 | 1047 | GridInfo 1048 | 1049 | GuidesLocked 1050 | NO 1051 | GuidesVisible 1052 | YES 1053 | HPages 1054 | 1 1055 | ImageCounter 1056 | 1 1057 | KeepToScale 1058 | 1059 | Layers 1060 | 1061 | 1062 | Lock 1063 | NO 1064 | Name 1065 | Layer 1 1066 | Print 1067 | YES 1068 | View 1069 | YES 1070 | 1071 | 1072 | LayoutInfo 1073 | 1074 | Animate 1075 | NO 1076 | circoMinDist 1077 | 18 1078 | circoSeparation 1079 | 0.0 1080 | layoutEngine 1081 | dot 1082 | neatoSeparation 1083 | 0.0 1084 | twopiSeparation 1085 | 0.0 1086 | 1087 | LinksVisible 1088 | NO 1089 | MagnetsVisible 1090 | NO 1091 | MasterSheets 1092 | 1093 | ModificationDate 1094 | 2014-01-29 16:50:18 +0000 1095 | Modifier 1096 | Traun Leyden 1097 | NotesVisible 1098 | NO 1099 | Orientation 1100 | 2 1101 | OriginVisible 1102 | NO 1103 | PageBreaks 1104 | YES 1105 | PrintInfo 1106 | 1107 | NSBottomMargin 1108 | 1109 | float 1110 | 41 1111 | 1112 | NSHorizonalPagination 1113 | 1114 | int 1115 | 0 1116 | 1117 | NSLeftMargin 1118 | 1119 | float 1120 | 18 1121 | 1122 | NSPaperSize 1123 | 1124 | coded 1125 | BAtzdHJlYW10eXBlZIHoA4QBQISEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAx7X05TU2l6ZT1mZn2WgWQCgRgDhg== 1126 | 1127 | NSPrintReverseOrientation 1128 | 1129 | int 1130 | 0 1131 | 1132 | NSRightMargin 1133 | 1134 | float 1135 | 18 1136 | 1137 | NSTopMargin 1138 | 1139 | float 1140 | 18 1141 | 1142 | 1143 | PrintOnePage 1144 | 1145 | ReadOnly 1146 | NO 1147 | RowAlign 1148 | 1 1149 | RowSpacing 1150 | 36 1151 | SheetTitle 1152 | Canvas 1 1153 | SmartAlignmentGuidesActive 1154 | YES 1155 | SmartDistanceGuidesActive 1156 | YES 1157 | UniqueID 1158 | 1 1159 | UseEntirePage 1160 | 1161 | VPages 1162 | 1 1163 | WindowInfo 1164 | 1165 | CurrentSheet 1166 | 0 1167 | ExpandedCanvases 1168 | 1169 | 1170 | name 1171 | Canvas 1 1172 | 1173 | 1174 | Frame 1175 | {{305, 48}, {710, 830}} 1176 | ListView 1177 | 1178 | OutlineWidth 1179 | 142 1180 | RightSidebar 1181 | 1182 | ShowRuler 1183 | 1184 | Sidebar 1185 | 1186 | SidebarWidth 1187 | 120 1188 | VisibleRegion 1189 | {{0, 33}, {575, 675}} 1190 | Zoom 1191 | 1 1192 | ZoomValues 1193 | 1194 | 1195 | Canvas 1 1196 | 1 1197 | 1 1198 | 1199 | 1200 | 1201 | saveQuickLookFiles 1202 | YES 1203 | 1204 | 1205 | -------------------------------------------------------------------------------- /docs/GrocerySync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/docs/GrocerySync.png -------------------------------------------------------------------------------- /docs/sync_gw_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": ["CRUD+", "REST+", "Changes+", "Attach+"], 3 | "databases": { 4 | "grocery-sync": { 5 | "server": "walrus:", 6 | "sync": ` 7 | function(doc){ 8 | channel(doc.channels); 9 | }`, 10 | "users": { 11 | "GUEST": {"disabled": false, "admin_channels": ["*"]} 12 | } 13 | 14 | } 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/GrocerySync-Android/d1184ff6584511bd58ef4ddce5d968dc2e99d95c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Dec 08 14:48:58 PST 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\" \"-Xmx1024m\" \"-Xms256m\" \"-XX:MaxPermSize=1024m\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /local.properties.example: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Studio. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must *NOT* be checked into Version Control Systems, 5 | # as it contains information specific to your local configuration. 6 | 7 | # Location of the SDK. This is only used by Gradle. 8 | # For customization when using a Version Control System, please read the 9 | # header note. 10 | sdk.dir=/Applications/Android Studio.app/sdk -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':GrocerySync-Android' 2 | 3 | --------------------------------------------------------------------------------