Browse Source

Merge branch 'master' into searchViewWrongFiles

Signed-off-by: Mario Danic <mario@lovelyhq.com>

# Conflicts:
#	src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
#	src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java
Mario Danic 8 years ago
parent
commit
b35b1f9c90
100 changed files with 731 additions and 485 deletions
  1. 1 1
      .drone.yml
  2. 0 0
      .drone.yml.sig
  3. 3 0
      CHANGELOG.md
  4. 1 2
      build.gradle
  5. 58 0
      drawable_resources/ic_checkbox_marked.svg
  6. 12 11
      drawable_resources/ic_list_empty_create_folder.svg
  7. 11 12
      drawable_resources/ic_list_empty_folder.svg
  8. 21 22
      drawable_resources/ic_list_empty_image.svg
  9. 11 10
      drawable_resources/ic_list_empty_upload.svg
  10. 25 26
      drawable_resources/ic_list_empty_video.svg
  11. 1 1
      scripts/lint/lint-results.txt
  12. 18 0
      scripts/lint/lint-up-wrapper.sh
  13. 4 0
      src/generic/java/com/owncloud/android/utils/PushUtils.java
  14. 2 22
      src/gplay/AndroidManifest.xml
  15. 0 46
      src/gplay/java/com/owncloud/android/ui/activity/ModifiedFileDisplayActivity.java
  16. 51 44
      src/gplay/java/com/owncloud/android/utils/PushUtils.java
  17. 2 3
      src/main/AndroidManifest.xml
  18. 2 7
      src/main/java/com/owncloud/android/MainApp.java
  19. 5 2
      src/main/java/com/owncloud/android/authentication/AccountUtils.java
  20. 1 1
      src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java
  21. 68 64
      src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
  22. 5 4
      src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
  23. 1 1
      src/main/java/com/owncloud/android/db/PreferenceManager.java
  24. 18 10
      src/main/java/com/owncloud/android/files/FileMenuFilter.java
  25. 7 7
      src/main/java/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
  26. 5 2
      src/main/java/com/owncloud/android/files/services/FileDownloader.java
  27. 2 1
      src/main/java/com/owncloud/android/files/services/IndexedForest.java
  28. 4 0
      src/main/java/com/owncloud/android/media/MediaControlView.java
  29. 0 1
      src/main/java/com/owncloud/android/media/MediaService.java
  30. 1 4
      src/main/java/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java
  31. 8 2
      src/main/java/com/owncloud/android/operations/DownloadFileOperation.java
  32. 7 5
      src/main/java/com/owncloud/android/services/ContactsBackupJob.java
  33. 2 1
      src/main/java/com/owncloud/android/ui/CustomPopup.java
  34. 21 4
      src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java
  35. 53 25
      src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
  36. 2 7
      src/main/java/com/owncloud/android/ui/activity/LogHistoryActivity.java
  37. 3 4
      src/main/java/com/owncloud/android/ui/activity/ParticipateActivity.java
  38. 0 5
      src/main/java/com/owncloud/android/ui/activity/StorageMigration.java
  39. 7 0
      src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java
  40. 7 8
      src/main/java/com/owncloud/android/ui/adapter/FileListListAdapter.java
  41. 2 1
      src/main/java/com/owncloud/android/ui/adapter/FolderSyncAdapter.java
  42. 1 1
      src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
  43. 2 3
      src/main/java/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.java
  44. 2 2
      src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.java
  45. 10 3
      src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java
  46. 2 1
      src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
  47. 5 6
      src/main/java/com/owncloud/android/ui/fragment/LocalFileListFragment.java
  48. 14 2
      src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
  49. 56 3
      src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java
  50. 44 13
      src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java
  51. 92 57
      src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
  52. 4 0
      src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java
  53. 14 16
      src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java
  54. 11 0
      src/main/java/com/owncloud/android/utils/DisplayUtils.java
  55. 0 4
      src/main/java/com/owncloud/android/utils/FileStorageUtils.java
  56. 22 8
      src/main/java/com/owncloud/android/utils/MimeTypeUtil.java
  57. BIN
      src/main/res/drawable-hdpi/ic_checkbox_marked.png
  58. BIN
      src/main/res/drawable-hdpi/ic_list_empty_create_folder.png
  59. BIN
      src/main/res/drawable-hdpi/ic_list_empty_folder.png
  60. BIN
      src/main/res/drawable-hdpi/ic_list_empty_upload.png
  61. BIN
      src/main/res/drawable-hdpi/nav_activity.png
  62. 0 0
      src/main/res/drawable-hdpi/nav_all_files.png
  63. BIN
      src/main/res/drawable-hdpi/nav_contacts.png
  64. 0 0
      src/main/res/drawable-hdpi/nav_favorites.png
  65. 0 0
      src/main/res/drawable-hdpi/nav_folder_sync.png
  66. 0 0
      src/main/res/drawable-hdpi/nav_logout.png
  67. BIN
      src/main/res/drawable-hdpi/nav_notifications.png
  68. 0 0
      src/main/res/drawable-hdpi/nav_on_device.png
  69. 0 0
      src/main/res/drawable-hdpi/nav_participate.png
  70. BIN
      src/main/res/drawable-hdpi/nav_photos.png
  71. 0 0
      src/main/res/drawable-hdpi/nav_recently.png
  72. BIN
      src/main/res/drawable-hdpi/nav_settings.png
  73. 0 0
      src/main/res/drawable-hdpi/nav_shared.png
  74. 0 0
      src/main/res/drawable-hdpi/nav_uploads.png
  75. BIN
      src/main/res/drawable-hdpi/nav_videos.png
  76. BIN
      src/main/res/drawable-mdpi/ic_checkbox_marked.png
  77. BIN
      src/main/res/drawable-mdpi/ic_list_empty_create_folder.png
  78. BIN
      src/main/res/drawable-mdpi/ic_list_empty_folder.png
  79. BIN
      src/main/res/drawable-mdpi/ic_list_empty_upload.png
  80. BIN
      src/main/res/drawable-mdpi/nav_activity.png
  81. BIN
      src/main/res/drawable-mdpi/nav_all_files.png
  82. BIN
      src/main/res/drawable-mdpi/nav_contacts.png
  83. 0 0
      src/main/res/drawable-mdpi/nav_favorites.png
  84. 0 0
      src/main/res/drawable-mdpi/nav_folder_sync.png
  85. 0 0
      src/main/res/drawable-mdpi/nav_logout.png
  86. BIN
      src/main/res/drawable-mdpi/nav_notifications.png
  87. 0 0
      src/main/res/drawable-mdpi/nav_on_device.png
  88. 0 0
      src/main/res/drawable-mdpi/nav_participate.png
  89. BIN
      src/main/res/drawable-mdpi/nav_photos.png
  90. 0 0
      src/main/res/drawable-mdpi/nav_recently.png
  91. BIN
      src/main/res/drawable-mdpi/nav_settings.png
  92. 0 0
      src/main/res/drawable-mdpi/nav_shared.png
  93. 0 0
      src/main/res/drawable-mdpi/nav_uploads.png
  94. BIN
      src/main/res/drawable-mdpi/nav_videos.png
  95. BIN
      src/main/res/drawable-xhdpi/ic_checkbox_marked.png
  96. BIN
      src/main/res/drawable-xhdpi/ic_list_empty_create_folder.png
  97. BIN
      src/main/res/drawable-xhdpi/ic_list_empty_folder.png
  98. BIN
      src/main/res/drawable-xhdpi/ic_list_empty_upload.png
  99. BIN
      src/main/res/drawable-xhdpi/nav_activity.png
  100. 0 0
      src/main/res/drawable-xhdpi/nav_all_files.png

+ 1 - 1
.drone.yml

@@ -34,7 +34,7 @@ pipeline:
         # needs gplay
         # needs gplay
         - sed -i '/com.google.*.gms/s/^.*\/\///g' build.gradle
         - sed -i '/com.google.*.gms/s/^.*\/\///g' build.gradle
         - export BRANCH=$(scripts/lint/getBranchName.sh ${GIT_USERNAME} ${GIT_TOKEN} ${DRONE_PULL_REQUEST})
         - export BRANCH=$(scripts/lint/getBranchName.sh ${GIT_USERNAME} ${GIT_TOKEN} ${DRONE_PULL_REQUEST})
-        - ruby scripts/lint/lint-up.rb ${GIT_USERNAME} ${GIT_TOKEN} $BRANCH
+        - scripts/lint/lint-up-wrapper.sh ${GIT_USERNAME} ${GIT_TOKEN} $BRANCH ${LOG_USERNAME} ${LOG_PASSWORD} ${DRONE_BUILD_NUMBER}
       when:
       when:
         matrix:
         matrix:
           FLAVOUR: Modified
           FLAVOUR: Modified

File diff suppressed because it is too large
+ 0 - 0
.drone.yml.sig


+ 3 - 0
CHANGELOG.md

@@ -1,3 +1,6 @@
+## 1.4.3 (May 22, 2017)
+- Hotfix: ignore oauth header for now and use basic auth to allow new logins for nc12
+
 ## 1.4.2 (March 14, 2017)
 ## 1.4.2 (March 14, 2017)
 - Auto Upload for newly taken photos/images (Android 6+)
 - Auto Upload for newly taken photos/images (Android 6+)
 - Auto Upload improvements and fixes
 - Auto Upload improvements and fixes

+ 1 - 2
build.gradle

@@ -52,7 +52,6 @@ repositories {
 android {
 android {
     lintOptions {
     lintOptions {
         abortOnError false
         abortOnError false
-        lintConfig file("${project.rootDir}/lint.xml")
         htmlReport true
         htmlReport true
         htmlOutput file("$project.buildDir/reports/lint/lint.html")
         htmlOutput file("$project.buildDir/reports/lint/lint.html")
         disable 'MissingTranslation'
         disable 'MissingTranslation'
@@ -179,7 +178,7 @@ dependencies {
     compile name: 'touch-image-view'
     compile name: 'touch-image-view'
     compile 'com.android.support:multidex:1.0.1'
     compile 'com.android.support:multidex:1.0.1'
 
 
-    compile 'com.github.nextcloud:android-library:1.0.17'
+    compile 'com.github.nextcloud:android-library:1.0.18'
     compile "com.android.support:support-v4:${supportLibraryVersion}"
     compile "com.android.support:support-v4:${supportLibraryVersion}"
     compile "com.android.support:design:${supportLibraryVersion}"
     compile "com.android.support:design:${supportLibraryVersion}"
     compile 'com.jakewharton:disklrucache:2.0.2'
     compile 'com.jakewharton:disklrucache:2.0.2'

+ 58 - 0
drawable_resources/ic_checkbox_marked.svg

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    fill="#000000"
+    height="24"
+    viewBox="0 0 24 24"
+    width="24"
+    id="svg2"
+    version="1.1"
+    inkscape:version="0.91 r13725"
+    sodipodi:docname="ic_check_box_black_24px.svg">
+    <metadata
+        id="metadata12">
+        <rdf:RDF>
+            <cc:Work
+                rdf:about="">
+                <dc:format>image/svg+xml</dc:format>
+                <dc:type
+                    rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+            </cc:Work>
+        </rdf:RDF>
+    </metadata>
+    <defs
+        id="defs10"/>
+    <sodipodi:namedview
+        pagecolor="#ffffff"
+        bordercolor="#666666"
+        borderopacity="1"
+        objecttolerance="10"
+        gridtolerance="10"
+        guidetolerance="10"
+        inkscape:pageopacity="0"
+        inkscape:pageshadow="2"
+        inkscape:window-width="1600"
+        inkscape:window-height="835"
+        id="namedview8"
+        showgrid="false"
+        inkscape:zoom="19.666667"
+        inkscape:cx="12.44099"
+        inkscape:cy="9.9174774"
+        inkscape:window-x="1600"
+        inkscape:window-y="0"
+        inkscape:window-maximized="1"
+        inkscape:current-layer="svg2"/>
+    <path
+        d="M0 0h24v24H0z"
+        fill="none"
+        id="path4"/>
+    <path
+        d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"
+        id="path6"
+        style="fill:#007cc2;fill-opacity:1"/>
+</svg>

+ 12 - 11
drawable_resources/ic_list_empty_create_folder.svg

@@ -7,15 +7,15 @@
    xmlns="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   height="16"
-   width="16"
+   height="17.066668"
+   width="17.066668"
    version="1"
    version="1"
    id="svg2"
    id="svg2"
-   inkscape:version="0.91 r13725"
+   inkscape:version="0.92.1 r15371"
    sodipodi:docname="ic_list_empty_create_folder.svg"
    sodipodi:docname="ic_list_empty_create_folder.svg"
-   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\designTweaks\res\drawable-mdpi\ic_list_empty_create_folder.png"
-   inkscape:export-xdpi="405"
-   inkscape:export-ydpi="405">
+   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\colorFolderNew\src\main\res\drawable-xxxhdpi\ic_list_empty_create_folder.png"
+   inkscape:export-xdpi="1620"
+   inkscape:export-ydpi="1620">
   <metadata
   <metadata
      id="metadata10">
      id="metadata10">
     <rdf:RDF>
     <rdf:RDF>
@@ -44,14 +44,15 @@
      id="namedview6"
      id="namedview6"
      showgrid="false"
      showgrid="false"
      inkscape:zoom="29.5"
      inkscape:zoom="29.5"
-     inkscape:cx="-12.171603"
-     inkscape:cy="13.899981"
+     inkscape:cx="4.4894139"
+     inkscape:cy="8.4762522"
      inkscape:window-x="-9"
      inkscape:window-x="-9"
      inkscape:window-y="-9"
      inkscape:window-y="-9"
      inkscape:window-maximized="1"
      inkscape:window-maximized="1"
      inkscape:current-layer="svg2" />
      inkscape:current-layer="svg2" />
   <path
   <path
-     style="fill:#99cde9;fill-opacity:1"
-     d="M 1.4570312 1.9960938 C 1.2070312 1.9960938 0.99609375 2.2070313 0.99609375 2.4570312 L 0.99609375 13.537109 C 0.99609375 13.797109 1.1990312 13.996094 1.4570312 13.996094 L 14.537109 13.996094 C 14.795109 13.996094 14.996094 13.797109 14.996094 13.537109 L 14.996094 4.4609375 C 14.996094 4.2109375 14.787109 3.9960937 14.537109 3.9960938 L 7.9960938 3.9960938 L 5.9960938 1.9960938 L 1.4570312 1.9960938 z M 9.9707031 6.2363281 L 11.306641 6.2363281 L 11.306641 8.25 L 13.314453 8.25 L 13.314453 9.5859375 L 11.306641 9.5859375 L 11.306641 11.589844 L 9.9707031 11.589844 L 9.9707031 9.5859375 L 7.9589844 9.5859375 L 7.9589844 8.25 L 9.9707031 8.25 L 9.9707031 6.2363281 z "
-     id="path4" />
+     style="fill:#0082c9;fill-opacity:1;stroke-width:1.06666672;opacity:0.5"
+     d="m 1.5541666,2.1291667 c -0.2666667,0 -0.4916666,0.225 -0.4916666,0.4916666 V 14.439583 c 0,0.277333 0.2164666,0.489584 0.4916666,0.489584 H 15.50625 c 0.2752,0 0.489584,-0.212251 0.489584,-0.489584 V 4.7583333 c 0,-0.2666666 -0.222918,-0.4958334 -0.489584,-0.4958332 H 8.5291667 L 6.3958334,2.1291667 Z m 9.0812504,4.5229166 h 1.425 V 8.8 h 2.141666 v 1.425 h -2.141666 v 2.1375 h -1.425 V 10.225 H 8.4895834 V 8.8 h 2.1458336 z"
+     id="path4"
+     inkscape:connector-curvature="0" />
 </svg>
 </svg>

+ 11 - 12
drawable_resources/ic_list_empty_folder.svg

@@ -7,15 +7,15 @@
    xmlns="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   height="16"
-   width="16"
+   height="17.066668"
+   width="17.066668"
    version="1"
    version="1"
    id="svg2"
    id="svg2"
-   inkscape:version="0.91 r13725"
-   sodipodi:docname="list_empty_folder_empty.svg"
-   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\designTweaks\res\drawable-mdpi\ic_folder_empty.png"
-   inkscape:export-xdpi="405"
-   inkscape:export-ydpi="405">
+   inkscape:version="0.92.1 r15371"
+   sodipodi:docname="ic_list_empty_folder.svg"
+   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\colorFolderNew\src\main\res\drawable-xxxhdpi\ic_list_empty_folder.png"
+   inkscape:export-xdpi="1620"
+   inkscape:export-ydpi="1620">
   <metadata
   <metadata
      id="metadata10">
      id="metadata10">
     <rdf:RDF>
     <rdf:RDF>
@@ -43,16 +43,15 @@
      id="namedview6"
      id="namedview6"
      showgrid="false"
      showgrid="false"
      inkscape:zoom="14.75"
      inkscape:zoom="14.75"
-     inkscape:cx="-10.20339"
+     inkscape:cx="1.4237286"
      inkscape:cy="8"
      inkscape:cy="8"
      inkscape:window-x="-9"
      inkscape:window-x="-9"
      inkscape:window-y="-9"
      inkscape:window-y="-9"
      inkscape:window-maximized="1"
      inkscape:window-maximized="1"
      inkscape:current-layer="svg2" />
      inkscape:current-layer="svg2" />
   <path
   <path
-     d="M1.457 1.997c-.25 0-.46.21-.46.46v11.08c0 .26.202.46.46.46h13.08c.258 0 .46-.2.46-.46V4.46c0-.25-.21-.463-.46-.463h-6.54l-2-2z"
-     fill-rule="evenodd"
-     fill="#0082c9"
+     d="m 1.5541333,2.1301333 c -0.2666666,0 -0.4906666,0.224 -0.4906666,0.4906667 v 11.818667 c 0,0.277333 0.2154666,0.490666 0.4906666,0.490666 H 15.506133 c 0.2752,0 0.490667,-0.213333 0.490667,-0.490666 V 4.7573333 c 0,-0.2666666 -0.224,-0.4938666 -0.490667,-0.4938666 H 8.5301333 L 6.3968,2.1301333 Z"
      id="path4"
      id="path4"
-     style="fill:#99cde9;fill-opacity:1" />
+     style="fill:#0082c9;fill-opacity:1;fill-rule:evenodd;stroke-width:1.06666672;opacity:0.5"
+     inkscape:connector-curvature="0" />
 </svg>
 </svg>

+ 21 - 22
drawable_resources/ic_list_empty_image.svg

@@ -1,21 +1,20 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <svg
 <svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   height="16"
-   width="16"
-   version="1"
-   id="svg4"
-   sodipodi:docname="ic_list_empty_image.svg"
-   inkscape:version="0.92.1 r15371"
-   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_image.png"
-   inkscape:export-xdpi="432"
-   inkscape:export-ydpi="432">
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    height="16"
+    width="16"
+    version="1"
+    id="svg4"
+    sodipodi:docname="ic_list_empty_image.svg"
+    inkscape:version="0.91 r13725"
+    inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_image.png"
+    inkscape:export-xdpi="432"
+    inkscape:export-ydpi="432">
   <metadata
   <metadata
      id="metadata10">
      id="metadata10">
     <rdf:RDF>
     <rdf:RDF>
@@ -38,19 +37,19 @@
      guidetolerance="10"
      guidetolerance="10"
      inkscape:pageopacity="0"
      inkscape:pageopacity="0"
      inkscape:pageshadow="2"
      inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1005"
+     inkscape:window-width="1600"
+     inkscape:window-height="835"
      id="namedview6"
      id="namedview6"
      showgrid="false"
      showgrid="false"
      inkscape:zoom="14.75"
      inkscape:zoom="14.75"
-     inkscape:cx="8"
+     inkscape:cx="17.694915"
      inkscape:cy="8"
      inkscape:cy="8"
-     inkscape:window-x="-9"
-     inkscape:window-y="-9"
+     inkscape:window-x="1600"
+     inkscape:window-y="0"
      inkscape:window-maximized="1"
      inkscape:window-maximized="1"
      inkscape:current-layer="svg4" />
      inkscape:current-layer="svg4" />
   <path
   <path
-     style="block-progression:tb;text-transform:none;text-indent:0;fill:#000000;fill-opacity:1;opacity:0.5"
+     style="block-progression:tb;text-transform:none;text-indent:0;fill:#757575;fill-opacity:1;opacity:1"
      d="M1.344 2A.445.445 0 0 0 1 2.438v11.124c0 .23.212.44.438.44h13.125a.457.457 0 0 0 .437-.44V2.61c0-.337-.264-.61-.515-.61zM2 3h12v5l-1-1-3 4-3-3-4 4H2zm2.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"
      d="M1.344 2A.445.445 0 0 0 1 2.438v11.124c0 .23.212.44.438.44h13.125a.457.457 0 0 0 .437-.44V2.61c0-.337-.264-.61-.515-.61zM2 3h12v5l-1-1-3 4-3-3-4 4H2zm2.5 1a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3z"
      fill="#969696"
      fill="#969696"
      color="#000"
      color="#000"

+ 11 - 10
drawable_resources/ic_list_empty_upload.svg

@@ -8,15 +8,15 @@
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    version="1.1"
    version="1.1"
-   width="24"
-   height="24"
+   width="25.6"
+   height="25.6"
    viewBox="0 0 24 24"
    viewBox="0 0 24 24"
    id="svg2"
    id="svg2"
-   inkscape:version="0.91 r13725"
+   inkscape:version="0.92.1 r15371"
    sodipodi:docname="ic_list_empty_upload.svg"
    sodipodi:docname="ic_list_empty_upload.svg"
-   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\designTweaks\res\drawable-xxxhdpi\ic_list_empty_upload.png"
-   inkscape:export-xdpi="1080"
-   inkscape:export-ydpi="1080">
+   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\colorFolderNew\src\main\res\drawable-mdpi\ic_list_empty_upload.png"
+   inkscape:export-xdpi="270"
+   inkscape:export-ydpi="270">
   <metadata
   <metadata
      id="metadata10">
      id="metadata10">
     <rdf:RDF>
     <rdf:RDF>
@@ -44,14 +44,15 @@
      id="namedview6"
      id="namedview6"
      showgrid="false"
      showgrid="false"
      inkscape:zoom="9.8333333"
      inkscape:zoom="9.8333333"
-     inkscape:cx="-15.305085"
-     inkscape:cy="12"
+     inkscape:cx="14.338983"
+     inkscape:cy="16.067797"
      inkscape:window-x="-9"
      inkscape:window-x="-9"
      inkscape:window-y="-9"
      inkscape:window-y="-9"
      inkscape:window-maximized="1"
      inkscape:window-maximized="1"
      inkscape:current-layer="svg2" />
      inkscape:current-layer="svg2" />
   <path
   <path
-     d="M9,16V10H5L12,3L19,10H15V16H9M5,20V18H19V20H5Z"
+     d="M 9,16 V 10 H 5 l 7,-7 7,7 h -4 v 6 H 9 m -4,4 v -2 h 14 v 2 z"
      id="path4"
      id="path4"
-     style="fill:#99cde9;fill-opacity:1" />
+     style="fill:#0082c9;fill-opacity:1;opacity:0.5"
+     inkscape:connector-curvature="0" />
 </svg>
 </svg>

+ 25 - 26
drawable_resources/ic_list_empty_video.svg

@@ -1,21 +1,20 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <svg
 <svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   height="16"
-   width="16"
-   version="1"
-   id="svg4"
-   sodipodi:docname="ic_list_empty_video.svg"
-   inkscape:version="0.92.1 r15371"
-   inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_video.png"
-   inkscape:export-xdpi="432"
-   inkscape:export-ydpi="432">
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    height="16"
+    width="16"
+    version="1"
+    id="svg4"
+    sodipodi:docname="ic_list_empty_video.svg"
+    inkscape:version="0.91 r13725"
+    inkscape:export-filename="C:\DEV\src\Android\Nextcloud\favourites\src\main\res\drawable-mdpi\ic_list_empty_video.png"
+    inkscape:export-xdpi="432"
+    inkscape:export-ydpi="432">
   <metadata
   <metadata
      id="metadata10">
      id="metadata10">
     <rdf:RDF>
     <rdf:RDF>
@@ -38,21 +37,21 @@
      guidetolerance="10"
      guidetolerance="10"
      inkscape:pageopacity="0"
      inkscape:pageopacity="0"
      inkscape:pageshadow="2"
      inkscape:pageshadow="2"
-     inkscape:window-width="1920"
-     inkscape:window-height="1005"
+     inkscape:window-width="1600"
+     inkscape:window-height="835"
      id="namedview6"
      id="namedview6"
      showgrid="false"
      showgrid="false"
-     inkscape:zoom="14.75"
-     inkscape:cx="8"
-     inkscape:cy="8"
-     inkscape:window-x="-9"
-     inkscape:window-y="-9"
+     inkscape:zoom="20.85965"
+     inkscape:cx="-15.290906"
+     inkscape:cy="9.1100694"
+     inkscape:window-x="1600"
+     inkscape:window-y="0"
      inkscape:window-maximized="1"
      inkscape:window-maximized="1"
      inkscape:current-layer="svg4" />
      inkscape:current-layer="svg4" />
   <path
   <path
-     style="block-progression:tb;text-transform:none;text-indent:0;fill:#000000;fill-opacity:1;opacity:0.5"
+     style="block-progression:tb;text-transform:none;text-indent:0;fill:#757575;fill-opacity:1;opacity:1"
      d="M1.344 2A.445.445 0 0 0 1 2.438v11.124c0 .23.212.44.438.44h13.124a.457.457 0 0 0 .438-.44V2.61c0-.336-.265-.61-.516-.61zM2 3h12v10H2zm3 2v6l6-3z"
      d="M1.344 2A.445.445 0 0 0 1 2.438v11.124c0 .23.212.44.438.44h13.124a.457.457 0 0 0 .438-.44V2.61c0-.336-.265-.61-.516-.61zM2 3h12v10H2zm3 2v6l6-3z"
+     id="path2"
      fill="#969696"
      fill="#969696"
-     color="#000"
-     id="path2" />
+     color="#000" />
 </svg>
 </svg>

+ 1 - 1
scripts/lint/lint-results.txt

@@ -1,2 +1,2 @@
 DO NOT TOUCH; GENERATED BY DRONE
 DO NOT TOUCH; GENERATED BY DRONE
-      <span class="mdl-layout-title">Lint Report: 74 errors and 859 warnings</span>
+      <span class="mdl-layout-title">Lint Report: 74 errors and 848 warnings</span>

+ 18 - 0
scripts/lint/lint-up-wrapper.sh

@@ -0,0 +1,18 @@
+#!/bin/sh
+
+#1: GIT_USERNAME
+#2: GIT_TOKEN
+#3: BRANCH
+#4: LOG_USERNAME
+#5: LOG_PASSWORD
+#6: DRONE_BUILD_NUMBER
+
+ruby scripts/lint/lint-up.rb $1 $2 $3
+
+if [ $? -eq 0 ]; then
+    echo "New master at: https://nextcloud.kaminsky.me/index.php/s/tXwtChzyqMj6I8v"
+    curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/droneLogs/master.html --upload-file build/reports/lint/lint.html
+else
+    echo "New results at https://nextcloud.kaminsky.me/index.php/s/tXwtChzyqMj6I8v ->" $6.html
+    curl -u $4:$5 -X PUT https://nextcloud.kaminsky.me/remote.php/webdav/droneLogs/$6.html --upload-file build/reports/lint/lint.html
+fi

+ 4 - 0
src/generic/java/com/owncloud/android/utils/PushUtils.java

@@ -22,4 +22,8 @@ package com.owncloud.android.utils;
 
 
 public class PushUtils {
 public class PushUtils {
     public static final String KEY_PUSH = "push";
     public static final String KEY_PUSH = "push";
+
+    public static void pushRegistrationToServer() {
+        // do nothing
+    }
 }
 }

+ 2 - 22
src/gplay/AndroidManifest.xml

@@ -19,8 +19,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           xmlns:tools="http://schemas.android.com/tools"
           xmlns:tools="http://schemas.android.com/tools"
           package="com.owncloud.android"
           package="com.owncloud.android"
-          android:versionCode="10040299"
-          android:versionName="1.4.2">
+          android:versionCode="10040399"
+          android:versionName="1.4.3">
 
 
     <application
     <application
         android:name=".MainApp"
         android:name=".MainApp"
@@ -33,17 +33,6 @@
         <meta-data android:name="com.google.android.gms.version"
         <meta-data android:name="com.google.android.gms.version"
                    android:value="@integer/google_play_services_version" />
                    android:value="@integer/google_play_services_version" />
 
 
-        <activity
-            android:name=".ui.activity.ModifiedFileDisplayActivity"
-            android:label="@string/app_name"
-            android:theme="@style/Theme.ownCloud.Toolbar.Drawer">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-
         <activity
         <activity
             android:name=".authentication.ModifiedAuthenticatorActivity"
             android:name=".authentication.ModifiedAuthenticatorActivity"
             android:exported="true"
             android:exported="true"
@@ -70,15 +59,6 @@
             </intent-filter>
             </intent-filter>
         </activity>
         </activity>
 
 
-        <activity
-            android:name=".ui.activity.FileDisplayActivity"
-            tools:node="remove"/>
-
-        <activity-alias
-            android:name=".ui.activity.FileDisplayActivity"
-            android:targetActivity=".ui.activity.ModifiedFileDisplayActivity"
-            tools:replace="android:targetActivity"/>
-
         <activity-alias
         <activity-alias
             android:name=".authentication.AuthenticatorActivity"
             android:name=".authentication.AuthenticatorActivity"
             android:targetActivity=".authentication.ModifiedAuthenticatorActivity"
             android:targetActivity=".authentication.ModifiedAuthenticatorActivity"

+ 0 - 46
src/gplay/java/com/owncloud/android/ui/activity/ModifiedFileDisplayActivity.java

@@ -1,46 +0,0 @@
-/**
- * Nextcloud Android client application
- *
- * @author Mario Danic
- * Copyright (C) 2017 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.owncloud.android.ui.activity;
-
-import android.os.Bundle;
-
-import com.owncloud.android.ui.events.TokenPushEvent;
-import com.owncloud.android.utils.PushUtils;
-
-import org.greenrobot.eventbus.EventBus;
-import org.greenrobot.eventbus.Subscribe;
-import org.greenrobot.eventbus.ThreadMode;
-
-public class ModifiedFileDisplayActivity extends FileDisplayActivity {
-
-    @Subscribe(threadMode = ThreadMode.BACKGROUND)
-    public void onMessageEvent(TokenPushEvent event) {
-        PushUtils.pushRegistrationToServer();
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        // see if there's stuff to push every time we start the app
-        EventBus.getDefault().post(new TokenPushEvent());
-    }
-
-}

+ 51 - 44
src/gplay/java/com/owncloud/android/utils/PushUtils.java

@@ -76,7 +76,7 @@ public class PushUtils {
 
 
     private static ArbitraryDataProvider arbitraryDataProvider;
     private static ArbitraryDataProvider arbitraryDataProvider;
 
 
-    private static String generateSHA512Hash(String pushToken) {
+    public static String generateSHA512Hash(String pushToken) {
         MessageDigest messageDigest = null;
         MessageDigest messageDigest = null;
         try {
         try {
             messageDigest = MessageDigest.getInstance("SHA-512");
             messageDigest = MessageDigest.getInstance("SHA-512");
@@ -88,7 +88,7 @@ public class PushUtils {
         return "";
         return "";
     }
     }
 
 
-    private static String bytesToHex(byte[] bytes) {
+    public static String bytesToHex(byte[] bytes) {
         StringBuilder result = new StringBuilder();
         StringBuilder result = new StringBuilder();
         for (byte individualByte : bytes) {
         for (byte individualByte : bytes) {
             result.append(Integer.toString((individualByte & 0xff) + 0x100, 16)
             result.append(Integer.toString((individualByte & 0xff) + 0x100, 16)
@@ -96,7 +96,7 @@ public class PushUtils {
         }
         }
         return result.toString();
         return result.toString();
     }
     }
-
+    
     private static int generateRsa2048KeyPair() {
     private static int generateRsa2048KeyPair() {
         String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
         String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
                 + KEYPAIR_FOLDER;
                 + KEYPAIR_FOLDER;
@@ -202,56 +202,63 @@ public class PushUtils {
 
 
                 Context context = MainApp.getAppContext();
                 Context context = MainApp.getAppContext();
                 String providerValue;
                 String providerValue;
+                PushConfigurationState accountPushData = null;
                 Gson gson = new Gson();
                 Gson gson = new Gson();
                 for (Account account : AccountUtils.getAccounts(context)) {
                 for (Account account : AccountUtils.getAccounts(context)) {
-                    if (!TextUtils.isEmpty(providerValue = arbitraryDataProvider.getValue(account, KEY_PUSH))) {
-                        PushConfigurationState accountPushData = gson.fromJson(providerValue,
+                    providerValue = arbitraryDataProvider.getValue(account, KEY_PUSH);
+                    if (!TextUtils.isEmpty(providerValue)) {
+                        accountPushData = gson.fromJson(providerValue,
                                 PushConfigurationState.class);
                                 PushConfigurationState.class);
-                        if (!accountPushData.getPushToken().equals(token) && !accountPushData.isShouldBeDeleted()) {
-                            try {
-                                OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
-                                OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
-                                        getClientFor(ocAccount, context);
+                    } else {
+                        accountPushData = null;
+                    }
+
+                    if (accountPushData != null && !accountPushData.getPushToken().equals(token) &&
+                            !accountPushData.isShouldBeDeleted() ||
+                            TextUtils.isEmpty(providerValue)) {
+                        try {
+                            OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
+                            OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                                    getClientFor(ocAccount, context);
+
+                            RemoteOperation registerAccountDeviceForNotificationsOperation =
+                                    new RegisterAccountDeviceForNotificationsOperation(pushTokenHash,
+                                            publicKey,
+                                            context.getResources().getString(R.string.push_server_url));
 
 
-                                RemoteOperation registerAccountDeviceForNotificationsOperation =
-                                        new RegisterAccountDeviceForNotificationsOperation(pushTokenHash,
-                                                publicKey,
-                                                context.getResources().getString(R.string.push_server_url));
+                            RemoteOperationResult remoteOperationResult = registerAccountDeviceForNotificationsOperation.
+                                    execute(mClient);
 
 
-                                RemoteOperationResult remoteOperationResult = registerAccountDeviceForNotificationsOperation.
-                                        execute(mClient);
+                            if (remoteOperationResult.isSuccess()) {
+                                PushResponse pushResponse = remoteOperationResult.getPushResponseData();
+
+                                RemoteOperation registerAccountDeviceForProxyOperation = new
+                                        RegisterAccountDeviceForProxyOperation(
+                                        context.getResources().getString(R.string.push_server_url),
+                                        token, pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
+                                        pushResponse.getPublicKey());
+
+                                remoteOperationResult = registerAccountDeviceForProxyOperation.execute(mClient);
 
 
                                 if (remoteOperationResult.isSuccess()) {
                                 if (remoteOperationResult.isSuccess()) {
-                                    PushResponse pushResponse = remoteOperationResult.getPushResponseData();
-
-                                    RemoteOperation registerAccountDeviceForProxyOperation = new
-                                            RegisterAccountDeviceForProxyOperation(
-                                            context.getResources().getString(R.string.push_server_url),
-                                            token, pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
-                                            pushResponse.getPublicKey());
-
-                                    remoteOperationResult = registerAccountDeviceForProxyOperation.execute(mClient);
-
-                                    if (remoteOperationResult.isSuccess()) {
-                                        PushConfigurationState pushArbitraryData = new PushConfigurationState(token,
-                                                pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
-                                                pushResponse.getPublicKey(), false);
-                                        arbitraryDataProvider.storeOrUpdateKeyValue(account, KEY_PUSH,
-                                                gson.toJson(pushArbitraryData));
-                                    }
+                                    PushConfigurationState pushArbitraryData = new PushConfigurationState(token,
+                                            pushResponse.getDeviceIdentifier(), pushResponse.getSignature(),
+                                            pushResponse.getPublicKey(), false);
+                                    arbitraryDataProvider.storeOrUpdateKeyValue(account, KEY_PUSH,
+                                            gson.toJson(pushArbitraryData));
                                 }
                                 }
-                            } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
-                                Log_OC.d(TAG, "Failed to find an account");
-                            } catch (AuthenticatorException e) {
-                                Log_OC.d(TAG, "Failed via AuthenticatorException");
-                            } catch (IOException e) {
-                                Log_OC.d(TAG, "Failed via IOException");
-                            } catch (OperationCanceledException e) {
-                                Log_OC.d(TAG, "Failed via OperationCanceledException");
                             }
                             }
-                        } else if (accountPushData.isShouldBeDeleted()) {
-                            deleteRegistrationForAccount(account);
+                        } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
+                            Log_OC.d(TAG, "Failed to find an account");
+                        } catch (AuthenticatorException e) {
+                            Log_OC.d(TAG, "Failed via AuthenticatorException");
+                        } catch (IOException e) {
+                            Log_OC.d(TAG, "Failed via IOException");
+                        } catch (OperationCanceledException e) {
+                            Log_OC.d(TAG, "Failed via OperationCanceledException");
                         }
                         }
+                    } else if (accountPushData != null && accountPushData.isShouldBeDeleted()) {
+                        deleteRegistrationForAccount(account);
                     }
                     }
                 }
                 }
             }
             }
@@ -261,7 +268,7 @@ public class PushUtils {
     public static Key readKeyFromFile(boolean readPublicKey) {
     public static Key readKeyFromFile(boolean readPublicKey) {
         String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
         String keyPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator
                 + KEYPAIR_FOLDER;
                 + KEYPAIR_FOLDER;
-        
+
         String privateKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PRIV_EXTENSION;
         String privateKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PRIV_EXTENSION;
         String publicKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PUB_EXTENSION;
         String publicKeyPath = keyPath + File.separator + KEYPAIR_FILE_NAME + KEYPAIR_PUB_EXTENSION;
 
 

+ 2 - 3
src/main/AndroidManifest.xml

@@ -19,10 +19,9 @@
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          xmlns:tools="http://schemas.android.com/tools"
           package="com.owncloud.android"
           package="com.owncloud.android"
-          android:versionCode="10040299"
-          android:versionName="1.4.2">
+          android:versionCode="10040399"
+          android:versionName="1.4.3">
 
 
     <uses-sdk
     <uses-sdk
         android:minSdkVersion="14"
         android:minSdkVersion="14"

+ 2 - 7
src/main/java/com/owncloud/android/MainApp.java

@@ -112,13 +112,8 @@ public class MainApp extends MultiDexApplication {
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
 
 
         if (BuildConfig.DEBUG) {
         if (BuildConfig.DEBUG) {
-
-            String dataFolder = getDataFolder();
-
-            // Set folder for store logs
-            Log_OC.setLogDataFolder(dataFolder);
-
-            Log_OC.startLogging(MainApp.storagePath);
+            // use app writable dir, no permissions needed
+            Log_OC.startLogging(getAppContext());
             Log_OC.d("Debug", "start logging");
             Log_OC.d("Debug", "start logging");
         }
         }
 
 

+ 5 - 2
src/main/java/com/owncloud/android/authentication/AccountUtils.java

@@ -156,7 +156,7 @@ public class AccountUtils {
                             .getDefaultSharedPreferences(context).edit();
                             .getDefaultSharedPreferences(context).edit();
                     appPrefs.putString("select_oc_account", accountName);
                     appPrefs.putString("select_oc_account", accountName);
     
     
-                    appPrefs.commit();
+                    appPrefs.apply();
                     result = true;
                     result = true;
                     break;
                     break;
                 }
                 }
@@ -208,7 +208,10 @@ public class AccountUtils {
             if (currentAccountVersion == null) {
             if (currentAccountVersion == null) {
                 Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION);
                 Log_OC.i(TAG, "Upgrading accounts to account version #" + ACCOUNT_VERSION);
                 Account[] ocAccounts = accountMgr.getAccountsByType(MainApp.getAccountType());
                 Account[] ocAccounts = accountMgr.getAccountsByType(MainApp.getAccountType());
-                String serverUrl, username, newAccountName, password;
+                String serverUrl;
+                String username;
+                String newAccountName;
+                String password;
                 Account newAccount;
                 Account newAccount;
                 for (Account account : ocAccounts) {
                 for (Account account : ocAccounts) {
                     // build new account name
                     // build new account name

+ 1 - 1
src/main/java/com/owncloud/android/authentication/AuthenticatorActivity.java

@@ -1791,7 +1791,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
                 SharedPreferences.Editor editor = PreferenceManager
                 SharedPreferences.Editor editor = PreferenceManager
                         .getDefaultSharedPreferences(this).edit();
                         .getDefaultSharedPreferences(this).edit();
                 editor.putString("select_oc_account", accountName);
                 editor.putString("select_oc_account", accountName);
-                editor.commit();
+                editor.apply();
             }
             }
 
 
             /// prepare result to return to the Authenticator
             /// prepare result to return to the Authenticator

+ 68 - 64
src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -312,49 +312,18 @@ public class FileDataStorageManager {
         Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
         Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
                 + " children and " + filesToRemove.size() + " files to remove");
                 + " children and " + filesToRemove.size() + " files to remove");
 
 
-        ArrayList<ContentProviderOperation> operations =
-                new ArrayList<ContentProviderOperation>(updatedFiles.size());
+        ArrayList<ContentProviderOperation> operations = new ArrayList<>(updatedFiles.size());
 
 
         // prepare operations to insert or update files to save in the given folder
         // prepare operations to insert or update files to save in the given folder
         for (OCFile file : updatedFiles) {
         for (OCFile file : updatedFiles) {
-            ContentValues cv = new ContentValues();
-            cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
-            cv.put(
-                    ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
-                    file.getModificationTimestampAtLastSyncForData()
-            );
-            cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
-            cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
-            cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
-            cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
-            //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
-            cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
-            cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
-            if (!file.isFolder()) {
-                cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
-            }
-            cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
-            cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
-            cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
-            cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isAvailableOffline() ? 1 : 0);
-            cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
-            cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
-            cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
-            cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
-            cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
-            cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
-            cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
-            cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
-            cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
-            cv.put(ProviderTableMeta.FILE_FAVORITE, file.getIsFavorite());
+            ContentValues cv = createContentValueForFile(file, folder);
 
 
             boolean existsByPath = fileExists(file.getRemotePath());
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
             if (existsByPath || fileExists(file.getFileId())) {
                 // updating an existing file
                 // updating an existing file
-                operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
-                        withValues(cv).
-                        withSelection(ProviderTableMeta._ID + "=?",
-                                new String[]{String.valueOf(file.getFileId())})
+                operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI)
+                        .withValues(cv)
+                        .withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(file.getFileId())})
                         .build());
                         .build());
 
 
             } else {
             } else {
@@ -373,9 +342,7 @@ public class FileDataStorageManager {
                 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                 if (file.isFolder()) {
                 if (file.isFolder()) {
                     operations.add(ContentProviderOperation.newDelete(
                     operations.add(ContentProviderOperation.newDelete(
-                            ContentUris.withAppendedId(
-                                    ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
-                            )
+                            ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())
                     ).withSelection(where, whereArgs).build());
                     ).withSelection(where, whereArgs).build());
 
 
                     File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
                     File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
@@ -384,8 +351,7 @@ public class FileDataStorageManager {
                     }
                     }
                 } else {
                 } else {
                     operations.add(ContentProviderOperation.newDelete(
                     operations.add(ContentProviderOperation.newDelete(
-                            ContentUris.withAppendedId(
-                                    ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
+                            ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
                             )
                             )
                     ).withSelection(where, whereArgs).build());
                     ).withSelection(where, whereArgs).build());
 
 
@@ -399,29 +365,7 @@ public class FileDataStorageManager {
         }
         }
 
 
         // update metadata of folder
         // update metadata of folder
-        ContentValues cv = new ContentValues();
-        cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
-        cv.put(
-                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
-                folder.getModificationTimestampAtLastSyncForData()
-        );
-        cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
-        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
-        cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
-        cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
-        cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
-        cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
-        cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
-        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
-        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
-        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isAvailableOffline() ? 1 : 0);
-        cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
-        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0);
-        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0);
-        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
-        cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
-        cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
-        cv.put(ProviderTableMeta.FILE_FAVORITE, folder.getIsFavorite());
+        ContentValues cv = createContentValueForFile(folder);
 
 
         operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
         operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
                 withValues(cv).
                 withValues(cv).
@@ -464,7 +408,67 @@ public class FileDataStorageManager {
                 }
                 }
             }
             }
         }
         }
+    }
 
 
+    private ContentValues createContentValueForFile(OCFile folder) {
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
+        cv.put(
+                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                folder.getModificationTimestampAtLastSyncForData()
+        );
+        cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
+        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
+        cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
+        cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
+        cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
+        cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
+        cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
+        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
+        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
+        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isAvailableOffline() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
+        cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
+        cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
+        cv.put(ProviderTableMeta.FILE_FAVORITE, folder.getIsFavorite());
+        return cv;
+    }
+
+    private ContentValues createContentValueForFile(OCFile file, OCFile folder) {
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
+        cv.put(
+                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                file.getModificationTimestampAtLastSyncForData()
+        );
+        cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
+        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
+        cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
+        cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
+        //cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
+        cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
+        cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
+        if (!file.isFolder()) {
+            cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
+        }
+        cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
+        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
+        cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
+        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isAvailableOffline() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
+        cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
+        cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
+        cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
+        cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
+        cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
+        cv.put(ProviderTableMeta.FILE_FAVORITE, file.getIsFavorite());
+        return cv;
     }
     }
 
 
 
 

+ 5 - 4
src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -425,12 +425,13 @@ public class ThumbnailsCacheManager {
                         thumbnail = doFileInBackground(mFile);
                         thumbnail = doFileInBackground(mFile);
                     }
                     }
                 }
                 }
+            } // the app should never break due to a problem with thumbnails
+            catch (OutOfMemoryError t) {
+                Log_OC.e(TAG, "Generation of thumbnail for " + mFile.getAbsolutePath() + " failed", t);
+                System.gc();
             } catch (Throwable t) {
             } catch (Throwable t) {
                 // the app should never break due to a problem with thumbnails
                 // the app should never break due to a problem with thumbnails
                 Log_OC.e(TAG, "Generation of thumbnail for " + mFile.getAbsolutePath() + " failed", t);
                 Log_OC.e(TAG, "Generation of thumbnail for " + mFile.getAbsolutePath() + " failed", t);
-                if (t instanceof OutOfMemoryError) {
-                    System.gc();
-                }
             }
             }
 
 
             return thumbnail;
             return thumbnail;
@@ -451,7 +452,7 @@ public class ThumbnailsCacheManager {
                 } else {
                 } else {
                     if (mFile != null) {
                     if (mFile != null) {
                         if (mFile.isDirectory()) {
                         if (mFile.isDirectory()) {
-                            imageView.setImageResource(R.drawable.ic_menu_archive);
+                            imageView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon());
                         } else {
                         } else {
                             if (MimeTypeUtil.isVideo(mFile)) {
                             if (MimeTypeUtil.isVideo(mFile)) {
                                 imageView.setImageBitmap(ThumbnailsCacheManager.mDefaultVideo);
                                 imageView.setImageBitmap(ThumbnailsCacheManager.mDefaultVideo);

+ 1 - 1
src/main/java/com/owncloud/android/db/PreferenceManager.java

@@ -274,7 +274,7 @@ public abstract class PreferenceManager {
     private static void saveStringPreferenceNow(Context context, String key, String value) {
     private static void saveStringPreferenceNow(Context context, String key, String value) {
         SharedPreferences.Editor appPreferences = getDefaultSharedPreferences(context.getApplicationContext()).edit();
         SharedPreferences.Editor appPreferences = getDefaultSharedPreferences(context.getApplicationContext()).edit();
         appPreferences.putString(key, value);
         appPreferences.putString(key, value);
-        appPreferences.commit();
+        appPreferences.apply();
     }
     }
 
 
     private static void saveIntPreference(Context context, String key, int value) {
     private static void saveIntPreference(Context context, String key, int value) {

+ 18 - 10
src/main/java/com/owncloud/android/files/FileMenuFilter.java

@@ -1,4 +1,4 @@
-/**
+/*
  * ownCloud Android client application
  * ownCloud Android client application
  *
  *
  * @author David A. Velasco
  * @author David A. Velasco
@@ -31,10 +31,11 @@ import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 import com.owncloud.android.ui.activity.ComponentsGetter;
+import com.owncloud.android.utils.MimeTypeUtil;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.List;
 
 
@@ -59,8 +60,7 @@ public class FileMenuFilter {
      * @param cg                Accessor to app components, needed to access synchronization services
      * @param cg                Accessor to app components, needed to access synchronization services
      * @param context           Android {@link Context}, needed to access build setup resources.
      * @param context           Android {@link Context}, needed to access build setup resources.
      */
      */
-    public FileMenuFilter(Collection<OCFile> targetFiles, Account account, ComponentsGetter cg,
-                          Context context) {
+    public FileMenuFilter(Collection<OCFile> targetFiles, Account account, ComponentsGetter cg, Context context) {
         mFiles = targetFiles;
         mFiles = targetFiles;
         mAccount = account;
         mAccount = account;
         mComponentsGetter = cg;
         mComponentsGetter = cg;
@@ -75,9 +75,8 @@ public class FileMenuFilter {
      * @param cg                Accessor to app components, needed to access synchronization services
      * @param cg                Accessor to app components, needed to access synchronization services
      * @param context           Android {@link Context}, needed to access build setup resources.
      * @param context           Android {@link Context}, needed to access build setup resources.
      */
      */
-    public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg,
-                          Context context) {
-        this(Arrays.asList(new OCFile[]{targetFile}), account, cg, context);
+    public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg, Context context) {
+        this(Collections.singletonList(targetFile), account, cg, context);
     }
     }
 
 
     /**
     /**
@@ -91,8 +90,8 @@ public class FileMenuFilter {
             hideAll(menu);
             hideAll(menu);
 
 
         } else {
         } else {
-            List<Integer> toShow = new ArrayList<Integer>();
-            List<Integer> toHide = new ArrayList<Integer>();
+            List<Integer> toShow = new ArrayList<>();
+            List<Integer> toHide = new ArrayList<>();
 
 
             filter(toShow, toHide);
             filter(toShow, toHide);
 
 
@@ -124,7 +123,6 @@ public class FileMenuFilter {
         }
         }
     }
     }
 
 
-
     /**
     /**
      * Performs the real filtering, to be applied in the {@link Menu} by the caller methods.
      * Performs the real filtering, to be applied in the {@link Menu} by the caller methods.
      *
      *
@@ -257,6 +255,12 @@ public class FileMenuFilter {
         }
         }
 
 
 
 
+        // SET PICTURE AS
+        if (isSingleImage() && !MimeTypeUtil.isSVG(mFiles.iterator().next())) {
+            toShow.add(R.id.action_set_as_wallpaper);
+        } else {
+            toHide.add(R.id.action_set_as_wallpaper);
+        }
     }
     }
 
 
     private boolean anyFileSynchronizing() {
     private boolean anyFileSynchronizing() {
@@ -312,6 +316,10 @@ public class FileMenuFilter {
         return isSingleSelection() && !mFiles.iterator().next().isFolder();
         return isSingleSelection() && !mFiles.iterator().next().isFolder();
     }
     }
 
 
+    private boolean isSingleImage() {
+        return isSingleSelection() && MimeTypeUtil.isImage(mFiles.iterator().next());
+    }
+
     private boolean allFiles() {
     private boolean allFiles() {
         return mFiles != null && !containsFolder();
         return mFiles != null && !containsFolder();
     }
     }

+ 7 - 7
src/main/java/com/owncloud/android/files/InstantUploadBroadcastReceiver.java

@@ -56,6 +56,13 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
     // http://developer.android.com/reference/android/hardware/Camera.html#ACTION_NEW_VIDEO
     // http://developer.android.com/reference/android/hardware/Camera.html#ACTION_NEW_VIDEO
     private static final String NEW_VIDEO_ACTION = "android.hardware.action.NEW_VIDEO";
     private static final String NEW_VIDEO_ACTION = "android.hardware.action.NEW_VIDEO";
 
 
+    /**
+     * Because we support NEW_PHOTO_ACTION and NEW_PHOTO_ACTION_UNOFFICIAL it can happen that
+     * handleNewPictureAction is called twice for the same photo. Use this simple static variable to
+     * remember last uploaded photo to filter duplicates. Must not be null!
+     */
+    static String lastUploadedPhotoPath = "";
+
     @Override
     @Override
     public void onReceive(Context context, Intent intent) {
     public void onReceive(Context context, Intent intent) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@@ -75,13 +82,6 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
         }
         }
     }
     }
 
 
-    /**
-     * Because we support NEW_PHOTO_ACTION and NEW_PHOTO_ACTION_UNOFFICIAL it can happen that
-     * handleNewPictureAction is called twice for the same photo. Use this simple static variable to
-     * remember last uploaded photo to filter duplicates. Must not be null!
-     */
-    static String lastUploadedPhotoPath = "";
-
     private void handleNewPictureAction(Context context, Intent intent) {
     private void handleNewPictureAction(Context context, Intent intent) {
         Cursor c = null;
         Cursor c = null;
         String file_path = null;
         String file_path = null;

+ 5 - 2
src/main/java/com/owncloud/android/files/services/FileDownloader.java

@@ -54,6 +54,7 @@ import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.ui.notifications.NotificationUtils;
 import com.owncloud.android.ui.notifications.NotificationUtils;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
@@ -174,9 +175,10 @@ public class FileDownloader extends Service
         } else {
         } else {
             final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
             final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
             final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
             final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
+            final String behaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR);
             AbstractList<String> requestedDownloads = new Vector<String>();
             AbstractList<String> requestedDownloads = new Vector<String>();
             try {
             try {
-                DownloadFileOperation newDownload = new DownloadFileOperation(account, file);
+                DownloadFileOperation newDownload = new DownloadFileOperation(account, file, behaviour);
                 newDownload.addDatatransferProgressListener(this);
                 newDownload.addDatatransferProgressListener(this);
                 newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder);
                 newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder);
                 Pair<String, String> putResult = mPendingDownloads.putIfAbsent(
                 Pair<String, String> putResult = mPendingDownloads.putIfAbsent(
@@ -490,7 +492,7 @@ public class FileDownloader extends Service
         file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
         file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
         file.setRemoteId(mCurrentDownload.getFile().getRemoteId());
         file.setRemoteId(mCurrentDownload.getFile().getRemoteId());
         mStorageManager.saveFile(file);
         mStorageManager.saveFile(file);
-        mStorageManager.triggerMediaScan(file.getStoragePath());
+        FileDataStorageManager.triggerMediaScan(file.getStoragePath());
         mStorageManager.saveConflict(file, null);
         mStorageManager.saveConflict(file, null);
     }
     }
 
 
@@ -639,6 +641,7 @@ public class FileDownloader extends Service
         end.putExtra(ACCOUNT_NAME, download.getAccount().name);
         end.putExtra(ACCOUNT_NAME, download.getAccount().name);
         end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
         end.putExtra(EXTRA_REMOTE_PATH, download.getRemotePath());
         end.putExtra(EXTRA_FILE_PATH, download.getSavePath());
         end.putExtra(EXTRA_FILE_PATH, download.getSavePath());
+        end.putExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR, download.getBehaviour());
         if (unlinkedFromRemotePath != null) {
         if (unlinkedFromRemotePath != null) {
             end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
             end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
         }
         }

+ 2 - 1
src/main/java/com/owncloud/android/files/services/IndexedForest.java

@@ -115,7 +115,8 @@ public class IndexedForest<V> {
             String currentPath = remotePath;
             String currentPath = remotePath;
             String parentPath = null;
             String parentPath = null;
             String parentKey = null;
             String parentKey = null;
-            Node<V> currentNode = valuedNode, parentNode = null;
+            Node<V> currentNode = valuedNode;
+            Node<V> parentNode = null;
             boolean linked = false;
             boolean linked = false;
             while (!OCFile.ROOT_PATH.equals(currentPath) && !linked) {
             while (!OCFile.ROOT_PATH.equals(currentPath) && !linked) {
                 parentPath = new File(currentPath).getParent();
                 parentPath = new File(currentPath).getParent();

+ 4 - 0
src/main/java/com/owncloud/android/media/MediaControlView.java

@@ -197,6 +197,10 @@ public class MediaControlView extends FrameLayout /* implements OnLayoutChangeLi
         updatePausePlay();
         updatePausePlay();
     }
     }
 
 
+    public void stopMediaPlayerMessages() {
+        mHandler.removeMessages(SHOW_PROGRESS);
+    }
+
 
 
     private void initControllerView(View v) {
     private void initControllerView(View v) {
         mPauseButton = (ImageButton) v.findViewById(R.id.playBtn);
         mPauseButton = (ImageButton) v.findViewById(R.id.playBtn);

+ 0 - 1
src/main/java/com/owncloud/android/media/MediaService.java

@@ -508,7 +508,6 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
             // nobody is bound
             // nobody is bound
             processStopRequest(true);
             processStopRequest(true);
         }
         }
-        return;
     }
     }
 
 
 
 

+ 1 - 4
src/main/java/com/owncloud/android/operations/DetectAuthenticationMethodOperation.java

@@ -98,11 +98,8 @@ public class DetectAuthenticationMethodOperation extends RemoteOperation {
         // analyze response  
         // analyze response  
         if (result.getHttpCode() == HttpStatus.SC_UNAUTHORIZED) {
         if (result.getHttpCode() == HttpStatus.SC_UNAUTHORIZED) {
             String authRequest = ((result.getAuthenticateHeader()).trim()).toLowerCase();
             String authRequest = ((result.getAuthenticateHeader()).trim()).toLowerCase();
-            if (authRequest.startsWith("basic")) {
+            if (authRequest.startsWith("basic") || authRequest.startsWith("bearer")) {
                 authMethod = AuthenticationMethod.BASIC_HTTP_AUTH;
                 authMethod = AuthenticationMethod.BASIC_HTTP_AUTH;
-                
-            } else if (authRequest.startsWith("bearer")) {
-                authMethod = AuthenticationMethod.BEARER_TOKEN;
             }
             }
             // else - fall back to UNKNOWN
             // else - fall back to UNKNOWN
                     
                     

+ 8 - 2
src/main/java/com/owncloud/android/operations/DownloadFileOperation.java

@@ -49,6 +49,7 @@ public class DownloadFileOperation extends RemoteOperation {
 
 
     private Account mAccount;
     private Account mAccount;
     private OCFile mFile;
     private OCFile mFile;
+    private String mBehaviour;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private long mModificationTimestamp = 0;
     private long mModificationTimestamp = 0;
     private String mEtag = "";
     private String mEtag = "";
@@ -56,8 +57,8 @@ public class DownloadFileOperation extends RemoteOperation {
     
     
     private DownloadRemoteFileOperation mDownloadOperation;
     private DownloadRemoteFileOperation mDownloadOperation;
 
 
-    
-    public DownloadFileOperation(Account account, OCFile file) {
+
+    public DownloadFileOperation(Account account, OCFile file, String behaviour) {
         if (account == null) {
         if (account == null) {
             throw new IllegalArgumentException("Illegal null account in DownloadFileOperation " +
             throw new IllegalArgumentException("Illegal null account in DownloadFileOperation " +
                     "creation");
                     "creation");
@@ -69,6 +70,7 @@ public class DownloadFileOperation extends RemoteOperation {
         
         
         mAccount = account;
         mAccount = account;
         mFile = file;
         mFile = file;
+        mBehaviour = behaviour;
     }
     }
 
 
 
 
@@ -80,6 +82,10 @@ public class DownloadFileOperation extends RemoteOperation {
         return mFile;
         return mFile;
     }
     }
 
 
+    public String getBehaviour() {
+        return mBehaviour;
+    }
+
     public String getSavePath() {
     public String getSavePath() {
         if (mFile.getStoragePath() != null) {
         if (mFile.getStoragePath() != null) {
             File path = new File(mFile.getStoragePath());  // re-downloads should be done over the original file
             File path = new File(mFile.getStoragePath());  // re-downloads should be done over the original file

+ 7 - 5
src/main/java/com/owncloud/android/services/ContactsBackupJob.java

@@ -1,20 +1,20 @@
-/**
+/*
  * Nextcloud Android client application
  * Nextcloud Android client application
  *
  *
  * @author Tobias Kaminsky
  * @author Tobias Kaminsky
  * Copyright (C) 2017 Tobias Kaminsky
  * Copyright (C) 2017 Tobias Kaminsky
  * Copyright (C) 2017 Nextcloud GmbH.
  * Copyright (C) 2017 Nextcloud GmbH.
- * <p>
+ *
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
  * it under the terms of the GNU Affero General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * the Free Software Foundation, either version 3 of the License, or
  * at your option) any later version.
  * at your option) any later version.
- * <p>
+ *
  * This program is distributed in the hope that it will be useful,
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Affero General Public License for more details.
  * GNU Affero General Public License for more details.
- * <p>
+ *
  * You should have received a copy of the GNU Affero General Public License
  * You should have received a copy of the GNU Affero General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
  */
@@ -173,7 +173,9 @@ public class ContactsBackupJob extends Job {
             cal.add(Calendar.DAY_OF_YEAR, -daysToExpire);
             cal.add(Calendar.DAY_OF_YEAR, -daysToExpire);
             Long timestampToExpire = cal.getTimeInMillis();
             Long timestampToExpire = cal.getTimeInMillis();
 
 
-            Log_OC.d(TAG, "expire: " + daysToExpire + " " + backupFolder.getFileName());
+            if (backupFolder != null) {
+                Log_OC.d(TAG, "expire: " + daysToExpire + " " + backupFolder.getFileName());
+            }
 
 
             Vector<OCFile> backups = storageManager.getFolderContent(backupFolder, false);
             Vector<OCFile> backups = storageManager.getFolderContent(backupFolder, false);
 
 

+ 2 - 1
src/main/java/com/owncloud/android/ui/CustomPopup.java

@@ -136,7 +136,8 @@ public class CustomPopup {
                 LayoutParams.WRAP_CONTENT));
                 LayoutParams.WRAP_CONTENT));
         root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
         root.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
 
 
-        int rootW = root.getWidth(), rootH = root.getHeight();
+        int rootW = root.getWidth();
+        int rootH = root.getHeight();
         int screenW = mWManager.getDefaultDisplay().getWidth();
         int screenW = mWManager.getDefaultDisplay().getWidth();
 
 
         int xpos = ((screenW - rootW) / 2) + x;
         int xpos = ((screenW - rootW) / 2) + x;

+ 21 - 4
src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java

@@ -274,10 +274,10 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
      * setup quota elements of the drawer.
      * setup quota elements of the drawer.
      */
      */
     private void setupQuotaElement() {
     private void setupQuotaElement() {
-        mQuotaView = (LinearLayout) findViewById(R.id.drawer_quota);
-        mQuotaProgressBar = (ProgressBar) findViewById(R.id.drawer_quota_ProgressBar);
-        mQuotaTextPercentage = (TextView) findViewById(R.id.drawer_quota_percentage);
-        mQuotaTextLink = (TextView) findViewById(R.id.drawer_quota_link);
+        mQuotaView = (LinearLayout) findQuotaViewById(R.id.drawer_quota);
+        mQuotaProgressBar = (ProgressBar) findQuotaViewById(R.id.drawer_quota_ProgressBar);
+        mQuotaTextPercentage = (TextView) findQuotaViewById(R.id.drawer_quota_percentage);
+        mQuotaTextLink = (TextView) findQuotaViewById(R.id.drawer_quota_link);
         DisplayUtils.colorPreLollipopHorizontalProgressBar(mQuotaProgressBar);
         DisplayUtils.colorPreLollipopHorizontalProgressBar(mQuotaProgressBar);
     }
     }
 
 
@@ -508,6 +508,7 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
             case Menu.NONE:
             case Menu.NONE:
                 // account clicked
                 // account clicked
                 accountClicked(menuItem.getTitle().toString());
                 accountClicked(menuItem.getTitle().toString());
+                break;
             default:
             default:
                 Log_OC.i(TAG, "Unknown drawer menu item clicked: " + menuItem.getTitle());
                 Log_OC.i(TAG, "Unknown drawer menu item clicked: " + menuItem.getTitle());
         }
         }
@@ -1100,6 +1101,22 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
         return ((NavigationView) findViewById(R.id.nav_view)).getHeaderView(0).findViewById(id);
         return ((NavigationView) findViewById(R.id.nav_view)).getHeaderView(0).findViewById(id);
     }
     }
 
 
+    /**
+     * Quota view can be either at navigation bottom or header
+     *
+     * @param id the view's id
+     * @return The view if found or <code>null</code> otherwise.
+     */
+    private View findQuotaViewById(int id) {
+        View v = ((NavigationView) findViewById(R.id.nav_view)).getHeaderView(0).findViewById(id);
+
+        if (v != null) {
+            return v;
+        } else {
+            return findViewById(id);
+        }
+    }
+
     /**
     /**
      * restart helper method which is called after a changing the current account.
      * restart helper method which is called after a changing the current account.
      */
      */

+ 53 - 25
src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -101,8 +101,11 @@ import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ErrorMessageAdapter;
 import com.owncloud.android.utils.ErrorMessageAdapter;
 import com.owncloud.android.utils.MimeTypeUtil;
 import com.owncloud.android.utils.MimeTypeUtil;
 import com.owncloud.android.utils.PermissionUtil;
 import com.owncloud.android.utils.PermissionUtil;
+import com.owncloud.android.utils.PushUtils;
 
 
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 import org.parceler.Parcels;
 import org.parceler.Parcels;
 
 
 import java.io.File;
 import java.io.File;
@@ -314,7 +317,7 @@ public class FileDisplayActivity extends HookActivity
                             dialog.dismiss();
                             dialog.dismiss();
                         }
                         }
                     })
                     })
-                    .setIcon(R.drawable.ic_cloud_upload)
+                    .setIcon(R.drawable.nav_folder_sync)
                     .show();
                     .show();
         }
         }
     }
     }
@@ -437,7 +440,12 @@ public class FileDisplayActivity extends HookActivity
 
 
             /// Second fragment
             /// Second fragment
             OCFile file = getFile();
             OCFile file = getFile();
-            Fragment secondFragment = chooseInitialSecondFragment(file);
+
+            Fragment secondFragment = getSecondFragment();
+            if (secondFragment == null) {
+                secondFragment = chooseInitialSecondFragment(file);
+            }
+
             if (secondFragment != null) {
             if (secondFragment != null) {
                 setSecondFragment(secondFragment);
                 setSecondFragment(secondFragment);
                 updateFragmentsVisibility(true);
                 updateFragmentsVisibility(true);
@@ -476,13 +484,9 @@ public class FileDisplayActivity extends HookActivity
         Fragment secondFragment = null;
         Fragment secondFragment = null;
         if (file != null && !file.isFolder()) {
         if (file != null && !file.isFolder()) {
             if (file.isDown() && PreviewMediaFragment.canBePreviewed(file)) {
             if (file.isDown() && PreviewMediaFragment.canBePreviewed(file)) {
-                int startPlaybackPosition =
-                        getIntent().getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
-                boolean autoplay =
-                        getIntent().getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true);
-                secondFragment = new PreviewMediaFragment(file, getAccount(),
-                        startPlaybackPosition, autoplay);
-
+                int startPlaybackPosition = getIntent().getIntExtra(PreviewVideoActivity.EXTRA_START_POSITION, 0);
+                boolean autoplay = getIntent().getBooleanExtra(PreviewVideoActivity.EXTRA_AUTOPLAY, true);
+                secondFragment = new PreviewMediaFragment(file, getAccount(), startPlaybackPosition, autoplay);
             } else if (file.isDown() && PreviewTextFragment.canBePreviewed(file)) {
             } else if (file.isDown() && PreviewTextFragment.canBePreviewed(file)) {
                 secondFragment = null;
                 secondFragment = null;
             } else {
             } else {
@@ -556,8 +560,7 @@ public class FileDisplayActivity extends HookActivity
     }
     }
 
 
     public FileFragment getSecondFragment() {
     public FileFragment getSecondFragment() {
-        Fragment second = getSupportFragmentManager().findFragmentByTag(
-                FileDisplayActivity.TAG_SECOND_FRAGMENT);
+        Fragment second = getSupportFragmentManager().findFragmentByTag(FileDisplayActivity.TAG_SECOND_FRAGMENT);
         if (second != null) {
         if (second != null) {
             return (FileFragment) second;
             return (FileFragment) second;
         }
         }
@@ -771,7 +774,7 @@ public class FileDisplayActivity extends HookActivity
                             R.drawable.ic_view_list));
                             R.drawable.ic_view_list));
                     getListOfFilesFragment().setGridAsPreferred();
                     getListOfFilesFragment().setGridAsPreferred();
                 }
                 }
-                return true;
+                break;
             }
             }
             default:
             default:
                 retval = super.onOptionsItemSelected(item);
                 retval = super.onOptionsItemSelected(item);
@@ -1390,28 +1393,35 @@ public class FileDisplayActivity extends HookActivity
         public void onReceive(Context context, Intent intent) {
         public void onReceive(Context context, Intent intent) {
             try {
             try {
                 boolean sameAccount = isSameAccount(intent);
                 boolean sameAccount = isSameAccount(intent);
-                String downloadedRemotePath =
-                        intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
+                String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
+                String downloadBehaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR);
                 boolean isDescendant = isDescendant(downloadedRemotePath);
                 boolean isDescendant = isDescendant(downloadedRemotePath);
 
 
                 if (sameAccount && isDescendant) {
                 if (sameAccount && isDescendant) {
-                    String linkedToRemotePath =
-                            intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
+                    String linkedToRemotePath = intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
                         refreshListOfFilesFragment(false);
                         refreshListOfFilesFragment(false);
                     }
                     }
                     refreshSecondFragment(
                     refreshSecondFragment(
                             intent.getAction(),
                             intent.getAction(),
                             downloadedRemotePath,
                             downloadedRemotePath,
-                            intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false)
-                    );
+                            intent.getBooleanExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, false));
                 }
                 }
 
 
                 if (mWaitingToSend != null) {
                 if (mWaitingToSend != null) {
-                    mWaitingToSend =
-                            getStorageManager().getFileByPath(mWaitingToSend.getRemotePath());
-                    if (mWaitingToSend.isDown()) {
-                        sendDownloadedFile();
+                    mWaitingToSend = getStorageManager().getFileByPath(mWaitingToSend.getRemotePath());
+                    if (mWaitingToSend.isDown() && downloadBehaviour != null) {
+                        switch (downloadBehaviour) {
+                            case OCFileListFragment.DOWNLOAD_SEND:
+                                sendDownloadedFile();
+                                break;
+                            case OCFileListFragment.DOWNLOAD_SET_AS:
+                                setPictureAs();
+                                break;
+                            default:
+                                // do nothing
+                                break;
+                        }
                     }
                     }
                 }
                 }
 
 
@@ -1889,12 +1899,13 @@ public class FileDisplayActivity extends HookActivity
         }
         }
     }
     }
 
 
-    private void requestForDownload(OCFile file) {
+    private void requestForDownload(OCFile file, String downloadBehaviour) {
         Account account = getAccount();
         Account account = getAccount();
         if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
         if (!mDownloaderBinder.isDownloading(account, mWaitingToPreview)) {
             Intent i = new Intent(this, FileDownloader.class);
             Intent i = new Intent(this, FileDownloader.class);
             i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
             i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
             i.putExtra(FileDownloader.EXTRA_FILE, file);
             i.putExtra(FileDownloader.EXTRA_FILE, file);
+            i.putExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR, downloadBehaviour);
             startService(i);
             startService(i);
         }
         }
     }
     }
@@ -1904,6 +1915,11 @@ public class FileDisplayActivity extends HookActivity
         mWaitingToSend = null;
         mWaitingToSend = null;
     }
     }
 
 
+    private void setPictureAs() {
+        getFileOperationsHelper().setPictureAs(mWaitingToSend);
+        mWaitingToSend = null;
+    }
+
 
 
     /**
     /**
      * Requests the download of the received {@link OCFile} , updates the UI
      * Requests the download of the received {@link OCFile} , updates the UI
@@ -1912,9 +1928,9 @@ public class FileDisplayActivity extends HookActivity
      *
      *
      * @param file {@link OCFile} to download and preview.
      * @param file {@link OCFile} to download and preview.
      */
      */
-    public void startDownloadForSending(OCFile file) {
+    public void startDownloadForSending(OCFile file, String downloadBehaviour) {
         mWaitingToSend = file;
         mWaitingToSend = file;
-        requestForDownload(mWaitingToSend);
+        requestForDownload(mWaitingToSend, downloadBehaviour);
         boolean hasSecondFragment = (getSecondFragment() != null);
         boolean hasSecondFragment = (getSecondFragment() != null);
         updateFragmentsVisibility(hasSecondFragment);
         updateFragmentsVisibility(hasSecondFragment);
     }
     }
@@ -2081,4 +2097,16 @@ public class FileDisplayActivity extends HookActivity
         super.showFiles(onDeviceOnly);
         super.showFiles(onDeviceOnly);
         getListOfFilesFragment().refreshDirectory();
         getListOfFilesFragment().refreshDirectory();
     }
     }
+
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
+    public void onMessageEvent(TokenPushEvent event) {
+        PushUtils.pushRegistrationToServer();
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        EventBus.getDefault().post(new TokenPushEvent());
+    }
+
 }
 }

+ 2 - 7
src/main/java/com/owncloud/android/ui/activity/LogHistoryActivity.java

@@ -40,7 +40,6 @@ import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.utils.AnalyticsUtils;
 import com.owncloud.android.utils.AnalyticsUtils;
-import com.owncloud.android.utils.FileStorageUtils;
 
 
 import java.io.BufferedReader;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.File;
@@ -64,7 +63,7 @@ public class LogHistoryActivity extends ToolbarActivity {
 
 
     private static final String SCREEN_NAME = "Logs";
     private static final String SCREEN_NAME = "Logs";
 
 
-    private String mLogPath = FileStorageUtils.getLogPath();
+    private String mLogPath = Log_OC.getLogPath();
     private File logDIR = null;
     private File logDIR = null;
     private String mLogText;
     private String mLogText;
 
 
@@ -166,11 +165,7 @@ public class LogHistoryActivity extends ToolbarActivity {
                 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                     uris.add(Uri.fromFile(logFile));
                     uris.add(Uri.fromFile(logFile));
                 } else {
                 } else {
-                    uris.add(FileProvider.getUriForFile(
-                            this,
-                            getString(R.string.file_provider_authority),
-                            logFile
-                    ));
+                    uris.add(FileProvider.getUriForFile(this, getString(R.string.file_provider_authority), logFile));
                 }
                 }
             }
             }
         }
         }

+ 3 - 4
src/main/java/com/owncloud/android/ui/activity/ParticipateActivity.java

@@ -84,13 +84,12 @@ public class ParticipateActivity extends FileActivity {
         TextView contributeTranslationView = (TextView) findViewById(R.id.participate_contribute_translate_text);
         TextView contributeTranslationView = (TextView) findViewById(R.id.participate_contribute_translate_text);
         contributeTranslationView.setMovementMethod(LinkMovementMethod.getInstance());
         contributeTranslationView.setMovementMethod(LinkMovementMethod.getInstance());
         contributeTranslationView.setText(Html.fromHtml(
         contributeTranslationView.setText(Html.fromHtml(
-                getString(R.string.participate_contribute_translate_text,
-                        getString(R.string.translation_link)
-                )));
+                getString(R.string.participate_contribute_translate_text, getString(R.string.translation_link))));
 
 
         TextView contributeGithubView = (TextView) findViewById(R.id.participate_contribute_github_text);
         TextView contributeGithubView = (TextView) findViewById(R.id.participate_contribute_github_text);
         contributeGithubView.setMovementMethod(LinkMovementMethod.getInstance());
         contributeGithubView.setMovementMethod(LinkMovementMethod.getInstance());
-        contributeGithubView.setText(Html.fromHtml(getString(R.string.participate_contribute_github_text)));
+        contributeGithubView.setText(Html.fromHtml(getString(R.string.participate_contribute_github_text,
+                getString(R.string.contributing_link))));
 
 
         findViewById(R.id.participate_testing_report).setOnClickListener(new View.OnClickListener() {
         findViewById(R.id.participate_testing_report).setOnClickListener(new View.OnClickListener() {
             @Override
             @Override

+ 0 - 5
src/main/java/com/owncloud/android/ui/activity/StorageMigration.java

@@ -296,7 +296,6 @@ public class StorageMigration {
         protected Integer doInBackground(Void... voids) {
         protected Integer doInBackground(Void... voids) {
             publishProgress(R.string.file_migration_preparing);
             publishProgress(R.string.file_migration_preparing);
 
 
-            Log_OC.stopLogging();
             boolean[] syncStates = null;
             boolean[] syncStates = null;
             try {
             try {
                 publishProgress(R.string.file_migration_saving_accounts_configuration);
                 publishProgress(R.string.file_migration_saving_accounts_configuration);
@@ -309,7 +308,6 @@ public class StorageMigration {
                 publishProgress(R.string.file_migration_restoring_accounts_configuration);
                 publishProgress(R.string.file_migration_restoring_accounts_configuration);
                 restoreAccountsSyncStatus(syncStates);
                 restoreAccountsSyncStatus(syncStates);
             }
             }
-            Log_OC.startLogging(mStorageTarget);
 
 
             return 0;
             return 0;
         }
         }
@@ -338,7 +336,6 @@ public class StorageMigration {
         @Override
         @Override
         protected Integer doInBackground(Void... args) {
         protected Integer doInBackground(Void... args) {
             publishProgress(R.string.file_migration_preparing);
             publishProgress(R.string.file_migration_preparing);
-            Log_OC.stopLogging();
 
 
             boolean[] syncState = null;
             boolean[] syncState = null;
 
 
@@ -372,14 +369,12 @@ public class StorageMigration {
 
 
             } catch (MigrationException e) {
             } catch (MigrationException e) {
                 rollback();
                 rollback();
-                Log_OC.startLogging(mStorageSource);
                 return e.getResId();
                 return e.getResId();
             } finally {
             } finally {
                 publishProgress(R.string.file_migration_restoring_accounts_configuration);
                 publishProgress(R.string.file_migration_restoring_accounts_configuration);
                 restoreAccountsSyncStatus(syncState);
                 restoreAccountsSyncStatus(syncState);
             }
             }
 
 
-            Log_OC.startLogging(mStorageTarget);
             publishProgress(R.string.file_migration_ok_finished);
             publishProgress(R.string.file_migration_ok_finished);
 
 
             return 0;
             return 0;

+ 7 - 0
src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java

@@ -66,6 +66,8 @@ import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.PushUtils;
 import com.owncloud.android.utils.PushUtils;
 
 
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 import org.parceler.Parcels;
 import org.parceler.Parcels;
 
 
 import butterknife.BindString;
 import butterknife.BindString;
@@ -446,4 +448,9 @@ public class UserInfoActivity extends FileActivity {
             outState.putParcelable(KEY_USER_DATA, Parcels.wrap(userInfo));
             outState.putParcelable(KEY_USER_DATA, Parcels.wrap(userInfo));
         }
         }
     }
     }
+
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
+    public void onMessageEvent(TokenPushEvent event) {
+        PushUtils.pushRegistrationToServer();
+    }
 }
 }

+ 7 - 8
src/main/java/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -328,18 +328,17 @@ public class FileListListAdapter extends BaseAdapter {
             view.setBackgroundColor(Color.WHITE);
             view.setBackgroundColor(Color.WHITE);
 
 
             AbsListView parentList = (AbsListView) parent;
             AbsListView parentList = (AbsListView) parent;
+
             if (parentList.getChoiceMode() != AbsListView.CHOICE_MODE_NONE &&
             if (parentList.getChoiceMode() != AbsListView.CHOICE_MODE_NONE &&
                     parentList.getCheckedItemCount() > 0
                     parentList.getCheckedItemCount() > 0
                     ) {
                     ) {
                 if (parentList.isItemChecked(position)) {
                 if (parentList.isItemChecked(position)) {
-                    view.setBackgroundColor(mContext.getResources().getColor(
-                            R.color.selected_item_background));
-                    checkBoxV.setImageResource(
-                            R.drawable.ic_checkbox_marked);
+                    view.setBackgroundColor(mContext.getResources().getColor(R.color.selected_item_background));
+                    checkBoxV.setImageDrawable(DisplayUtils.tintDrawable(R.drawable.ic_checkbox_marked,
+                            R.color.primary));
                 } else {
                 } else {
                     view.setBackgroundColor(Color.WHITE);
                     view.setBackgroundColor(Color.WHITE);
-                    checkBoxV.setImageResource(
-                            R.drawable.ic_checkbox_blank_outline);
+                    checkBoxV.setImageResource(R.drawable.ic_checkbox_blank_outline);
                 }
                 }
                 checkBoxV.setVisibility(View.VISIBLE);
                 checkBoxV.setVisibility(View.VISIBLE);
             }
             }
@@ -410,8 +409,8 @@ public class FileListListAdapter extends BaseAdapter {
 
 
             } else {
             } else {
                 // Folder
                 // Folder
-                fileIcon.setImageResource(
-                        MimeTypeUtil.getFolderTypeIconId(
+                fileIcon.setImageDrawable(
+                        MimeTypeUtil.getFolderTypeIcon(
                                 file.isSharedWithMe() || file.isSharedWithSharee(),
                                 file.isSharedWithMe() || file.isSharedWithSharee(),
                                 file.isSharedViaLink()
                                 file.isSharedViaLink()
                         )
                         )

+ 2 - 1
src/main/java/com/owncloud/android/ui/adapter/FolderSyncAdapter.java

@@ -35,6 +35,7 @@ import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
 import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
+import com.owncloud.android.utils.DisplayUtils;
 
 
 import java.io.File;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.ArrayList;
@@ -188,7 +189,7 @@ public class FolderSyncAdapter extends SectionedRecyclerViewAdapter<FolderSyncAd
 
 
     private void setSyncButtonActiveIcon(ImageButton syncStatusButton, boolean enabled) {
     private void setSyncButtonActiveIcon(ImageButton syncStatusButton, boolean enabled) {
         if(enabled) {
         if(enabled) {
-            syncStatusButton.setImageResource(R.drawable.ic_cloud_sync_on);
+            syncStatusButton.setImageDrawable(DisplayUtils.tintDrawable(R.drawable.ic_cloud_sync_on, R.color.primary));
         } else {
         } else {
             syncStatusButton.setImageResource(R.drawable.ic_cloud_sync_off);
             syncStatusButton.setImageResource(R.drawable.ic_cloud_sync_off);
         }
         }

+ 1 - 1
src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java

@@ -164,7 +164,7 @@ public class LocalFileListAdapter extends BaseAdapter implements FilterableListA
             if (!file.isDirectory()) {
             if (!file.isDirectory()) {
                 fileIcon.setImageResource(R.drawable.file);
                 fileIcon.setImageResource(R.drawable.file);
             } else {
             } else {
-                fileIcon.setImageResource(R.drawable.ic_menu_archive);
+                fileIcon.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon());
             }
             }
             fileIcon.setTag(file.hashCode());
             fileIcon.setTag(file.hashCode());
 
 

+ 2 - 3
src/main/java/com/owncloud/android/ui/dialog/CreateFolderDialogFragment.java

@@ -49,6 +49,8 @@ public class CreateFolderDialogFragment
     
     
     public static final String CREATE_FOLDER_FRAGMENT = "CREATE_FOLDER_FRAGMENT";
     public static final String CREATE_FOLDER_FRAGMENT = "CREATE_FOLDER_FRAGMENT";
 
 
+    private OCFile mParentFolder;
+
     /**
     /**
      * Public factory method to create new CreateFolderDialogFragment instances.
      * Public factory method to create new CreateFolderDialogFragment instances.
      *
      *
@@ -63,9 +65,6 @@ public class CreateFolderDialogFragment
         return frag;
         return frag;
         
         
     }
     }
-
-    private OCFile mParentFolder;
-    
     
     
     @Override
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
     public Dialog onCreateDialog(Bundle savedInstanceState) {

+ 2 - 2
src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.java

@@ -54,6 +54,8 @@ public class RenameFileDialogFragment
 
 
     private static final String ARG_TARGET_FILE = "TARGET_FILE";
     private static final String ARG_TARGET_FILE = "TARGET_FILE";
 
 
+    private OCFile mTargetFile;
+
     /**
     /**
      * Public factory method to create new RenameFileDialogFragment instances.
      * Public factory method to create new RenameFileDialogFragment instances.
      * 
      * 
@@ -69,8 +71,6 @@ public class RenameFileDialogFragment
         
         
     }
     }
 
 
-    private OCFile mTargetFile;
-    
     @Override
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         mTargetFile = getArguments().getParcelable(ARG_TARGET_FILE);
         mTargetFile = getArguments().getParcelable(ARG_TARGET_FILE);

+ 10 - 3
src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java

@@ -68,6 +68,7 @@ import com.owncloud.android.ui.activity.UploadFilesActivity;
 import com.owncloud.android.ui.adapter.FileListListAdapter;
 import com.owncloud.android.ui.adapter.FileListListAdapter;
 import com.owncloud.android.ui.adapter.LocalFileListAdapter;
 import com.owncloud.android.ui.adapter.LocalFileListAdapter;
 import com.owncloud.android.ui.events.SearchEvent;
 import com.owncloud.android.ui.events.SearchEvent;
+import com.owncloud.android.utils.DisplayUtils;
 
 
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.EventBus;
 import org.parceler.Parcel;
 import org.parceler.Parcel;
@@ -282,8 +283,13 @@ public class ExtendedListFragment extends Fragment
     }
     }
 
 
     public boolean onQueryTextChange(final String query) {
     public boolean onQueryTextChange(final String query) {
-        performSearch(query, false);
-        return true;
+        if (getFragmentManager() != null && getFragmentManager().
+                findFragmentByTag(FileDisplayActivity.TAG_SECOND_FRAGMENT) instanceof ExtendedListFragment) {
+            performSearch(query, false);
+            return true;
+        } else {
+            return false;
+        }
     }
     }
 
 
     @Override
     @Override
@@ -632,7 +638,8 @@ public class ExtendedListFragment extends Fragment
                 if (mEmptyListContainer != null && mEmptyListMessage != null) {
                 if (mEmptyListContainer != null && mEmptyListMessage != null) {
                     mEmptyListHeadline.setText(headline);
                     mEmptyListHeadline.setText(headline);
                     mEmptyListMessage.setText(message);
                     mEmptyListMessage.setText(message);
-                    mEmptyListIcon.setImageResource(icon);
+
+                    mEmptyListIcon.setImageDrawable(DisplayUtils.tintDrawable(icon, R.color.primary));
 
 
                     mEmptyListIcon.setVisibility(View.VISIBLE);
                     mEmptyListIcon.setVisibility(View.VISIBLE);
                     mEmptyListProgress.setVisibility(View.GONE);
                     mEmptyListProgress.setVisibility(View.GONE);

+ 2 - 1
src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -307,7 +307,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 // Obtain the file
                 // Obtain the file
                 if (!getFile().isDown()) {  // Download the file                    
                 if (!getFile().isDown()) {  // Download the file                    
                     Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded");
                     Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded");
-                    ((FileDisplayActivity) mContainerActivity).startDownloadForSending(getFile());
+                    ((FileDisplayActivity) mContainerActivity).startDownloadForSending(getFile(),
+                            OCFileListFragment.DOWNLOAD_SEND);
                 }
                 }
                 else {
                 else {
                     mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
                     mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());

+ 5 - 6
src/main/java/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -98,9 +98,8 @@ public class LocalFileListFragment extends ExtendedListFragment {
         setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
         setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
         setSwipeEnabled(false); // Disable pull-to-refresh
         setSwipeEnabled(false); // Disable pull-to-refresh
         setFabEnabled(false); // Disable FAB
         setFabEnabled(false); // Disable FAB
-        setMessageForEmptyList(
-                R.string.file_list_empty_headline, R.string.local_file_list_empty, R.drawable.ic_list_empty_folder
-        );
+        setMessageForEmptyList(R.string.file_list_empty_headline, R.string.local_file_list_empty,
+                R.drawable.ic_list_empty_folder);
         Log_OC.i(TAG, "onCreateView() end");
         Log_OC.i(TAG, "onCreateView() end");
         return v;
         return v;
     }
     }
@@ -289,7 +288,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
          *  
          *  
          * @param directory
          * @param directory
          */
          */
-        public void onDirectoryClick(File directory);
+        void onDirectoryClick(File directory);
         
         
         /**
         /**
          * Callback method invoked when a file (non directory)
          * Callback method invoked when a file (non directory)
@@ -297,7 +296,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
          *  
          *  
          * @param file
          * @param file
          */
          */
-        public void onFileClick(File file);
+        void onFileClick(File file);
         
         
         
         
         /**
         /**
@@ -306,7 +305,7 @@ public class LocalFileListFragment extends ExtendedListFragment {
          * 
          * 
          * @return  Directory to list firstly. Can be NULL.
          * @return  Directory to list firstly. Can be NULL.
          */
          */
-        public File getInitialDirectory();
+        File getInitialDirectory();
 
 
     }
     }
 
 

+ 14 - 2
src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -121,6 +121,10 @@ public class OCFileListFragment extends ExtendedListFragment implements OCFileLi
     public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL";
     public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL";
     public final static String ARG_HIDE_FAB = MY_PACKAGE + ".HIDE_FAB";
     public final static String ARG_HIDE_FAB = MY_PACKAGE + ".HIDE_FAB";
 
 
+    public static final String DOWNLOAD_BEHAVIOUR = "DOWNLOAD_BEHAVIOUR";
+    public static final String DOWNLOAD_SEND = "DOWNLOAD_SEND";
+    public static final String DOWNLOAD_SET_AS = "DOWNLOAD_SET_AS";
+
     public static final String SEARCH_EVENT = "SEARCH_EVENT";
     public static final String SEARCH_EVENT = "SEARCH_EVENT";
 
 
     private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
     private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE";
@@ -889,13 +893,21 @@ public class OCFileListFragment extends ExtendedListFragment implements OCFileLi
                     // Obtain the file
                     // Obtain the file
                     if (!singleFile.isDown()) {  // Download the file
                     if (!singleFile.isDown()) {  // Download the file
                         Log_OC.d(TAG, singleFile.getRemotePath() + " : File must be downloaded");
                         Log_OC.d(TAG, singleFile.getRemotePath() + " : File must be downloaded");
-                        ((FileDisplayActivity) mContainerActivity).startDownloadForSending(singleFile);
-
+                        ((FileDisplayActivity) mContainerActivity).startDownloadForSending(singleFile, DOWNLOAD_SEND);
                     } else {
                     } else {
                         mContainerActivity.getFileOperationsHelper().sendDownloadedFile(singleFile);
                         mContainerActivity.getFileOperationsHelper().sendDownloadedFile(singleFile);
                     }
                     }
                     return true;
                     return true;
                 }
                 }
+                case R.id.action_set_as_wallpaper: {
+                    if (singleFile.isDown()) {
+                        mContainerActivity.getFileOperationsHelper().setPictureAs(singleFile);
+                    } else {
+                        Log_OC.d(TAG, singleFile.getRemotePath() + " : File must be downloaded");
+                        ((FileDisplayActivity) mContainerActivity).startDownloadForSending(singleFile, DOWNLOAD_SET_AS);
+                    }
+                    return true;
+                }
             }
             }
         }
         }
 
 

+ 56 - 3
src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java

@@ -23,9 +23,11 @@ package com.owncloud.android.ui.fragment.contactsbackup;
 
 
 import android.Manifest;
 import android.Manifest;
 import android.accounts.Account;
 import android.accounts.Account;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.database.Cursor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapFactory;
@@ -53,6 +55,7 @@ import android.widget.LinearLayout;
 import com.evernote.android.job.JobRequest;
 import com.evernote.android.job.JobRequest;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
+import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -71,6 +74,8 @@ import org.greenrobot.eventbus.ThreadMode;
 import java.io.File;
 import java.io.File;
 import java.io.IOException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.List;
 import java.util.Set;
 import java.util.Set;
@@ -102,6 +107,7 @@ public class ContactListFragment extends FileFragment {
     public Button restoreContacts;
     public Button restoreContacts;
 
 
     private ContactListAdapter contactListAdapter;
     private ContactListAdapter contactListAdapter;
+    private Account account;
 
 
     public static ContactListFragment newInstance(OCFile file, Account account) {
     public static ContactListFragment newInstance(OCFile file, Account account) {
         ContactListFragment frag = new ContactListFragment();
         ContactListFragment frag = new ContactListFragment();
@@ -140,16 +146,37 @@ public class ContactListFragment extends FileFragment {
         try {
         try {
             OCFile ocFile = getArguments().getParcelable(FILE_NAME);
             OCFile ocFile = getArguments().getParcelable(FILE_NAME);
             setFile(ocFile);
             setFile(ocFile);
-            Account account = getArguments().getParcelable(ACCOUNT);
+            account = getArguments().getParcelable(ACCOUNT);
 
 
             if (!ocFile.isDown()) {
             if (!ocFile.isDown()) {
                 Intent i = new Intent(getContext(), FileDownloader.class);
                 Intent i = new Intent(getContext(), FileDownloader.class);
                 i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
                 i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
                 i.putExtra(FileDownloader.EXTRA_FILE, ocFile);
                 i.putExtra(FileDownloader.EXTRA_FILE, ocFile);
                 getContext().startService(i);
                 getContext().startService(i);
+
+                // Listen for download messages
+                IntentFilter downloadIntentFilter = new IntentFilter(FileDownloader.getDownloadAddedMessage());
+                downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage());
+                DownloadFinishReceiver mDownloadFinishReceiver = new DownloadFinishReceiver();
+                getContext().registerReceiver(mDownloadFinishReceiver, downloadIntentFilter);
             } else {
             } else {
                 File file = new File(ocFile.getStoragePath());
                 File file = new File(ocFile.getStoragePath());
                 vCards.addAll(Ezvcard.parse(file).all());
                 vCards.addAll(Ezvcard.parse(file).all());
+                Collections.sort(vCards, new Comparator<VCard>() {
+                    @Override
+                    public int compare(VCard o1, VCard o2) {
+                        if (o1.getFormattedName() != null && o2.getFormattedName() != null) {
+                            return o1.getFormattedName().getValue().compareTo(o2.getFormattedName().getValue());
+                        } else {
+                            if (o1.getFormattedName() == null) {
+                                return 1; // Send the contact to the end of the list
+                            } else {
+                                return -1;
+                            }
+
+                        }
+                    }
+                });
             }
             }
         } catch (IOException e) {
         } catch (IOException e) {
             Log_OC.e(TAG, "Error processing contacts file!", e);
             Log_OC.e(TAG, "Error processing contacts file!", e);
@@ -251,7 +278,7 @@ public class ContactListFragment extends FileFragment {
 
 
     private void setSelectAllMenuItem(MenuItem selectAll, boolean checked) {
     private void setSelectAllMenuItem(MenuItem selectAll, boolean checked) {
         selectAll.setChecked(checked);
         selectAll.setChecked(checked);
-        if(checked) {
+        if (checked) {
             selectAll.setIcon(R.drawable.ic_select_none);
             selectAll.setIcon(R.drawable.ic_select_none);
         } else {
         } else {
             selectAll.setIcon(R.drawable.ic_select_all);
             selectAll.setIcon(R.drawable.ic_select_all);
@@ -429,6 +456,27 @@ public class ContactListFragment extends FileFragment {
             return displayName;
             return displayName;
         }
         }
     }
     }
+
+    private class DownloadFinishReceiver extends BroadcastReceiver {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equalsIgnoreCase(FileDownloader.getDownloadFinishMessage())){
+                String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
+
+                FileDataStorageManager storageManager = new FileDataStorageManager(account,
+                        getContext().getContentResolver());
+                OCFile ocFile = storageManager.getFileByPath(downloadedRemotePath);
+                File file = new File(ocFile.getStoragePath());
+
+                try {
+                    contactListAdapter.replaceVCards(Ezvcard.parse(file).all());
+                } catch (IOException e) {
+                    Log_OC.e(TAG, "IO Exception: " + file.getAbsolutePath());
+                }
+            }
+        }
+    }
 }
 }
 
 
 class ContactListAdapter extends RecyclerView.Adapter<ContactListFragment.ContactItemViewHolder> {
 class ContactListAdapter extends RecyclerView.Adapter<ContactListFragment.ContactItemViewHolder> {
@@ -458,12 +506,17 @@ class ContactListAdapter extends RecyclerView.Adapter<ContactListFragment.Contac
         }
         }
     }
     }
 
 
+    public void replaceVCards(List<VCard> vCards) {
+        this.vCards = vCards;
+        notifyDataSetChanged();
+    }
+
     public int[] getCheckedIntArray() {
     public int[] getCheckedIntArray() {
         int[] intArray;
         int[] intArray;
         if (checkedVCards != null && checkedVCards.size() > 0) {
         if (checkedVCards != null && checkedVCards.size() > 0) {
             intArray = new int[checkedVCards.size()];
             intArray = new int[checkedVCards.size()];
             int i = 0;
             int i = 0;
-            for (int position: checkedVCards) {
+            for (int position : checkedVCards) {
                 intArray[i] = position;
                 intArray[i] = position;
                 i++;
                 i++;
             }
             }

+ 44 - 13
src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java

@@ -1,4 +1,4 @@
-/**
+/*
  * Nextcloud Android client application
  * Nextcloud Android client application
  *
  *
  * @author Mario Danic
  * @author Mario Danic
@@ -24,6 +24,7 @@ import android.Manifest;
 import android.accounts.Account;
 import android.accounts.Account;
 import android.app.DatePickerDialog;
 import android.app.DatePickerDialog;
 import android.content.DialogInterface;
 import android.content.DialogInterface;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.Nullable;
@@ -44,7 +45,10 @@ import com.evernote.android.job.JobRequest;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.ArbitraryDataProvider;
 import com.owncloud.android.datamodel.ArbitraryDataProvider;
+import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.operations.RefreshFolderOperation;
 import com.owncloud.android.services.ContactsBackupJob;
 import com.owncloud.android.services.ContactsBackupJob;
 import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
 import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
 import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
@@ -167,21 +171,48 @@ public class ContactsBackupFragment extends FileFragment implements DatePickerDi
             }
             }
         }
         }
 
 
-        final ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+        ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
 
 
-        String backupFolderString = getResources().getString(R.string.contacts_backup_folder) + OCFile.PATH_SEPARATOR;
-        OCFile backupFolder = contactsPreferenceActivity.getStorageManager().getFileByPath(backupFolderString);
+        String backupFolderPath = getResources().getString(R.string.contacts_backup_folder) + OCFile.PATH_SEPARATOR;
+        refreshBackupFolder(backupFolderPath, contactsPreferenceActivity);
+    }
 
 
-        Vector<OCFile> backupFiles = contactsPreferenceActivity.getStorageManager().getFolderContent(backupFolder,
-                false);
+    private void refreshBackupFolder(final String backupFolderPath,
+                                     final ContactsPreferenceActivity contactsPreferenceActivity) {
+        AsyncTask<String, Integer, Boolean> task = new AsyncTask<String, Integer, Boolean>() {
+            @Override
+            protected Boolean doInBackground(String... path) {
+                FileDataStorageManager storageManager = new FileDataStorageManager(account,
+                        getActivity().getContentResolver());
 
 
-        if (backupFiles == null || backupFiles.size() == 0) {
-            contactsRestoreHeader.setVisibility(View.GONE);
-            contactsDatePickerBtn.setVisibility(View.GONE);
-        } else {
-            contactsRestoreHeader.setVisibility(View.VISIBLE);
-            contactsDatePickerBtn.setVisibility(View.VISIBLE);
-        }
+                OCFile folder = storageManager.getFileByPath(path[0]);
+                RefreshFolderOperation operation = new RefreshFolderOperation(folder, System.currentTimeMillis(),
+                        false, false, false, storageManager, account, getContext());
+
+                RemoteOperationResult result = operation.execute(account, getContext());
+                return result.isSuccess();
+            }
+
+            @Override
+            protected void onPostExecute(Boolean result) {
+                if (result) {
+                    OCFile backupFolder = contactsPreferenceActivity.getStorageManager().getFileByPath(backupFolderPath);
+
+                    Vector<OCFile> backupFiles = contactsPreferenceActivity.getStorageManager()
+                            .getFolderContent(backupFolder, false);
+
+                    if (backupFiles == null || backupFiles.size() == 0) {
+                        contactsRestoreHeader.setVisibility(View.GONE);
+                        contactsDatePickerBtn.setVisibility(View.GONE);
+                    } else {
+                        contactsRestoreHeader.setVisibility(View.VISIBLE);
+                        contactsDatePickerBtn.setVisibility(View.VISIBLE);
+                    }
+                }
+            }
+        };
+
+        task.execute(backupFolderPath);
     }
     }
 
 
 
 

+ 92 - 57
src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -1,23 +1,22 @@
 /**
 /**
- *   ownCloud Android client application
- *
- *   @author masensio
- *   @author David A. Velasco
- *   @author Juan Carlos González Cabrero
- *   Copyright (C) 2015 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ * ownCloud Android client application
  *
  *
+ * @author masensio
+ * @author David A. Velasco
+ * @author Juan Carlos González Cabrero
+ * Copyright (C) 2015 ownCloud Inc.
+ * <p>
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ * <p>
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
  */
 
 
 package com.owncloud.android.ui.helpers;
 package com.owncloud.android.ui.helpers;
@@ -29,11 +28,14 @@ import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.net.Uri;
+import android.os.Build;
 import android.support.annotation.Nullable;
 import android.support.annotation.Nullable;
 import android.support.v4.app.DialogFragment;
 import android.support.v4.app.DialogFragment;
+import android.support.v4.content.FileProvider;
 import android.webkit.MimeTypeMap;
 import android.webkit.MimeTypeMap;
 import android.widget.Toast;
 import android.widget.Toast;
 
 
+import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.datamodel.OCFile;
@@ -53,6 +55,7 @@ import com.owncloud.android.ui.events.FavoriteEvent;
 import org.greenrobot.eventbus.EventBus;
 import org.greenrobot.eventbus.EventBus;
 
 
 import java.io.BufferedReader;
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.InputStreamReader;
@@ -68,7 +71,7 @@ import java.util.regex.Pattern;
 public class FileOperationsHelper {
 public class FileOperationsHelper {
 
 
     private static final String TAG = FileOperationsHelper.class.getSimpleName();
     private static final String TAG = FileOperationsHelper.class.getSimpleName();
-    
+
     private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
     private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
 
 
     protected FileActivity mFileActivity = null;
     protected FileActivity mFileActivity = null;
@@ -76,21 +79,21 @@ public class FileOperationsHelper {
     /// Identifier of operation in progress which result shouldn't be lost 
     /// Identifier of operation in progress which result shouldn't be lost 
     private long mWaitingForOpId = Long.MAX_VALUE;
     private long mWaitingForOpId = Long.MAX_VALUE;
 
 
-	private static final Pattern mPatternUrl = Pattern.compile("^URL=(.+)$");
-	private static final Pattern mPatternString = Pattern.compile("<string>(.+)</string>");
+    private static final Pattern mPatternUrl = Pattern.compile("^URL=(.+)$");
+    private static final Pattern mPatternString = Pattern.compile("<string>(.+)</string>");
 
 
     public FileOperationsHelper(FileActivity fileActivity) {
     public FileOperationsHelper(FileActivity fileActivity) {
         mFileActivity = fileActivity;
         mFileActivity = fileActivity;
     }
     }
 
 
-	@Nullable
+    @Nullable
     private String getUrlFromFile(String storagePath, Pattern pattern) {
     private String getUrlFromFile(String storagePath, Pattern pattern) {
         String url = null;
         String url = null;
 
 
         InputStreamReader fr = null;
         InputStreamReader fr = null;
         BufferedReader br = null;
         BufferedReader br = null;
         try {
         try {
-            fr =  new InputStreamReader(new FileInputStream(storagePath), "UTF8");
+            fr = new InputStreamReader(new FileInputStream(storagePath), "UTF8");
             br = new BufferedReader(fr);
             br = new BufferedReader(fr);
 
 
             String line;
             String line;
@@ -102,7 +105,7 @@ public class FileOperationsHelper {
                 }
                 }
             }
             }
         } catch (IOException e) {
         } catch (IOException e) {
-			Log_OC.d(TAG, e.getMessage());
+            Log_OC.d(TAG, e.getMessage());
         } finally {
         } finally {
             if (br != null) {
             if (br != null) {
                 try {
                 try {
@@ -121,20 +124,20 @@ public class FileOperationsHelper {
             }
             }
         }
         }
         return url;
         return url;
-	}
-	
+    }
+
     @Nullable
     @Nullable
     private Intent createIntentFromFile(String storagePath) {
     private Intent createIntentFromFile(String storagePath) {
         String url = null;
         String url = null;
         int lastIndexOfDot = storagePath.lastIndexOf('.');
         int lastIndexOfDot = storagePath.lastIndexOf('.');
         if (lastIndexOfDot >= 0) {
         if (lastIndexOfDot >= 0) {
             String fileExt = storagePath.substring(lastIndexOfDot + 1);
             String fileExt = storagePath.substring(lastIndexOfDot + 1);
-            if (fileExt.equalsIgnoreCase("url") ||fileExt.equalsIgnoreCase("desktop")) {
-				// Windows internet shortcut file .url
-				// Ubuntu internet shortcut file .desktop
+            if (fileExt.equalsIgnoreCase("url") || fileExt.equalsIgnoreCase("desktop")) {
+                // Windows internet shortcut file .url
+                // Ubuntu internet shortcut file .desktop
                 url = getUrlFromFile(storagePath, mPatternUrl);
                 url = getUrlFromFile(storagePath, mPatternUrl);
             } else if (fileExt.equalsIgnoreCase("webloc")) {
             } else if (fileExt.equalsIgnoreCase("webloc")) {
-				// mac internet shortcut file .webloc
+                // mac internet shortcut file .webloc
                 url = getUrlFromFile(storagePath, mPatternString);
                 url = getUrlFromFile(storagePath, mPatternString);
             }
             }
         }
         }
@@ -162,7 +165,7 @@ public class FileOperationsHelper {
                 }
                 }
             }
             }
 
 
-            if(openFileWithIntent == null) {
+            if (openFileWithIntent == null) {
                 openFileWithIntent = createIntentFromFile(storagePath);
                 openFileWithIntent = createIntentFromFile(storagePath);
             }
             }
 
 
@@ -179,7 +182,7 @@ public class FileOperationsHelper {
             List<ResolveInfo> launchables = mFileActivity.getPackageManager().
             List<ResolveInfo> launchables = mFileActivity.getPackageManager().
                     queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS);
                     queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS);
 
 
-            if(launchables != null && launchables.size() > 0) {
+            if (launchables != null && launchables.size() > 0) {
                 try {
                 try {
                     mFileActivity.startActivity(
                     mFileActivity.startActivity(
                             Intent.createChooser(
                             Intent.createChooser(
@@ -247,7 +250,7 @@ public class FileOperationsHelper {
         }
         }
     }
     }
 
 
-    public void getFileWithLink(OCFile file){
+    public void getFileWithLink(OCFile file) {
         if (isSharedSupported()) {
         if (isSharedSupported()) {
             if (file != null) {
             if (file != null) {
                 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
                 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
@@ -284,7 +287,7 @@ public class FileOperationsHelper {
         if (file != null) {
         if (file != null) {
             // TODO check capability?
             // TODO check capability?
             mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
             mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
-                getString(R.string.wait_a_moment));
+                    getString(R.string.wait_a_moment));
 
 
             Intent service = new Intent(mFileActivity, OperationsService.class);
             Intent service = new Intent(mFileActivity, OperationsService.class);
             service.setAction(OperationsService.ACTION_CREATE_SHARE_WITH_SHAREE);
             service.setAction(OperationsService.ACTION_CREATE_SHARE_WITH_SHAREE);
@@ -332,7 +335,7 @@ public class FileOperationsHelper {
         queueShareIntent(unshareService);
         queueShareIntent(unshareService);
     }
     }
 
 
-    public void unshareFileWithUserOrGroup(OCFile file, ShareType shareType, String userOrGroup){
+    public void unshareFileWithUserOrGroup(OCFile file, ShareType shareType, String userOrGroup) {
 
 
         // Unshare the file: Create the intent
         // Unshare the file: Create the intent
         Intent unshareService = new Intent(mFileActivity, OperationsService.class);
         Intent unshareService = new Intent(mFileActivity, OperationsService.class);
@@ -346,7 +349,7 @@ public class FileOperationsHelper {
     }
     }
 
 
 
 
-    private void queueShareIntent(Intent shareIntent){
+    private void queueShareIntent(Intent shareIntent) {
         if (isSharedSupported()) {
         if (isSharedSupported()) {
             // Unshare the file
             // Unshare the file
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().
@@ -370,7 +373,7 @@ public class FileOperationsHelper {
      *
      *
      * @param file  File to share or unshare.
      * @param file  File to share or unshare.
      */
      */
-    public void showShareFile(OCFile file){
+    public void showShareFile(OCFile file) {
         Intent intent = new Intent(mFileActivity, ShareActivity.class);
         Intent intent = new Intent(mFileActivity, ShareActivity.class);
         intent.putExtra(FileActivity.EXTRA_FILE, file);
         intent.putExtra(FileActivity.EXTRA_FILE, file);
         intent.putExtra(FileActivity.EXTRA_ACCOUNT, mFileActivity.getAccount());
         intent.putExtra(FileActivity.EXTRA_ACCOUNT, mFileActivity.getAccount());
@@ -508,8 +511,8 @@ public class FileOperationsHelper {
             // set MimeType
             // set MimeType
             sendIntent.setType(file.getMimetype());
             sendIntent.setType(file.getMimetype());
             sendIntent.putExtra(
             sendIntent.putExtra(
-                Intent.EXTRA_STREAM,
-                file.getExposedFileUri(mFileActivity)
+                    Intent.EXTRA_STREAM,
+                    file.getExposedFileUri(mFileActivity)
             );
             );
             sendIntent.putExtra(Intent.ACTION_SEND, true);      // Send Action
             sendIntent.putExtra(Intent.ACTION_SEND, true);      // Send Action
 
 
@@ -524,18 +527,50 @@ public class FileOperationsHelper {
     }
     }
 
 
     public void syncFiles(Collection<OCFile> files) {
     public void syncFiles(Collection<OCFile> files) {
-        for (OCFile file: files) {
+        for (OCFile file : files) {
             syncFile(file);
             syncFile(file);
         }
         }
     }
     }
 
 
+    public void setPictureAs(OCFile file) {
+        if (file != null) {
+            if (file.isDown()) {
+                Context context = MainApp.getAppContext();
+
+                try {
+                    File externalFile = new File(file.getStoragePath());
+                    Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
+                    Uri sendUri;
+
+                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                        sendUri = FileProvider.getUriForFile(context,
+                                context.getResources().getString(R.string.file_provider_authority), externalFile);
+                    } else {
+                        sendUri = Uri.fromFile(externalFile);
+                    }
+
+                    intent.setDataAndType(sendUri, file.getMimetype());
+                    intent.putExtra("mimeType", file.getMimetype());
+                    mFileActivity.startActivityForResult(Intent.createChooser(intent,
+                            mFileActivity.getString(R.string.set_as)), 200);
+
+                } catch (ActivityNotFoundException exception) {
+                    Toast.makeText(context, R.string.picture_set_as_no_app, Toast.LENGTH_LONG).show();
+                }
+            }
+        } else {
+            Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
+        }
+    }
+
     /**
     /**
      * Request the synchronization of a file or folder with the OC server, including its contents.
      * Request the synchronization of a file or folder with the OC server, including its contents.
      *
      *
      * @param file          The file or folder to synchronize
      * @param file          The file or folder to synchronize
      */
      */
     public void syncFile(OCFile file) {
     public void syncFile(OCFile file) {
-        if (!file.isFolder()){
+        if (!file.isFolder()) {
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_SYNC_FILE);
             intent.setAction(OperationsService.ACTION_SYNC_FILE);
             intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
             intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
@@ -543,8 +578,8 @@ public class FileOperationsHelper {
             intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
             intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
             mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
             mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
-                getString(R.string.wait_a_moment));
-            
+                    getString(R.string.wait_a_moment));
+
         } else {
         } else {
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
             intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
@@ -557,37 +592,37 @@ public class FileOperationsHelper {
 
 
     public void toggleFavoriteFiles(Collection<OCFile> files, boolean shouldBeFavorite) {
     public void toggleFavoriteFiles(Collection<OCFile> files, boolean shouldBeFavorite) {
         List<OCFile> alreadyRightStateList = new ArrayList<>();
         List<OCFile> alreadyRightStateList = new ArrayList<>();
-        for(OCFile file : files) {
-            if(file.getIsFavorite() == shouldBeFavorite) {
+        for (OCFile file : files) {
+            if (file.getIsFavorite() == shouldBeFavorite) {
                 alreadyRightStateList.add(file);
                 alreadyRightStateList.add(file);
             }
             }
         }
         }
 
 
         files.removeAll(alreadyRightStateList);
         files.removeAll(alreadyRightStateList);
 
 
-        for (OCFile file: files) {
+        for (OCFile file : files) {
             toggleFavoriteFile(file, shouldBeFavorite);
             toggleFavoriteFile(file, shouldBeFavorite);
         }
         }
     }
     }
 
 
     public void toggleFavoriteFile(OCFile file, boolean shouldBeFavorite) {
     public void toggleFavoriteFile(OCFile file, boolean shouldBeFavorite) {
-        if(file.getIsFavorite() != shouldBeFavorite) {
+        if (file.getIsFavorite() != shouldBeFavorite) {
             EventBus.getDefault().post(new FavoriteEvent(file.getRemotePath(), shouldBeFavorite, file.getRemoteId()));
             EventBus.getDefault().post(new FavoriteEvent(file.getRemotePath(), shouldBeFavorite, file.getRemoteId()));
         }
         }
     }
     }
 
 
 
 
-    public void toogleOfflineFiles(Collection<OCFile> files, boolean isAvailableOffline){
+    public void toogleOfflineFiles(Collection<OCFile> files, boolean isAvailableOffline) {
         List<OCFile> alreadyRightStateList = new ArrayList<>();
         List<OCFile> alreadyRightStateList = new ArrayList<>();
-        for(OCFile file : files) {
-            if(file.isAvailableOffline() == isAvailableOffline) {
+        for (OCFile file : files) {
+            if (file.isAvailableOffline() == isAvailableOffline) {
                 alreadyRightStateList.add(file);
                 alreadyRightStateList.add(file);
             }
             }
         }
         }
 
 
         files.removeAll(alreadyRightStateList);
         files.removeAll(alreadyRightStateList);
 
 
-        for (OCFile file: files) {
+        for (OCFile file : files) {
             toggleOfflineFile(file, isAvailableOffline);
             toggleOfflineFile(file, isAvailableOffline);
         }
         }
     }
     }
@@ -612,7 +647,7 @@ public class FileOperationsHelper {
             }
             }
         }
         }
     }
     }
-    
+
     public void renameFile(OCFile file, String newFilename) {
     public void renameFile(OCFile file, String newFilename) {
         // RenameFile
         // RenameFile
         Intent service = new Intent(mFileActivity, OperationsService.class);
         Intent service = new Intent(mFileActivity, OperationsService.class);
@@ -621,7 +656,7 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
         service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
         service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
-        
+
         mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
         mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
     }
     }
 
 
@@ -643,7 +678,7 @@ public class FileOperationsHelper {
             service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
             service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
         }
         }
-        
+
         mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
         mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
     }
     }
 
 
@@ -655,8 +690,8 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
         service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
         service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
-        mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
-        
+        mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
+
         mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
         mFileActivity.showLoadingDialog(mFileActivity.getString(R.string.wait_a_moment));
     }
     }
 
 
@@ -754,7 +789,7 @@ public class FileOperationsHelper {
         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
 
 
         mFileActivity.showLoadingDialog(
         mFileActivity.showLoadingDialog(
-            mFileActivity.getString(R.string.wait_checking_credentials)
+                mFileActivity.getString(R.string.wait_checking_credentials)
         );
         );
     }
     }
 }
 }

+ 4 - 0
src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -365,6 +365,10 @@ public class PreviewImageFragment extends FileFragment {
                 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
                 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
                 return true;
                 return true;
 
 
+            case R.id.action_set_as_wallpaper:
+                mContainerActivity.getFileOperationsHelper().setPictureAs(getFile());
+                return true;
+
             default:
             default:
                 return super.onOptionsItemSelected(item);
                 return super.onOptionsItemSelected(item);
         }
         }

+ 14 - 16
src/main/java/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -106,6 +106,7 @@ public class PreviewMediaFragment extends FileFragment implements
     private MediaServiceConnection mMediaServiceConnection = null;
     private MediaServiceConnection mMediaServiceConnection = null;
     private VideoHelper mVideoHelper;
     private VideoHelper mVideoHelper;
     private boolean mAutoplay;
     private boolean mAutoplay;
+    private static boolean mOnResume = false;
     public boolean mPrepared;
     public boolean mPrepared;
 
 
     private static final String TAG = PreviewMediaFragment.class.getSimpleName();
     private static final String TAG = PreviewMediaFragment.class.getSimpleName();
@@ -220,6 +221,7 @@ public class PreviewMediaFragment extends FileFragment implements
      */
      */
     @Override
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
     public void onActivityCreated(Bundle savedInstanceState) {
+        mOnResume = true;
         super.onActivityCreated(savedInstanceState);
         super.onActivityCreated(savedInstanceState);
         Log_OC.v(TAG, "onActivityCreated");
         Log_OC.v(TAG, "onActivityCreated");
 
 
@@ -234,14 +236,11 @@ public class PreviewMediaFragment extends FileFragment implements
             if (!file.isDown()) {
             if (!file.isDown()) {
                 throw new IllegalStateException("There is no local file to preview");
                 throw new IllegalStateException("There is no local file to preview");
             }
             }
-
-        }
-        else {
-            file = (OCFile) savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE);
+        } else {
+            file = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE);
             setFile(file);
             setFile(file);
             mAccount = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_ACCOUNT);
             mAccount = savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_ACCOUNT);
-            mSavedPlaybackPosition =
-                    savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION);
+            mSavedPlaybackPosition = savedInstanceState.getInt(PreviewMediaFragment.EXTRA_PLAY_POSITION);
             mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING);
             mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING);
 
 
         }
         }
@@ -251,15 +250,12 @@ public class PreviewMediaFragment extends FileFragment implements
                 mVideoPreview.setVisibility(View.VISIBLE);
                 mVideoPreview.setVisibility(View.VISIBLE);
                 mImagePreview.setVisibility(View.GONE);
                 mImagePreview.setVisibility(View.GONE);
                 prepareVideo();
                 prepareVideo();
-
-            }
-            else {
+            } else {
                 mVideoPreview.setVisibility(View.GONE);
                 mVideoPreview.setVisibility(View.GONE);
                 mImagePreview.setVisibility(View.VISIBLE);
                 mImagePreview.setVisibility(View.VISIBLE);
                 extractAndSetCoverArt(file);
                 extractAndSetCoverArt(file);
             }
             }
         }
         }
-
     }
     }
 
 
     /**
     /**
@@ -307,11 +303,8 @@ public class PreviewMediaFragment extends FileFragment implements
         }
         }
         else {
         else {
             if (mMediaServiceBinder != null) {
             if (mMediaServiceBinder != null) {
-                outState.putInt(
-                        PreviewMediaFragment.EXTRA_PLAY_POSITION,
-                        mMediaServiceBinder.getCurrentPosition());
-                outState.putBoolean(
-                        PreviewMediaFragment.EXTRA_PLAYING, mMediaServiceBinder.isPlaying());
+                outState.putInt(PreviewMediaFragment.EXTRA_PLAY_POSITION, mMediaServiceBinder.getCurrentPosition());
+                outState.putBoolean(PreviewMediaFragment.EXTRA_PLAYING, mMediaServiceBinder.isPlaying());
             }
             }
         }
         }
     }
     }
@@ -565,6 +558,8 @@ public class PreviewMediaFragment extends FileFragment implements
     @Override
     @Override
     public void onResume() {
     public void onResume() {
         super.onResume();
         super.onResume();
+        mOnResume = !mOnResume;
+
         if (getActivity() != null) {
         if (getActivity() != null) {
             AnalyticsUtils.setCurrentScreenName(getActivity(), SCREEN_NAME, TAG);
             AnalyticsUtils.setCurrentScreenName(getActivity(), SCREEN_NAME, TAG);
         }
         }
@@ -585,6 +580,7 @@ public class PreviewMediaFragment extends FileFragment implements
         if (mMediaServiceConnection != null) {
         if (mMediaServiceConnection != null) {
             Log_OC.d(TAG, "Unbinding from MediaService ...");
             Log_OC.d(TAG, "Unbinding from MediaService ...");
             if (mMediaServiceBinder != null && mMediaController != null) {
             if (mMediaServiceBinder != null && mMediaController != null) {
+                mMediaController.stopMediaPlayerMessages();
                 mMediaServiceBinder.unregisterMediaController(mMediaController);
                 mMediaServiceBinder.unregisterMediaController(mMediaController);
             }
             }
             getActivity().unbindService(mMediaServiceConnection);
             getActivity().unbindService(mMediaServiceConnection);
@@ -638,7 +634,7 @@ public class PreviewMediaFragment extends FileFragment implements
 
 
     private void playAudio() {
     private void playAudio() {
         OCFile file = getFile();
         OCFile file = getFile();
-        if (!mMediaServiceBinder.isPlaying(file)) {
+        if (!mMediaServiceBinder.isPlaying(file) && !mOnResume) {
             Log_OC.d(TAG, "starting playback of " + file.getStoragePath());
             Log_OC.d(TAG, "starting playback of " + file.getStoragePath());
             mMediaServiceBinder.start(mAccount, file, mAutoplay, mSavedPlaybackPosition);
             mMediaServiceBinder.start(mAccount, file, mAutoplay, mSavedPlaybackPosition);
 
 
@@ -649,6 +645,8 @@ public class PreviewMediaFragment extends FileFragment implements
                 mMediaController.updatePausePlay();
                 mMediaController.updatePausePlay();
             }
             }
         }
         }
+
+        mOnResume = false;
     }
     }
 
 
 
 

+ 11 - 0
src/main/java/com/owncloud/android/utils/DisplayUtils.java

@@ -38,11 +38,15 @@ import android.graphics.drawable.PictureDrawable;
 import android.net.Uri;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Build;
 import android.support.annotation.ColorInt;
 import android.support.annotation.ColorInt;
+import android.support.annotation.ColorRes;
+import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.NonNull;
 import android.support.design.widget.BottomNavigationView;
 import android.support.design.widget.BottomNavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.graphics.drawable.DrawableCompat;
 import android.text.Spannable;
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.SpannableStringBuilder;
 import android.text.format.DateUtils;
 import android.text.format.DateUtils;
@@ -677,4 +681,11 @@ public class DisplayUtils {
         return text.toString();
         return text.toString();
     }
     }
 
 
+    public static Drawable tintDrawable(@DrawableRes int id, @ColorRes int color) {
+        Drawable drawable = ResourcesCompat.getDrawable(MainApp.getAppContext().getResources(), id, null);
+        drawable = DrawableCompat.wrap(drawable);
+        DrawableCompat.setTint(drawable, MainApp.getAppContext().getResources().getColor(color));
+        return drawable;
+    }
+
 }
 }

+ 0 - 4
src/main/java/com/owncloud/android/utils/FileStorageUtils.java

@@ -115,10 +115,6 @@ public class FileStorageUtils {
         return savePath.getUsableSpace();
         return savePath.getUsableSpace();
     }
     }
 
 
-    public static String getLogPath() {
-        return MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator + "log";
-    }
-
     /**
     /**
      * Returns the a string like 2016/08/ for the passed date. If date is 0 an empty
      * Returns the a string like 2016/08/ for the passed date. If date is 0 an empty
      * string is returned
      * string is returned

+ 22 - 8
src/main/java/com/owncloud/android/utils/MimeTypeUtil.java

@@ -1,23 +1,24 @@
 /**
 /**
  * ownCloud Android client application
  * ownCloud Android client application
- *
+ * <p>
  * Copyright (C) 2016 ownCloud Inc.
  * Copyright (C) 2016 ownCloud Inc.
- *
+ * <p>
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
  * it under the terms of the GNU General Public License version 2,
  * as published by the Free Software Foundation.
  * as published by the Free Software Foundation.
- *
+ * <p>
  * This program is distributed in the hope that it will be useful,
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  * GNU General Public License for more details.
- *
+ * <p>
  * You should have received a copy of the GNU General Public License
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
  */
 
 
 package com.owncloud.android.utils;
 package com.owncloud.android.utils;
 
 
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.net.Uri;
 import android.webkit.MimeTypeMap;
 import android.webkit.MimeTypeMap;
 
 
@@ -94,16 +95,25 @@ public class MimeTypeUtil {
      * @param isSharedViaLink flag if the folder is publicly shared via link
      * @param isSharedViaLink flag if the folder is publicly shared via link
      * @return Identifier of an image resource.
      * @return Identifier of an image resource.
      */
      */
-    public static int getFolderTypeIconId(boolean isSharedViaUsers, boolean isSharedViaLink) {
+    public static Drawable getFolderTypeIcon(boolean isSharedViaUsers, boolean isSharedViaLink) {
+        int drawableId;
+
         if (isSharedViaLink) {
         if (isSharedViaLink) {
-            return R.drawable.folder_public;
+            drawableId = R.drawable.folder_public;
         } else if (isSharedViaUsers) {
         } else if (isSharedViaUsers) {
-            return R.drawable.shared_with_me_folder;
+            drawableId = R.drawable.shared_with_me_folder;
+        } else {
+            drawableId = R.drawable.ic_menu_archive;
         }
         }
 
 
-        return R.drawable.ic_menu_archive;
+        return DisplayUtils.tintDrawable(drawableId, R.color.primary);
     }
     }
 
 
+    public static Drawable getDefaultFolderIcon() {
+        return getFolderTypeIcon(false, false);
+    }
+
+
     /**
     /**
      * Returns a single MIME type of all the possible, by inspection of the file extension, and taking
      * Returns a single MIME type of all the possible, by inspection of the file extension, and taking
      * into account the MIME types known by ownCloud first.
      * into account the MIME types known by ownCloud first.
@@ -175,6 +185,10 @@ public class MimeTypeUtil {
         return isImage(extractMimeType(file));
         return isImage(extractMimeType(file));
     }
     }
 
 
+    public static boolean isSVG(OCFile file) {
+        return "image/svg+xml".equalsIgnoreCase(file.getMimetype());
+    }
+
     /**
     /**
      * @param file the file to be analyzed
      * @param file the file to be analyzed
      * @return 'True' if the file contains audio
      * @return 'True' if the file contains audio

BIN
src/main/res/drawable-hdpi/ic_checkbox_marked.png


BIN
src/main/res/drawable-hdpi/ic_list_empty_create_folder.png


BIN
src/main/res/drawable-hdpi/ic_list_empty_folder.png


BIN
src/main/res/drawable-hdpi/ic_list_empty_upload.png


BIN
src/main/res/drawable-hdpi/nav_activity.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_folder_open.png → src/main/res/drawable-hdpi/nav_all_files.png


BIN
src/main/res/drawable-hdpi/nav_contacts.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_star.png → src/main/res/drawable-hdpi/nav_favorites.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_cloud_upload.png → src/main/res/drawable-hdpi/nav_folder_sync.png


+ 0 - 0
src/main/res/drawable-hdpi/logout.png → src/main/res/drawable-hdpi/nav_logout.png


BIN
src/main/res/drawable-hdpi/nav_notifications.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_action_available_offline.png → src/main/res/drawable-hdpi/nav_on_device.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_participate.png → src/main/res/drawable-hdpi/nav_participate.png


BIN
src/main/res/drawable-hdpi/nav_photos.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_recent.png → src/main/res/drawable-hdpi/nav_recently.png


BIN
src/main/res/drawable-hdpi/nav_settings.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_shared.png → src/main/res/drawable-hdpi/nav_shared.png


+ 0 - 0
src/main/res/drawable-hdpi/ic_uploads.png → src/main/res/drawable-hdpi/nav_uploads.png


BIN
src/main/res/drawable-hdpi/nav_videos.png


BIN
src/main/res/drawable-mdpi/ic_checkbox_marked.png


BIN
src/main/res/drawable-mdpi/ic_list_empty_create_folder.png


BIN
src/main/res/drawable-mdpi/ic_list_empty_folder.png


BIN
src/main/res/drawable-mdpi/ic_list_empty_upload.png


BIN
src/main/res/drawable-mdpi/nav_activity.png


BIN
src/main/res/drawable-mdpi/nav_all_files.png


BIN
src/main/res/drawable-mdpi/nav_contacts.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_star.png → src/main/res/drawable-mdpi/nav_favorites.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_cloud_upload.png → src/main/res/drawable-mdpi/nav_folder_sync.png


+ 0 - 0
src/main/res/drawable-mdpi/logout.png → src/main/res/drawable-mdpi/nav_logout.png


BIN
src/main/res/drawable-mdpi/nav_notifications.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_action_available_offline.png → src/main/res/drawable-mdpi/nav_on_device.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_participate.png → src/main/res/drawable-mdpi/nav_participate.png


BIN
src/main/res/drawable-mdpi/nav_photos.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_recent.png → src/main/res/drawable-mdpi/nav_recently.png


BIN
src/main/res/drawable-mdpi/nav_settings.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_shared.png → src/main/res/drawable-mdpi/nav_shared.png


+ 0 - 0
src/main/res/drawable-mdpi/ic_uploads.png → src/main/res/drawable-mdpi/nav_uploads.png


BIN
src/main/res/drawable-mdpi/nav_videos.png


BIN
src/main/res/drawable-xhdpi/ic_checkbox_marked.png


BIN
src/main/res/drawable-xhdpi/ic_list_empty_create_folder.png


BIN
src/main/res/drawable-xhdpi/ic_list_empty_folder.png


BIN
src/main/res/drawable-xhdpi/ic_list_empty_upload.png


BIN
src/main/res/drawable-xhdpi/nav_activity.png


+ 0 - 0
src/main/res/drawable-xhdpi/ic_folder_open.png → src/main/res/drawable-xhdpi/nav_all_files.png


Some files were not shown because too many files changed in this diff