Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stefan-niedermann/nextcloud-notes.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--.idea/.name1
-rw-r--r--.idea/codeStyleSettings.xml229
-rw-r--r--.idea/compiler.xml22
-rw-r--r--.idea/copyright/profiles_settings.xml3
-rw-r--r--.idea/gradle.xml19
-rw-r--r--.idea/misc.xml46
-rw-r--r--.idea/modules.xml9
-rw-r--r--.idea/runConfigurations.xml12
-rw-r--r--.idea/vcs.xml6
-rw-r--r--.navigation/app/raw/main.nvg.xml0
-rw-r--r--OwnCloudNotes.iml19
-rw-r--r--app/.classpath9
-rw-r--r--app/.gitignore1
-rw-r--r--app/.project33
-rw-r--r--app/app.iml103
-rw-r--r--app/build.gradle29
-rw-r--r--app/ic_launcher-web.pngbin0 -> 51394 bytes
-rw-r--r--app/proguard-project.txt20
-rw-r--r--app/proguard-rules.pro17
-rw-r--r--app/project.properties14
-rw-r--r--app/src/androidTest/java/it/niedermann/owncloud/notes/ApplicationTest.java13
-rw-r--r--app/src/androidTest/java/it/niedermann/owncloud/notes/util/URLValidatorAsyncTaskTest.java14
-rw-r--r--app/src/main/AndroidManifest.xml63
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java14
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/CreateNoteActivity.java66
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java64
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteActivity.java120
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java359
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/android/activity/SettingsActivity.java175
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/DBStatus.java20
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/Note.java74
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/model/NoteAdapter.java70
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java305
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java295
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/ICallback.java8
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java207
-rw-r--r--app/src/main/java/it/niedermann/owncloud/notes/util/NotesClientUtil.java84
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_cancel.pngbin0 -> 402 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_copy.pngbin0 -> 534 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_delete.pngbin0 -> 399 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_done.pngbin0 -> 400 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_done_dark.pngbin0 -> 729 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_edit.pngbin0 -> 302 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_new.pngbin0 -> 97 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_settings.pngbin0 -> 1153 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_action_share.pngbin0 -> 980 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/ic_launcher.pngbin0 -> 2198 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_cancel.pngbin0 -> 304 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_copy.pngbin0 -> 370 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_delete.pngbin0 -> 274 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_done.pngbin0 -> 306 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_done_dark.pngbin0 -> 502 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_edit.pngbin0 -> 239 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_new.pngbin0 -> 97 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_settings.pngbin0 -> 781 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_action_share.pngbin0 -> 646 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/ic_launcher.pngbin0 -> 1685 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_cancel.pngbin0 -> 499 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_copy.pngbin0 -> 663 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_delete.pngbin0 -> 506 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_done.pngbin0 -> 519 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_done_dark.pngbin0 -> 923 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_edit.pngbin0 -> 355 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_new.pngbin0 -> 102 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_settings.pngbin0 -> 1573 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_action_share.pngbin0 -> 1343 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/ic_launcher.pngbin0 -> 3395 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_cancel.pngbin0 -> 834 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_copy.pngbin0 -> 1027 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_delete.pngbin0 -> 715 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_done.pngbin0 -> 732 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_done_dark.pngbin0 -> 1260 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_edit.pngbin0 -> 522 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_new.pngbin0 -> 113 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_settings.pngbin0 -> 2756 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_action_share.pngbin0 -> 2143 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 4496 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_cancel.pngbin0 -> 1065 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_copy.pngbin0 -> 1398 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_delete.pngbin0 -> 957 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_done.pngbin0 -> 1002 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_done_dark.pngbin0 -> 1732 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_edit.pngbin0 -> 653 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_new.pngbin0 -> 116 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_settings.pngbin0 -> 4088 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/ic_action_share.pngbin0 -> 3361 bytes
-rw-r--r--app/src/main/res/drawable/list_item_background_selector.xml7
-rw-r--r--app/src/main/res/drawable/list_item_color_selector.xml7
-rw-r--r--app/src/main/res/drawable/list_item_color_selector_low.xml7
-rw-r--r--app/src/main/res/drawable/settings.xml8
-rw-r--r--app/src/main/res/layout/activity_about.xml53
-rw-r--r--app/src/main/res/layout/activity_create.xml24
-rw-r--r--app/src/main/res/layout/activity_edit.xml22
-rw-r--r--app/src/main/res/layout/activity_notes_list_view.xml29
-rw-r--r--app/src/main/res/layout/activity_settings.xml103
-rw-r--r--app/src/main/res/layout/activity_single_note.xml21
-rw-r--r--app/src/main/res/layout/fragment_notes_list_view.xml34
-rw-r--r--app/src/main/res/menu/menu_list_context_multiple.xml12
-rw-r--r--app/src/main/res/menu/menu_list_context_single.xml24
-rw-r--r--app/src/main/res/menu/menu_list_view.xml18
-rw-r--r--app/src/main/res/menu/menu_menu_create.xml18
-rw-r--r--app/src/main/res/menu/menu_menu_edit.xml18
-rw-r--r--app/src/main/res/menu/menu_note_list_view.xml24
-rw-r--r--app/src/main/res/values-de/strings.xml55
-rw-r--r--app/src/main/res/values/colors.xml14
-rw-r--r--app/src/main/res/values/dimens.xml12
-rw-r--r--app/src/main/res/values/strings.xml56
-rw-r--r--app/src/main/res/values/styles.xml27
-rw-r--r--build.gradle23
-rw-r--r--gradle.properties18
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties6
-rw-r--r--gradlew164
-rw-r--r--gradlew.bat90
-rw-r--r--settings.gradle1
116 files changed, 3445 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..ec870c9f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 00000000..84405a01
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+OwnCloudNotes \ No newline at end of file
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
new file mode 100644
index 00000000..d8f708f1
--- /dev/null
+++ b/.idea/codeStyleSettings.xml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectCodeStyleSettingsManager">
+ <option name="PER_PROJECT_SETTINGS">
+ <value>
+ <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
+ <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
+ <value />
+ </option>
+ <option name="IMPORT_LAYOUT_TABLE">
+ <value>
+ <package name="android" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="com" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="junit" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="net" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="org" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="java" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="javax" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="false" />
+ <emptyLine />
+ <package name="" withSubpackages="true" static="true" />
+ <emptyLine />
+ </value>
+ </option>
+ <option name="RIGHT_MARGIN" value="100" />
+ <AndroidXmlCodeStyleSettings>
+ <option name="USE_CUSTOM_SETTINGS" value="true" />
+ </AndroidXmlCodeStyleSettings>
+ <Objective-C-extensions>
+ <option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
+ <option name="RELEASE_STYLE" value="IVAR" />
+ <option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
+ <file>
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
+ </file>
+ <class>
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
+ <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
+ </class>
+ <extensions>
+ <pair source="cpp" header="h" />
+ <pair source="c" header="h" />
+ </extensions>
+ </Objective-C-extensions>
+ <XML>
+ <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
+ </XML>
+ <codeStyleSettings language="XML">
+ <option name="FORCE_REARRANGE_MODE" value="1" />
+ <indentOptions>
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ </indentOptions>
+ <arrangement>
+ <rules>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:android</NAME>
+ <XML_NAMESPACE>Namespace:</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>xmlns:.*</NAME>
+ <XML_NAMESPACE>Namespace:</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:id</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:name</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>name</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>style</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_NAMESPACE>^$</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:layout_width</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:layout_height</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:layout_.*</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:width</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*:height</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ <section>
+ <rule>
+ <match>
+ <AND>
+ <NAME>.*</NAME>
+ <XML_NAMESPACE>.*</XML_NAMESPACE>
+ </AND>
+ </match>
+ <order>BY_NAME</order>
+ </rule>
+ </section>
+ </rules>
+ </arrangement>
+ </codeStyleSettings>
+ </value>
+ </option>
+ <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 00000000..96cc43ef
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerConfiguration">
+ <resourceExtensions />
+ <wildcardResourcePatterns>
+ <entry name="!?*.java" />
+ <entry name="!?*.form" />
+ <entry name="!?*.class" />
+ <entry name="!?*.groovy" />
+ <entry name="!?*.scala" />
+ <entry name="!?*.flex" />
+ <entry name="!?*.kt" />
+ <entry name="!?*.clj" />
+ <entry name="!?*.aj" />
+ </wildcardResourcePatterns>
+ <annotationProcessing>
+ <profile default="true" name="Default" enabled="false">
+ <processorPath useClasspath="true" />
+ </profile>
+ </annotationProcessing>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 00000000..e7bedf33
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+<component name="CopyrightManager">
+ <settings default="" />
+</component> \ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 00000000..0833b17c
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="GradleSettings">
+ <option name="linkedExternalProjectsSettings">
+ <GradleProjectSettings>
+ <option name="distributionType" value="LOCAL" />
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
+ <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.4" />
+ <option name="gradleJvm" value="1.7" />
+ <option name="modules">
+ <set>
+ <option value="$PROJECT_DIR$" />
+ <option value="$PROJECT_DIR$/app" />
+ </set>
+ </option>
+ </GradleProjectSettings>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 00000000..1a3eaffb
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="EntryPointsManager">
+ <entry_points version="2.0" />
+ </component>
+ <component name="NullableNotNullManager">
+ <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+ <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+ <option name="myNullables">
+ <value>
+ <list size="4">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+ <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+ <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+ </list>
+ </value>
+ </option>
+ <option name="myNotNulls">
+ <value>
+ <list size="4">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+ <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+ <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+ </list>
+ </value>
+ </option>
+ </component>
+ <component name="ProjectLevelVcsManager" settingsEditedManually="false">
+ <OptionsSetting value="true" id="Add" />
+ <OptionsSetting value="true" id="Remove" />
+ <OptionsSetting value="true" id="Checkout" />
+ <OptionsSetting value="true" id="Update" />
+ <OptionsSetting value="true" id="Status" />
+ <OptionsSetting value="true" id="Edit" />
+ <ConfirmationsSetting value="0" id="Add" />
+ <ConfirmationsSetting value="0" id="Remove" />
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/build/classes" />
+ </component>
+ <component name="ProjectType">
+ <option name="id" value="Android" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..c884bee9
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/OwnCloudNotes.iml" filepath="$PROJECT_DIR$/OwnCloudNotes.iml" />
+ <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
+ </modules>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 00000000..7f68460d
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="RunConfigurationProducerService">
+ <option name="ignoredProducers">
+ <set>
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+ </set>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..6564d52d
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="VcsDirectoryMappings">
+ <mapping directory="" vcs="" />
+ </component>
+</project> \ No newline at end of file
diff --git a/.navigation/app/raw/main.nvg.xml b/.navigation/app/raw/main.nvg.xml
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.navigation/app/raw/main.nvg.xml
diff --git a/OwnCloudNotes.iml b/OwnCloudNotes.iml
new file mode 100644
index 00000000..dd9b22e6
--- /dev/null
+++ b/OwnCloudNotes.iml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id="OwnCloudNotes" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="java-gradle" name="Java-Gradle">
+ <configuration>
+ <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
+ <option name="BUILDABLE" value="false" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ </component>
+</module> \ No newline at end of file
diff --git a/app/.classpath b/app/.classpath
new file mode 100644
index 00000000..51769745
--- /dev/null
+++ b/app/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 00000000..3543521e
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/.project b/app/.project
new file mode 100644
index 00000000..b3936bdb
--- /dev/null
+++ b/app/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>OwnCloudNotes</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/app/app.iml b/app/app.iml
new file mode 100644
index 00000000..b52645ec
--- /dev/null
+++ b/app/app.iml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="OwnCloudNotes" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android-gradle" name="Android-Gradle">
+ <configuration>
+ <option name="GRADLE_PROJECT_PATH" value=":app" />
+ </configuration>
+ </facet>
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
+ <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+ <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+ <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
+ <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
+ <afterSyncTasks>
+ <task>generateDebugAndroidTestSources</task>
+ <task>generateDebugSources</task>
+ </afterSyncTasks>
+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
+ <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+ <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+ <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.0.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/gridlayout-v7/23.0.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.commonsware.cwac/anddown/0.2.4/jars" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+ <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" exported="" name="gridlayout-v7-23.0.1" level="project" />
+ <orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
+ <orderEntry type="library" exported="" name="anddown-0.2.4" level="project" />
+ <orderEntry type="library" exported="" name="design-23.0.1" level="project" />
+ <orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
+ <orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
+ </component>
+</module> \ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 00000000..05ec6f3e
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,29 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 23
+ buildToolsVersion "23.0.1"
+
+ defaultConfig {
+ applicationId "it.niedermann.owncloud.notes"
+ minSdkVersion 22
+ targetSdkVersion 23
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile 'com.commonsware.cwac:anddown:0.2.4'
+ compile 'com.android.support:support-v4:23.0.1'
+ compile 'com.android.support:appcompat-v7:23.0.1'
+ compile 'com.android.support:gridlayout-v7:23.0.1'
+ compile 'com.android.support:design:23.0.1'
+ compile fileTree(include: ['*.jar'], dir: 'libs')
+}
diff --git a/app/ic_launcher-web.png b/app/ic_launcher-web.png
new file mode 100644
index 00000000..a18cbb48
--- /dev/null
+++ b/app/ic_launcher-web.png
Binary files differ
diff --git a/app/proguard-project.txt b/app/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/app/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 00000000..67f98d96
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\Users\stnieder\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/app/project.properties b/app/project.properties
new file mode 100644
index 00000000..4ab12569
--- /dev/null
+++ b/app/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
diff --git a/app/src/androidTest/java/it/niedermann/owncloud/notes/ApplicationTest.java b/app/src/androidTest/java/it/niedermann/owncloud/notes/ApplicationTest.java
new file mode 100644
index 00000000..f1ce72e4
--- /dev/null
+++ b/app/src/androidTest/java/it/niedermann/owncloud/notes/ApplicationTest.java
@@ -0,0 +1,13 @@
+package it.niedermann.owncloud.notes;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+} \ No newline at end of file
diff --git a/app/src/androidTest/java/it/niedermann/owncloud/notes/util/URLValidatorAsyncTaskTest.java b/app/src/androidTest/java/it/niedermann/owncloud/notes/util/URLValidatorAsyncTaskTest.java
new file mode 100644
index 00000000..213bd1db
--- /dev/null
+++ b/app/src/androidTest/java/it/niedermann/owncloud/notes/util/URLValidatorAsyncTaskTest.java
@@ -0,0 +1,14 @@
+package it.niedermann.owncloud.notes.util;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests the URLValidatorAsyncTask
+ * Created by stefan on 24.09.15.
+ */
+public class URLValidatorAsyncTaskTest extends TestCase {
+ public void testIsHttp() {
+ assertTrue(URLValidatorAsyncTask.isHttp("http://www.example.com/"));
+ assertFalse(URLValidatorAsyncTask.isHttp("https://www.example.com/"));
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..390d4aa0
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="it.niedermann.owncloud.notes"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk
+ android:minSdkVersion="11"
+ android:targetSdkVersion="23" />
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.USE_CREDENTIALS" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/OwnCloud"
+ android:fullBackupContent="true"
+ android:supportsRtl="true"
+ >
+ <activity
+ android:name="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="it.niedermann.owncloud.notes.android.activity.NoteActivity"
+ android:label="@string/app_name"
+ android:parentActivityName="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" >
+ </activity>
+ <activity
+ android:name="it.niedermann.owncloud.notes.android.activity.SettingsActivity"
+ android:label="@string/app_name"
+ android:parentActivityName="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" >
+ </activity>
+ <activity
+ android:name="it.niedermann.owncloud.notes.android.activity.CreateNoteActivity"
+ android:label="@string/action_create"
+ android:windowSoftInputMode="stateVisible" >
+ <intent-filter>
+ <action android:name="android.intent.action.SEND" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="text/plain" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name="it.niedermann.owncloud.notes.android.activity.EditNoteActivity"
+ android:label="@string/menu_edit"
+ android:windowSoftInputMode="stateVisible" >
+ </activity>
+ <activity
+ android:name="it.niedermann.owncloud.notes.android.activity.AboutActivity"
+ android:label="@string/menu_about"
+ android:parentActivityName="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity" >
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java
new file mode 100644
index 00000000..d1f58cda
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/AboutActivity.java
@@ -0,0 +1,14 @@
+package it.niedermann.owncloud.notes.android.activity;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+
+import it.niedermann.owncloud.notes.R;
+public class AboutActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_about);
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/CreateNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/CreateNoteActivity.java
new file mode 100644
index 00000000..942905a4
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/CreateNoteActivity.java
@@ -0,0 +1,66 @@
+package it.niedermann.owncloud.notes.android.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.model.Note;
+import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
+
+public class CreateNoteActivity extends AppCompatActivity {
+ private EditText editTextField = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_create);
+ editTextField = (EditText) findViewById(R.id.createContent);
+
+ // Get intent, action and MIME type
+ Intent intent = getIntent();
+ String action = intent.getAction();
+ String type = intent.getType();
+
+ if (Intent.ACTION_SEND.equals(action) && type != null) {
+ if ("text/plain".equals(type)) {
+ editTextField.setText(intent.getStringExtra(Intent.EXTRA_TEXT));
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_menu_create, menu);
+ return true;
+ }
+
+ /**
+ * Main-Menu
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ switch (id) {
+ case R.id.action_create_save:
+ editTextField.setEnabled(false);
+ String content = editTextField.getText().toString();
+ NoteSQLiteOpenHelper db = new NoteSQLiteOpenHelper(this);
+ db.addNoteAndSync(content);
+ Intent data = new Intent();
+ //FIXME send correct note back to NotesListView
+ data.putExtra(NotesListViewActivity.CREATED_NOTE, new Note(-1, null, "", content));
+ setResult(RESULT_OK, data);
+ finish();
+ return true;
+ case R.id.action_create_cancel:
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java
new file mode 100644
index 00000000..5dadd4b7
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/EditNoteActivity.java
@@ -0,0 +1,64 @@
+package it.niedermann.owncloud.notes.android.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.EditText;
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.model.Note;
+import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
+
+public class EditNoteActivity extends AppCompatActivity {
+ private EditText content = null;
+ private Note note = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_edit);
+ note = (Note) getIntent().getSerializableExtra(
+ NoteActivity.EDIT_NOTE);
+ content = (EditText) findViewById(R.id.editContent);
+ content.setEnabled(false);
+ content.setText(note.getContent());
+ content.setSelection(note.getContent().length());
+ content.setEnabled(true);
+ }
+
+ /**
+ * Create Action Menu
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_menu_edit, menu);
+ return true;
+ }
+
+ /**
+ * Handle Action Menu
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ switch (id) {
+ case R.id.action_edit_save:
+ content.setEnabled(false);
+ note.setContent(((EditText) findViewById(R.id.editContent)).getText().toString());
+ NoteSQLiteOpenHelper db = new NoteSQLiteOpenHelper(this);
+ db.updateNoteAndSync(note);
+ Intent data = new Intent();
+ data.setAction(Intent.ACTION_VIEW);
+ data.putExtra(NoteActivity.EDIT_NOTE, note);
+ setResult(RESULT_OK, data);
+ finish();
+ return true;
+ case R.id.action_edit_cancel:
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteActivity.java
new file mode 100644
index 00000000..1b637241
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NoteActivity.java
@@ -0,0 +1,120 @@
+package it.niedermann.owncloud.notes.android.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.webkit.WebView;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.model.Note;
+import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
+
+public class NoteActivity extends AppCompatActivity implements View.OnClickListener {
+ private Note note = null;
+ private int notePosition = 0;
+ private WebView noteContent = null;
+ private ActionBar actionBar = null;
+ // Intent backToListViewIntent = null;
+ public final static String EDIT_NOTE = "it.niedermann.owncloud.notes.edit_note_id";
+ public final static int EDIT_NOTE_CMD = 1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // backToListViewIntent = new Intent();
+ setContentView(R.layout.activity_single_note);
+ note = (Note) getIntent().getSerializableExtra(
+ NotesListViewActivity.SELECTED_NOTE);
+ notePosition = getIntent().getIntExtra(
+ NotesListViewActivity.SELECTED_NOTE_POSITION, 0);
+ findViewById(R.id.fab_edit).setOnClickListener(this);
+ actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle(note.getTitle());
+ actionBar.setSubtitle(note.getModified("dd.MM.yyyy HH:mm"));
+ }
+ noteContent = (WebView) findViewById(R.id.singleNoteContent);
+ noteContent.loadData(note.getHtmlContent(), "text/html", "UTF-8");
+ }
+
+ @Override
+ public void onClick(View v) {
+ Intent editIntent = new Intent(this, EditNoteActivity.class);
+ editIntent.putExtra(EDIT_NOTE, note);
+ startActivityForResult(editIntent, EDIT_NOTE_CMD);
+ }
+
+ /**
+ * Main-Menu
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_note_list_view, menu);
+ return true;
+ }
+
+ /**
+ * Main-Menu-Handler
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ NoteSQLiteOpenHelper db = null;
+ switch (id) {
+ case R.id.menu_delete:
+ //setContentView(R.layout.activity_notes_list_view);
+ db = new NoteSQLiteOpenHelper(this);
+ db.deleteNoteAndSync(note.getId());
+ finish();
+ return true;
+ case R.id.menu_share:
+ Log.v("Note", "Share Action pressed.");
+ Intent shareIntent = new Intent();
+ shareIntent.setAction(Intent.ACTION_SEND);
+ shareIntent.setType("text/plain");
+ shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
+ note.getTitle());
+ shareIntent.putExtra(android.content.Intent.EXTRA_TEXT,
+ note.getContent());
+ startActivity(shareIntent);
+ return true;
+ case R.id.menu_copy:
+ Log.v("Note", "Copy Action pressed.");
+ db = new NoteSQLiteOpenHelper(this);
+ Note newNote = db.getNote(db.addNoteAndSync(note.getContent()));
+ newNote.setTitle(note.getTitle() + " (" + getResources().getString(R.string.copy) + ")");
+ db.updateNote(newNote);
+ finish();
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // Check which request we're responding to
+ if (requestCode == EDIT_NOTE_CMD) {
+ // Make sure the request was successful
+ if (resultCode == RESULT_OK) {
+ Note editedNote = (Note) data.getExtras().getSerializable(
+ EDIT_NOTE);
+ if (editedNote != null) {
+ noteContent.loadData(editedNote.getHtmlContent(), "text/html", "UTF-8");
+ actionBar.setTitle(editedNote.getTitle());
+ actionBar.setSubtitle(editedNote.getModified("dd.MM.yyyy HH:mm"));
+ }
+ // TODO Fire changed note to noteslistviewactivity
+ data.putExtra(NotesListViewActivity.SELECTED_NOTE_POSITION,
+ notePosition);
+ setResult(RESULT_OK, data);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
new file mode 100644
index 00000000..49fbf6f9
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/NotesListViewActivity.java
@@ -0,0 +1,359 @@
+package it.niedermann.owncloud.notes.android.activity;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v4.widget.SwipeRefreshLayout;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.view.ActionMode;
+import android.util.Log;
+import android.util.SparseBooleanArray;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ListView;
+
+import java.util.List;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.model.Note;
+import it.niedermann.owncloud.notes.model.NoteAdapter;
+import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
+import it.niedermann.owncloud.notes.util.ICallback;
+
+public class NotesListViewActivity extends AppCompatActivity implements
+ OnItemClickListener, View.OnClickListener {
+
+ public final static String SELECTED_NOTE = "it.niedermann.owncloud.notes.clicked_note";
+ public final static String CREATED_NOTE = "it.niedermann.owncloud.notes.created_notes";
+ public final static String SELECTED_NOTE_POSITION = "it.niedermann.owncloud.notes.clicked_note_position";
+
+ private final static int create_note_cmd = 0;
+ private final static int show_single_note_cmd = 1;
+ private final static int server_settings = 2;
+ private final static int about = 3;
+
+ private ListView listView = null;
+ private NoteAdapter adapter = null;
+ private ActionMode mActionMode;
+ private SwipeRefreshLayout swipeRefreshLayout = null;
+ private NoteSQLiteOpenHelper db = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // First Run Wizard
+ SharedPreferences preferences = PreferenceManager
+ .getDefaultSharedPreferences(getApplicationContext());
+ Log.v("Note", "First Run: " + preferences.getBoolean(SettingsActivity.SETTINGS_FIRST_RUN, true));
+ if(preferences.getBoolean(SettingsActivity.SETTINGS_FIRST_RUN, true)) {
+ Log.v("Note", "Seems to be the First Run...");
+ Intent settingsIntent = new Intent(this, SettingsActivity.class);
+ startActivityForResult(settingsIntent, server_settings);
+ }
+
+ setContentView(R.layout.activity_notes_list_view);
+
+ // Display Data
+ db = new NoteSQLiteOpenHelper(this);
+ db.synchronizeWithServer();
+ setListView(db.getNotes());
+
+ // Pull to Refresh
+ swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swiperefreshlayout);
+ swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ Log.d("Swipe", "Refreshing Notes");
+ db.synchronizeWithServer();
+ db.getNoteServerSyncHelper().addCallback(new ICallback() {
+ @Override
+ public void onFinish() {
+ swipeRefreshLayout.setRefreshing(false);
+ setListView(db.getNotes());
+ }
+ });
+ }
+ });
+
+ // Floating Action Button
+ findViewById(R.id.fab_create).setOnClickListener(this);
+ }
+
+ /**
+ * Click listener for <strong>Floating Action Button</strong>
+ * <p/>
+ * Creates a new Instance of CreateNoteActivity.
+ *
+ * @param v View
+ */
+ @Override
+ public void onClick(View v) {
+ Intent createIntent = new Intent(this, CreateNoteActivity.class);
+ startActivityForResult(createIntent, create_note_cmd);
+ }
+
+ /**
+ * Allows other classes to set a List of Notes.
+ *
+ * @param noteList List&lt;Note&gt;
+ */
+ @SuppressWarnings("WeakerAccess")
+ public void setListView(List<Note> noteList) {
+ adapter = new NoteAdapter(getApplicationContext(), noteList);
+ listView = (ListView) findViewById(R.id.list_view);
+ listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(this);
+ listView.setOnItemLongClickListener(new OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView<?> parent, View view,
+ int position, long id) {
+ onListItemSelect(position);
+ return true;
+ }
+ });
+ }
+
+ /**
+ * A short click on one list item. Creates a new instance of NoteActivity.
+ */
+ @Override
+ public void onItemClick(AdapterView<?> parentView, View childView,
+ int position, long id) {
+ listView.setItemChecked(position, !listView.isItemChecked(position));
+ Log.v("Note", "getCheckedItemCount " + listView.getCheckedItemCount());
+ if (listView.getCheckedItemCount() < 1) {
+ removeSelection();
+ Intent intent = new Intent(getApplicationContext(),
+ NoteActivity.class);
+ Note note = adapter.getItem(position);
+ intent.putExtra(SELECTED_NOTE, note);
+ intent.putExtra(SELECTED_NOTE_POSITION, position);
+ Log.v("Note",
+ "notePosition | NotesListViewActivity wurde abgesendet "
+ + position);
+ startActivityForResult(intent, show_single_note_cmd);
+ } else { // perform long click if already something is selected
+ onListItemSelect(position);
+ }
+ }
+
+ /**
+ * Adds the Menu Items to the Action Bar.
+ *
+ * @param menu Menu
+ * @return boolean
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_list_view, menu);
+ return true;
+ }
+
+ /**
+ * Handels click events on the Buttons in the Action Bar.
+ *
+ * @param item MenuItem - the clicked menu item
+ * @return boolean
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ switch (id) {
+ case R.id.action_settings:
+ Intent settingsIntent = new Intent(this, SettingsActivity.class);
+ startActivityForResult(settingsIntent, server_settings);
+ return true;
+ case R.id.action_about:
+ Intent aboutIntent = new Intent(this, AboutActivity.class);
+ startActivityForResult(aboutIntent, about);
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ /**
+ * Handles the Results of started Sub Activities (Created Note, Edited Note)
+ *
+ * @param requestCode int to distinguish between the different Sub Activities
+ * @param resultCode int Return Code
+ * @param data Intent
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ // Check which request we're responding to
+ if (requestCode == create_note_cmd) {
+ // Make sure the request was successful
+ if (resultCode == RESULT_OK) {
+ Note createdNote = (Note) data.getExtras().getSerializable(
+ CREATED_NOTE);
+ adapter.add(createdNote);
+ }
+ } else if (requestCode == NoteActivity.EDIT_NOTE_CMD) {
+ if (resultCode == RESULT_OK) {
+ Log.v("Note", "Note was edited from single view");
+
+ Note editedNote = (Note) data.getExtras().getSerializable(
+ NoteActivity.EDIT_NOTE);
+ Log.v("Note", "Neuer Titel: " + editedNote);
+
+ int notePosition = data.getExtras().getInt(
+ SELECTED_NOTE_POSITION);
+ Log.v("Note", "notePosition | NotesListViewActivity kam an "
+ + notePosition);
+
+ adapter.remove(adapter.getItem(notePosition));
+ adapter.add(editedNote);
+ }
+ }
+ setListView(db.getNotes());
+ }
+
+ // private class SingleSelectedActionModeCallback implements
+ // ActionMode.Callback {
+ //
+ // @Override
+ // public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ // // inflate contextual menu
+ // mode.getMenuInflater().inflate(R.menu.menu_list_context_single,
+ // menu);
+ // return true;
+ // }
+ //
+ // @Override
+ // public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ // return false;
+ // }
+ //
+ // @Override
+ // public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ // switch (item.getItemId()) {
+ // case R.id.menu_delete:
+ // SparseBooleanArray checkedItemPositions = listView
+ // .getCheckedItemPositions();
+ // for (int i = (checkedItemPositions.size() - 1); i >= 0; i--) {
+ // if (checkedItemPositions.valueAt(i)) {
+ //
+ // Note checkedItem = adapter.getItem(checkedItemPositions
+ // .keyAt(i));
+ //
+ // NoteDeleterAsyncTask deleter = new NoteDeleterAsyncTask();
+ // deleter.execute(checkedItem);
+ // }
+ // }
+ // mode.finish(); // Action picked, so close the CAB
+ // return true;
+ // default:
+ // return false;
+ // }
+ // }
+ //
+ // @Override
+ // public void onDestroyActionMode(ActionMode mode) {
+ // removeSelection();
+ // mActionMode = null;
+ // adapter.notifyDataSetChanged();
+ // }
+ // }
+
+ /**
+ * Long click on one item in the list view. It starts the Action Mode and allows selecting more
+ * items and execute bulk functions (e. g. delete)
+ *
+ * @param position int - position of the clicked item
+ */
+ private void onListItemSelect(int position) {
+ listView.setItemChecked(position, !listView.isItemChecked(position));
+ int checkedItemCount = listView.getCheckedItemCount();
+ boolean hasCheckedItems = checkedItemCount > 0;
+
+ if (hasCheckedItems && mActionMode == null) {
+ // TODO differ if one or more items are selected
+ // if (checkedItemCount == 1) {
+ // mActionMode = startActionMode(new
+ // SingleSelectedActionModeCallback());
+ // } else {
+ // there are some selected items, start the actionMode
+ mActionMode = startSupportActionMode(new MultiSelectedActionModeCallback());
+ // }
+ } else if (!hasCheckedItems && mActionMode != null) {
+ // there no selected items, finish the actionMode
+ mActionMode.finish();
+ }
+
+ if (mActionMode != null) {
+ mActionMode.setTitle(String.valueOf(listView.getCheckedItemCount())
+ + " " + getString(R.string.ab_selected));
+ }
+ }
+
+ /**
+ * Handler for the MultiSelect Actions
+ */
+ private class MultiSelectedActionModeCallback implements
+ ActionMode.Callback {
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ // inflate contextual menu
+ mode.getMenuInflater().inflate(R.menu.menu_list_context_multiple,
+ menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ /**
+ * @param mode ActionMode - used to close the Action Bar after all work is done.
+ * @param item MenuItem - the item in the List that contains the Node
+ * @return boolean
+ */
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_delete:
+ SparseBooleanArray checkedItemPositions = listView
+ .getCheckedItemPositions();
+ for (int i = (checkedItemPositions.size() - 1); i >= 0; i--) {
+ if (checkedItemPositions.valueAt(i)) {
+ Note note = adapter.getItem(checkedItemPositions
+ .keyAt(i));
+ db.deleteNoteAndSync(note.getId());
+ adapter.remove(note);
+ }
+ }
+ mode.finish(); // Action picked, so close the CAB
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ removeSelection();
+ mActionMode = null;
+ adapter.notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * Removes all selections.
+ */
+ private void removeSelection() {
+ SparseBooleanArray checkedItemPositions = listView
+ .getCheckedItemPositions();
+ for (int i = 0; i < checkedItemPositions.size(); i++) {
+ listView.setItemChecked(i, false);
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SettingsActivity.java b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SettingsActivity.java
new file mode 100644
index 00000000..a9cd6006
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/android/activity/SettingsActivity.java
@@ -0,0 +1,175 @@
+package it.niedermann.owncloud.notes.android.activity;
+
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.v7.app.AppCompatActivity;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
+import it.niedermann.owncloud.notes.util.NotesClientUtil;
+
+/**
+ * Allows to set Settings like URL, Username and Password for Server-Synchronization
+ * Created by stefan on 22.09.15.
+ */
+public class SettingsActivity extends AppCompatActivity implements View.OnClickListener {
+
+ public static final String SETTINGS_FIRST_RUN = "firstRun";
+ public static final String SETTINGS_URL = "settingsUrl";
+ public static final String SETTINGS_USERNAME = "settingsUsername";
+ public static final String SETTINGS_PASSWORD = "settingsPassword";
+ public static final String DEFAULT_SETTINGS = "";
+
+ private SharedPreferences preferences = null;
+ private EditText field_url = null;
+ private EditText field_username = null;
+ private EditText field_password = null;
+ private Button btn_submit = null;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_settings);
+
+ preferences = PreferenceManager
+ .getDefaultSharedPreferences(getApplicationContext());
+
+ field_url = (EditText) findViewById(R.id.settings_url);
+ field_username = (EditText) findViewById(R.id.settings_username);
+ field_password = (EditText) findViewById(R.id.settings_password);
+ btn_submit = (Button) findViewById(R.id.settings_submit);
+
+ field_url.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ String url = ((EditText) findViewById(R.id.settings_url)).getText().toString();
+ new URLValidatorAsyncTask().execute(url);
+
+ if (NotesClientUtil.isHttp(url)) {
+ findViewById(R.id.settings_url_warn_http).setVisibility(View.VISIBLE);
+ } else {
+ findViewById(R.id.settings_url_warn_http).setVisibility(View.GONE);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {}
+ });
+
+ // Load current Preferences
+ field_url.setText(preferences.getString(SETTINGS_URL, DEFAULT_SETTINGS));
+ field_username.setText(preferences.getString(SETTINGS_USERNAME, DEFAULT_SETTINGS));
+ field_password.setText(preferences.getString(SETTINGS_PASSWORD, DEFAULT_SETTINGS));
+
+ btn_submit.setOnClickListener(this);
+ }
+
+ /**
+ * Handle Submit Button Click
+ * Checks and Writes the new Preferences into the SharedPreferences Object.
+ *
+ * @param v View
+ */
+ @Override
+ public void onClick(View v) {
+ String url = field_url.getText().toString();
+ String username = field_username.getText().toString();
+ String password = field_password.getText().toString();
+
+ if (!url.endsWith("/")) {
+ url += "/";
+ }
+
+ new LoginValidatorAsyncTask().execute(url, username, password);
+ }
+
+ /************************************ Async Tasks ************************************/
+
+ /**
+ * Checks if the given URL returns a valid status code and sets the Check next to the URL-Input Field to visible.
+ * Created by stefan on 23.09.15.
+ */
+ private class URLValidatorAsyncTask extends AsyncTask<String, Void, Boolean> {
+
+ @Override
+ protected void onPreExecute() {
+ findViewById(R.id.settings_url_check).setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ protected Boolean doInBackground(String... params) {
+ return NotesClientUtil.isValidURL(params[0]);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean o) {
+ Log.v("Note", "Set Visible: " + o);
+ if (o) {
+ findViewById(R.id.settings_url_check).setVisibility(View.VISIBLE);
+ } else {
+ findViewById(R.id.settings_url_check).setVisibility(View.INVISIBLE);
+ }
+ }
+ }
+
+ /**
+ * If Log-In-Credentials are correct, save Credentials to Shared Preferences and finish First Run Wizard.
+ */
+ private class LoginValidatorAsyncTask extends AsyncTask<String, Void, Boolean> {
+ String url, username, password;
+
+ @Override
+ protected void onPreExecute() {
+ btn_submit.setEnabled(false);
+ }
+
+ /**
+ * @param params url, username and password
+ * @return isValidLogin
+ */
+ @Override
+ protected Boolean doInBackground(String... params) {
+ url = params[0];
+ username = params[1];
+ password = params[2];
+ return NotesClientUtil.isValidLogin(url, username, password);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean isValidLogin) {
+ if(isValidLogin) {
+ Log.v("Note", "Valid Credentials.");
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putString(SETTINGS_URL, url);
+ editor.putString(SETTINGS_USERNAME, username);
+ editor.putString(SETTINGS_PASSWORD, password);
+
+ // Now it is no more First Run
+ Log.v("Note", "set First_Run to false.");
+ editor.putBoolean(SETTINGS_FIRST_RUN, false);
+
+ editor.apply();
+
+ NoteSQLiteOpenHelper db = new NoteSQLiteOpenHelper(getApplicationContext());
+ db.synchronizeWithServer();
+
+ finish();
+ } else {
+ Log.v("Note", "Invalid Credentials!");
+ btn_submit.setEnabled(true);
+ //TODO Show Error Message
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/DBStatus.java b/app/src/main/java/it/niedermann/owncloud/notes/model/DBStatus.java
new file mode 100644
index 00000000..fc27f826
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/DBStatus.java
@@ -0,0 +1,20 @@
+package it.niedermann.owncloud.notes.model;
+
+/**
+ * Helps to distinguish between different local change types for Server Synchronization.
+ * Created by stefan on 19.09.15.
+ */
+public enum DBStatus {
+
+ VOID(""), LOCAL_CREATED("LOCAL_CREATED"), LOCAL_EDITED("LOCAL_EDITED"), LOCAL_DELETED("LOCAL_DELETED");
+
+ private final String title;
+
+ public String getTitle() {
+ return title;
+ }
+
+ DBStatus(String title) {
+ this.title = title;
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/Note.java b/app/src/main/java/it/niedermann/owncloud/notes/model/Note.java
new file mode 100644
index 00000000..3bf4af7f
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/Note.java
@@ -0,0 +1,74 @@
+package it.niedermann.owncloud.notes.model;
+
+import android.text.Html;
+
+import com.commonsware.cwac.anddown.AndDown;
+
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
+
+import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
+
+@SuppressWarnings("serial")
+public class Note implements Serializable {
+
+ private static final AndDown and_down = new AndDown();
+ private long id = 0;
+ private String title = "";
+ private Calendar modified = null;
+ private String content = "";
+ private String htmlContent = null;
+
+ public Note(long id, Calendar modified, String title, String content) {
+ this.id = id;
+ if(title != null)
+ this.title = Html.fromHtml(and_down.markdownToHtml(title)).toString().trim();
+ this.modified = modified;
+ this.content = content;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ public Calendar getModified() {
+ return modified;
+ }
+
+ public String getModified(String format) {
+ return new SimpleDateFormat(format, Locale.GERMANY)
+ .format(this.getModified().getTime());
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ this.htmlContent = null;
+ }
+
+ public String getHtmlContent() {
+ if(htmlContent == null && getContent() != null) {
+ htmlContent = and_down.markdownToHtml(getContent());
+ }
+ return htmlContent;
+ }
+
+ @Override
+ public String toString() {
+ return "#" + getId() + " " + getTitle() + " (" + getModified(NoteSQLiteOpenHelper.DATE_FORMAT) + ")";
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/model/NoteAdapter.java b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteAdapter.java
new file mode 100644
index 00000000..a4b92915
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/model/NoteAdapter.java
@@ -0,0 +1,70 @@
+package it.niedermann.owncloud.notes.model;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.List;
+
+import it.niedermann.owncloud.notes.R;
+
+public class NoteAdapter extends ArrayAdapter<Note> {
+ private List<Note> noteList = null;
+
+ // private SparseBooleanArray mSelectedItemsIds;
+
+ public NoteAdapter(Context context,
+ List<Note> noteList) {
+ super(context, android.R.layout.simple_list_item_1, noteList);
+ // mSelectedItemsIds = new SparseBooleanArray();
+ this.noteList = noteList;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View v = convertView;
+
+ // first check to see if the view is null. if so, we have to inflate it.
+ // to inflate it basically means to render, or show, the view.
+ if (v == null) {
+ LayoutInflater inflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ v = inflater.inflate(R.layout.fragment_notes_list_view, null);
+ }
+
+ /*
+ * Recall that the variable position is sent in as an argument to this
+ * method. The variable simply refers to the position of the current
+ * object in the list. (The ArrayAdapter iterates through the list we
+ * sent it)
+ *
+ * Therefore, i refers to the current Item object.
+ */
+ Note note = noteList.get(position);
+
+ if (note != null) {
+
+ // This is how you obtain a reference to the TextViews.
+ // These TextViews are created in the XML files we defined.
+
+ TextView noteTitle = (TextView) v.findViewById(R.id.noteTitle);
+ TextView noteModified = (TextView) v
+ .findViewById(R.id.noteModified);
+
+ // check to see if each individual textview is null.
+ // if not, assign some text!
+ if (noteTitle != null) {
+ noteTitle.setText(note.getTitle());
+ }
+ if (noteModified != null) {
+ noteModified.setText(note.getModified("dd.MM.yyyy HH:mm"));
+ }
+ }
+
+ // the view must be returned to our activity
+ return v;
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java
new file mode 100644
index 00000000..bc272a40
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteSQLiteOpenHelper.java
@@ -0,0 +1,305 @@
+package it.niedermann.owncloud.notes.persistence;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+
+import it.niedermann.owncloud.notes.model.DBStatus;
+import it.niedermann.owncloud.notes.model.Note;
+
+/**
+ * Helps to add, get, update and delete Notes with the option to trigger a Resync with the Server.
+ * <p/>
+ * Created by stefan on 19.09.15.
+ */
+public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
+ public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+ private static final int database_version = 4;
+ private static final String database_name = "OWNCLOUD_NOTES";
+ private static final String table_notes = "NOTES";
+ private static final String key_id = "ID";
+ private static final String key_status = "STATUS";
+ private static final String key_title = "TITLE";
+ private static final String key_modified = "MODIFIED";
+ private static final String key_content = "CONTENT";
+ private static final String[] columns = {key_id, key_status, key_title, key_modified, key_content};
+
+ private NoteServerSyncHelper serverSyncHelper = null;
+ private Context context = null;
+
+ public NoteSQLiteOpenHelper(Context context) {
+ super(context, database_name, null, database_version);
+ this.context = context;
+ serverSyncHelper = new NoteServerSyncHelper(this);
+ }
+
+ public NoteServerSyncHelper getNoteServerSyncHelper() {
+ return serverSyncHelper;
+ }
+
+ /**
+ * Creates initial the Database
+ *
+ * @param db Database
+ */
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ Log.v("Note", "Creating Database");
+ db.execSQL("CREATE TABLE '" + table_notes + "' ( '" +
+ key_id + "' INTEGER PRIMARY KEY AUTOINCREMENT, '" +
+ key_status + "' VARCHAR(50), '" +
+ key_title + "' TEXT, '" +
+ key_modified + "' TEXT, '" +
+ key_content + "' TEXT)");
+ }
+
+ /**
+ * Creates a new Note in the Database and adds a Synchronization Flag.
+ *
+ * @param content String
+ */
+ @SuppressWarnings("UnusedReturnValue")
+ public long addNoteAndSync(String content) {
+ Log.v("Note", "addNoteAndSync");
+ SQLiteDatabase db = this.getWritableDatabase();
+
+ ContentValues values = new ContentValues();
+ values.put(key_status, DBStatus.LOCAL_CREATED.getTitle());
+ values.put(key_content, content);
+
+ long id = db.insert(table_notes,
+ null,
+ values);
+ db.close();
+ serverSyncHelper.uploadNewNotes();
+ return id;
+ }
+
+ /**
+ * Inserts a note directly into the Database.
+ * No Synchronisation will be triggered! Use addNoteAndSync()!
+ *
+ * @param note Note to be added
+ */
+ public void addNote(Note note) {
+ Log.v("Note", "addNote (" + note + ")");
+ SQLiteDatabase db = this.getWritableDatabase();
+
+ ContentValues values = new ContentValues();
+ values.put(NoteSQLiteOpenHelper.key_id, note.getId());
+ values.put(NoteSQLiteOpenHelper.key_status, DBStatus.VOID.getTitle());
+ values.put(NoteSQLiteOpenHelper.key_title, note.getTitle());
+ values.put(NoteSQLiteOpenHelper.key_modified, note.getModified(NoteSQLiteOpenHelper.DATE_FORMAT));
+ values.put(NoteSQLiteOpenHelper.key_content, note.getContent());
+
+ db.insert(NoteSQLiteOpenHelper.table_notes,
+ null,
+ values);
+ db.close();
+ }
+
+ /**
+ * Get a single Note by ID
+ *
+ * @param id int - ID of the requested Note
+ * @return requested Note
+ */
+ @SuppressWarnings("unused")
+ public Note getNote(long id) {
+ Log.v("Note", "getNote(" + id + ")");
+ SQLiteDatabase db = this.getReadableDatabase();
+ Cursor cursor =
+ db.query(table_notes,
+ columns,
+ key_id + " = ? AND " + key_status + " != ?",
+ new String[]{String.valueOf(id), DBStatus.LOCAL_DELETED.getTitle()},
+ null,
+ null,
+ null,
+ null);
+ if (cursor != null) {
+ cursor.moveToFirst();
+ }
+ Calendar modified = Calendar.getInstance();
+ try {
+ String modifiedStr = cursor != null ? cursor.getString(3) : null;
+ if (modifiedStr != null)
+ modified.setTime(new SimpleDateFormat(DATE_FORMAT, Locale.GERMANY).parse(modifiedStr));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ Note note = new Note(Long.valueOf(cursor != null ? cursor.getString(0) : null), modified, cursor != null ? cursor.getString(2) : null, cursor.getString(4));
+ cursor.close();
+ return note;
+ }
+
+ /**
+ * Returns a list of all Notes in the Database
+ *
+ * @return List&lt;Note&gt;
+ */
+ public List<Note> getNotes() {
+ Log.v("Note", "getNotes");
+ List<Note> notes = new ArrayList<>();
+ SQLiteDatabase db = this.getWritableDatabase();
+ Cursor cursor = db.rawQuery("SELECT * FROM " + table_notes + " WHERE " + key_status + " != ?", new String[]{DBStatus.LOCAL_DELETED.getTitle()});
+ if (cursor.moveToFirst()) {
+ do {
+ Calendar modified = Calendar.getInstance();
+ try {
+ String modifiedStr = cursor.getString(3);
+ if (modifiedStr != null)
+ modified.setTime(new SimpleDateFormat(DATE_FORMAT, Locale.GERMANY).parse(modifiedStr));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ notes.add(new Note(Long.valueOf(cursor.getString(0)), modified, cursor.getString(2), cursor.getString(4)));
+ } while (cursor.moveToNext());
+ }
+ cursor.close();
+ return notes;
+ }
+
+ /**
+ * Returns a list of all Notes in the Database with a sepcial status, e.g. Edited, Deleted,...
+ *
+ * @return List&lt;Note&gt;
+ */
+ public List<Note> getNotesByStatus(DBStatus status) {
+ Log.v("Note", "getNotesByStatus(" + status.getTitle() + ")");
+ List<Note> notes = new ArrayList<>();
+ SQLiteDatabase db = this.getWritableDatabase();
+ Cursor cursor = db.rawQuery("SELECT * FROM " + table_notes + " WHERE " + key_status + " = ?", new String[]{status.getTitle()});
+ if (cursor.moveToFirst()) {
+ do {
+ Calendar modified = Calendar.getInstance();
+ try {
+ String modifiedStr = cursor.getString(3);
+ if (modifiedStr != null)
+ modified.setTime(new SimpleDateFormat(DATE_FORMAT, Locale.GERMANY).parse(modifiedStr));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ notes.add(new Note(Long.valueOf(cursor.getString(0)), modified, cursor.getString(2), cursor.getString(4)));
+ } while (cursor.moveToNext());
+ }
+ cursor.close();
+ return notes;
+ }
+
+ /**
+ * Updates a single Note and sets a synchronization Flag.
+ *
+ * @param note Note - Note with the updated Information
+ * @return The number of the Rows affected.
+ */
+ @SuppressWarnings("UnusedReturnValue")
+ public int updateNoteAndSync(Note note) {
+ Log.v("Note", "updateNoteAndSync(" + note + ")");
+ SQLiteDatabase db = this.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(key_id, note.getId());
+ values.put(key_status, DBStatus.LOCAL_EDITED.getTitle());
+ values.put(key_title, note.getTitle());
+ values.put(key_modified, note.getModified(DATE_FORMAT));
+ values.put(key_content, note.getContent());
+ int i = db.update(table_notes,
+ values,
+ key_id + " = ?",
+ new String[]{String.valueOf(note.getId())});
+ db.close();
+ serverSyncHelper.uploadEditedNotes();
+ return i;
+ }
+
+ /**
+ * Updates a single Note. No Synchronization will be triggered. Use updateNoteAndSync()!
+ *
+ * @param note Note - Note with the updated Information
+ * @return The number of the Rows affected.
+ */
+ @SuppressWarnings("UnusedReturnValue")
+ public int updateNote(Note note) {
+ Log.v("Note", "updateNote(" + note + ")");
+ SQLiteDatabase db = this.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(key_id, note.getId());
+ values.put(key_status, DBStatus.VOID.getTitle());
+ values.put(key_title, note.getTitle());
+ values.put(key_modified, note.getModified(DATE_FORMAT));
+ values.put(key_content, note.getContent());
+ int i = db.update(table_notes,
+ values,
+ key_id + " = ?",
+ new String[]{String.valueOf(note.getId())});
+ db.close();
+ return i;
+ }
+
+ /**
+ * Marks a Note in the Database as Deleted. In the next Synchronization it will be deleted
+ * from the Server.
+ *
+ * @param id long - ID of the Note that should be deleted
+ * @return Affected rows
+ */
+ @SuppressWarnings("UnusedReturnValue")
+ public int deleteNoteAndSync(long id) {
+ Log.v("Note", "deleteNoteAndSync(" + id + ")");
+ SQLiteDatabase db = this.getWritableDatabase();
+ ContentValues values = new ContentValues();
+ values.put(key_status, DBStatus.LOCAL_DELETED.getTitle());
+ int i = db.update(table_notes,
+ values,
+ key_id + " = ?",
+ new String[]{String.valueOf(id)});
+ db.close();
+ serverSyncHelper.uploadDeletedNotes();
+ return i;
+ }
+
+ /**
+ * Delete a single Note from the Database
+ *
+ * @param id long - ID of the Note that should be deleted.
+ */
+ public void deleteNote(long id) {
+ Log.v("Note", "deleteNote(" + id + ")");
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.delete(table_notes,
+ key_id + " = ?",
+ new String[]{String.valueOf(id)});
+ db.close();
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ Log.v("Note", "onUpgrade - DELETE *");
+ clearDatabase();
+ }
+
+ public void clearDatabase() {
+ SQLiteDatabase db = this.getWritableDatabase();
+ db.delete(table_notes, null, null);
+ db.close();
+ }
+
+ public Context getContext() {
+ return context;
+ }
+
+ public void synchronizeWithServer() {
+ serverSyncHelper.synchronize();
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
new file mode 100644
index 00000000..10722a67
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/persistence/NoteServerSyncHelper.java
@@ -0,0 +1,295 @@
+package it.niedermann.owncloud.notes.persistence;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.support.design.widget.Snackbar;
+import android.util.Log;
+import android.view.View;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import it.niedermann.owncloud.notes.R;
+import it.niedermann.owncloud.notes.android.activity.SettingsActivity;
+import it.niedermann.owncloud.notes.model.DBStatus;
+import it.niedermann.owncloud.notes.model.Note;
+import it.niedermann.owncloud.notes.util.ICallback;
+import it.niedermann.owncloud.notes.util.NotesClient;
+
+/**
+ * Helps to synchronize the Database to the Server.
+ * <p/>
+ * Created by stefan on 20.09.15.
+ */
+public class NoteServerSyncHelper {
+
+ private NotesClient client = null;
+ private NoteSQLiteOpenHelper db = null;
+
+ private int operationsCount = 0;
+ private int operationsFinished = 0;
+
+ private List<ICallback> callbacks = new ArrayList<>();
+
+ private final View.OnClickListener goToSettingsListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Activity parent = (Activity) db.getContext();
+ Intent intent = new Intent(parent, SettingsActivity.class);
+ parent.startActivity(intent);
+ }
+ };
+
+ public void addCallback(ICallback callback) {
+ callbacks.add(callback);
+ }
+
+ public boolean isFinished() {
+ return operationsFinished == operationsCount;
+ }
+
+ public NoteServerSyncHelper(NoteSQLiteOpenHelper db) {
+ this.db = db;
+ SharedPreferences preferences = PreferenceManager
+ .getDefaultSharedPreferences(db.getContext().getApplicationContext());
+ String url = preferences.getString(SettingsActivity.SETTINGS_URL,
+ SettingsActivity.DEFAULT_SETTINGS);
+ String username = preferences.getString(SettingsActivity.SETTINGS_USERNAME,
+ SettingsActivity.DEFAULT_SETTINGS);
+ String password = preferences.getString(SettingsActivity.SETTINGS_PASSWORD,
+ SettingsActivity.DEFAULT_SETTINGS);
+ client = new NotesClient(url, username, password);
+ }
+
+ public void synchronize() {
+ uploadEditedNotes();
+ uploadNewNotes();
+ uploadDeletedNotes();
+ downloadNotes();
+ final Handler handler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ for (ICallback callback : callbacks) {
+ callback.onFinish();
+ }
+ }
+ };
+ Timer timer = new Timer();
+ timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ Log.v("Note", "Sync operations: " + operationsFinished + "/" + operationsCount);
+ if (isFinished()) {
+ handler.obtainMessage(1).sendToTarget();
+ cancel();
+ }
+ }
+ }, 0, 200);
+ }
+
+ public void uploadEditedNotes() {
+ List<Note> notes = db.getNotesByStatus(DBStatus.LOCAL_EDITED);
+ for (Note note : notes) {
+ UploadEditedNotesTask editedNotesTask = new UploadEditedNotesTask();
+ editedNotesTask.execute(note);
+ }
+ }
+
+ public void uploadNewNotes() {
+ List<Note> notes = db.getNotesByStatus(DBStatus.LOCAL_CREATED);
+ for (Note note : notes) {
+ UploadNewNoteTask newNotesTask = new UploadNewNoteTask();
+ newNotesTask.execute(note);
+ }
+ }
+
+ public void uploadDeletedNotes() {
+ List<Note> notes = db.getNotesByStatus(DBStatus.LOCAL_DELETED);
+ for (Note note : notes) {
+ UploadDeletedNoteTask deletedNotesTask = new UploadDeletedNoteTask();
+ deletedNotesTask.execute(note);
+ }
+ }
+
+ public void downloadNotes() {
+ DownloadNotesTask downloadNotesTask = new DownloadNotesTask();
+ downloadNotesTask.execute();
+ }
+
+ private class UploadNewNoteTask extends AsyncTask<Object, Void, Object[]> {
+ @Override
+ protected Object[] doInBackground(Object... params) {
+ operationsCount++;
+ Note oldNote = (Note) params[0];
+ try {
+ Note note = client.createNote(oldNote.getContent());
+ return new Object[]{note, oldNote.getId()};
+ } catch (MalformedURLException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_url_malformed, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Activity parent = (Activity) db.getContext();
+ Intent intent = new Intent(parent, SettingsActivity.class);
+ parent.startActivity(intent);
+ }
+ })
+ .show();
+ e.printStackTrace();
+ } catch (JSONException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_json, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Activity parent = (Activity) db.getContext();
+ Intent intent = new Intent(parent, SettingsActivity.class);
+ parent.startActivity(intent);
+ }
+ })
+ .show();
+ e.printStackTrace();
+ } catch (IOException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_io, Snackbar.LENGTH_LONG)
+ .show();
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Object[] params) {
+ if(params != null) {
+ Long id = (Long) params[1];
+ if (id != null) {
+ db.deleteNote(((Long) params[1]));
+ }
+ db.addNote((Note) params[0]);
+ }
+ operationsFinished++;
+ }
+ }
+
+ private class UploadEditedNotesTask extends AsyncTask<Object, Void, Note> {
+ @Override
+ protected Note doInBackground(Object... params) {
+ operationsCount++;
+ try {
+ Note oldNote = (Note) params[0];
+ return client.editNote(oldNote.getId(), oldNote.getContent());
+ } catch (MalformedURLException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_url_malformed, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, goToSettingsListener)
+ .show();
+ e.printStackTrace();
+ } catch (JSONException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_json, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, goToSettingsListener)
+ .show();
+ e.printStackTrace();
+ } catch (IOException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_io, Snackbar.LENGTH_LONG)
+ .show();
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Note note) {
+ db.updateNote(note);
+ operationsFinished++;
+ }
+ }
+
+ private class UploadDeletedNoteTask extends AsyncTask<Object, Void, Void> {
+ Long id = null;
+
+ @Override
+ protected Void doInBackground(Object... params) {
+ operationsCount++;
+ try {
+ id = ((Note) params[0]).getId();
+ client.deleteNote(id);
+ } catch (MalformedURLException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_url_malformed, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, goToSettingsListener)
+ .show();
+ e.printStackTrace();
+ } catch (IOException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_io, Snackbar.LENGTH_LONG)
+ .show();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ db.deleteNote(id);
+ operationsFinished++;
+ }
+ }
+
+ private class DownloadNotesTask extends AsyncTask<Object, Void, List<Note>> {
+ private boolean serverError = false;
+
+ @Override
+ protected List<Note> doInBackground(Object... params) {
+ operationsCount++;
+ List<Note> notes = new ArrayList<>();
+ try {
+ notes = client.getNotes();
+ } catch (MalformedURLException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_url_malformed, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, goToSettingsListener)
+ .show();
+ serverError = true;
+ e.printStackTrace();
+ } catch (JSONException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_json, Snackbar.LENGTH_LONG)
+ .setAction(R.string.snackbar_settings, goToSettingsListener)
+ .show();
+ serverError = true;
+ e.printStackTrace();
+ } catch (IOException e) {
+ Snackbar
+ .make(((Activity) db.getContext()).getWindow().getDecorView(), R.string.error_io, Snackbar.LENGTH_LONG)
+ .show();
+ serverError = true;
+ e.printStackTrace();
+ }
+ return notes;
+ }
+
+ @Override
+ protected void onPostExecute(List<Note> result) {
+ // Clear Database only if there is an Server
+ if(!serverError) {
+ db.clearDatabase();
+ }
+ for (Note note : result) {
+ db.addNote(note);
+ }
+ operationsFinished++;
+ }
+ }
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/ICallback.java b/app/src/main/java/it/niedermann/owncloud/notes/util/ICallback.java
new file mode 100644
index 00000000..7b0d8c88
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/ICallback.java
@@ -0,0 +1,8 @@
+package it.niedermann.owncloud.notes.util;
+
+/**
+ * Created by stefan on 01.10.15.
+ */
+public interface ICallback {
+ public void onFinish();
+}
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java b/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java
new file mode 100644
index 00000000..e8b6df6d
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClient.java
@@ -0,0 +1,207 @@
+package it.niedermann.owncloud.notes.util;
+
+import android.util.Base64;
+import android.util.Log;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import it.niedermann.owncloud.notes.model.Note;
+
+public class NotesClient {
+
+ private String url = "";
+ private String username = "";
+ private String password = "";
+
+ public NotesClient(String url, String username, String password) {
+ this.url = url;
+ this.username = username;
+ this.password = password;
+ }
+
+ public List<Note> getNotes() throws JSONException,
+ IOException {
+ List<Note> notesList = new ArrayList<>();
+ JSONArray notes = new JSONArray(requestServer("notes", "GET", null));
+ long noteId = 0;
+ String noteTitle = "";
+ String noteContent = "";
+ Calendar noteModified = null;
+ JSONObject currentItem;
+ for (int i = 0; i < notes.length(); i++) {
+ currentItem = notes.getJSONObject(i);
+
+ if (!currentItem.isNull("id")) {
+ noteId = currentItem.getLong("id");
+ }
+ if (!currentItem.isNull("title")) {
+ noteTitle = currentItem.getString("title");
+ }
+ if (!currentItem.isNull("content")) {
+ noteContent = currentItem.getString("content");
+ }
+ if (!currentItem.isNull("modified")) {
+ noteModified = GregorianCalendar.getInstance();
+ noteModified
+ .setTimeInMillis(currentItem.getLong("modified") * 1000);
+ }
+ notesList
+ .add(new Note(noteId, noteModified, noteTitle, noteContent));
+ }
+ return notesList;
+ }
+
+ /**
+ * Fetches on Note by ID from Server
+ * TODO Maybe fetch only id, title and modified from server until a note has been opened?
+ * @param id long - ID of the wanted note
+ * @return Requested Note
+ * @throws JSONException
+ * @throws IOException
+ */
+ @SuppressWarnings("unused")
+ public Note getNoteById(long id) throws
+ JSONException, IOException {
+ long noteId = 0;
+ String noteTitle = "";
+ String noteContent = "";
+ Calendar noteModified = null;
+ JSONObject currentItem = new JSONObject(
+ requestServer("notes/" + id, "GET", null));
+
+ if (!currentItem.isNull("id")) {
+ noteId = currentItem.getLong("id");
+ }
+ if (!currentItem.isNull("title")) {
+ noteTitle = currentItem.getString("title");
+ }
+ if (!currentItem.isNull("content")) {
+ noteContent = currentItem.getString("content");
+ }
+ if (!currentItem.isNull("modified")) {
+ noteModified = GregorianCalendar.getInstance();
+ noteModified
+ .setTimeInMillis(currentItem.getLong("modified") * 1000);
+ }
+ return new Note(noteId, noteModified, noteTitle, noteContent);
+ }
+
+ /**
+ * Creates a Note on the Server
+ * @param content String - Content of the new Note
+ * @return Created Note including generated Title, ID and lastModified-Date
+ * @throws JSONException
+ * @throws IOException
+ */
+ public Note createNote(String content) throws
+ JSONException, IOException {
+ long noteId = 0;
+ String noteTitle = "";
+ String noteContent = "";
+ Calendar noteModified = null;
+
+ JSONObject paramObject = new JSONObject();
+ paramObject.accumulate("content", content);
+ JSONObject currentItem = new JSONObject(requestServer("notes", "POST",
+ paramObject));
+
+ if (!currentItem.isNull("id")) {
+ noteId = currentItem.getLong("id");
+ }
+ if (!currentItem.isNull("title")) {
+ noteTitle = currentItem.getString("title");
+ }
+ if (!currentItem.isNull("content")) {
+ noteContent = currentItem.getString("content");
+ }
+ if (!currentItem.isNull("modified")) {
+ noteModified = GregorianCalendar.getInstance();
+ noteModified
+ .setTimeInMillis(currentItem.getLong("modified") * 1000);
+ }
+ return new Note(noteId, noteModified, noteTitle, noteContent);
+ }
+
+ public Note editNote(long noteId, String content)
+ throws JSONException, IOException {
+ String noteTitle = "";
+ Calendar noteModified = null;
+
+ JSONObject paramObject = new JSONObject();
+ paramObject.accumulate("content", content);
+ JSONObject currentItem = new JSONObject(requestServer(
+ "notes/" + noteId, "PUT", paramObject));
+
+ if (!currentItem.isNull("title")) {
+ noteTitle = currentItem.getString("title");
+ }
+ if (!currentItem.isNull("modified")) {
+ noteModified = GregorianCalendar.getInstance();
+ noteModified
+ .setTimeInMillis(currentItem.getLong("modified") * 1000);
+ }
+ return new Note(noteId, noteModified, noteTitle, content);
+ }
+
+ public void deleteNote(long noteId) throws
+ IOException {
+ this.requestServer("notes/" + noteId, "DELETE", null);
+ }
+
+ /**
+ * Request-Method for POST, PUT with or without JSON-Object-Parameter
+ *
+ * @param target Filepath to the wanted function
+ * @param method GET, POST, DELETE or PUT
+ * @param params JSON Object which shall be transferred to the server.
+ * @return Body of answer
+ * @throws MalformedURLException
+ * @throws IOException
+ */
+ private String requestServer(String target, String method, JSONObject params)
+ throws IOException {
+ String result = "";
+ String targetURL = url + "index.php/apps/notes/api/v0.2/" + target;
+ Log.v("Note", targetURL);
+ HttpURLConnection con = (HttpURLConnection) new URL(targetURL)
+ .openConnection();
+ con.setRequestMethod(method);
+ con.setRequestProperty(
+ "Authorization",
+ "Basic "
+ + new String(Base64.encode((username + ":"
+ + password).getBytes(), Base64.NO_WRAP)));
+ con.setConnectTimeout(10 * 1000); // 10 seconds
+ if (params != null) {
+ con.setFixedLengthStreamingMode(params.toString().getBytes().length);
+ con.setRequestProperty("Content-Type", "application/json");
+ con.setDoOutput(true);
+ OutputStream os = con.getOutputStream();
+ Log.v("Note", params.toString());
+ os.write(params.toString().getBytes());
+ os.flush();
+ os.close();
+ }
+ BufferedReader rd;
+ String line;
+ rd = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ while ((line = rd.readLine()) != null) {
+ result += line;
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClientUtil.java b/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClientUtil.java
new file mode 100644
index 00000000..cc02c0a8
--- /dev/null
+++ b/app/src/main/java/it/niedermann/owncloud/notes/util/NotesClientUtil.java
@@ -0,0 +1,84 @@
+package it.niedermann.owncloud.notes.util;
+
+import android.util.Base64;
+import android.util.Log;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Utils for Validation etc
+ * Created by stefan on 25.09.15.
+ */
+public class NotesClientUtil {
+
+ /**
+ * Checks if the given url String starts with http:// or https://
+ *
+ * @param url String
+ * @return true, if the given String is only http
+ */
+ public static boolean isHttp(String url) {
+ return url.length() > 4 && url.startsWith("http") && url.charAt(4) != 's';
+ }
+
+ /**
+ * Checks if the given URL returns a valid status code and sets the Check next to the URL-Input Field to visible.
+ * @param urlStr String URL
+ * @return URL is valid
+ */
+ public static boolean isValidURL(String urlStr) {
+ try {
+ URL url = new URL(urlStr);
+ HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
+ urlc.setRequestProperty("Connection", "close");
+ urlc.setConnectTimeout(1000 * 10); // mTimeout is in seconds
+ urlc.connect();
+ if (urlc.getResponseCode() == 200) {
+ Log.v("Note", "ResponseCode: " + urlc.getResponseCode());
+ return true;
+ } else {
+ return false;
+ }
+ } catch (MalformedURLException e1) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+
+ /**
+ *
+ * @param url String
+ * @param username String
+ * @param password String
+ * @return Username and Password are a valid Login-Combination for the given URL.
+ */
+ public static boolean isValidLogin(String url, String username, String password) {
+ try {
+ String targetURL = url + "index.php/apps/notes/api/v0.2/notes";
+ Log.v("Note", targetURL);
+ HttpURLConnection con = (HttpURLConnection) new URL(targetURL)
+ .openConnection();
+ con.setRequestMethod("GET");
+ con.setRequestProperty(
+ "Authorization",
+ "Basic "
+ + new String(Base64.encode((username + ":"
+ + password).getBytes(), Base64.NO_WRAP)));
+ con.setConnectTimeout(10 * 1000); // 10 seconds
+ con.connect();
+ if (con.getResponseCode() == 200) {
+ return true;
+ }
+ } catch (MalformedURLException e1) {
+ return false;
+ } catch (IOException e) {
+ return false;
+ }
+ return false;
+ }
+
+} \ No newline at end of file
diff --git a/app/src/main/res/drawable-hdpi/ic_action_cancel.png b/app/src/main/res/drawable-hdpi/ic_action_cancel.png
new file mode 100644
index 00000000..71d5e118
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_cancel.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_copy.png b/app/src/main/res/drawable-hdpi/ic_action_copy.png
new file mode 100644
index 00000000..c170a270
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_copy.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_delete.png b/app/src/main/res/drawable-hdpi/ic_action_delete.png
new file mode 100644
index 00000000..21287cbd
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_delete.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_done.png b/app/src/main/res/drawable-hdpi/ic_action_done.png
new file mode 100644
index 00000000..c6503fd0
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_done.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_done_dark.png b/app/src/main/res/drawable-hdpi/ic_action_done_dark.png
new file mode 100644
index 00000000..392a259e
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_done_dark.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_edit.png b/app/src/main/res/drawable-hdpi/ic_action_edit.png
new file mode 100644
index 00000000..02e19d04
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_edit.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_new.png b/app/src/main/res/drawable-hdpi/ic_action_new.png
new file mode 100644
index 00000000..0fdced8f
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_new.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_settings.png b/app/src/main/res/drawable-hdpi/ic_action_settings.png
new file mode 100644
index 00000000..a1a19400
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_settings.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_action_share.png b/app/src/main/res/drawable-hdpi/ic_action_share.png
new file mode 100644
index 00000000..0c460c47
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_action_share.png
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..439747ce
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_cancel.png b/app/src/main/res/drawable-mdpi/ic_action_cancel.png
new file mode 100644
index 00000000..46907806
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_cancel.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_copy.png b/app/src/main/res/drawable-mdpi/ic_action_copy.png
new file mode 100644
index 00000000..afd28ddd
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_copy.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_delete.png b/app/src/main/res/drawable-mdpi/ic_action_delete.png
new file mode 100644
index 00000000..9b0e2dbd
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_delete.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_done.png b/app/src/main/res/drawable-mdpi/ic_action_done.png
new file mode 100644
index 00000000..4eb240b3
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_done.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_done_dark.png b/app/src/main/res/drawable-mdpi/ic_action_done_dark.png
new file mode 100644
index 00000000..3f9b108f
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_done_dark.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_edit.png b/app/src/main/res/drawable-mdpi/ic_action_edit.png
new file mode 100644
index 00000000..5a06bff5
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_edit.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_new.png b/app/src/main/res/drawable-mdpi/ic_action_new.png
new file mode 100644
index 00000000..67bb598e
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_new.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_settings.png b/app/src/main/res/drawable-mdpi/ic_action_settings.png
new file mode 100644
index 00000000..8a2f886d
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_settings.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_action_share.png b/app/src/main/res/drawable-mdpi/ic_action_share.png
new file mode 100644
index 00000000..1cafd213
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_action_share.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..de725181
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_cancel.png b/app/src/main/res/drawable-xhdpi/ic_action_cancel.png
new file mode 100644
index 00000000..172acd0f
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_cancel.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_copy.png b/app/src/main/res/drawable-xhdpi/ic_action_copy.png
new file mode 100644
index 00000000..c4d15780
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_copy.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_delete.png b/app/src/main/res/drawable-xhdpi/ic_action_delete.png
new file mode 100644
index 00000000..beb1637e
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_delete.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_done.png b/app/src/main/res/drawable-xhdpi/ic_action_done.png
new file mode 100644
index 00000000..c297f32d
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_done.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_done_dark.png b/app/src/main/res/drawable-xhdpi/ic_action_done_dark.png
new file mode 100644
index 00000000..3400099d
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_done_dark.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_edit.png b/app/src/main/res/drawable-xhdpi/ic_action_edit.png
new file mode 100644
index 00000000..d6668a05
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_edit.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_new.png b/app/src/main/res/drawable-xhdpi/ic_action_new.png
new file mode 100644
index 00000000..d64c22e9
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_new.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_settings.png b/app/src/main/res/drawable-xhdpi/ic_action_settings.png
new file mode 100644
index 00000000..2fbddd2f
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_settings.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_action_share.png b/app/src/main/res/drawable-xhdpi/ic_action_share.png
new file mode 100644
index 00000000..e275d938
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_action_share.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..be0cc6a5
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png b/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png
new file mode 100644
index 00000000..ef610fb4
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_copy.png b/app/src/main/res/drawable-xxhdpi/ic_action_copy.png
new file mode 100644
index 00000000..eead97da
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_copy.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_delete.png b/app/src/main/res/drawable-xxhdpi/ic_action_delete.png
new file mode 100644
index 00000000..026c3313
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_delete.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_done.png b/app/src/main/res/drawable-xxhdpi/ic_action_done.png
new file mode 100644
index 00000000..e43c8985
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_done.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png b/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png
new file mode 100644
index 00000000..7f67ee04
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_edit.png b/app/src/main/res/drawable-xxhdpi/ic_action_edit.png
new file mode 100644
index 00000000..377b2e8d
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_edit.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_new.png b/app/src/main/res/drawable-xxhdpi/ic_action_new.png
new file mode 100644
index 00000000..7e699137
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_new.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png
new file mode 100644
index 00000000..ccdaf494
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_share.png b/app/src/main/res/drawable-xxhdpi/ic_action_share.png
new file mode 100644
index 00000000..19c907fd
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_action_share.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..4f2f0572
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png b/app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png
new file mode 100644
index 00000000..ba88f122
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_copy.png b/app/src/main/res/drawable-xxxhdpi/ic_action_copy.png
new file mode 100644
index 00000000..cf9da9d1
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_copy.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_delete.png b/app/src/main/res/drawable-xxxhdpi/ic_action_delete.png
new file mode 100644
index 00000000..7cc287bd
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_delete.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_done.png b/app/src/main/res/drawable-xxxhdpi/ic_action_done.png
new file mode 100644
index 00000000..7cec5ed4
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_done.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_done_dark.png b/app/src/main/res/drawable-xxxhdpi/ic_action_done_dark.png
new file mode 100644
index 00000000..e63d05b4
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_done_dark.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_edit.png b/app/src/main/res/drawable-xxxhdpi/ic_action_edit.png
new file mode 100644
index 00000000..bde8b21c
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_edit.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_new.png b/app/src/main/res/drawable-xxxhdpi/ic_action_new.png
new file mode 100644
index 00000000..165c907d
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_new.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png
new file mode 100644
index 00000000..06bf6e3c
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_share.png b/app/src/main/res/drawable-xxxhdpi/ic_action_share.png
new file mode 100644
index 00000000..04be4201
--- /dev/null
+++ b/app/src/main/res/drawable-xxxhdpi/ic_action_share.png
Binary files differ
diff --git a/app/src/main/res/drawable/list_item_background_selector.xml b/app/src/main/res/drawable/list_item_background_selector.xml
new file mode 100644
index 00000000..bd502458
--- /dev/null
+++ b/app/src/main/res/drawable/list_item_background_selector.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Selector is used for Background Colors in List Items -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- :selected -->
+ <item android:drawable="@color/bg_highlighted" android:state_activated="true"/>
+ <item android:drawable="@color/bg_normal"/>
+</selector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/list_item_color_selector.xml b/app/src/main/res/drawable/list_item_color_selector.xml
new file mode 100644
index 00000000..14de8d58
--- /dev/null
+++ b/app/src/main/res/drawable/list_item_color_selector.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Selector is used for Header Color in List Items -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- :selected -->
+ <item android:color="@color/fg_default_selection" android:state_activated="true"/>
+ <item android:color="@color/fg_default"/>
+</selector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/list_item_color_selector_low.xml b/app/src/main/res/drawable/list_item_color_selector_low.xml
new file mode 100644
index 00000000..727f5c93
--- /dev/null
+++ b/app/src/main/res/drawable/list_item_color_selector_low.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Selector is used for Sub Title Color in List Items -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <!-- :selected -->
+ <!--item android:color="@color/fg_contrast" android:state_activated="true"/-->
+ <item android:color="@color/fg_default_low"/>
+</selector> \ No newline at end of file
diff --git a/app/src/main/res/drawable/settings.xml b/app/src/main/res/drawable/settings.xml
new file mode 100644
index 00000000..3f626603
--- /dev/null
+++ b/app/src/main/res/drawable/settings.xml
@@ -0,0 +1,8 @@
+<!-- drawable/settings.xml -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#000" android:pathData="M12,15.5A3.5,3.5 0 0,1 8.5,12A3.5,3.5 0 0,1 12,8.5A3.5,3.5 0 0,1 15.5,12A3.5,3.5 0 0,1 12,15.5M19.43,12.97C19.47,12.65 19.5,12.33 19.5,12C19.5,11.67 19.47,11.34 19.43,11L21.54,9.37C21.73,9.22 21.78,8.95 21.66,8.73L19.66,5.27C19.54,5.05 19.27,4.96 19.05,5.05L16.56,6.05C16.04,5.66 15.5,5.32 14.87,5.07L14.5,2.42C14.46,2.18 14.25,2 14,2H10C9.75,2 9.54,2.18 9.5,2.42L9.13,5.07C8.5,5.32 7.96,5.66 7.44,6.05L4.95,5.05C4.73,4.96 4.46,5.05 4.34,5.27L2.34,8.73C2.21,8.95 2.27,9.22 2.46,9.37L4.57,11C4.53,11.34 4.5,11.67 4.5,12C4.5,12.33 4.53,12.65 4.57,12.97L2.46,14.63C2.27,14.78 2.21,15.05 2.34,15.27L4.34,18.73C4.46,18.95 4.73,19.03 4.95,18.95L7.44,17.94C7.96,18.34 8.5,18.68 9.13,18.93L9.5,21.58C9.54,21.82 9.75,22 10,22H14C14.25,22 14.46,21.82 14.5,21.58L14.87,18.93C15.5,18.67 16.04,18.34 16.56,17.94L19.05,18.95C19.27,19.03 19.54,18.95 19.66,18.73L21.66,15.27C21.78,15.05 21.73,14.78 21.54,14.63L19.43,12.97Z" />
+</vector> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml
new file mode 100644
index 00000000..31bfe772
--- /dev/null
+++ b/app/src/main/res/layout/activity_about.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="@dimen/activity_horizontal_margin">
+
+ <TextView
+ android:id="@+id/about_version_title"
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/about_version_title"/>
+
+ <TextView
+ android:id="@+id/about_version"
+ style="?android:attr/editTextPreferenceStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:text="@string/about_version"/>
+
+ <TextView
+ android:id="@+id/about_author_title"
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/about_author_title"/>
+
+ <TextView
+ android:id="@+id/about_author"
+ style="?android:attr/editTextPreferenceStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:text="@string/about_author"/>
+
+ <TextView
+ android:id="@+id/about_icon_disclaimer_title"
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/about_icon_disclaimer_title"/>
+
+ <TextView
+ android:id="@+id/about_icon_disclaimer"
+ style="?android:attr/editTextPreferenceStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:text="@string/about_icon_disclaimer"/>
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_create.xml b/app/src/main/res/layout/activity_create.xml
new file mode 100644
index 00000000..03b6ba66
--- /dev/null
+++ b/app/src/main/res/layout/activity_create.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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:orientation="vertical"
+ tools:context="it.niedermann.owncloud.notes.android.activity.CreateNoteActivity"
+ android:id="@+id/createContentContainer"
+ android:weightSum="1">
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/scrollView">
+
+ <EditText
+ android:id="@+id/createContent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textMultiLine" />
+ </ScrollView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml
new file mode 100644
index 00000000..a9134c2b
--- /dev/null
+++ b/app/src/main/res/layout/activity_edit.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<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:orientation="vertical"
+ tools:context="it.niedermann.owncloud.notes.android.activity.CreateNoteActivity"
+ android:id="@+id/editContentContainer" >
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/scrollView2" >
+
+ <EditText
+ android:id="@+id/editContent"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="textMultiLine" />
+ </ScrollView>
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_notes_list_view.xml b/app/src/main/res/layout/activity_notes_list_view.xml
new file mode 100644
index 00000000..128eec61
--- /dev/null
+++ b/app/src/main/res/layout/activity_notes_list_view.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.support.v4.widget.SwipeRefreshLayout
+ android:id="@+id/swiperefreshlayout"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="it.niedermann.owncloud.notes.android.activity.NotesListViewActivity"
+ tools:ignore="MergeRootFrame">
+
+ <ListView
+ android:id="@+id/list_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ </ListView>
+ </android.support.v4.widget.SwipeRefreshLayout>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab_create"
+ style="@style/fab"
+ android:src="@drawable/ic_action_new"
+ app:backgroundTint="@color/primary"
+ app:rippleColor="@color/primary_dark"/>
+</merge> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
new file mode 100644
index 00000000..2a079658
--- /dev/null
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v7.widget.GridLayout
+ android:id="@+id/settings_grid_layout"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/activity_horizontal_margin"
+ app:columnCount="2"
+ app:orientation="horizontal"
+ >
+
+ <android.support.design.widget.TextInputLayout
+ android:id="@+id/settings_url_wrapper"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_column="0"
+ app:layout_row="0"
+ app:layout_gravity="fill"
+ >
+
+ <EditText
+ android:id="@+id/settings_url"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/settings_url"
+ android:inputType="textUri"/>
+ </android.support.design.widget.TextInputLayout>
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/settings_url_check"
+ android:src="@drawable/ic_action_done_dark"
+ android:contentDescription="@string/settings_url_check_description"
+ android:visibility="invisible"
+ app:layout_column="1"
+ app:layout_row="0"
+ />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/settings_url_warn_http"
+ android:visibility="gone"
+ android:text="@string/settings_url_warn_http"
+ app:layout_columnSpan="2"/>
+
+ <android.support.design.widget.TextInputLayout
+ android:id="@+id/settings_username_wrapper"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_column="0"
+ app:layout_row="2"
+ app:layout_gravity="fill">
+
+ <EditText
+ android:id="@+id/settings_username"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/settings_username"/>
+ </android.support.design.widget.TextInputLayout>
+
+ <android.support.design.widget.TextInputLayout
+ android:id="@+id/settings_password_wrapper"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ app:layout_column="0"
+ app:layout_row="3"
+ app:layout_gravity="fill">
+
+ <EditText
+ android:id="@+id/settings_password"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/settings_password"
+ android:inputType="textPassword"/>
+ </android.support.design.widget.TextInputLayout>
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/settings_password_check"
+ android:src="@drawable/ic_action_done_dark"
+ android:contentDescription="@string/settings_password_check_description"
+ android:visibility="invisible"
+ app:layout_column="1"
+ app:layout_row="3"
+ />
+
+ <Button
+ android:id="@+id/settings_submit"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:shadowColor="@color/fg_default_low"
+ android:text="@string/settings_submit"
+ app:layout_gravity="end"
+ app:layout_row="4"
+ app:layout_column="0"
+ app:layout_columnSpan="2"
+ />
+
+</android.support.v7.widget.GridLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/activity_single_note.xml b/app/src/main/res/layout/activity_single_note.xml
new file mode 100644
index 00000000..0fa8dcb5
--- /dev/null
+++ b/app/src/main/res/layout/activity_single_note.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <WebView
+ android:id="@+id/singleNoteContent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="10dp"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab_edit"
+ style="@style/fab"
+ android:src="@drawable/ic_action_edit"
+ app:backgroundTint="@color/primary"
+ app:rippleColor="@color/primary_dark"/>
+</merge> \ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_notes_list_view.xml b/app/src/main/res/layout/fragment_notes_list_view.xml
new file mode 100644
index 00000000..c37f00e8
--- /dev/null
+++ b/app/src/main/res/layout/fragment_notes_list_view.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:padding="16dp"
+ android:background="@drawable/list_item_background_selector"
+ android:id="@+id/noteItem" >
+
+ <TextView
+ android:id="@+id/noteTitle"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:layout_alignWithParentIfMissing="true"
+ android:gravity="center_vertical"
+ android:textColor="@drawable/list_item_color_selector"
+ android:textSize="16sp" />
+
+ <TextView
+ android:id="@+id/noteModified"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:ellipsize="marquee"
+ android:singleLine="true"
+ android:layout_below="@id/noteTitle"
+ android:textColor="@drawable/list_item_color_selector_low"
+ android:textSize="14sp" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_list_context_multiple.xml b/app/src/main/res/menu/menu_list_context_multiple.xml
new file mode 100644
index 00000000..f32c4146
--- /dev/null
+++ b/app/src/main/res/menu/menu_list_context_multiple.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/menu_delete"
+ android:icon="@drawable/ic_action_delete"
+ android:orderInCategory="100"
+ app:showAsAction="ifRoom"
+ android:title="@string/menu_delete"/>
+
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_list_context_single.xml b/app/src/main/res/menu/menu_list_context_single.xml
new file mode 100644
index 00000000..fbb97083
--- /dev/null
+++ b/app/src/main/res/menu/menu_list_context_single.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto" >
+
+ <item
+ android:id="@+id/menu_edit"
+ android:icon="@drawable/ic_action_edit"
+ android:orderInCategory="100"
+ app:showAsAction="ifRoom"
+ android:title="@string/menu_edit"/>
+ <item
+ android:id="@+id/menu_share"
+ android:actionProviderClass="android.widget.ShareActionProvider"
+ android:icon="@drawable/ic_action_share"
+ app:showAsAction="ifRoom"
+ android:title="@string/menu_share"/>
+ <item
+ android:id="@+id/menu_delete"
+ android:icon="@drawable/ic_action_delete"
+ android:orderInCategory="100"
+ app:showAsAction="ifRoom"
+ android:title="@string/menu_delete"/>
+
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_list_view.xml b/app/src/main/res/menu/menu_list_view.xml
new file mode 100644
index 00000000..f3c48bbe
--- /dev/null
+++ b/app/src/main/res/menu/menu_list_view.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.example.owncloudnotes.NotesListViewActivity"
+ xmlns:app="http://schemas.android.com/apk/res-auto" >
+ <item
+ android:id="@+id/action_settings"
+ android:icon="@drawable/ic_action_settings"
+ android:orderInCategory="100"
+ app:showAsAction="never"
+ android:title="@string/action_settings"/>
+ <item
+ android:id="@+id/action_about"
+ android:orderInCategory="100"
+ app:showAsAction="never"
+ android:title="@string/action_about"/>
+
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_menu_create.xml b/app/src/main/res/menu/menu_menu_create.xml
new file mode 100644
index 00000000..bb9b27c3
--- /dev/null
+++ b/app/src/main/res/menu/menu_menu_create.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto" >
+
+ <item
+ android:id="@+id/action_create_cancel"
+ android:icon="@drawable/ic_action_cancel"
+ android:orderInCategory="90"
+ app:showAsAction="always"
+ android:title="@string/action_create_save"/>
+
+ <item
+ android:id="@+id/action_create_save"
+ android:icon="@drawable/ic_action_done"
+ android:orderInCategory="90"
+ app:showAsAction="always"
+ android:title="@string/action_create_save"/>
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/menu_menu_edit.xml b/app/src/main/res/menu/menu_menu_edit.xml
new file mode 100644
index 00000000..db01a4b5
--- /dev/null
+++ b/app/src/main/res/menu/menu_menu_edit.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto" >
+
+ <item
+ android:id="@+id/action_edit_cancel"
+ android:icon="@drawable/ic_action_cancel"
+ android:orderInCategory="90"
+ app:showAsAction="always"
+ android:title="@string/action_edit_save"/>
+ <item
+ android:id="@+id/action_edit_save"
+ android:icon="@drawable/ic_action_done"
+ android:orderInCategory="90"
+ app:showAsAction="always"
+ android:title="@string/action_edit_save"/>
+
+</menu>
diff --git a/app/src/main/res/menu/menu_note_list_view.xml b/app/src/main/res/menu/menu_note_list_view.xml
new file mode 100644
index 00000000..bc19345f
--- /dev/null
+++ b/app/src/main/res/menu/menu_note_list_view.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto" >
+ <item
+ android:id="@+id/menu_share"
+ android:actionProviderClass="android.widget.ShareActionProvider"
+ android:icon="@drawable/ic_action_share"
+ android:orderInCategory="100"
+ app:showAsAction="never"
+ android:title="@string/menu_share"/>
+ <item
+ android:id="@+id/menu_copy"
+ android:icon="@drawable/ic_action_copy"
+ android:orderInCategory="110"
+ app:showAsAction="never"
+ android:title="@string/menu_copy"/>
+ <item
+ android:id="@+id/menu_delete"
+ android:icon="@drawable/ic_action_delete"
+ android:orderInCategory="120"
+ app:showAsAction="never"
+ android:title="@string/menu_delete"/>
+
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
new file mode 100644
index 00000000..261f963d
--- /dev/null
+++ b/app/src/main/res/values-de/strings.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OwnCloud Notes</string>
+ <string name="action_create">Neue Notiz</string>
+ <string name="action_settings">Einstellungen</string>
+ <string name="action_create_save">Speichern</string>
+ <string name="action_edit_save">Speichern</string>
+ <string name="action_about">Über</string>
+ <string name="menu_delete">Löschen</string>
+ <string name="menu_copy">Kopieren</string>
+ <string name="menu_edit">Bearbeiten</string>
+ <string name="menu_share">Teilen</string>
+ <string name="menu_about">Über</string>
+
+ <string name="ab_selected">ausgewählt</string>
+
+ <string name="copy">Kopie</string>
+
+ <!-- About -->
+
+ <string name="about_version_title">Version</string>
+ <string name="about_version">Sie benutzen aktuell <strong>v0.1.0</strong></string>
+ <string name="about_author_title">Autor</string>
+ <string name="about_author">Diese Android-App wird entwickelt von <a href="http://www.niedermann.it/">Niedermann IT-Dienstleistungen</a></string>
+ <string name="about_icon_disclaimer_title">App-Icon</string>
+ <string name="about_icon_disclaimer"><p>Ursprüngliches Icon wurde erstellt von <a href="http://www.freepik.com" title="Freepik">Freepik</a> auf <a href="http://www.flaticon.com/free-icon/ceo-copyrighting_15475" title="Flaticon">www.flaticon.com</a></p></string>
+
+ <!-- Settings -->
+
+ <string name="settings_server">Server</string>
+ <string name="settings_url">URL</string>
+ <string name="settings_url_check_description">Zeigt an, ob die angegebene URL erreichbar ist.</string>
+ <string name="settings_url_warn_http">WARNUNG: http ist unsicher. Bitte benutzen Sie https.</string>
+ <string name="settings_username">Benutzername</string>
+ <string name="settings_password">Passwort</string>
+ <string name="settings_password_check_description">Zeigt an, ob die angegebenen Zugangsdaten korrekt sind.</string>
+ <string name="settings_submit">OK</string>
+
+ <!-- Network -->
+
+ <string name="network_connecting">Verbindung wird hergestellt</string>
+ <string name="network_connected">Verbunden</string>
+ <string name="network_disconnected">Kein Netzwerk verfügbar</string>
+
+ <!-- Error -->
+
+ <string name="error_url_malformed">URL nicht korrekt</string>
+ <string name="error_json">JSON Fehler</string>
+ <string name="error_io">IO Fehler</string>
+ <string name="error_username_password_invalid">Benutzername / Passwort nicht korrekt</string>
+
+ <!-- Snackbar Actions -->
+ <string name="snackbar_settings">Einstellungen</string>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..b0fbfe3b
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <!-- Colors -->
+
+ <color name="primary">#1d2d44</color>
+ <color name="primary_dark">#112233</color>
+
+ <color name="bg_highlighted">#f3f3f3</color>
+ <color name="bg_normal">#ffffff</color>
+ <color name="fg_default">#000000</color>
+ <color name="fg_default_selection">#333333</color>
+ <color name="fg_default_low">#666666</color>
+ <color name="fg_contrast">#ffffff</color>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..50c11bc9
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+ <!-- Buttons -->
+ <dimen name="button_padding">16dp</dimen>
+ <dimen name="button_elevation">5dp</dimen>
+
+</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..5b4ed838
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OwnCloud Notes</string>
+ <string name="action_create">New Note</string>
+ <string name="action_settings">Settings</string>
+ <string name="action_create_save">Save</string>
+ <string name="action_edit_save">Save</string>
+ <string name="action_about">About</string>
+ <string name="menu_delete">Delete</string>
+ <string name="menu_copy">Copy</string>
+ <string name="menu_edit">Edit</string>
+ <string name="menu_share">Share</string>
+ <string name="menu_about">About</string>
+
+ <string name="ab_selected">selected</string>
+
+ <string name="copy">Copy</string>
+
+ <!-- About -->
+
+ <string name="about_version_title">Version</string>
+ <string name="about_version">You are currently using <strong>v0.1.0</strong></string>
+ <string name="about_author_title">Author</string>
+ <string name="about_author">This Android-Application is developed and presented by <a href="http://www.niedermann.it/">Niedermann IT-Dienstleistungen</a></string>
+ <string name="about_icon_disclaimer_title">App-Icon</string>
+ <string name="about_icon_disclaimer"><p>Original icon made by <a href="http://www.freepik.com" title="Freepik">Freepik</a> from <a href="http://www.flaticon.com/free-icon/ceo-copyrighting_15475" title="Flaticon">www.flaticon.com</a></p></string>
+
+ <!-- Settings -->
+
+ <string name="settings_server">Server</string>
+ <string name="settings_url">URL</string>
+ <string name="settings_url_check_description">Shows if the URL can be pinged.</string>
+ <string name="settings_url_warn_http">WARNING: http is unsafe. Please use https.</string>
+ <string name="settings_username">Username</string>
+ <string name="settings_password">Password</string>
+ <string name="settings_password_check_description">Shows if the given credentials are correct.</string>
+ <string name="settings_submit">OK</string>
+
+ <!-- Network -->
+
+ <string name="network_connecting">Verbindung wird hergestellt</string>
+ <string name="network_connected">Verbunden</string>
+ <string name="network_disconnected">Kein Netzwerk verfügbar</string>
+
+ <!-- Error -->
+
+ <string name="error_url_malformed">URL Malformed</string>
+ <string name="error_json">JSON Error</string>
+ <string name="error_io">IO Error</string>
+ <string name="error_username_password_invalid">Username / Password invalid</string>
+
+ <!-- Snackbar Actions -->
+ <string name="snackbar_settings">Settings</string>
+
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..396713a0
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="OwnCloud" parent="@style/Theme.AppCompat.Light.DarkActionBar">
+ <!-- Main theme colors -->
+ <!-- App Bar -->
+ <item name="colorPrimary">@color/primary</item>
+ <!-- Status Bar and contextual Status Bars -->
+ <item name="colorPrimaryDark">@color/primary_dark</item>
+ <!-- Snackbar Action Link -->
+ <item name="colorAccent">@color/primary</item>
+ <item name="android:buttonStyle">@style/OCButton</item>
+ </style>
+ <style name="fab">
+ <item name="android:layout_margin">16dp</item>
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_gravity">end|bottom</item>
+ <item name="android:layout_alignParentBottom">true</item>
+ <item name="android:layout_alignParentRight">true</item>
+ </style>
+ <style name="OCButton" parent="android:style/Widget.Button">
+ <item name="android:background">@color/bg_normal</item>
+ <item name="android:textColor">@color/primary</item>
+ <item name="android:padding">@dimen/button_padding</item>
+ <item name="android:elevation">@dimen/button_elevation</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 00000000..0a932adb
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,23 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ apply plugin: 'maven'
+ classpath 'com.android.tools.build:gradle:1.3.0'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ maven {
+ url "https://s3.amazonaws.com/repo.commonsware.com"
+ }
+ }
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..9b6ae2a0
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true \ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..8c0fb64a
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..23476b9f
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue Sep 15 07:02:51 CEST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 00000000..91a7e269
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 00000000..d3db1092
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+include ':app'