From: tobiasKaminsky Date: Thu, 29 Oct 2015 17:21:20 +0000 (+0100) Subject: Merge remote-tracking branch 'remotes/upstream/material_buttons' into beta X-Git-Tag: beta-20151122~90 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/b23d07d8a134acf8a7632db6287376452739359f?hp=2603a351059848dd59b080578a12cd61ca1ed122 Merge remote-tracking branch 'remotes/upstream/material_buttons' into beta --- diff --git a/.gitignore b/.gitignore index 8346dbfc..9b1a0d0c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ # built application files -*.apk *.ap_ # files for the dex VM @@ -39,4 +38,4 @@ tests/proguard-project.txt build # Actionbarsherlock is now ignored since scripts takes care of init the sub-modules. -actionbarsherlock \ No newline at end of file +actionbarsherlock diff --git a/AndroidManifest.xml b/AndroidManifest.xml index acb5f1d8..dacb8b89 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -110,12 +110,17 @@ + + + + + + + diff --git a/CHANGELOG.md b/CHANGELOG.md index 099a4456..d56c9f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,60 +1,10 @@ -## 1.8.0 (September 2015) -- New MATERIAL DESIGN theme -- Updated FILE TYPE ICONS -- Preview TXT files within the app -- COPY files & folders -- Preview the full file/folder name from the long press menu -- Set a file as FAVORITE (kept-in-sync) from the CONTEXT MENU -- Updated CONFLICT RESOLUTION dialog (wording) -- Updated background for images with TRANSPARENCY in GALLERY -- Hidden files will not enforce list view instead of GRID VIEW (folders from Picasa & others) -- Security: - + Updated network stack with security fixes (Jackrabbit 2.10.1) -- Bugs fixed: - + Fixed crash when ETag is lost - + Passcode creation not restarted on device rotation - + Recovered share icon shown on folders 'shared with me' - + User name added to subject when sending a share link through e-mail (fixed on SAMLed apps) - -## 1.7.2 (July 2015) -- New navigation drawer -- Improved Passcode -- Automatic grid view just for folders full of images -- More characters allowed in file names -- Support for servers in same domain, different path -- Bugs fixed: - + Frequent crashes in folder with several images - + Sync error in servers with huge quota and external storage enable - + Share by link error - + Some other crashes and minor bugs - -## 1.7.1 (April 2015) - -- Share link even with password enforced by server -- Get the app ready for oc 8.1 servers -- Added option to create new folder in uploads from external apps -- Improved management of deleted users -- Bugs fixed - + Fixed crash on Android 2.x devices - + Improvements on uploads - -## 1.7.0 (February 2015) - -- Download full folders -- Grid view for images -- Remote thumbnails (OC Server 8.0+) -- Added number of files and folders at the end of the list -- "Open with" in contextual menu -- Downloads added to Media Provider -- Uploads: - + Local thumbnails in section "Files" - + Multiple selection in "Content from other apps" (Android 4.3+) -- Gallery: - + proper handling of EXIF - + obey sorting in the list of files -- Settings view updated -- Improved subjects in e-mails -- Bugs fixed - +# 2015-10-29 +- PR [#1099](https://github.com/owncloud/android/pull/1099) "Switch list vs grid" merged +- PR [#1100](https://github.com/owncloud/android/pull/1100) "Material FAB with speed dial implementation" merged +# 2015-10-26 +- start of branch +- PR [#745](https://github.com/owncloud/android/pull/745) merged +- PR [#1044](https://github.com/owncloud/android/pull/1044) merged: < 8.1: GalleryPlus app needed, >= 8.2 Gallery app needed +- PR [#1111](https://github.com/owncloud/android/pull/1111) merged \ No newline at end of file diff --git a/README.md b/README.md index e3ff5353..d8808f1b 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ -#This is the Android client for [ownCloud][0] +#This is the BETA Android client for [ownCloud][0] + +The BETA app is only intended to be used by experienced users that want to use and test the latest features. +All pull requests labeled "3 - to review" or higher will be included into the branch. +If you find a bug please comment in the corresponding pull request or create a new issue with the label "Beta". + +The compiled APKs can be found [here][2] + +The changelog is found [here][3] The app performs file synchronization with an ownCloud server. Other ownCloud features may be added in the future, but they are not a priority right now. ## Build Status on -Git master: ![Build Status](https://api.travis-ci.org/owncloud/android.svg?branch=master) - -Git stable: ![Build Status](https://api.travis-ci.org/owncloud/android.svg?branch=stable) +Git beta: ![Build Status](https://api.travis-ci.org/owncloud/android.svg?branch=beta) ## Development @@ -14,6 +20,8 @@ Make sure you read [SETUP.md][1] when you start working on this project. [0]: https://github.com/owncloud/core [1]: https://github.com/owncloud/android/blob/master/SETUP.md +[2]: https://github.com/owncloud/android/tree/beta/apks/ +[3]: https://github.com/owncloud/android/blob/beta/CHANGELOG.md ### Contributing Please see [Contribution Guidelines](https://owncloud.org/contribute/). Fork this repository and contribute back using diff --git a/SETUP.md b/SETUP.md index 0f1bc8ed..64c04c97 100644 --- a/SETUP.md +++ b/SETUP.md @@ -90,6 +90,7 @@ The generated APK file is saved in android/build/outputs/apk as android-debug.ap * Choose the projects with the next names under the 'New Project Name' column: ** owncloud-android ** android-support-appcompat-v7-exploded-aar +** com-getbase-floatingactionbutton-1-10-0-exploded-aar ** owncloud-android-workaround-accounts (optional) ** ownCloud Android Library ** ownCloud Sample Client (optional) @@ -102,11 +103,12 @@ The generated APK file is saved in android/build/outputs/apk as android-debug.ap * If any error persists, clean and build manually the next projects in order: ** ownCloud Android Library ** android-support-appcompat-v7-exploded-aar +** com-getbase-floatingactionbutton-1-10-0-exploded-aar ** owncloud-android * If any error on those projects persists, check the project properties. In the 'Android' section, API Level should be ** ownCloud Android Library -> API level 19 ** android-support-appcompat-v7-exploded-aa -> API level 22 -** owncloud-android -> API level 22 ; in this project, two library projects should appear referred in the bottom of the dialog: libs\android-support-appcompat-v7-exploded-aar and owncloud-android-library. Add them if needed. +** owncloud-android -> API level 22 ; in this project, three library projects should appear referred in the bottom of the dialog: libs\android-support-appcompat-v7-exploded-aar, ** com-getbase-floatingactionbutton-1-10-0-exploded-aar and owncloud-android-library. Add them if needed. * After those actions you should be good to go. HAVE FUN! diff --git a/THIRD_PARTY.txt b/THIRD_PARTY.txt index 6fd3e5b3..034ecb32 100644 --- a/THIRD_PARTY.txt +++ b/THIRD_PARTY.txt @@ -59,4 +59,8 @@ The third party software included and used by this project is: modifications com.ortiz.touch.ExtendedViewPager and com.ortiz.touch.TouchImageView classes. See https://github.com/MikeOrtiz/TouchImageView - \ No newline at end of file + * floatingactionbutton 1.10.0. + Copyright (c) 2014 Jerzy Chalupski + Licensed under Apache License, Version 2.0. + placed at libs/com-getbase-floatingactionbutton-1-10-0-exploded-aar has been exploded by ownCloud Inc. + See https://github.com/futuresimple/android-floating-action-button \ No newline at end of file diff --git a/android-release.apk b/android-release.apk new file mode 100644 index 00000000..61a3b3bc Binary files /dev/null and b/android-release.apk differ diff --git a/apks/owncloud-beta-2015-10-26.apk b/apks/owncloud-beta-2015-10-26.apk new file mode 100644 index 00000000..61a3b3bc Binary files /dev/null and b/apks/owncloud-beta-2015-10-26.apk differ diff --git a/build.gradle b/build.gradle index a0db0184..be674c9f 100644 --- a/build.gradle +++ b/build.gradle @@ -24,11 +24,17 @@ dependencies { compile project(':owncloud-android-library') compile 'com.jakewharton:disklrucache:2.0.2' compile 'com.android.support:appcompat-v7:22.2.1' + compile 'com.getbase:floatingactionbutton:1.10.1' } android { compileSdkVersion 22 buildToolsVersion "22.0.1" + + defaultConfig { + applicationId "com.owncloud.android.beta" + } + sourceSets { main { manifest.srcFile 'AndroidManifest.xml' diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/.classpath b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/.classpath new file mode 100644 index 00000000..7bc01d9a --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/AndroidManifest.xml b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/AndroidManifest.xml new file mode 100644 index 00000000..f29e9873 --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/R.txt b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/R.txt new file mode 100644 index 00000000..c6d56648 --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/R.txt @@ -0,0 +1,55 @@ +int attr fab_addButtonColorNormal 0x7f010009 +int attr fab_addButtonColorPressed 0x7f010008 +int attr fab_addButtonPlusIconColor 0x7f01000b +int attr fab_addButtonSize 0x7f01000a +int attr fab_addButtonStrokeVisible 0x7f01000c +int attr fab_colorDisabled 0x7f010002 +int attr fab_colorNormal 0x7f010003 +int attr fab_colorPressed 0x7f010001 +int attr fab_expandDirection 0x7f01000f +int attr fab_icon 0x7f010004 +int attr fab_labelStyle 0x7f01000d +int attr fab_labelsPosition 0x7f01000e +int attr fab_plusIconColor 0x7f010000 +int attr fab_size 0x7f010005 +int attr fab_stroke_visible 0x7f010007 +int attr fab_title 0x7f010006 +int dimen fab_actions_spacing 0x7f030000 +int dimen fab_icon_size 0x7f030001 +int dimen fab_labels_margin 0x7f030002 +int dimen fab_plus_icon_size 0x7f030003 +int dimen fab_plus_icon_stroke 0x7f030004 +int dimen fab_shadow_offset 0x7f030005 +int dimen fab_shadow_radius 0x7f030006 +int dimen fab_size_mini 0x7f030007 +int dimen fab_size_normal 0x7f030008 +int dimen fab_stroke_width 0x7f030009 +int drawable fab_bg_mini 0x7f020000 +int drawable fab_bg_normal 0x7f020001 +int id down 0x7f040006 +int id fab_expand_menu_button 0x7f040000 +int id fab_label 0x7f040001 +int id left 0x7f040004 +int id mini 0x7f040002 +int id normal 0x7f040003 +int id right 0x7f040005 +int id up 0x7f040007 +int[] styleable AddFloatingActionButton { 0x7f010000 } +int styleable AddFloatingActionButton_fab_plusIconColor 0 +int[] styleable FloatingActionButton { 0x7f010001, 0x7f010002, 0x7f010003, 0x7f010004, 0x7f010005, 0x7f010006, 0x7f010007 } +int styleable FloatingActionButton_fab_colorDisabled 1 +int styleable FloatingActionButton_fab_colorNormal 2 +int styleable FloatingActionButton_fab_colorPressed 0 +int styleable FloatingActionButton_fab_icon 3 +int styleable FloatingActionButton_fab_size 4 +int styleable FloatingActionButton_fab_stroke_visible 6 +int styleable FloatingActionButton_fab_title 5 +int[] styleable FloatingActionsMenu { 0x7f010008, 0x7f010009, 0x7f01000a, 0x7f01000b, 0x7f01000c, 0x7f01000d, 0x7f01000e, 0x7f01000f } +int styleable FloatingActionsMenu_fab_addButtonColorNormal 1 +int styleable FloatingActionsMenu_fab_addButtonColorPressed 0 +int styleable FloatingActionsMenu_fab_addButtonPlusIconColor 3 +int styleable FloatingActionsMenu_fab_addButtonSize 2 +int styleable FloatingActionsMenu_fab_addButtonStrokeVisible 4 +int styleable FloatingActionsMenu_fab_expandDirection 7 +int styleable FloatingActionsMenu_fab_labelStyle 5 +int styleable FloatingActionsMenu_fab_labelsPosition 6 diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/aapt/AndroidManifest.xml b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/aapt/AndroidManifest.xml new file mode 100644 index 00000000..f29e9873 --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/aapt/AndroidManifest.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/annotations.zip b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/annotations.zip new file mode 100644 index 00000000..a46d2cee Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/annotations.zip differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/build.xml b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/build.xml new file mode 100644 index 00000000..4317fb0c --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/jars/classes.jar b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/jars/classes.jar new file mode 100644 index 00000000..723d01e0 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/jars/classes.jar differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/libs/classes.jar b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/libs/classes.jar new file mode 100644 index 00000000..723d01e0 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/libs/classes.jar differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/proguard.txt b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/proguard.txt new file mode 100644 index 00000000..b5429595 --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/proguard.txt @@ -0,0 +1,5 @@ +# keep getters/setters in RotatingDrawable so that animations can still work. +-keepclassmembers class com.getbase.floatingactionbutton.FloatingActionsMenu$RotatingDrawable { + void set*(***); + *** get*(); +} diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/project.properties b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/project.properties new file mode 100644 index 00000000..362a0a30 --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-22 +android.library=true diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_mini.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_mini.png new file mode 100644 index 00000000..4b48351c Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_mini.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_normal.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_normal.png new file mode 100644 index 00000000..4daec66d Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_normal.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_mini.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_mini.png new file mode 100644 index 00000000..218cf044 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_mini.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_normal.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_normal.png new file mode 100644 index 00000000..c157df36 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_normal.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_mini.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_mini.png new file mode 100644 index 00000000..d56bfe82 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_mini.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_normal.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_normal.png new file mode 100644 index 00000000..41614b93 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_normal.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_mini.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_mini.png new file mode 100644 index 00000000..1cdd2b1d Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_mini.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_normal.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_normal.png new file mode 100644 index 00000000..14608fff Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_normal.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_mini.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_mini.png new file mode 100644 index 00000000..6fea6746 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_mini.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_normal.png b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_normal.png new file mode 100644 index 00000000..0e78ff60 Binary files /dev/null and b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_normal.png differ diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/values/values.xml b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/values/values.xml new file mode 100644 index 00000000..8139c61d --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/values/values.xml @@ -0,0 +1,22 @@ + + + + + + + + 16dp + 24dp + 8dp + 14dp + 2dp + 3dp + 9dp + 40dp + 56dp + 1dp + + + + + \ No newline at end of file diff --git a/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/src/.readme b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/src/.readme new file mode 100644 index 00000000..4bcebad8 --- /dev/null +++ b/libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/src/.readme @@ -0,0 +1,2 @@ +This hidden file is there to ensure there is an src folder. +Once we support binary library this will go away. \ No newline at end of file diff --git a/owncloud-android-library b/owncloud-android-library index ecc3415e..652cd28b 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit ecc3415e3e3c13fa8f73fdd51a88c1ab7087b199 +Subproject commit 652cd28bb15672eaedfe8c1d9a46cf293c909b89 diff --git a/project.properties b/project.properties index b7cabddb..3b4370c0 100644 --- a/project.properties +++ b/project.properties @@ -11,3 +11,4 @@ target=android-22 android.library.reference.1=owncloud-android-library android.library.reference.2=libs/android-support-appcompat-v7-exploded-aar +android.library.reference.3=libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar diff --git a/res/drawable-hdpi-v9/ic_action_download.png b/res/drawable-hdpi-v9/ic_action_download.png deleted file mode 100644 index 25476cd7..00000000 Binary files a/res/drawable-hdpi-v9/ic_action_download.png and /dev/null differ diff --git a/res/drawable-hdpi-v9/ic_action_refresh.png b/res/drawable-hdpi-v9/ic_action_refresh.png deleted file mode 100644 index a7fdc0df..00000000 Binary files a/res/drawable-hdpi-v9/ic_action_refresh.png and /dev/null differ diff --git a/res/drawable-hdpi-v9/ic_action_settings.png b/res/drawable-hdpi-v9/ic_action_settings.png deleted file mode 100644 index 86b54f4c..00000000 Binary files a/res/drawable-hdpi-v9/ic_action_settings.png and /dev/null differ diff --git a/res/drawable-hdpi/ic_checkbox_blank_outline.png b/res/drawable-hdpi/ic_checkbox_blank_outline.png index 198568de..164dcb53 100644 Binary files a/res/drawable-hdpi/ic_checkbox_blank_outline.png and b/res/drawable-hdpi/ic_checkbox_blank_outline.png differ diff --git a/res/drawable-hdpi/ic_checkbox_marked.png b/res/drawable-hdpi/ic_checkbox_marked.png index 92d4109c..330d7b95 100644 Binary files a/res/drawable-hdpi/ic_checkbox_marked.png and b/res/drawable-hdpi/ic_checkbox_marked.png differ diff --git a/res/drawable-hdpi/ic_import.png b/res/drawable-hdpi/ic_import.png new file mode 100644 index 00000000..ad728378 Binary files /dev/null and b/res/drawable-hdpi/ic_import.png differ diff --git a/res/drawable-hdpi/ic_view_list.png b/res/drawable-hdpi/ic_view_list.png new file mode 100644 index 00000000..64ad8e14 Binary files /dev/null and b/res/drawable-hdpi/ic_view_list.png differ diff --git a/res/drawable-hdpi/ic_view_module.png b/res/drawable-hdpi/ic_view_module.png new file mode 100644 index 00000000..7982e383 Binary files /dev/null and b/res/drawable-hdpi/ic_view_module.png differ diff --git a/res/drawable-mdpi-v9/ic_action_download.png b/res/drawable-mdpi-v9/ic_action_download.png deleted file mode 100644 index 2684c83f..00000000 Binary files a/res/drawable-mdpi-v9/ic_action_download.png and /dev/null differ diff --git a/res/drawable-mdpi-v9/ic_action_refresh.png b/res/drawable-mdpi-v9/ic_action_refresh.png deleted file mode 100644 index bb9d855f..00000000 Binary files a/res/drawable-mdpi-v9/ic_action_refresh.png and /dev/null differ diff --git a/res/drawable-mdpi-v9/ic_action_settings.png b/res/drawable-mdpi-v9/ic_action_settings.png deleted file mode 100644 index 47ef3f44..00000000 Binary files a/res/drawable-mdpi-v9/ic_action_settings.png and /dev/null differ diff --git a/res/drawable-mdpi/ic_checkbox_blank_outline.png b/res/drawable-mdpi/ic_checkbox_blank_outline.png new file mode 100644 index 00000000..d4ca47c6 Binary files /dev/null and b/res/drawable-mdpi/ic_checkbox_blank_outline.png differ diff --git a/res/drawable-mdpi/ic_checkbox_marked.png b/res/drawable-mdpi/ic_checkbox_marked.png new file mode 100644 index 00000000..99df2742 Binary files /dev/null and b/res/drawable-mdpi/ic_checkbox_marked.png differ diff --git a/res/drawable-mdpi/ic_import.png b/res/drawable-mdpi/ic_import.png new file mode 100644 index 00000000..3bc69d1b Binary files /dev/null and b/res/drawable-mdpi/ic_import.png differ diff --git a/res/drawable-mdpi/ic_view_list.png b/res/drawable-mdpi/ic_view_list.png new file mode 100644 index 00000000..4aca55c6 Binary files /dev/null and b/res/drawable-mdpi/ic_view_list.png differ diff --git a/res/drawable-mdpi/ic_view_module.png b/res/drawable-mdpi/ic_view_module.png new file mode 100644 index 00000000..f308a32b Binary files /dev/null and b/res/drawable-mdpi/ic_view_module.png differ diff --git a/res/drawable-xhdpi/ic_import.png b/res/drawable-xhdpi/ic_import.png new file mode 100644 index 00000000..bf2f72ea Binary files /dev/null and b/res/drawable-xhdpi/ic_import.png differ diff --git a/res/drawable-xhdpi/ic_view_list.png b/res/drawable-xhdpi/ic_view_list.png new file mode 100644 index 00000000..b81d9102 Binary files /dev/null and b/res/drawable-xhdpi/ic_view_list.png differ diff --git a/res/drawable-xhdpi/ic_view_module.png b/res/drawable-xhdpi/ic_view_module.png new file mode 100644 index 00000000..b3548535 Binary files /dev/null and b/res/drawable-xhdpi/ic_view_module.png differ diff --git a/res/drawable-xxhdpi/ic_import.png b/res/drawable-xxhdpi/ic_import.png new file mode 100644 index 00000000..a4412aac Binary files /dev/null and b/res/drawable-xxhdpi/ic_import.png differ diff --git a/res/drawable-xxhdpi/ic_sort_variant.png b/res/drawable-xxhdpi/ic_sort_variant.png new file mode 100644 index 00000000..2918126d Binary files /dev/null and b/res/drawable-xxhdpi/ic_sort_variant.png differ diff --git a/res/drawable/fab_label_background.xml b/res/drawable/fab_label_background.xml new file mode 100644 index 00000000..4460dab0 --- /dev/null +++ b/res/drawable/fab_label_background.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/res/layout/list_footer.xml b/res/layout/list_footer.xml index a5a0e264..964b8453 100644 --- a/res/layout/list_footer.xml +++ b/res/layout/list_footer.xml @@ -14,7 +14,7 @@ android:padding="@dimen/standard_padding" android:layout_gravity="center" android:gravity="center" - android:textColor="@color/setup_text_hint" + android:textColor="@color/secondaryTextColor" /> \ No newline at end of file diff --git a/res/layout/list_fragment.xml b/res/layout/list_fragment.xml index 81b52100..ac28fcf2 100644 --- a/res/layout/list_fragment.xml +++ b/res/layout/list_fragment.xml @@ -17,17 +17,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . --> + + + android:layout_height="match_parent"> @@ -79,4 +83,52 @@ - \ No newline at end of file + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/list_item.xml b/res/layout/list_item.xml index 49bae2a1..754fd9e8 100644 --- a/res/layout/list_item.xml +++ b/res/layout/list_item.xml @@ -81,7 +81,7 @@ android:ellipsize="middle" android:singleLine="true" android:text="TextView" - android:textColor="#303030" + android:textColor="@color/textColor" android:textSize="@dimen/two_line_primary_text_size" /> + Visas datnes + Iestatījumi + Aizvērt Atvērt Vispārīgi Vairāk @@ -40,6 +43,8 @@ Palīdzība Ieteikt draugam Atsauksmes + Izmēģini %1$s uz savu viedtālruni! + Pārbaudīt serveri Lietotājvārds Parole Datnes @@ -56,6 +61,7 @@ Augšupielādē sekundes atpakaļ Te vēl nekas nav. Rīkojies, sāc augšupielādēt! + Ielādē… Šajā mapē nav failu Uzsitiet uz datnes, lai redzētu papildinformāciju. Izmērs: @@ -65,6 +71,8 @@ Lejupielādēt Atsvaidzināt failu Datne tika pārsaukta uz %1$s augšupielādes laikā + Dalīt saiti + Pārtraukt dalīt saiti Jā Nē Labi @@ -119,6 +127,7 @@ Izņemt Tikai lokālos Tikai lokālos + No servera Veiksmīgi izņemts Neizdevās izņemt Ievadīt jaunu nosaukumu @@ -126,6 +135,7 @@ Nevarēja pabeigt pārsaukšanu Nevarēja atzīmēt attālinātas datnes Datnes saturs jau ir sinhronizēts + Mapi nevarēja izveidot Uzgaidīt brīdi Negaidīta problēma; lūdzu, izvēlieties datni no citas lietotnes Netika izvēlēta neviena datne @@ -151,14 +161,35 @@ Kam: Paraksts: Algoritms: + PNG attēls Attēlus augšupielādēt tikai caur WiFi /TūlītējaAugšupielāde Paturēt abas + Šo attēlu nevar attēlot + Ievadiet paroli + Jums ir jāievada paroli Sūtīt + Kopēt saiti + lai pārsauktu šo datni + lai dzēstu šo datni + lai dalītu šo datni + lai pārtrauktu šis datnes dalīšanu + lai izveidotu datni Konti + Pievienot kontu + Ielādē datus… Nepareiza parole + Pārvietot + Šeit nekā nav. Jūs varat pievienot mapi! Izvēlieties + lai pārvietotu šo datni + lai kopētu šo datni Drošība + koplietots + ar jums Servera adrese + Lietotājvārds + 1 mape + 1 datne diff --git a/res/values-nb-rNO/strings.xml b/res/values-nb-rNO/strings.xml index bbf1061f..9ba35995 100644 --- a/res/values-nb-rNO/strings.xml +++ b/res/values-nb-rNO/strings.xml @@ -71,6 +71,7 @@ for få sekunder siden Ingenting her. Last opp noe! Laster... + Ingen app funnet for filtypen! Det er ingen filer i denne mappen. Trykk på en fil for å vise ekstra informasjon. Størrelse: diff --git a/res/values-tzl/strings.xml b/res/values-tzl/strings.xml deleted file mode 100644 index 37e61524..00000000 --- a/res/values-tzl/strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/res/values/colors.xml b/res/values/colors.xml index dab9b3fb..694e231b 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -23,12 +23,16 @@ #35537A #00ddff - #989898 + @color/secondaryTextColor #000000 #FFFFFF - #303030 + #fafafa + #f1f1f1 + #808080 + #B2000000 + @color/black #000000 - #fff0f0f0 + #eee #DDDDDD #EEEEEE #757575 @@ -36,6 +40,9 @@ @color/owncloud_blue_accent #D6D7D7 #00000000 + #a0a0a0 + #f8f8f8 + #55739a @color/owncloud_blue_accent diff --git a/res/values/setup.xml b/res/values/setup.xml index 76bdd9f8..5c775e92 100644 --- a/res/values/setup.xml +++ b/res/values/setup.xml @@ -1,12 +1,12 @@ - ownCloud + Owncloud Beta owncloud org.owncloud - owncloud.db + owncloud-beta.db ownCloud - owncloud + owncloud-beta Owncloud_ ownCloud Mozilla/5.0 (Android) ownCloud-android/%1$s diff --git a/res/values/strings.xml b/res/values/strings.xml index 267d713e..43cb0d96 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -263,9 +263,11 @@ 389 KB 2012/05/18 12:23 PM 12:23:45 - - Upload pictures via WiFi only - Upload videos via WiFi only + + Upload pictures via wifi only + Upload when charging only + Upload videos via wifi only + Upload when charging only /InstantUpload File conflict Which files do you want to keep? If you select both versions, the local file will have a number added to its name. @@ -277,7 +279,7 @@ This image cannot be shown %1$s could not be copied to %2$s local folder - Upload Path + Upload path Sorry, sharing is not enabled on your server. Please contact your administrator. @@ -342,7 +344,7 @@ Instant Uploads Security - Upload Video Path + Upload video path Download of %1$s folder could not be completed shared @@ -365,5 +367,6 @@ %1$d files %1$d files, 1 folder %1$d files, %2$d folders - + Switch to grid view + Switch to list view diff --git a/res/values/styles.xml b/res/values/styles.xml index 7df7639e..15b989ee 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -51,7 +51,9 @@ @color/primary - @@ -127,6 +130,11 @@ @style/Theme.ownCloud.Dialog.ButtonBar + + - + - + + - - - + + + + - + android:dependency="instant_uploading" + android:disableDependentsState="true" + android:title="@string/instant_upload_on_wifi" + android:key="instant_upload_on_wifi"/> + + + + android:dependency="instant_video_uploading" + android:disableDependentsState="true" + android:title="@string/prefs_instant_video_upload_path_title" + android:key="instant_video_upload_path" /> - - - - - - - - - - - + + + + + + - + diff --git a/setup_env.bat b/setup_env.bat index 8ccfeee1..b0fef5ee 100644 --- a/setup_env.bat +++ b/setup_env.bat @@ -23,6 +23,7 @@ call git submodule init call git submodule update call android.bat update project -p libs/android-support-appcompat-v7-exploded-aar --target android-22 +call android.bat update project -p libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar --target android-22 call android.bat update lib-project -p owncloud-android-library call android.bat update project -p . call android.bat update project -p oc_jb_workaround diff --git a/setup_env.sh b/setup_env.sh index 76ba2a32..6ca3a859 100755 --- a/setup_env.sh +++ b/setup_env.sh @@ -18,6 +18,7 @@ function initForAnt { #Prepare project android-support-appcompat-v7 ; JAR file is not enough, includes resources android update lib-project -p libs/android-support-appcompat-v7-exploded-aar --target android-22 + android update lib-project -p libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar --target android-22 #As default it updates the ant scripts android update lib-project -p owncloud-android-library diff --git a/src/com/owncloud/android/datamodel/OCFile.java b/src/com/owncloud/android/datamodel/OCFile.java index 4baf1ea5..0c7cc714 100644 --- a/src/com/owncloud/android/datamodel/OCFile.java +++ b/src/com/owncloud/android/datamodel/OCFile.java @@ -27,6 +27,7 @@ import android.webkit.MimeTypeMap; import com.owncloud.android.lib.common.utils.Log_OC; import java.io.File; +import java.util.Enumeration; import third_parties.daveKoeller.AlphanumComparator; public class OCFile implements Parcelable, Comparable { @@ -74,6 +75,8 @@ public class OCFile implements Parcelable, Comparable { private boolean mIsDownloading; + private boolean mShowGridView; + /** * Create new {@link OCFile} with given path. diff --git a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index f0ecf767..e8496951 100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -29,18 +29,25 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.Point; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.ThumbnailUtils; import android.net.Uri; import android.os.AsyncTask; +import android.view.Display; +import android.view.View; +import android.view.WindowManager; import android.widget.ImageView; +import android.widget.ProgressBar; import com.owncloud.android.MainApp; import com.owncloud.android.R; @@ -142,11 +149,12 @@ public class ThumbnailsCacheManager { public static class ThumbnailGenerationTask extends AsyncTask { private final WeakReference mImageViewReference; + private WeakReference mProgressWheelRef; private static Account mAccount; private Object mFile; + private Boolean mIsThumbnail; private FileDataStorageManager mStorageManager; - public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) { // Use a WeakReference to ensure the ImageView can be garbage collected @@ -157,6 +165,12 @@ public class ThumbnailsCacheManager { mAccount = account; } + public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, + Account account, ProgressBar progressWheel) { + this(imageView, storageManager, account); + mProgressWheelRef = new WeakReference(progressWheel); + } + public ThumbnailGenerationTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can be garbage collected mImageViewReference = new WeakReference(imageView); @@ -175,12 +189,15 @@ public class ThumbnailsCacheManager { } mFile = params[0]; + mIsThumbnail = (Boolean) params[1]; + if (mFile instanceof OCFile) { - thumbnail = doOCFileInBackground(); + thumbnail = doOCFileInBackground(mIsThumbnail); } else if (mFile instanceof File) { - thumbnail = doFileInBackground(); - //} else { do nothing + thumbnail = doFileInBackground(mIsThumbnail); + } else { + // do nothing } }catch(Throwable t){ @@ -206,7 +223,14 @@ public class ThumbnailsCacheManager { tagId = String.valueOf(mFile.hashCode()); } if (String.valueOf(imageView.getTag()).equals(tagId)) { + if (mProgressWheelRef != null) { + final ProgressBar progressWheel = mProgressWheelRef.get(); + if (progressWheel != null) { + progressWheel.setVisibility(View.GONE); + } + } imageView.setImageBitmap(bitmap); + imageView.setVisibility(View.VISIBLE); } } } @@ -217,12 +241,13 @@ public class ThumbnailsCacheManager { * @param imageKey: thumb key * @param bitmap: image for extracting thumbnail * @param path: image path - * @param px: thumbnail dp + * @param pxW: thumbnail width + * @param pxH: thumbnail height * @return Bitmap */ - private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int px){ + private Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int pxW, int pxH){ - Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); + Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH); // Rotate image, obeying exif tag thumbnail = BitmapUtils.rotateImage(thumbnail,path); @@ -243,31 +268,56 @@ public class ThumbnailsCacheManager { return Math.round(r.getDimension(R.dimen.file_icon_size_grid)); } - private Bitmap doOCFileInBackground() { + private Point getScreenDimension(){ + WindowManager wm = (WindowManager) MainApp.getAppContext().getSystemService(Context.WINDOW_SERVICE); + Display display = wm.getDefaultDisplay(); + Point test = new Point(); + display.getSize(test); + return test; + } + + private Bitmap doOCFileInBackground(Boolean isThumbnail) { + Bitmap thumbnail = null; OCFile file = (OCFile)mFile; - final String imageKey = String.valueOf(file.getRemoteId()); + // distinguish between thumbnail and resized image + String temp = String.valueOf(file.getRemoteId()); + if (isThumbnail){ + temp = "t" + temp; + } else { + temp = "r" + temp; + } + + final String imageKey = temp; // Check disk cache in background thread - Bitmap thumbnail = getBitmapFromDiskCache(imageKey); + thumbnail = getBitmapFromDiskCache(imageKey); // Not found in disk cache if (thumbnail == null || file.needsUpdateThumbnail()) { - - int px = getThumbnailDimension(); + int pxW = 0; + int pxH = 0; + if (mIsThumbnail) { + pxW = pxH = getThumbnailDimension(); + } else { + Point p = getScreenDimension(); + pxW = p.x; + pxH = p.y; + } if (file.isDown()) { - Bitmap temp = BitmapUtils.decodeSampledBitmapFromFile( - file.getStoragePath(), px, px); - Bitmap bitmap = ThumbnailUtils.extractThumbnail(temp, px, px); + Bitmap tempBitmap = BitmapUtils.decodeSampledBitmapFromFile( + file.getStoragePath(), pxW, pxH); + Bitmap bitmap = ThumbnailUtils.extractThumbnail(tempBitmap, pxW, pxH); if (bitmap != null) { // Handle PNG if (file.getMimetype().equalsIgnoreCase("image/png")) { - bitmap = handlePNG(bitmap, px); + bitmap = handlePNG(bitmap, pxW); } - thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), px); + thumbnail = addThumbnailToCache(imageKey, bitmap, + file.getStoragePath(), pxW, pxH); file.setNeedsUpdateThumbnail(false); mStorageManager.saveFile(file); @@ -279,27 +329,51 @@ public class ThumbnailsCacheManager { if (mClient != null && serverOCVersion != null) { if (serverOCVersion.supportsRemoteThumbnails()) { try { - String uri = mClient.getBaseUri() + "" + - "/index.php/apps/files/api/v1/thumbnail/" + - px + "/" + px + Uri.encode(file.getRemotePath(), "/"); - Log_OC.d("Thumbnail", "URI: " + uri); - GetMethod get = new GetMethod(uri); - int status = mClient.executeMethod(get); - if (status == HttpStatus.SC_OK) { - InputStream inputStream = get.getResponseBodyAsStream(); - Bitmap bitmap = BitmapFactory.decodeStream(inputStream); - thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px); - - // Handle PNG - if (file.getMimetype().equalsIgnoreCase("image/png")) { - thumbnail = handlePNG(thumbnail, px); + if (mIsThumbnail) { + String uri = mClient.getBaseUri() + "" + + "/index.php/apps/files/api/v1/thumbnail/" + + pxW + "/" + pxH + Uri.encode(file.getRemotePath(), "/"); + Log_OC.d("Thumbnail", "Download URI: " + uri); + GetMethod get = new GetMethod(uri); + int status = mClient.executeMethod(get); + if (status == HttpStatus.SC_OK) { + InputStream inputStream = get.getResponseBodyAsStream(); + Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH); + } else { + Log_OC.d(TAG, "Status: " + status); + } + } else { + String gallery = ""; + if (serverOCVersion.supportsNativeGallery()){ + gallery = "gallery"; + } else { + gallery = "galleryplus"; } - // Add thumbnail to cache - if (thumbnail != null) { - addBitmapToCache(imageKey, thumbnail); + String uri = mClient.getBaseUri() + + "/index.php/apps/" + gallery + "/api/preview/" + Integer.parseInt(file.getRemoteId().substring(0,8)) + + "/" + pxW + "/" + pxH; + Log_OC.d("Thumbnail", "FileName: " + file.getFileName() + " Download URI: " + uri); + GetMethod get = new GetMethod(uri); + int status = mClient.executeMethod(get); + if (status == HttpStatus.SC_OK) { + InputStream inputStream = get.getResponseBodyAsStream(); + Bitmap bitmap = BitmapFactory.decodeStream(inputStream); + // Download via gallery app + thumbnail = bitmap; } } + + // Handle PNG + if (thumbnail != null && file.getMimetype().equalsIgnoreCase("image/png")) { + thumbnail = handlePNG(thumbnail, pxW); + } + + // Add thumbnail to cache + if (thumbnail != null) { + addBitmapToCache(imageKey, thumbnail); + } } catch (Exception e) { e.printStackTrace(); } @@ -327,24 +401,32 @@ public class ThumbnailsCacheManager { return resultBitmap; } - private Bitmap doFileInBackground() { + private Bitmap doFileInBackground(Boolean mIsThumbnail) { + Bitmap thumbnail = null; File file = (File)mFile; final String imageKey = String.valueOf(file.hashCode()); // Check disk cache in background thread - Bitmap thumbnail = getBitmapFromDiskCache(imageKey); + thumbnail = getBitmapFromDiskCache(imageKey); // Not found in disk cache if (thumbnail == null) { - - int px = getThumbnailDimension(); + int pxW = 0; + int pxH = 0; + if (mIsThumbnail) { + pxW = pxH = getThumbnailDimension(); + } else { + Point p = getScreenDimension(); + pxW = p.x; + pxH = p.y; + } Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile( - file.getAbsolutePath(), px, px); + file.getAbsolutePath(), pxW, pxH); if (bitmap != null) { - thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px); + thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH); } } return thumbnail; diff --git a/src/com/owncloud/android/files/FileMenuFilter.java b/src/com/owncloud/android/files/FileMenuFilter.java index f7fee626..1d5ca454 100644 --- a/src/com/owncloud/android/files/FileMenuFilter.java +++ b/src/com/owncloud/android/files/FileMenuFilter.java @@ -229,7 +229,6 @@ public class FileMenuFilter { } else { toShow.add(R.id.action_unfavorite_file); } - } } diff --git a/src/com/owncloud/android/files/FileOperationsHelper.java b/src/com/owncloud/android/files/FileOperationsHelper.java index fba62091..88cc8843 100644 --- a/src/com/owncloud/android/files/FileOperationsHelper.java +++ b/src/com/owncloud/android/files/FileOperationsHelper.java @@ -27,14 +27,17 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.graphics.Bitmap; import android.net.Uri; import android.support.v4.app.DialogFragment; import android.webkit.MimeTypeMap; import android.widget.Toast; +import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; import com.owncloud.android.lib.common.network.WebdavUtils; @@ -43,12 +46,19 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion; import com.owncloud.android.services.OperationsService; import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.ui.activity.FileActivity; +import com.owncloud.android.ui.adapter.DiskLruImageCacheFileProvider; import com.owncloud.android.ui.dialog.ShareLinkToDialog; import org.apache.http.protocol.HTTP; import java.util.List; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + /** * */ @@ -236,6 +246,24 @@ public class FileOperationsHelper { } } + public void sendCachedImage(OCFile file) { + if (file != null) { + Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND); + // set MimeType + sendIntent.setType(file.getMimetype()); +// sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + "/#" + file.getRemoteId() + "#" + file.getFileName())); + sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + file.getRemotePath())); + sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action + + // Show dialog, without the own app + String[] packagesToExclude = new String[] { mFileActivity.getPackageName() }; + DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file); + chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG); + } else { + Log_OC.wtf(TAG, "Trying to send a NULL OCFile"); + } + } + public void syncFile(OCFile file) { diff --git a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java index 47f7127b..33ad1cc1 100644 --- a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java +++ b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java @@ -29,14 +29,15 @@ import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.utils.FileStorageUtils; - import android.accounts.Account; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.database.Cursor; import android.net.ConnectivityManager; import android.net.NetworkInfo.State; +import android.os.BatteryManager; import android.preference.PreferenceManager; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; @@ -58,7 +59,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log_OC.d(TAG, "Received: " + intent.getAction()); - if (intent.getAction().equals(android.net.ConnectivityManager.CONNECTIVITY_ACTION)) { + if (intent.getAction().equals(android.net.ConnectivityManager.CONNECTIVITY_ACTION) || intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)) { handleConnectivityAction(context, intent); }else if (intent.getAction().equals(NEW_PHOTO_ACTION_UNOFFICIAL)) { handleNewPictureAction(context, intent); @@ -103,7 +104,6 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { file_name = c.getString(c.getColumnIndex(Images.Media.DISPLAY_NAME)); mime_type = c.getString(c.getColumnIndex(Images.Media.MIME_TYPE)); c.close(); - Log_OC.d(TAG, file_path + ""); // save always temporally the picture to upload @@ -111,7 +111,10 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { db.putFileForLater(file_path, account.name, null); db.close(); - if (!isOnline(context) || (instantPictureUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context))) { + if (!isOnline(context) + || (instantPictureUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context)) + || (instantUploadWhenChargingOnly(context) && !isCharging(context)) + ) { return; } @@ -155,8 +158,16 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { mime_type = c.getString(c.getColumnIndex(Video.Media.MIME_TYPE)); c.close(); Log_OC.d(TAG, file_path + ""); + + // save always temporally the picture to upload + DbHandler db = new DbHandler(context); + db.putFileForLater(file_path, account.name, null); + db.close(); - if (!isOnline(context) || (instantVideoUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context))) { + if (!isOnline(context) + || (instantVideoUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context)) + || (instantVideoUploadWhenChargingOnly(context) && !isCharging(context)) + ) { return; } @@ -172,14 +183,18 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { } private void handleConnectivityAction(Context context, Intent intent) { - if (!instantPictureUploadEnabled(context)) { + if (!instantPictureUploadEnabled(context) && !instantVideoUploadEnabled(context)) { Log_OC.d(TAG, "Instant upload disabled, don't upload anything"); return; } if (!intent.hasExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY) && isOnline(context) - && (!instantPictureUploadViaWiFiOnly(context) || (instantPictureUploadViaWiFiOnly(context) == isConnectedViaWiFi(context) == true))) { + && (!instantUploadWhenChargingOnly(context) || (instantUploadWhenChargingOnly(context) && isCharging(context))) + && (!instantVideoUploadWhenChargingOnly(context) || (instantVideoUploadWhenChargingOnly(context) && isCharging(context))) + && (!instantPictureUploadViaWiFiOnly(context) || (instantPictureUploadViaWiFiOnly(context) && isConnectedViaWiFi(context))) + && (!instantVideoUploadViaWiFiOnly(context) || (instantVideoUploadViaWiFiOnly(context) && isConnectedViaWiFi(context))) + ) { DbHandler db = new DbHandler(context); Cursor c = db.getAwaitingFiles(); if (c.moveToFirst()) { @@ -217,7 +232,6 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { c.close(); db.close(); } - } public static boolean isOnline(Context context) { @@ -231,6 +245,18 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { && cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI && cm.getActiveNetworkInfo().getState() == State.CONNECTED; } + + public static boolean isCharging(Context context){ + IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); + Intent batteryStatus = context.registerReceiver(null, ifilter); + + int status = 0; + if (batteryStatus != null) { + status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1); + } + return status == BatteryManager.BATTERY_STATUS_CHARGING || + status == BatteryManager.BATTERY_STATUS_FULL; + } public static boolean instantPictureUploadEnabled(Context context) { return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("instant_uploading", false); @@ -247,4 +273,10 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { public static boolean instantVideoUploadViaWiFiOnly(Context context) { return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("instant_video_upload_on_wifi", false); } + public static boolean instantUploadWhenChargingOnly(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("instant_upload_on_charging", false); + } + public static boolean instantVideoUploadWhenChargingOnly(Context context) { + return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("instant_video_upload_on_charging", false); + } } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index f5026459..7b97a9c8 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -149,13 +149,14 @@ public class FileDisplayActivity extends HookActivity private boolean mSyncInProgress = false; private static String DIALOG_UNTRUSTED_CERT = "DIALOG_UNTRUSTED_CERT"; - private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"; + public static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"; private static String DIALOG_UPLOAD_SOURCE = "DIALOG_UPLOAD_SOURCE"; private static String DIALOG_CERT_NOT_SAVED = "DIALOG_CERT_NOT_SAVED"; private OCFile mWaitingToSend; + private Menu mOptionsMenu; + - @Override protected void onCreate(Bundle savedInstanceState) { Log_OC.v(TAG, "onCreate() start"); @@ -316,6 +317,12 @@ public class FileDisplayActivity extends HookActivity startTextPreview(file); } + if (DisplayUtils.isGridView(getFile(), getStorageManager())){ + switchToGridView(); + } else { + switchToListView(); + } + } else { Log_OC.wtf(TAG, "initFragments() called with invalid NULLs!"); if (getAccount() == null) { @@ -480,10 +487,9 @@ public class FileDisplayActivity extends HookActivity @Override public boolean onPrepareOptionsMenu(Menu menu) { boolean drawerOpen = mDrawerLayout.isDrawerOpen(GravityCompat.START); - menu.findItem(R.id.action_upload).setVisible(!drawerOpen); - menu.findItem(R.id.action_create_dir).setVisible(!drawerOpen); menu.findItem(R.id.action_sort).setVisible(!drawerOpen); menu.findItem(R.id.action_sync_account).setVisible(!drawerOpen); + menu.findItem(R.id.action_switch_view).setVisible(!drawerOpen); return super.onPrepareOptionsMenu(menu); } @@ -492,6 +498,13 @@ public class FileDisplayActivity extends HookActivity public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); + menu.findItem(R.id.action_create_dir).setVisible(false); + mOptionsMenu = menu; + + MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view); + + changeGridIcon(); + return true; } @@ -500,23 +513,10 @@ public class FileDisplayActivity extends HookActivity public boolean onOptionsItemSelected(MenuItem item) { boolean retval = true; switch (item.getItemId()) { - case R.id.action_create_dir: { - CreateFolderDialogFragment dialog = - CreateFolderDialogFragment.newInstance(getCurrentDir()); - dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER); - break; - } - case R.id.action_sync_account: { startSynchronization(); break; } - case R.id.action_upload: { - UploadSourceDialogFragment dialog = - UploadSourceDialogFragment.newInstance(getAccount()); - dialog.show(getSupportFragmentManager(), DIALOG_UPLOAD_SOURCE); - break; - } case android.R.id.home: { FileFragment second = getSecondFragment(); OCFile currentDir = getCurrentDir(); @@ -559,12 +559,57 @@ public class FileDisplayActivity extends HookActivity builder.create().show(); break; } + case R.id.action_switch_view:{ + if (isGridView()){ + item.setTitle(getApplicationContext().getString(R.string.action_switch_grid_view)); + item.setIcon(ContextCompat.getDrawable(getApplicationContext(), + R.drawable.ic_view_module)); + DisplayUtils.setViewMode(getFile(), false); + switchToListView(); + } else { + item.setTitle(getApplicationContext().getString(R.string.action_switch_list_view)); + item.setIcon(ContextCompat.getDrawable(getApplicationContext(), + R.drawable.ic_view_list)); + DisplayUtils.setViewMode(getFile(), true); + switchToGridView(); + } + + return true; + } default: retval = super.onOptionsItemSelected(item); } return retval; } + public void createFolder() { + CreateFolderDialogFragment dialog = + CreateFolderDialogFragment.newInstance(getCurrentDir()); + dialog.show(getSupportFragmentManager(), DIALOG_CREATE_FOLDER); + } + + public void uploadLocalFilesSelected() { + Intent action = new Intent(this, UploadFilesActivity.class); + action.putExtra( + UploadFilesActivity.EXTRA_ACCOUNT, + getAccount() + ); + startActivityForResult(action, ACTION_SELECT_MULTIPLE_FILES); + } + + public void uploadFromOtherAppsSelected() { + Intent action = new Intent(Intent.ACTION_GET_CONTENT); + action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); + //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + } + startActivityForResult( + Intent.createChooser(action, getString(R.string.upload_chooser_title)), + ACTION_SELECT_CONTENT_FROM_APPS + ); + } + private void startSynchronization() { Log_OC.d(TAG, "Got to start sync"); if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) { @@ -777,7 +822,26 @@ public class FileDisplayActivity extends HookActivity @Override public void onBackPressed() { - if (!isDrawerOpen()){ + boolean isFabOpen = isFabOpen(); + boolean isDrawerOpen = isDrawerOpen(); + + /* + * BackPressed priority/hierarchy: + * 1. close drawer if opened + * 2. close FAB if open (only if drawer isn't open) + * 3. navigate up (only if drawer and FAB aren't open) + */ + if(isDrawerOpen && isFabOpen) { + // close drawer first + super.onBackPressed(); + } else if(isDrawerOpen && !isFabOpen) { + // close drawer + super.onBackPressed(); + } else if (!isDrawerOpen && isFabOpen) { + // close fab + getListOfFilesFragment().getFabMain().collapse(); + } else { + // all closed OCFileListFragment listOfFiles = getListOfFilesFragment(); if (mDualPane || getSecondFragment() == null) { OCFile currentDir = getCurrentDir(); @@ -793,8 +857,20 @@ public class FileDisplayActivity extends HookActivity setFile(listOfFiles.getCurrentFile()); } cleanSecondFragment(); + changeGridIcon(); + } + } + + private void changeGridIcon(){ + MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view); + if (DisplayUtils.isGridView(getFile(), getStorageManager())){ + menuItem.setTitle(getApplicationContext().getString(R.string.action_switch_list_view)); + menuItem.setIcon(ContextCompat.getDrawable(getApplicationContext(), + R.drawable.ic_view_list)); } else { - super.onBackPressed(); + menuItem.setTitle(getApplicationContext().getString(R.string.action_switch_grid_view)); + menuItem.setIcon(ContextCompat.getDrawable(getApplicationContext(), + R.drawable.ic_view_module)); } } @@ -873,6 +949,14 @@ public class FileDisplayActivity extends HookActivity Log_OC.v(TAG, "onPause() end"); } + public boolean isFabOpen() { + if(getListOfFilesFragment() != null && getListOfFilesFragment().getFabMain() != null && getListOfFilesFragment().getFabMain().isExpanded()) { + return true; + } else { + return false; + } + } + private class SyncBroadcastReceiver extends BroadcastReceiver { @@ -1195,6 +1279,15 @@ public class FileDisplayActivity extends HookActivity cleanSecondFragment(); // Sync Folder startSyncFolderOperation(directory, false); + + MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view); + + changeGridIcon(); + if (DisplayUtils.isGridView(directory, getStorageManager())){ + switchToGridView(); + } else { + switchToListView(); + } } /** @@ -1792,6 +1885,13 @@ public class FileDisplayActivity extends HookActivity private void sortByName(boolean ascending) { getListOfFilesFragment().sortByName(ascending); } + private boolean isGridView(){ return getListOfFilesFragment().isGridView(); } + private void switchToGridView() { + getListOfFilesFragment().switchToGridView(); + } + private void switchToListView() { + getListOfFilesFragment().switchToListView(); + } public void allFilesOption() { browseToRoot(); diff --git a/src/com/owncloud/android/ui/activity/FolderPickerActivity.java b/src/com/owncloud/android/ui/activity/FolderPickerActivity.java index 4b558f00..c3b96dae 100644 --- a/src/com/owncloud/android/ui/activity/FolderPickerActivity.java +++ b/src/com/owncloud/android/ui/activity/FolderPickerActivity.java @@ -155,6 +155,7 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C Bundle args = new Bundle(); args.putBoolean(OCFileListFragment.ARG_JUST_FOLDERS, true); args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, false); + args.putBoolean(OCFileListFragment.ARG_HIDE_FAB, true); listOfFiles.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.fragment_container, listOfFiles, TAG_LIST_OF_FOLDERS); @@ -263,7 +264,6 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); - menu.findItem(R.id.action_upload).setVisible(false); menu.findItem(R.id.action_sort).setVisible(false); return true; } diff --git a/src/com/owncloud/android/ui/activity/Preferences.java b/src/com/owncloud/android/ui/activity/Preferences.java index e1c5c10d..d980b977 100644 --- a/src/com/owncloud/android/ui/activity/Preferences.java +++ b/src/com/owncloud/android/ui/activity/Preferences.java @@ -457,8 +457,8 @@ public class Preferences extends PreferenceActivity mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPathWiFi); mPrefInstantUploadCategory.addPreference(mPrefInstantUploadPath); } else { - mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi); - mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath); +// mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPathWiFi); +// mPrefInstantUploadCategory.removePreference(mPrefInstantUploadPath); } } @@ -467,8 +467,8 @@ public class Preferences extends PreferenceActivity mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPathWiFi); mPrefInstantUploadCategory.addPreference(mPrefInstantVideoUploadPath); } else { - mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi); - mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath); +// mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPathWiFi); +// mPrefInstantUploadCategory.removePreference(mPrefInstantVideoUploadPath); } } @@ -805,7 +805,7 @@ public class Preferences extends PreferenceActivity SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); mUploadVideoPath = appPrefs.getString("instant_video_upload_path", getString(R.string.instant_upload_path)); - mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath); +// mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath); } /** diff --git a/src/com/owncloud/android/ui/activity/Uploader.java b/src/com/owncloud/android/ui/activity/Uploader.java index d221bc92..83b029f7 100644 --- a/src/com/owncloud/android/ui/activity/Uploader.java +++ b/src/com/owncloud/android/ui/activity/Uploader.java @@ -658,7 +658,6 @@ public class Uploader extends FileActivity public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); - menu.findItem(R.id.action_upload).setVisible(false); menu.findItem(R.id.action_sort).setVisible(false); menu.findItem(R.id.action_sync_account).setVisible(false); return true; diff --git a/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java b/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java index 0f2536f5..ab80aef2 100644 --- a/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java +++ b/src/com/owncloud/android/ui/adapter/DiskLruImageCache.java @@ -120,10 +120,10 @@ public class DiskLruImageCache { } final InputStream in = snapshot.getInputStream( 0 ); if ( in != null ) { - final BufferedInputStream buffIn = + final BufferedInputStream buffIn = new BufferedInputStream( in, IO_BUFFER_SIZE ); - bitmap = BitmapFactory.decodeStream( buffIn ); - } + bitmap = BitmapFactory.decodeStream( buffIn ); + } } catch ( IOException e ) { e.printStackTrace(); } finally { diff --git a/src/com/owncloud/android/ui/adapter/DiskLruImageCacheFileProvider.java b/src/com/owncloud/android/ui/adapter/DiskLruImageCacheFileProvider.java new file mode 100644 index 00000000..fe3f6ea2 --- /dev/null +++ b/src/com/owncloud/android/ui/adapter/DiskLruImageCacheFileProvider.java @@ -0,0 +1,121 @@ +/** + * ownCloud Android client application + * + * Copyright (C) 2015 Tobias Kaminsky + * 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 . + * + * adapted from: http://stephendnicholas.com/archives/974 + * + */ + +package com.owncloud.android.ui.adapter; + +import android.accounts.Account; +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.UriMatcher; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.ParcelFileDescriptor; + +import com.owncloud.android.MainApp; +import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.datamodel.ThumbnailsCacheManager; +import com.owncloud.android.lib.common.utils.Log_OC; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +public class DiskLruImageCacheFileProvider extends ContentProvider { + private static String TAG = FileDataStorageManager.class.getSimpleName(); + + public static final String AUTHORITY = "com.owncloud.imageCache.provider"; + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + Account account = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext()); + FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(account, + MainApp.getAppContext().getContentResolver()); + + OCFile ocFile = fileDataStorageManager.getFileByPath(uri.getPath()); + + Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache( + String.valueOf("r" + ocFile.getRemoteId())); + + // create a file to write bitmap data + File f = new File(MainApp.getAppContext().getCacheDir(), ocFile.getFileName()); + try { + f.createNewFile(); + + //Convert bitmap to byte array + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bos); + byte[] bitmapdata = bos.toByteArray(); + + //write the bytes in file + FileOutputStream fos = null; + try { + fos = new FileOutputStream(f); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + fos.write(bitmapdata); + fos.flush(); + fos.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + + return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY); + } + + + @Override + public boolean onCreate() { + return true; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return null; + } + + @Override + public String getType(Uri uri) { + return null; + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + return null; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } +} diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 51883670..410eeeda 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java @@ -322,7 +322,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { task ); fileIcon.setImageDrawable(asyncDrawable); - task.execute(file); + task.execute(file, true); } } @@ -490,4 +490,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter { public void setGridMode(boolean gridMode) { mGridMode = gridMode; } + + public boolean isGridMode() { + return mGridMode; + } } diff --git a/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java b/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java index 24015d08..6d93ab33 100644 --- a/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java +++ b/src/com/owncloud/android/ui/fragment/ExtendedListFragment.java @@ -22,6 +22,7 @@ package com.owncloud.android.ui.fragment; import java.util.ArrayList; +import android.app.Activity; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -36,12 +37,16 @@ import android.widget.GridView; import android.widget.ListAdapter; import android.widget.ListView; import android.widget.TextView; +import android.widget.Toast; +import com.getbase.floatingactionbutton.FloatingActionButton; +import com.getbase.floatingactionbutton.FloatingActionsMenu; import com.owncloud.android.R; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.ExtendedListView; import com.owncloud.android.ui.activity.OnEnforceableRefreshListener; import com.owncloud.android.ui.adapter.FileListListAdapter; +import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import third_parties.in.srain.cube.GridViewWithHeaderAndFooter; @@ -64,6 +69,11 @@ public class ExtendedListFragment extends Fragment private SwipeRefreshLayout mRefreshGridLayout; private SwipeRefreshLayout mRefreshEmptyLayout; private TextView mEmptyListMessage; + + private FloatingActionsMenu fabMain; + private FloatingActionButton fabUpload; + private FloatingActionButton fabMkdir; + private FloatingActionButton fabUploadFromApp; // Save the state of the scroll in browsing private ArrayList mIndexes; @@ -96,8 +106,23 @@ public class ExtendedListFragment extends Fragment return mCurrentListView; } + public FloatingActionButton getFabUpload() { + return fabUpload; + } + + public FloatingActionButton getFabUploadFromApp() { + return fabUploadFromApp; + } + + public FloatingActionButton getFabMkdir() { + return fabMkdir; + } + + public FloatingActionsMenu getFabMain() { + return fabMain; + } - protected void switchToGridView() { + public void switchToGridView() { if ((mCurrentListView == mListView)) { mListView.setAdapter(null); @@ -112,8 +137,8 @@ public class ExtendedListFragment extends Fragment mCurrentListView = mGridView; } } - - protected void switchToListView() { + + public void switchToListView() { if (mCurrentListView == mGridView) { mGridView.setAdapter(null); mRefreshGridLayout.setVisibility(View.GONE); @@ -127,6 +152,13 @@ public class ExtendedListFragment extends Fragment mCurrentListView = mListView; } } + + public boolean isGridView(){ + if (mAdapter instanceof FileListListAdapter) { + return ((FileListListAdapter) mAdapter).isGridMode(); + } + return false; + } @Override @@ -171,6 +203,11 @@ public class ExtendedListFragment extends Fragment mCurrentListView = mListView; // list as default + fabMain = (FloatingActionsMenu) v.findViewById(R.id.fab_main); + fabUpload = (FloatingActionButton) v.findViewById(R.id.fab_upload); + fabMkdir = (FloatingActionButton) v.findViewById(R.id.fab_mkdir); + fabUploadFromApp = (FloatingActionButton) v.findViewById(R.id.fab_upload_from_app); + return v; } @@ -320,6 +357,23 @@ public class ExtendedListFragment extends Fragment } /** + * Disables FAB. + * + * Sets the 'visibility' state of the FAB contained in the fragment. + * + * When 'false' is set, FAB visibility is set to View.GONE programatically, + * + * @param enabled Desired visibility for the FAB. + */ + public void setFabEnabled(boolean enabled) { + if(enabled) { + fabMain.setVisibility(View.VISIBLE); + } else { + fabMain.setVisibility(View.GONE); + } + } + + /** * Set message for empty list view */ public void setMessageForEmptyList(String message) { diff --git a/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java b/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java index df5b34aa..5441aead 100644 --- a/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/LocalFileListFragment.java @@ -54,7 +54,6 @@ public class LocalFileListFragment extends ExtendedListFragment { /** Adapter to connect the data from the directory with the View object */ private LocalFileListAdapter mAdapter = null; - /** * {@inheritDoc} */ @@ -79,6 +78,7 @@ public class LocalFileListFragment extends ExtendedListFragment { View v = super.onCreateView(inflater, container, savedInstanceState); setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); setSwipeEnabled(false); // Disable pull-to-refresh + setFabEnabled(false); // Disable FAB setMessageForEmptyList(getString(R.string.local_file_list_empty)); Log_OC.i(TAG, "onCreateView() end"); return v; diff --git a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java index 02bd845d..5a40b29c 100644 --- a/src/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/src/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -24,7 +24,10 @@ package com.owncloud.android.ui.fragment; import android.app.Activity; import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v4.widget.SwipeRefreshLayout; import android.view.ContextMenu; import android.view.Menu; @@ -34,6 +37,8 @@ import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.PopupMenu; +import android.widget.TextView; +import android.widget.Toast; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; @@ -46,13 +51,17 @@ import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.activity.FileDisplayActivity; import com.owncloud.android.ui.activity.FolderPickerActivity; import com.owncloud.android.ui.activity.OnEnforceableRefreshListener; +import com.owncloud.android.ui.activity.UploadFilesActivity; import com.owncloud.android.ui.adapter.FileListListAdapter; import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; +import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.FileActionsDialogFragment; import com.owncloud.android.ui.dialog.RemoveFileDialogFragment; import com.owncloud.android.ui.dialog.RenameFileDialogFragment; +import com.owncloud.android.ui.dialog.UploadSourceDialogFragment; import com.owncloud.android.ui.preview.PreviewImageFragment; import com.owncloud.android.ui.preview.PreviewMediaFragment; +import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.ui.preview.PreviewTextFragment; @@ -72,8 +81,12 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi public final static String ARG_JUST_FOLDERS = MY_PACKAGE + ".JUST_FOLDERS"; public final static String ARG_ALLOW_CONTEXTUAL_ACTIONS = MY_PACKAGE + ".ALLOW_CONTEXTUAL"; + public final static String ARG_HIDE_FAB = MY_PACKAGE + ".HIDE_FAB"; private static final String KEY_FILE = MY_PACKAGE + ".extra.FILE"; + private static final String KEY_FAB_EVER_CLICKED = "FAB_EVER_CLICKED"; + + private static String DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"; private FileFragment.ContainerActivity mContainerActivity; @@ -82,8 +95,8 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi private boolean mJustFolders; private OCFile mTargetFile; - - + + private boolean miniFabClicked = false; /** * {@inheritDoc} @@ -144,8 +157,164 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi setListAdapter(mAdapter); registerLongClickListener(); + + boolean hideFab = (args != null) && args.getBoolean(ARG_HIDE_FAB, false); + if (hideFab) { + setFabEnabled(false); + } else { + setFabEnabled(true); + registerFabListeners(); + + // detect if a mini FAB has ever been clicked + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); + if(prefs.getLong(KEY_FAB_EVER_CLICKED, 0) > 0) { + miniFabClicked = true; + } + + // add labels to the min FABs when none of them has ever been clicked on + if(!miniFabClicked) { + setFabLabels(); + } else { + removeFabLabels(); + } + } } + /** + * adds labels to all mini FABs. + */ + private void setFabLabels() { + getFabUpload().setTitle(getResources().getString(R.string.actionbar_upload)); + getFabMkdir().setTitle(getResources().getString(R.string.actionbar_mkdir)); + getFabUploadFromApp().setTitle(getResources().getString(R.string.actionbar_upload_from_apps)); + } + + /** + * registers all listeners on all mini FABs. + */ + private void registerFabListeners() { + registerFabUploadListeners(); + registerFabMkDirListeners(); + registerFabUploadFromAppListeners(); + } + + /** + * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener} + * on the Upload mini FAB for the linked action and {@link Toast} showing the underlying action. + */ + private void registerFabUploadListeners() { + getFabUpload().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent action = new Intent(getActivity(), UploadFilesActivity.class); + action.putExtra( + UploadFilesActivity.EXTRA_ACCOUNT, + ((FileActivity) getActivity()).getAccount() + ); + getActivity().startActivityForResult(action, UploadSourceDialogFragment.ACTION_SELECT_MULTIPLE_FILES); + getFabMain().collapse(); + recordMiniFabClick(); + } + }); + + getFabUpload().setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + Toast.makeText(getActivity(), R.string.actionbar_upload, Toast.LENGTH_SHORT).show(); + return true; + } + }); + } + + /** + * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener} + * on the 'Create Dir' mini FAB for the linked action and {@link Toast} showing the underlying action. + */ + private void registerFabMkDirListeners() { + getFabMkdir().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + CreateFolderDialogFragment dialog = + CreateFolderDialogFragment.newInstance(mFile); + dialog.show(getActivity().getSupportFragmentManager(), FileDisplayActivity.DIALOG_CREATE_FOLDER); + getFabMain().collapse(); + recordMiniFabClick(); + } + }); + + getFabMkdir().setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + Toast.makeText(getActivity(), R.string.actionbar_mkdir, Toast.LENGTH_SHORT).show(); + return true; + } + }); + } + + /** + * registers {@link android.view.View.OnClickListener} and {@link android.view.View.OnLongClickListener} + * on the Upload from App mini FAB for the linked action and {@link Toast} showing the underlying action. + */ + private void registerFabUploadFromAppListeners() { + getFabUploadFromApp().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent action = new Intent(Intent.ACTION_GET_CONTENT); + action = action.setType("*/*").addCategory(Intent.CATEGORY_OPENABLE); + + //Intent.EXTRA_ALLOW_MULTIPLE is only supported on api level 18+, Jelly Bean + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + action.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + } + + getActivity().startActivityForResult( + Intent.createChooser(action, getString(R.string.upload_chooser_title)), + UploadSourceDialogFragment.ACTION_SELECT_CONTENT_FROM_APPS + ); + getFabMain().collapse(); + recordMiniFabClick(); + } + }); + + getFabUploadFromApp().setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + Toast.makeText(getActivity(), + R.string.actionbar_upload_from_apps, + Toast.LENGTH_SHORT).show(); + return true; + } + }); + } + + /** + * records a click on a mini FAB and thus: + *
    + *
  1. persists the click fact
  2. + *
  3. removes the mini FAB labels
  4. + *
+ */ + private void recordMiniFabClick() { + // only record if it hasn't been done already at some other time + if(!miniFabClicked) { + final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); + sp.edit().putLong(KEY_FAB_EVER_CLICKED, 1).commit(); + miniFabClicked = true; + } + } + + /** + * removes the labels on all known min FABs. + */ + private void removeFabLabels() { + getFabUpload().setTitle(null); + getFabMkdir().setTitle(null); + getFabUploadFromApp().setTitle(null); + ((TextView) getFabUpload().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE); + ((TextView) getFabMkdir().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE); + ((TextView) getFabUploadFromApp().getTag(com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE); + } + private void registerLongClickListener() { getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { public boolean onItemLongClick(AdapterView arg0, View v, @@ -156,7 +325,6 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi }); } - private void showFileAction(int fileIndex) { Bundle args = getArguments(); PopupMenu pm = new PopupMenu(getActivity(),null); @@ -210,11 +378,11 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi /** * Call this, when the user presses the up button. - * - * Tries to move up the current folder one level. If the parent folder was removed from the - * database, it continues browsing up until finding an existing folders. - *

- * return Count of folder levels browsed up. + *

+ * Tries to move up the current folder one level. If the parent folder was removed from the + * database, it continues browsing up until finding an existing folders. + *

+ * @return Count of folder levels browsed up. */ public int onBrowseUp() { OCFile parentDir = null; @@ -281,12 +449,8 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi } else { mContainerActivity.getFileOperationsHelper().openFile(file); } - - } else { - // automatic download, preview on finish - ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file); + } - } } else { @@ -331,6 +495,9 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi item.setEnabled(false); } } + +// String.format(mContext.getString(R.string.subject_token), +// getClient().getCredentials().getUsername(), file.getFileName())); } } @@ -521,7 +688,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi OwnCloudVersion version = AccountUtils.getServerVersion( ((FileActivity)mContainerActivity).getAccount()); if (version != null && version.supportsRemoteThumbnails() && - imagesCount > 0 && imagesCount == filesCount) { + DisplayUtils.isGridView(mFile, mContainerActivity.getStorageManager())) { switchToGridView(); registerLongClickListener(); } else { diff --git a/src/com/owncloud/android/ui/preview/ImageViewCustom.java b/src/com/owncloud/android/ui/preview/ImageViewCustom.java index 69182d6e..5bb24e7b 100644 --- a/src/com/owncloud/android/ui/preview/ImageViewCustom.java +++ b/src/com/owncloud/android/ui/preview/ImageViewCustom.java @@ -4,12 +4,16 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Movie; import android.os.Build; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; -import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.datamodel.OCFile; + +import java.io.FileInputStream; +import java.io.InputStream; public class ImageViewCustom extends ImageView { @@ -23,7 +27,12 @@ public class ImageViewCustom extends ImageView { private int mBitmapHeight; private int mBitmapWidth; - + private Movie mGifMovie; + private int mMovieWidth, mMovieHeight; + private long mMovieDuration; + private long mMovieRunDuration; + private long mLastTick; + public ImageViewCustom(Context context) { super(context); } @@ -39,18 +48,58 @@ public class ImageViewCustom extends ImageView { @SuppressLint("NewApi") @Override protected void onDraw(Canvas canvas) { - if(IS_ICS_OR_HIGHER && checkIfMaximumBitmapExceed(canvas) || IS_VERSION_BUGGY_ON_RECYCLES ) { // Software type is set with two targets: // 1. prevent that bitmaps larger than maximum textures allowed are shown as black views in devices // with LAYER_TYPE_HARDWARE enabled by default; - // 2. grant that bitmaps are correctly dellocated from memory in versions suffering the bug fixed in + // 2. grant that bitmaps are correctly de-allocated from memory in versions suffering the bug fixed in // https://android.googlesource.com/platform/frameworks/base/+/034de6b1ec561797a2422314e6ef03e3cd3e08e0; // setLayerType(View.LAYER_TYPE_SOFTWARE, null); } - super.onDraw(canvas); + if(mGifMovie == null){ + super.onDraw(canvas); + } else { + long nowTick = android.os.SystemClock.uptimeMillis(); + if (mLastTick == 0) { + mMovieRunDuration = 0; + } else { + mMovieRunDuration += nowTick - mLastTick; + if(mMovieRunDuration > mMovieDuration){ + mMovieRunDuration = 0; + } + } + + mGifMovie.setTime((int) mMovieRunDuration); + + float scale; + if(mGifMovie.height() > getHeight() || mGifMovie.width() > getWidth()) { + scale = (1f / Math.min(canvas.getHeight() / mGifMovie.height(), + canvas.getWidth() / mGifMovie.width())) + 0.25f; + } else { + scale = Math.min(canvas.getHeight() / mGifMovie.height(), + canvas.getWidth() / mGifMovie.width()); + } + + canvas.scale(scale, scale); + canvas.translate(((float) getWidth() / scale - (float) mGifMovie.width()) / 2f, + ((float) getHeight() / scale - (float) mGifMovie.height()) /2f); + + mGifMovie.draw(canvas, 0, 0); + + mLastTick = nowTick; + invalidate(); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (mGifMovie == null){ + setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); + } else { + setMeasuredDimension(mMovieWidth, mMovieHeight); + } } /** @@ -60,13 +109,9 @@ public class ImageViewCustom extends ImageView { */ @SuppressLint("NewApi") private boolean checkIfMaximumBitmapExceed(Canvas canvas) { - Log_OC.v(TAG, "Canvas maximum: " + canvas.getMaximumBitmapWidth() + " - " + canvas.getMaximumBitmapHeight()); - if (mBitmapWidth > canvas.getMaximumBitmapWidth() - || mBitmapHeight > canvas.getMaximumBitmapHeight()) { - return true; - } - - return false; + return mBitmapWidth > canvas.getMaximumBitmapWidth() + || mBitmapHeight > canvas.getMaximumBitmapHeight(); + } @Override @@ -74,10 +119,25 @@ public class ImageViewCustom extends ImageView { * Keeps the size of the bitmap cached in member variables for faster access in {@link #onDraw(Canvas)} , * but without keeping another reference to the {@link Bitmap} */ - public void setImageBitmap (Bitmap bm) { + public void setImageBitmap(Bitmap bm) { mBitmapWidth = bm.getWidth(); mBitmapHeight = bm.getHeight(); super.setImageBitmap(bm); } + public void setGifImage(OCFile file){ + try { + InputStream gifInputStream = new FileInputStream(file.getStoragePath()); + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + setFocusable(true); + + mGifMovie = Movie.decodeStream(gifInputStream); + mMovieWidth = mGifMovie.width(); + mMovieHeight = mGifMovie.height(); + mMovieDuration = mGifMovie.duration(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } diff --git a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java index 5cbacfcf..4b622cbf 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageActivity.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageActivity.java @@ -430,12 +430,7 @@ public class PreviewImageActivity extends FileActivity implements OCFile currentFile = mPreviewImagePagerAdapter.getFileAt(position); getSupportActionBar().setTitle(currentFile.getFileName()); mDrawerToggle.setDrawerIndicatorEnabled(false); - if (!currentFile.isDown()) { - if (!mPreviewImagePagerAdapter.pendingErrorAt(position)) { - requestForDownload(currentFile); - } - } - + // Call to reset image zoom to initial state ((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom(); } diff --git a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java index e61e3355..c45f76cf 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImageFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewImageFragment.java @@ -41,8 +41,10 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; +import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.files.FileMenuFilter; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.dialog.ConfirmationDialogFragment; @@ -74,6 +76,8 @@ public class PreviewImageFragment extends FileFragment { private TextView mMessageView; private ProgressBar mProgressWheel; + private Boolean mShowResizedImage = false; + public Bitmap mBitmap = null; private static final String TAG = PreviewImageFragment.class.getSimpleName(); @@ -97,8 +101,10 @@ public class PreviewImageFragment extends FileFragment { * {@link FragmentStatePagerAdapter} * ; TODO better solution */ - public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState){ + public static PreviewImageFragment newInstance(OCFile imageFile, boolean ignoreFirstSavedState, + boolean showResizedImage){ PreviewImageFragment frag = new PreviewImageFragment(); + frag.mShowResizedImage = showResizedImage; Bundle args = new Bundle(); args.putParcelable(ARG_FILE, imageFile); args.putBoolean(ARG_IGNORE_FIRST, ignoreFirstSavedState); @@ -179,9 +185,6 @@ public class PreviewImageFragment extends FileFragment { if (getFile() == null) { throw new IllegalStateException("Instanced with a NULL OCFile"); } - if (!getFile().isDown()) { - throw new IllegalStateException("There is no local file to preview"); - } } @@ -199,10 +202,43 @@ public class PreviewImageFragment extends FileFragment { public void onStart() { super.onStart(); if (getFile() != null) { - mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel); - //mLoadBitmapTask.execute(new String[]{getFile().getStoragePath()}); -// mLoadBitmapTask.execute(getFile().getStoragePath()); - mLoadBitmapTask.execute(getFile()); + mImageView.setTag(getFile().getFileId()); + + if (mShowResizedImage){ + Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache( + String.valueOf("r" + getFile().getRemoteId()) + ); + + if (thumbnail != null && !getFile().needsUpdateThumbnail()){ + mProgressWheel.setVisibility(View.GONE); + mImageView.setImageBitmap(thumbnail); + mImageView.setVisibility(View.VISIBLE); + mBitmap = thumbnail; + } else { + // generate new Thumbnail + if (ThumbnailsCacheManager.cancelPotentialWork(getFile(), mImageView)) { + final ThumbnailsCacheManager.ThumbnailGenerationTask task = + new ThumbnailsCacheManager.ThumbnailGenerationTask( + mImageView, mContainerActivity.getStorageManager(), + mContainerActivity.getStorageManager().getAccount(), + mProgressWheel); + if (thumbnail == null) { + thumbnail = ThumbnailsCacheManager.mDefaultImg; + } + final ThumbnailsCacheManager.AsyncDrawable asyncDrawable = + new ThumbnailsCacheManager.AsyncDrawable( + MainApp.getAppContext().getResources(), + thumbnail, + task + ); + mImageView.setImageDrawable(asyncDrawable); + task.execute(getFile(), false); + } + } + } else { + mLoadBitmapTask = new LoadBitmapTask(mImageView, mMessageView, mProgressWheel); + mLoadBitmapTask.execute(getFile()); + } } } @@ -307,8 +343,13 @@ public class PreviewImageFragment extends FileFragment { return true; } case R.id.action_send_file: { - mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); - return true; + if (getFile().isImage() && !getFile().isDown()){ + mContainerActivity.getFileOperationsHelper().sendCachedImage(getFile()); + return true; + } else { + mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile()); + return true; + } } case R.id.action_sync_file: { mContainerActivity.getFileOperationsHelper().syncFile(getFile()); @@ -509,7 +550,12 @@ public class PreviewImageFragment extends FileFragment { imageView.setBackground(backrepeat); } - imageView.setImageBitmap(bitmap); + if (result.ocFile.getMimetype().equalsIgnoreCase("image/gif")){ + imageView.setGifImage(result.ocFile); + } else { + imageView.setImageBitmap(bitmap); + } + imageView.setVisibility(View.VISIBLE); mBitmap = bitmap; // needs to be kept for recycling when not useful } diff --git a/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java b/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java index dda7dda2..d6ea3479 100644 --- a/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java +++ b/src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java @@ -27,6 +27,7 @@ import java.util.Set; import java.util.Vector; import android.accounts.Account; +import android.graphics.Bitmap; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; @@ -34,6 +35,8 @@ import android.view.ViewGroup; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.datamodel.ThumbnailsCacheManager; +import com.owncloud.android.ui.adapter.FileListListAdapter; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.utils.FileStorageUtils; @@ -104,17 +107,15 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter { Fragment fragment = null; if (file.isDown()) { fragment = PreviewImageFragment.newInstance(file, - mObsoletePositions.contains(Integer.valueOf(i))); + mObsoletePositions.contains(Integer.valueOf(i)), false); } else if (mDownloadErrors.contains(Integer.valueOf(i))) { fragment = FileDownloadFragment.newInstance(file, mAccount, true); ((FileDownloadFragment)fragment).setError(true); mDownloadErrors.remove(Integer.valueOf(i)); - } else { - fragment = FileDownloadFragment.newInstance( - file, mAccount, mObsoletePositions.contains(Integer.valueOf(i)) - ); + fragment = PreviewImageFragment.newInstance(file, + mObsoletePositions.contains(Integer.valueOf(i)), true); } mObsoletePositions.remove(Integer.valueOf(i)); return fragment; diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java index 46c66737..f63d7ec4 100644 --- a/src/com/owncloud/android/utils/DisplayUtils.java +++ b/src/com/owncloud/android/utils/DisplayUtils.java @@ -22,9 +22,21 @@ package com.owncloud.android.utils; +import java.io.File; +import java.net.IDN; +import java.text.DateFormat; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.Vector; + import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.Point; import android.graphics.PorterDuff; import android.os.Build; @@ -35,6 +47,7 @@ import android.widget.SeekBar; import com.owncloud.android.MainApp; import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import java.math.BigDecimal; @@ -214,8 +227,17 @@ public class DisplayUtils { dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags); } } - - return dateString.toString().split(",")[0]; + + String[] parts = dateString.toString().split(","); + if (parts.length == 2) { + if (parts[1].contains(":") && !parts[0].contains(":")) { + return parts[0]; + } else if (parts[0].contains(":") && !parts[1].contains(":")) { + return parts[1]; + } + } + //dateString contains unexpected format. use localized, absolute date. + return DisplayUtils.unixTimeToHumanReadable(time); } /** @@ -252,6 +274,67 @@ public class DisplayUtils { } /** + * Determines if user set folder to grid or list view. If folder is not set itself, + * it finds a parent that is set (at least root is set). + * @param file + * @param storageManager + * @return + */ + public static boolean isGridView(OCFile file, FileDataStorageManager storageManager){ + if (file != null) { + OCFile fileToTest = file; + OCFile parentDir = null; + String parentPath = null; + + SharedPreferences setting = MainApp.getAppContext().getSharedPreferences( + "viewMode", Context.MODE_PRIVATE); + + if (setting.contains(fileToTest.getRemoteId())) { + return setting.getBoolean(fileToTest.getRemoteId(), false); + } else { + do { + if (fileToTest.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) { + parentPath = new File(fileToTest.getRemotePath()).getParent(); + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : + parentPath + OCFile.PATH_SEPARATOR; + parentDir = storageManager.getFileByPath(parentPath); + } else { + parentDir = storageManager.getFileByPath(OCFile.ROOT_PATH); + } + + while (parentDir == null) { + parentPath = new File(parentPath).getParent(); + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : + parentPath + OCFile.PATH_SEPARATOR; + parentDir = storageManager.getFileByPath(parentPath); + } + fileToTest = parentDir; + } while (endWhile(parentDir, setting)); + return setting.getBoolean(fileToTest.getRemoteId(), false); + } + } else { + return false; + } + } + + private static boolean endWhile(OCFile parentDir, SharedPreferences setting) { + if (parentDir.getRemotePath().compareToIgnoreCase(OCFile.ROOT_PATH) == 0) { + return false; + } else { + return !setting.contains(parentDir.getRemoteId()); + } + } + + public static void setViewMode(OCFile file, boolean setGrid){ + SharedPreferences setting = MainApp.getAppContext().getSharedPreferences( + "viewMode", Context.MODE_PRIVATE); + + SharedPreferences.Editor editor = setting.edit(); + editor.putBoolean(file.getRemoteId(), setGrid); + editor.commit(); + } + + /** * sets the coloring of the given progress bar to color_accent. * * @param progressBar the progress bar to be colored