diff options
author | Stefan Niedermann <stefan.niedermann@googlemail.com> | 2015-10-01 18:54:20 +0300 |
---|---|---|
committer | Stefan Niedermann <stefan.niedermann@googlemail.com> | 2015-10-01 18:54:20 +0300 |
commit | 820540ce48d756be16c51889ca8b00f77691369b (patch) | |
tree | bf7fb2fd02484c2cf1d8f2e214c396725cef1cc1 |
Initial commit
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 Binary files differnew file mode 100644 index 00000000..a18cbb48 --- /dev/null +++ b/app/ic_launcher-web.png 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<Note> + */ + @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<Note> + */ + 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<Note> + */ + 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 Binary files differnew file mode 100644 index 00000000..71d5e118 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_cancel.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_copy.png b/app/src/main/res/drawable-hdpi/ic_action_copy.png Binary files differnew file mode 100644 index 00000000..c170a270 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_copy.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_delete.png b/app/src/main/res/drawable-hdpi/ic_action_delete.png Binary files differnew file mode 100644 index 00000000..21287cbd --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_delete.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_done.png b/app/src/main/res/drawable-hdpi/ic_action_done.png Binary files differnew file mode 100644 index 00000000..c6503fd0 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_done.png 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 Binary files differnew file mode 100644 index 00000000..392a259e --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_done_dark.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_edit.png b/app/src/main/res/drawable-hdpi/ic_action_edit.png Binary files differnew file mode 100644 index 00000000..02e19d04 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_edit.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_new.png b/app/src/main/res/drawable-hdpi/ic_action_new.png Binary files differnew file mode 100644 index 00000000..0fdced8f --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_new.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_settings.png b/app/src/main/res/drawable-hdpi/ic_action_settings.png Binary files differnew file mode 100644 index 00000000..a1a19400 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-hdpi/ic_action_share.png b/app/src/main/res/drawable-hdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..0c460c47 --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_action_share.png diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..439747ce --- /dev/null +++ b/app/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_cancel.png b/app/src/main/res/drawable-mdpi/ic_action_cancel.png Binary files differnew file mode 100644 index 00000000..46907806 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_cancel.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_copy.png b/app/src/main/res/drawable-mdpi/ic_action_copy.png Binary files differnew file mode 100644 index 00000000..afd28ddd --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_copy.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_delete.png b/app/src/main/res/drawable-mdpi/ic_action_delete.png Binary files differnew file mode 100644 index 00000000..9b0e2dbd --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_delete.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_done.png b/app/src/main/res/drawable-mdpi/ic_action_done.png Binary files differnew file mode 100644 index 00000000..4eb240b3 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_done.png 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 Binary files differnew file mode 100644 index 00000000..3f9b108f --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_done_dark.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_edit.png b/app/src/main/res/drawable-mdpi/ic_action_edit.png Binary files differnew file mode 100644 index 00000000..5a06bff5 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_edit.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_new.png b/app/src/main/res/drawable-mdpi/ic_action_new.png Binary files differnew file mode 100644 index 00000000..67bb598e --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_new.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_settings.png b/app/src/main/res/drawable-mdpi/ic_action_settings.png Binary files differnew file mode 100644 index 00000000..8a2f886d --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-mdpi/ic_action_share.png b/app/src/main/res/drawable-mdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..1cafd213 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_action_share.png diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..de725181 --- /dev/null +++ b/app/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_cancel.png b/app/src/main/res/drawable-xhdpi/ic_action_cancel.png Binary files differnew file mode 100644 index 00000000..172acd0f --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_cancel.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_copy.png b/app/src/main/res/drawable-xhdpi/ic_action_copy.png Binary files differnew file mode 100644 index 00000000..c4d15780 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_copy.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_delete.png b/app/src/main/res/drawable-xhdpi/ic_action_delete.png Binary files differnew file mode 100644 index 00000000..beb1637e --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_delete.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_done.png b/app/src/main/res/drawable-xhdpi/ic_action_done.png Binary files differnew file mode 100644 index 00000000..c297f32d --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_done.png 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 Binary files differnew file mode 100644 index 00000000..3400099d --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_done_dark.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_edit.png b/app/src/main/res/drawable-xhdpi/ic_action_edit.png Binary files differnew file mode 100644 index 00000000..d6668a05 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_edit.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_new.png b/app/src/main/res/drawable-xhdpi/ic_action_new.png Binary files differnew file mode 100644 index 00000000..d64c22e9 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_new.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_settings.png b/app/src/main/res/drawable-xhdpi/ic_action_settings.png Binary files differnew file mode 100644 index 00000000..2fbddd2f --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-xhdpi/ic_action_share.png b/app/src/main/res/drawable-xhdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..e275d938 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_action_share.png diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..be0cc6a5 --- /dev/null +++ b/app/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png b/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png Binary files differnew file mode 100644 index 00000000..ef610fb4 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_cancel.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_copy.png b/app/src/main/res/drawable-xxhdpi/ic_action_copy.png Binary files differnew file mode 100644 index 00000000..eead97da --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_copy.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_delete.png b/app/src/main/res/drawable-xxhdpi/ic_action_delete.png Binary files differnew file mode 100644 index 00000000..026c3313 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_delete.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_done.png b/app/src/main/res/drawable-xxhdpi/ic_action_done.png Binary files differnew file mode 100644 index 00000000..e43c8985 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_done.png 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 Binary files differnew file mode 100644 index 00000000..7f67ee04 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_edit.png b/app/src/main/res/drawable-xxhdpi/ic_action_edit.png Binary files differnew file mode 100644 index 00000000..377b2e8d --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_edit.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_new.png b/app/src/main/res/drawable-xxhdpi/ic_action_new.png Binary files differnew file mode 100644 index 00000000..7e699137 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_new.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png Binary files differnew file mode 100644 index 00000000..ccdaf494 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_share.png b/app/src/main/res/drawable-xxhdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..19c907fd --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_action_share.png diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png Binary files differnew file mode 100644 index 00000000..4f2f0572 --- /dev/null +++ b/app/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png b/app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png Binary files differnew file mode 100644 index 00000000..ba88f122 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_copy.png b/app/src/main/res/drawable-xxxhdpi/ic_action_copy.png Binary files differnew file mode 100644 index 00000000..cf9da9d1 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_copy.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_delete.png b/app/src/main/res/drawable-xxxhdpi/ic_action_delete.png Binary files differnew file mode 100644 index 00000000..7cc287bd --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_delete.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_done.png b/app/src/main/res/drawable-xxxhdpi/ic_action_done.png Binary files differnew file mode 100644 index 00000000..7cec5ed4 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_done.png 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 Binary files differnew file mode 100644 index 00000000..e63d05b4 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_done_dark.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_edit.png b/app/src/main/res/drawable-xxxhdpi/ic_action_edit.png Binary files differnew file mode 100644 index 00000000..bde8b21c --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_edit.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_new.png b/app/src/main/res/drawable-xxxhdpi/ic_action_new.png Binary files differnew file mode 100644 index 00000000..165c907d --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_new.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png Binary files differnew file mode 100644 index 00000000..06bf6e3c --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_settings.png diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_share.png b/app/src/main/res/drawable-xxxhdpi/ic_action_share.png Binary files differnew file mode 100644 index 00000000..04be4201 --- /dev/null +++ b/app/src/main/res/drawable-xxxhdpi/ic_action_share.png 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 Binary files differnew file mode 100644 index 00000000..8c0fb64a --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar 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'
|