Initial commit
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
.gradle
|
||||||
|
/local.properties
|
||||||
|
/.idea/workspace.xml
|
||||||
|
/.idea/libraries
|
||||||
|
.DS_Store
|
||||||
|
/build
|
||||||
|
/captures
|
1
.idea/.name
Normal file
|
@ -0,0 +1 @@
|
||||||
|
OwnCloudNotes
|
229
.idea/codeStyleSettings.xml
Normal file
|
@ -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>
|
22
.idea/compiler.xml
Normal file
|
@ -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>
|
3
.idea/copyright/profiles_settings.xml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<component name="CopyrightManager">
|
||||||
|
<settings default="" />
|
||||||
|
</component>
|
19
.idea/gradle.xml
Normal file
|
@ -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>
|
46
.idea/misc.xml
Normal file
|
@ -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>
|
9
.idea/modules.xml
Normal file
|
@ -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>
|
12
.idea/runConfigurations.xml
Normal file
|
@ -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>
|
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="" />
|
||||||
|
</component>
|
||||||
|
</project>
|
0
.navigation/app/raw/main.nvg.xml
Normal file
19
OwnCloudNotes.iml
Normal file
|
@ -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>
|
9
app/.classpath
Normal file
|
@ -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>
|
1
app/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build
|
33
app/.project
Normal file
|
@ -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>
|
103
app/app.iml
Normal file
|
@ -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>
|
29
app/build.gradle
Normal file
|
@ -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')
|
||||||
|
}
|
BIN
app/ic_launcher-web.png
Normal file
After Width: | Height: | Size: 50 KiB |
20
app/proguard-project.txt
Normal file
|
@ -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 *;
|
||||||
|
#}
|
17
app/proguard-rules.pro
vendored
Normal file
|
@ -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 *;
|
||||||
|
#}
|
14
app/project.properties
Normal file
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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/"));
|
||||||
|
}
|
||||||
|
}
|
63
app/src/main/AndroidManifest.xml
Normal file
|
@ -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>
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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) + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package it.niedermann.owncloud.notes.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by stefan on 01.10.15.
|
||||||
|
*/
|
||||||
|
public interface ICallback {
|
||||||
|
public void onFinish();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
app/src/main/res/drawable-hdpi/ic_action_cancel.png
Normal file
After Width: | Height: | Size: 402 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_copy.png
Normal file
After Width: | Height: | Size: 534 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_delete.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_done.png
Normal file
After Width: | Height: | Size: 400 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 729 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_edit.png
Normal file
After Width: | Height: | Size: 302 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 97 B |
BIN
app/src/main/res/drawable-hdpi/ic_action_settings.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-hdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 980 B |
BIN
app/src/main/res/drawable-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/drawable-mdpi/ic_action_cancel.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_copy.png
Normal file
After Width: | Height: | Size: 370 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_delete.png
Normal file
After Width: | Height: | Size: 274 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_done.png
Normal file
After Width: | Height: | Size: 306 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 502 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_edit.png
Normal file
After Width: | Height: | Size: 239 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 97 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_settings.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
app/src/main/res/drawable-mdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 646 B |
BIN
app/src/main/res/drawable-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_action_cancel.png
Normal file
After Width: | Height: | Size: 499 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_copy.png
Normal file
After Width: | Height: | Size: 663 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_delete.png
Normal file
After Width: | Height: | Size: 506 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_done.png
Normal file
After Width: | Height: | Size: 519 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 923 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_edit.png
Normal file
After Width: | Height: | Size: 355 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 102 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_settings.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_cancel.png
Normal file
After Width: | Height: | Size: 834 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_copy.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_delete.png
Normal file
After Width: | Height: | Size: 715 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_done.png
Normal file
After Width: | Height: | Size: 732 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_edit.png
Normal file
After Width: | Height: | Size: 522 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 113 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_settings.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_cancel.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_copy.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_delete.png
Normal file
After Width: | Height: | Size: 957 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_done.png
Normal file
After Width: | Height: | Size: 1,002 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_done_dark.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_edit.png
Normal file
After Width: | Height: | Size: 653 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_new.png
Normal file
After Width: | Height: | Size: 116 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_settings.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_share.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
|
@ -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>
|
7
app/src/main/res/drawable/list_item_color_selector.xml
Normal file
|
@ -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>
|
|
@ -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>
|
8
app/src/main/res/drawable/settings.xml
Normal file
|
@ -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>
|
53
app/src/main/res/layout/activity_about.xml
Normal file
|
@ -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>
|
24
app/src/main/res/layout/activity_create.xml
Normal file
|
@ -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>
|
22
app/src/main/res/layout/activity_edit.xml
Normal file
|
@ -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>
|
29
app/src/main/res/layout/activity_notes_list_view.xml
Normal file
|
@ -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>
|
103
app/src/main/res/layout/activity_settings.xml
Normal file
|
@ -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>
|
21
app/src/main/res/layout/activity_single_note.xml
Normal file
|
@ -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>
|
34
app/src/main/res/layout/fragment_notes_list_view.xml
Normal file
|
@ -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>
|
12
app/src/main/res/menu/menu_list_context_multiple.xml
Normal file
|
@ -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>
|
24
app/src/main/res/menu/menu_list_context_single.xml
Normal file
|
@ -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>
|