Merge remote-tracking branch 'remotes/upstream/switchOfflineFiles' into beta
authortobiasKaminsky <tobias@kaminsky.me>
Sat, 21 Nov 2015 08:33:26 +0000 (09:33 +0100)
committertobiasKaminsky <tobias@kaminsky.me>
Sat, 21 Nov 2015 08:33:26 +0000 (09:33 +0100)
325 files changed:
.gitignore
.travis.yml
AndroidManifest.xml
CHANGELOG.md
README.md
SETUP.md
THIRD_PARTY.txt
apks/latest [new file with mode: 0644]
apks/latest.apk [new file with mode: 0644]
apks/owncloud-beta-2015-10-26.apk [new file with mode: 0644]
apks/owncloud-beta-2015-10-29.apk [new file with mode: 0644]
apks/owncloud-beta-2015-10-30.apk [new file with mode: 0644]
apks/owncloud-beta-2015-10-31-10-00-00.apk [new file with mode: 0644]
apks/owncloud-beta-2015-10-31.apk [new file with mode: 0644]
apks/owncloud-beta-2015-11-01.apk [new file with mode: 0644]
apks/owncloud-beta-2015-11-02.apk [new file with mode: 0644]
apks/owncloud-beta-20151105.apk [new file with mode: 0644]
apks/owncloud-beta-20151109.apk [new file with mode: 0644]
apks/owncloud-beta-20151113.apk [new file with mode: 0644]
apks/owncloud-beta-20151118.apk [new file with mode: 0644]
apks/owncloud-beta-20151120.apk [new file with mode: 0644]
build.gradle
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/.classpath [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/AndroidManifest.xml [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/R.txt [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/aapt/AndroidManifest.xml [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/annotations.zip [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/build.xml [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/jars/classes.jar [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/libs/classes.jar [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/proguard.txt [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/project.properties [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_mini.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-hdpi-v4/fab_bg_normal.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_mini.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-mdpi-v4/fab_bg_normal.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_mini.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xhdpi-v4/fab_bg_normal.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_mini.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxhdpi-v4/fab_bg_normal.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_mini.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/drawable-xxxhdpi-v4/fab_bg_normal.png [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/res/values/values.xml [new file with mode: 0644]
libs/com-getbase-floatingactionbutton-1-10-1-exploded-aar/src/.readme [new file with mode: 0644]
oc_jb_workaround/build.gradle
owncloud-android-library
project.properties
res/drawable-hdpi-v9/ic_action_download.png [deleted file]
res/drawable-hdpi-v9/ic_action_refresh.png [deleted file]
res/drawable-hdpi-v9/ic_action_settings.png [deleted file]
res/drawable-hdpi/ic_checkbox_blank_outline.png [new file with mode: 0644]
res/drawable-hdpi/ic_checkbox_marked.png [new file with mode: 0644]
res/drawable-hdpi/ic_import.png [new file with mode: 0644]
res/drawable-hdpi/ic_play_arrow.png [new file with mode: 0644]
res/drawable-hdpi/ic_view_list.png [new file with mode: 0644]
res/drawable-hdpi/ic_view_module.png [new file with mode: 0644]
res/drawable-hdpi/icon.png
res/drawable-hdpi/shared_via_link.png [new file with mode: 0644]
res/drawable-hdpi/shared_via_users.png [new file with mode: 0644]
res/drawable-hdpi/shared_with_me.png [deleted file]
res/drawable-hdpi/sharedlink.png [deleted file]
res/drawable-hdpi/view_play.png [new file with mode: 0644]
res/drawable-mdpi-v9/ic_action_download.png [deleted file]
res/drawable-mdpi-v9/ic_action_refresh.png [deleted file]
res/drawable-mdpi-v9/ic_action_settings.png [deleted file]
res/drawable-mdpi/ic_checkbox_blank_outline.png [new file with mode: 0644]
res/drawable-mdpi/ic_checkbox_marked.png [new file with mode: 0644]
res/drawable-mdpi/ic_import.png [new file with mode: 0644]
res/drawable-mdpi/ic_play_arrow.png [new file with mode: 0644]
res/drawable-mdpi/ic_view_list.png [new file with mode: 0644]
res/drawable-mdpi/ic_view_module.png [new file with mode: 0644]
res/drawable-mdpi/icon.png
res/drawable-mdpi/shared_via_link.png [new file with mode: 0644]
res/drawable-mdpi/shared_via_users.png [new file with mode: 0644]
res/drawable-mdpi/shared_with_me.png [deleted file]
res/drawable-mdpi/sharedlink.png [deleted file]
res/drawable-mdpi/view_play.png [new file with mode: 0644]
res/drawable-xhdpi/ic_checkbox_blank_outline.png [new file with mode: 0644]
res/drawable-xhdpi/ic_checkbox_marked.png [new file with mode: 0644]
res/drawable-xhdpi/ic_import.png [new file with mode: 0644]
res/drawable-xhdpi/ic_play_arrow.png [new file with mode: 0644]
res/drawable-xhdpi/ic_view_list.png [new file with mode: 0644]
res/drawable-xhdpi/ic_view_module.png [new file with mode: 0644]
res/drawable-xhdpi/icon.png
res/drawable-xhdpi/shared_via_link.png [new file with mode: 0644]
res/drawable-xhdpi/shared_via_users.png [new file with mode: 0644]
res/drawable-xhdpi/shared_with_me.png [deleted file]
res/drawable-xhdpi/sharedlink.png [deleted file]
res/drawable-xhdpi/view_play.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_checkbox_blank_outline.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_checkbox_marked.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_import.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_play_arrow.png [new file with mode: 0644]
res/drawable-xxhdpi/ic_sort_variant.png [new file with mode: 0644]
res/drawable-xxhdpi/icon.png [new file with mode: 0644]
res/drawable-xxhdpi/view_play.png [new file with mode: 0644]
res/drawable-xxxhdpi/icon.png [new file with mode: 0644]
res/drawable-xxxhdpi/view_play.png [new file with mode: 0644]
res/drawable/conflict_file_indicator.png [new file with mode: 0644]
res/drawable/fab_label_background.xml [new file with mode: 0644]
res/drawable/synchronizing_file_indicator.png [new file with mode: 0644]
res/layout-land/account_setup.xml
res/layout-v14/generic_explanation.xml
res/layout/account_setup.xml
res/layout/drawer.xml
res/layout/drawer_list_item.xml
res/layout/drawer_radiobutton.xml
res/layout/error_send.xml [new file with mode: 0644]
res/layout/file_details_fragment.xml
res/layout/file_preview.xml
res/layout/files_folder_picker.xml
res/layout/generic_explanation.xml
res/layout/grid_image.xml
res/layout/grid_item.xml
res/layout/list_footer.xml
res/layout/list_fragment.xml
res/layout/list_item.xml
res/layout/listrow_details.xml
res/layout/listrow_group.xml
res/layout/loading_dialog.xml
res/layout/log_item.xml
res/layout/log_send_file.xml
res/layout/migration_layout.xml [new file with mode: 0644]
res/layout/passcodelock.xml
res/layout/search_users_groups_layout.xml [new file with mode: 0644]
res/layout/share_activity.xml [new file with mode: 0644]
res/layout/share_file_layout.xml [new file with mode: 0644]
res/layout/share_user_item.xml [new file with mode: 0644]
res/layout/ssl_untrusted_cert_layout.xml
res/layout/ssl_validator_layout.xml
res/layout/upload_files_layout.xml
res/layout/uploader_layout.xml
res/layout/uploader_list_item_layout.xml
res/menu/file_actions_menu.xml
res/menu/main_menu.xml
res/menu/multiple_file_actions_menu.xml [new file with mode: 0644]
res/menu/uploader_menu.xml [new file with mode: 0644]
res/values-ar/strings.xml
res/values-az/strings.xml
res/values-bg-rBG/strings.xml
res/values-bn-rBD/strings.xml
res/values-bn-rIN/strings.xml
res/values-bs/strings.xml
res/values-ca/strings.xml
res/values-cs-rCZ/strings.xml
res/values-cy-rGB/strings.xml
res/values-da/strings.xml
res/values-de-rAT/strings.xml
res/values-de-rCH/strings.xml
res/values-de-rDE/strings.xml
res/values-de/strings.xml
res/values-el/strings.xml
res/values-en-rGB/strings.xml
res/values-eo/strings.xml
res/values-es-rAR/strings.xml
res/values-es-rCL/strings.xml
res/values-es-rMX/strings.xml
res/values-es/strings.xml
res/values-et-rEE/strings.xml
res/values-eu/strings.xml
res/values-fa/strings.xml
res/values-fi-rFI/strings.xml
res/values-fr/strings.xml
res/values-gl/strings.xml
res/values-he/strings.xml
res/values-hr/strings.xml
res/values-hu-rHU/strings.xml
res/values-hy/strings.xml
res/values-ia/strings.xml
res/values-id/strings.xml
res/values-is/strings.xml
res/values-it/strings.xml
res/values-ja-rJP/strings.xml
res/values-ka-rGE/strings.xml
res/values-km/strings.xml
res/values-kn/strings.xml
res/values-ko/strings.xml
res/values-ku-rIQ/strings.xml
res/values-lb/strings.xml
res/values-lo/strings.xml
res/values-lt-rLT/strings.xml
res/values-lv/strings.xml
res/values-mk/strings.xml
res/values-mn/strings.xml
res/values-ms-rMY/strings.xml
res/values-nb-rNO/strings.xml
res/values-nl/strings.xml
res/values-nn-rNO/strings.xml
res/values-oc/strings.xml
res/values-pa/strings.xml
res/values-pl/strings.xml
res/values-pt-rBR/strings.xml
res/values-pt-rPT/strings.xml
res/values-ro/strings.xml
res/values-ru-rRU/strings.xml
res/values-ru/strings.xml
res/values-si-rLK/strings.xml
res/values-sk-rSK/strings.xml
res/values-sl/strings.xml
res/values-sq/strings.xml
res/values-sr-rSP/strings.xml
res/values-sr/strings.xml
res/values-sv/strings.xml
res/values-ta-rLK/strings.xml
res/values-th-rTH/strings.xml
res/values-tr/strings.xml
res/values-tzl/strings.xml [deleted file]
res/values-ug/strings.xml
res/values-uk/strings.xml
res/values-ur-rPK/strings.xml
res/values-v11/versioned_styles.xml
res/values-v21/styles.xml
res/values-vi/strings.xml
res/values-zh-rCN/strings.xml
res/values-zh-rHK/strings.xml
res/values-zh-rTW/strings.xml
res/values/attrs.xml
res/values/colors.xml
res/values/setup.xml
res/values/strings.xml
res/values/styles.xml
res/values/versioned_styles.xml
res/xml/preferences.xml
res/xml/users_and_groups_searchable.xml [new file with mode: 0644]
setup_env.bat
setup_env.sh
src/com/owncloud/android/MainApp.java
src/com/owncloud/android/authentication/AccountUtils.java
src/com/owncloud/android/authentication/AuthenticatorActivity.java
src/com/owncloud/android/authentication/PassCodeManager.java
src/com/owncloud/android/datamodel/FileDataStorageManager.java
src/com/owncloud/android/datamodel/OCFile.java
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
src/com/owncloud/android/db/ProviderMeta.java
src/com/owncloud/android/files/FileMenuFilter.java
src/com/owncloud/android/files/FileOperationsHelper.java
src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
src/com/owncloud/android/files/services/FileDownloader.java
src/com/owncloud/android/files/services/FileUploader.java
src/com/owncloud/android/media/MediaService.java
src/com/owncloud/android/notifications/NotificationBuilderWithProgressBar.java
src/com/owncloud/android/operations/CreateFolderOperation.java
src/com/owncloud/android/operations/CreateShareOperation.java [deleted file]
src/com/owncloud/android/operations/CreateShareViaLinkOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/CreateShareWithShareeOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/DownloadFileOperation.java
src/com/owncloud/android/operations/GetCapabilitiesOperarion.java [new file with mode: 0644]
src/com/owncloud/android/operations/GetSharesForFileOperation.java
src/com/owncloud/android/operations/GetSharesOperation.java [deleted file]
src/com/owncloud/android/operations/RefreshFolderOperation.java
src/com/owncloud/android/operations/SynchronizeFileOperation.java
src/com/owncloud/android/operations/SynchronizeFolderOperation.java
src/com/owncloud/android/operations/UnshareLinkOperation.java [deleted file]
src/com/owncloud/android/operations/UnshareOperation.java [new file with mode: 0644]
src/com/owncloud/android/operations/UploadFileOperation.java
src/com/owncloud/android/operations/common/SyncOperation.java
src/com/owncloud/android/providers/FileContentProvider.java
src/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java [new file with mode: 0644]
src/com/owncloud/android/services/OperationsService.java
src/com/owncloud/android/syncadapter/FileSyncAdapter.java
src/com/owncloud/android/ui/activity/ErrorReportActivity.java [new file with mode: 0644]
src/com/owncloud/android/ui/activity/FileActivity.java
src/com/owncloud/android/ui/activity/FileDisplayActivity.java
src/com/owncloud/android/ui/activity/FolderPickerActivity.java
src/com/owncloud/android/ui/activity/LocalDirectorySelectorActivity.java [new file with mode: 0644]
src/com/owncloud/android/ui/activity/PassCodeActivity.java
src/com/owncloud/android/ui/activity/Preferences.java
src/com/owncloud/android/ui/activity/ShareActivity.java [new file with mode: 0644]
src/com/owncloud/android/ui/activity/StorageMigrationActivity.java [new file with mode: 0644]
src/com/owncloud/android/ui/activity/UploadFilesActivity.java
src/com/owncloud/android/ui/activity/Uploader.java
src/com/owncloud/android/ui/adapter/DiskLruImageCache.java
src/com/owncloud/android/ui/adapter/DiskLruImageCacheFileProvider.java [new file with mode: 0644]
src/com/owncloud/android/ui/adapter/FileListListAdapter.java
src/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
src/com/owncloud/android/ui/adapter/ShareUserListAdapter.java [new file with mode: 0644]
src/com/owncloud/android/ui/adapter/X509CertificateViewAdapter.java
src/com/owncloud/android/ui/dialog/AccountActionsDialogFragment.java
src/com/owncloud/android/ui/dialog/OwnCloudListPreference.java [new file with mode: 0644]
src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java
src/com/owncloud/android/ui/dialog/RemoveFilesDialogFragment.java [new file with mode: 0644]
src/com/owncloud/android/ui/fragment/ExtendedListFragment.java
src/com/owncloud/android/ui/fragment/FileDetailFragment.java
src/com/owncloud/android/ui/fragment/FileFragment.java
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/fragment/SearchShareesFragment.java [new file with mode: 0644]
src/com/owncloud/android/ui/fragment/ShareFileFragment.java [new file with mode: 0644]
src/com/owncloud/android/ui/preview/ImageViewCustom.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImageFragment.java
src/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java
src/com/owncloud/android/ui/preview/PreviewMediaFragment.java
src/com/owncloud/android/ui/preview/PreviewTextFragment.java
src/com/owncloud/android/ui/preview/PreviewVideoActivity.java
src/com/owncloud/android/utils/DisplayUtils.java
src/com/owncloud/android/utils/ErrorMessageAdapter.java
src/com/owncloud/android/utils/ExceptionHandler.java [new file with mode: 0644]
src/com/owncloud/android/utils/FileStorageUtils.java
src/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java [new file with mode: 0644]
src/com/owncloud/android/utils/MimetypeIconUtil.java
src/third_parties/daveKoeller/AlphanumComparator.java
user_manual/android_app.rst
user_manual/images/android-1.png [new file with mode: 0644]
user_manual/images/android-10.png [new file with mode: 0644]
user_manual/images/android-11.png [new file with mode: 0644]
user_manual/images/android-2.png [new file with mode: 0644]
user_manual/images/android-3.png [new file with mode: 0644]
user_manual/images/android-4.png [new file with mode: 0644]
user_manual/images/android-5.png [new file with mode: 0644]
user_manual/images/android-6.png [new file with mode: 0644]
user_manual/images/android-7.png [new file with mode: 0644]
user_manual/images/android-8.png [new file with mode: 0644]
user_manual/images/android-9.png [new file with mode: 0644]
user_manual/images/android-downloads.png [deleted file]
user_manual/images/android-file-list.png [deleted file]
user_manual/images/android-file-options.png [deleted file]
user_manual/images/android-file.png [deleted file]
user_manual/images/android-files-page.png [deleted file]
user_manual/images/android-first-screen.jpg [deleted file]
user_manual/images/android-help.png [deleted file]
user_manual/images/android-new-account.png [deleted file]
user_manual/images/android-settings.png [deleted file]
user_manual/images/android-ssl-cert.png [deleted file]
user_manual/images/android-upload.png [deleted file]

index 8346dbf..009ead4 100644 (file)
@@ -1,5 +1,4 @@
 # built application files
-*.apk
 *.ap_
 
 # files for the dex VM
@@ -14,6 +13,7 @@ build/
 *.iml
 gen/
 target/
+build/
 
 # Local configuration files (sdk path, etc)
 local.properties
@@ -39,4 +39,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
index 5f42267..1d64863 100644 (file)
@@ -1,3 +1,4 @@
+sudo: false
 language: android
 android:
   components:
@@ -7,6 +8,6 @@ before_install:
   - rm pom.xml
 script:
   - ./setup_env.sh ant
-  - ant clean
-  - ant debug
+  - ant clean -Djava.source=7 -Djava.target=7
+  - ant debug -Djava.source=7 -Djava.target=7
   
index acb5f1d..12bd3f1 100644 (file)
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ownCloud Android client application
 
   Copyright (C) 2012  Bartek Przybylski
  -->
 <manifest package="com.owncloud.android"
     android:versionCode="10800000"
-    android:versionName="1.8.0" xmlns:android="http://schemas.android.com/apk/res/android">
+    android:versionName="ownCloud beta" xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="22" />
 
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
-    <uses-permission android:name="android.permission.WAKE_LOCK"/>
-    
-    <uses-sdk
-        android:minSdkVersion="14"
-        android:targetSdkVersion="22" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+    <android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
 
     <application
         android:name=".MainApp"
         android:icon="@drawable/icon"
         android:label="@string/app_name"
-        android:theme="@style/Theme.ownCloud">
+        android:theme="@style/Theme.ownCloud" >
         <activity
             android:name=".ui.activity.FileDisplayActivity"
-            android:label="@string/app_name">
+            android:label="@string/app_name" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
+
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <activity android:name=".ui.activity.UploadFilesActivity"></activity>
-        <activity android:name=".ui.activity.Uploader">
+        <activity android:name=".ui.activity.UploadFilesActivity" />
+        <activity android:name=".ui.activity.LocalDirectorySelectorActivity" />
+        <activity android:name=".ui.activity.StorageMigrationActivity" />
+        <activity android:name=".ui.activity.Uploader"
+            android:label="@string/uploader_top_message"
+            android:theme="@style/Theme.ownCloud">
             <intent-filter>
-                <action android:name="android.intent.action.SEND"></action>
+                <action android:name="android.intent.action.SEND" />
 
-                <category android:name="android.intent.category.DEFAULT"></category>
+                <category android:name="android.intent.category.DEFAULT" />
 
-                <data android:mimeType="*/*"></data>
+                <data android:mimeType="*/*" />
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.SEND_MULTIPLE"></action>
-
-                <category android:name="android.intent.category.DEFAULT"></category>
+                <action android:name="android.intent.action.SEND_MULTIPLE" />
 
-                <data android:mimeType="*/*"></data>
+                <category android:name="android.intent.category.DEFAULT" />
 
+                <data android:mimeType="*/*" />
             </intent-filter>
         </activity>
         <activity
             android:name=".ui.activity.Preferences"
             android:theme="@style/Theme.ownCloud" >
         </activity>
-        <activity      
+        <activity
             android:name=".ui.preview.PreviewImageActivity"
-            android:theme="@style/Theme.ownCloud.Overlay"
-            />
-                       
-        <activity      
+            android:theme="@style/Theme.ownCloud.Overlay" />
+        <activity
             android:name=".ui.preview.PreviewVideoActivity"
             android:label="@string/app_name"
-            android:theme="@style/Theme.ownCloud.Fullscreen"></activity>
+            android:theme="@style/Theme.ownCloud.Fullscreen" />
 
         <service
             android:name=".authentication.AccountAuthenticatorService"
-            android:exported="true">
-            <intent-filter android:priority="100">
+            android:exported="true" >
+            <intent-filter android:priority="100" >
                 <action android:name="android.accounts.AccountAuthenticator" />
             </intent-filter>
 
         </service>
         <service
             android:name=".syncadapter.FileSyncService"
-            android:exported="true">
+            android:exported="true" >
             <intent-filter>
                 <action android:name="android.content.SyncAdapter" />
             </intent-filter>
             android:name=".providers.FileContentProvider"
             android:authorities="@string/authority"
             android:enabled="true"
-            android:exported="false"
+            android:exported="true"
             android:label="@string/sync_string_files"
-            android:syncable="true"></provider>
+            android:syncable="true" />
+
+        <provider
+            android:name=".providers.UsersAndGroupsSearchProvider"
+            android:authorities="com.owncloud.android.providers.UsersAndGroupsSearchProvider"
+            android:enabled="true"
+            android:exported="false"
+            android:label="@string/search_users_and_groups_hint" />
+
+        <provider
+            android:name=".ui.adapter.DiskLruImageCacheFileProvider"
+            android:authorities="@string/authorityCache"
+            android:exported="true">
+        </provider>
 
         <activity
             android:name=".authentication.AuthenticatorActivity"
             android:exported="true"
-            android:theme="@style/Theme.ownCloud.noActionBar"
-            android:launchMode="singleTask">
+            android:launchMode="singleTask"
+            android:theme="@style/Theme.ownCloud.noActionBar" >
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
 
             </intent-filter>
             <intent-filter>
                 <action android:name="com.owncloud.android.workaround.accounts.CREATE" />
+
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
         <activity android:name=".ui.activity.ErrorsWhileCopyingHandlerActivity"/>
         
         <activity android:name=".ui.activity.LogHistoryActivity"/>
-        
+        <activity android:name=".ui.activity.ErrorReportActivity"/>
+
         <receiver android:name=".files.InstantUploadBroadcastReceiver">
             <intent-filter>
+
                 <!-- unofficially supported by many Android phones but not by HTC devices: -->
                 <action android:name="com.android.camera.NEW_PICTURE" />
                 <!-- officially supported since Android 4.0 (SDK 14, works even for HTC devices): -->
                 <action android:name="android.hardware.action.NEW_PICTURE" />
+
                 <data android:mimeType="image/*" />
             </intent-filter>
             <intent-filter>
                 <action android:name="android.hardware.action.NEW_VIDEO" />
+
                 <data android:mimeType="video/*" />
             </intent-filter>
             <intent-filter>
                 <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
             </intent-filter>
+            <intent-filter>
+                               <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
+                           <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
+                       </intent-filter>
         </receiver>
-        <receiver android:name=".files.BootupBroadcastReceiver">
+        <receiver android:name=".files.BootupBroadcastReceiver" >
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
             </intent-filter>
         </receiver>
-        <service android:name=".services.observer.FileObserverService"/>
-        
-               <activity
-                       android:name=".ui.activity.CopyToClipboardActivity"
-                       android:label="@string/copy_link"
-                       android:icon="@drawable/copy_link"/>
 
-        <activity
-                       android:name=".ui.activity.FolderPickerActivity"
-                       android:label="@string/app_name"/>
+        <service android:name=".services.observer.FileObserverService" />
 
         <activity
-                       android:name=".ui.activity.UploadPathActivity"
-                       android:label="@string/app_name"/>
-        
+            android:name=".ui.activity.CopyToClipboardActivity"
+            android:icon="@drawable/copy_link"
+            android:label="@string/copy_link" />
+        <activity
+            android:name=".ui.activity.FolderPickerActivity"
+            android:label="@string/app_name" />
+        <activity
+            android:name=".ui.activity.UploadPathActivity"
+            android:label="@string/app_name" />
+        <activity
+            android:name=".ui.activity.ShareActivity"
+            android:label="@string/share_dialog_title"
+            android:theme="@style/Theme.ownCloud.Dialog"
+            android:launchMode="singleTop"
+            android:windowSoftInputMode="adjustResize" >
+            <intent-filter>
+                <action android:name="android.intent.action.SEARCH" />
+            </intent-filter>
+            <meta-data android:name="android.app.searchable"
+                       android:resource="@xml/users_and_groups_searchable"/>
+        </activity>
     </application>
 
 </manifest>
index 099a445..97ea0e3 100644 (file)
@@ -1,60 +1,55 @@
-## 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-11-20
+- PR [#1293] (https://github.com/owncloud/android/pull/1293) "External SD by przybylski" merged
+- PR [#1296] (https://github.com/owncloud/android/pull/1296) "Don't allow to remove passcode without entering it. Don't allow to set incomplete passcode by przybylski" merged
+
+# 2015-11-18
+- update all PR
+- fix #1259
+
+# 2015-11-13
+- update all PR
+
+# 2015-11-10
+- update master
+- PR [#1277] (https://github.com/owncloud/android/pull/1277) "Optimized uploader layout and user configured sorting" merged
+
+# 2015-11-05
+- update master
+- fix #1244
+- add changelog
+- add check for update of beta version
+
+# 2015-11-02
+- PR [#1240](https://github.com/owncloud/android/pull/1240) "Set as wallpaper" merged
+- updated other PRs
+
+# 2015-11-01
+- PR [#1236](https://github.com/owncloud/android/pull/1236) "Streaming video/audio" merged
+- PR [#1035](https://github.com/owncloud/android/pull/1035) "Enable video thumbnail" merged
+
+# 2015-10-31
+- updated all PR
+- bugfix: #1234, #1230
+- implement Crash Handler
+- implement direct download of latest apk in settings -> last item on bottom
+
+# 2015-10-30
+- fixed problem with Authority
+
+# 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
+- PR [#1209](https://github.com/owncloud/android/pull/1209) "Material buttons - before in #1090" merged
+- PR [#1205](https://github.com/owncloud/android/pull/1205) "Switch between online and offline files" merged
+- PR [#1195](https://github.com/owncloud/android/pull/1195) "Resize Cache" merged
+- PR [#1187](https://github.com/owncloud/android/pull/1187) "Video: Big thumbnails" merged
+- PR [#1058](https://github.com/owncloud/android/pull/1058) "add sort to UploadFileActiviy" merged
+- PR [#1168](https://github.com/owncloud/android/pull/1168) "Avoid duplicate files" merged
+- PR [#1176](https://github.com/owncloud/android/pull/1176) "Multi select" 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
index e3ff535..a239144 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,11 +1,18 @@
-#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 verify first if it is *really* a bug in beta, then comment in the corresponding pull request or create a new issue with the prefix "Beta YYYY-MM-DD:".
+
+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 +21,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
index 0f1bc8e..64c04c9 100644 (file)
--- 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!
 
 
index 6fd3e5b..034ecb3 100644 (file)
@@ -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/apks/latest b/apks/latest
new file mode 100644 (file)
index 0000000..7ed440b
--- /dev/null
@@ -0,0 +1 @@
+20151120
diff --git a/apks/latest.apk b/apks/latest.apk
new file mode 100644 (file)
index 0000000..aa2cf9d
Binary files /dev/null and b/apks/latest.apk differ
diff --git a/apks/owncloud-beta-2015-10-26.apk b/apks/owncloud-beta-2015-10-26.apk
new file mode 100644 (file)
index 0000000..61a3b3b
Binary files /dev/null and b/apks/owncloud-beta-2015-10-26.apk differ
diff --git a/apks/owncloud-beta-2015-10-29.apk b/apks/owncloud-beta-2015-10-29.apk
new file mode 100644 (file)
index 0000000..0b07ac8
Binary files /dev/null and b/apks/owncloud-beta-2015-10-29.apk differ
diff --git a/apks/owncloud-beta-2015-10-30.apk b/apks/owncloud-beta-2015-10-30.apk
new file mode 100644 (file)
index 0000000..6ebbf4e
Binary files /dev/null and b/apks/owncloud-beta-2015-10-30.apk differ
diff --git a/apks/owncloud-beta-2015-10-31-10-00-00.apk b/apks/owncloud-beta-2015-10-31-10-00-00.apk
new file mode 100644 (file)
index 0000000..ab15cda
Binary files /dev/null and b/apks/owncloud-beta-2015-10-31-10-00-00.apk differ
diff --git a/apks/owncloud-beta-2015-10-31.apk b/apks/owncloud-beta-2015-10-31.apk
new file mode 100644 (file)
index 0000000..f8e7bab
Binary files /dev/null and b/apks/owncloud-beta-2015-10-31.apk differ
diff --git a/apks/owncloud-beta-2015-11-01.apk b/apks/owncloud-beta-2015-11-01.apk
new file mode 100644 (file)
index 0000000..567891a
Binary files /dev/null and b/apks/owncloud-beta-2015-11-01.apk differ
diff --git a/apks/owncloud-beta-2015-11-02.apk b/apks/owncloud-beta-2015-11-02.apk
new file mode 100644 (file)
index 0000000..924f626
Binary files /dev/null and b/apks/owncloud-beta-2015-11-02.apk differ
diff --git a/apks/owncloud-beta-20151105.apk b/apks/owncloud-beta-20151105.apk
new file mode 100644 (file)
index 0000000..aa2cf9d
Binary files /dev/null and b/apks/owncloud-beta-20151105.apk differ
diff --git a/apks/owncloud-beta-20151109.apk b/apks/owncloud-beta-20151109.apk
new file mode 100644 (file)
index 0000000..e770472
Binary files /dev/null and b/apks/owncloud-beta-20151109.apk differ
diff --git a/apks/owncloud-beta-20151113.apk b/apks/owncloud-beta-20151113.apk
new file mode 100644 (file)
index 0000000..6f1f3b8
Binary files /dev/null and b/apks/owncloud-beta-20151113.apk differ
diff --git a/apks/owncloud-beta-20151118.apk b/apks/owncloud-beta-20151118.apk
new file mode 100644 (file)
index 0000000..9641cf6
Binary files /dev/null and b/apks/owncloud-beta-20151118.apk differ
diff --git a/apks/owncloud-beta-20151120.apk b/apks/owncloud-beta-20151120.apk
new file mode 100644 (file)
index 0000000..056d0ec
Binary files /dev/null and b/apks/owncloud-beta-20151120.apk differ
index a0db018..25504ff 100644 (file)
@@ -3,13 +3,12 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:1.2.3'
+        classpath 'com.android.tools.build:gradle:1.3.0'
     }
 }
 
 apply plugin: 'com.android.application'
 
-
 repositories {
     mavenCentral()
 
@@ -20,15 +19,23 @@ repositories {
 
 dependencies {
     compile name: 'touch-image-view'
-    compile 'com.android.support:support-v4:22.2.1'
     compile project(':owncloud-android-library')
+    compile 'com.android.support:support-v4:22.2.1'
     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"
+        versionCode computeVersionCode()
+        versionName "ownCloud beta"
+    }
+
     sourceSets {
         main {
             manifest.srcFile 'AndroidManifest.xml'
@@ -58,7 +65,7 @@ android {
             abortOnError false
         }
     }
-    
+
     productFlavors {
     }
 
@@ -68,3 +75,11 @@ android {
 }
 
 
+
+
+
+def computeVersionCode() {
+    def date = new Date()
+    def formattedDate = date.format('yyyyMMdd').toInteger()
+    return formattedDate
+}
\ No newline at end of file
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 (file)
index 0000000..7bc01d9
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="src" path="gen"/>
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+       <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+       <classpathentry kind="output" path="bin/classes"/>
+</classpath>
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 (file)
index 0000000..f29e987
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest
+    package="com.getbase.floatingactionbutton"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:versionCode="15"
+    android:versionName="1.10.1" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="22" />
+
+    <application />
+
+</manifest>
\ 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 (file)
index 0000000..c6d5664
--- /dev/null
@@ -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 (file)
index 0000000..f29e987
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest
+    package="com.getbase.floatingactionbutton"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:versionCode="15"
+    android:versionName="1.10.1" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="22" />
+
+    <application />
+
+</manifest>
\ 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 (file)
index 0000000..a46d2ce
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 (file)
index 0000000..4317fb0
--- /dev/null
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="com-getbase-floatingactionbutton-1-10-0-exploded-aar" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var.
+         This must be done before we load project.properties since
+         the proguard config can use sdk.dir -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
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 (file)
index 0000000..723d01e
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 (file)
index 0000000..723d01e
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 (file)
index 0000000..b542959
--- /dev/null
@@ -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 (file)
index 0000000..362a0a3
--- /dev/null
@@ -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 (file)
index 0000000..4b48351
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 (file)
index 0000000..4daec66
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 (file)
index 0000000..218cf04
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 (file)
index 0000000..c157df3
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 (file)
index 0000000..d56bfe8
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 (file)
index 0000000..41614b9
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 (file)
index 0000000..1cdd2b1
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 (file)
index 0000000..14608ff
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 (file)
index 0000000..6fea674
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 (file)
index 0000000..0e78ff6
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 (file)
index 0000000..8139c61
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="AddFloatingActionButton"><attr format="color" name="fab_plusIconColor"/></declare-styleable>
+    <declare-styleable name="FloatingActionButton"><attr format="color" name="fab_colorPressed"/><attr format="color" name="fab_colorDisabled"/><attr format="color" name="fab_colorNormal"/><attr format="reference" name="fab_icon"/><attr format="enum" name="fab_size"><enum name="normal" value="0"/><enum name="mini" value="1"/></attr><attr format="string" name="fab_title"/><attr format="boolean" name="fab_stroke_visible"/></declare-styleable>
+    <declare-styleable name="FloatingActionsMenu"><attr format="color" name="fab_addButtonColorPressed"/><attr format="color" name="fab_addButtonColorNormal"/><attr format="enum" name="fab_addButtonSize"><enum name="normal" value="0"/><enum name="mini" value="1"/></attr><attr format="color" name="fab_addButtonPlusIconColor"/><attr format="boolean" name="fab_addButtonStrokeVisible"/><attr format="reference" name="fab_labelStyle"/><attr format="enum" name="fab_labelsPosition"><enum name="left" value="0"/><enum name="right" value="1"/></attr><attr format="enum" name="fab_expandDirection"><enum name="up" value="0"/><enum name="down" value="1"/><enum name="left" value="2"/><enum name="right" value="3"/></attr></declare-styleable>
+    <!-- From: file:/Users/chalup/src/android-floating-action-button/library/src/main/res/values/dimens.xml -->
+    <eat-comment/>
+    <dimen name="fab_actions_spacing">16dp</dimen>
+    <dimen name="fab_icon_size">24dp</dimen>
+    <dimen name="fab_labels_margin">8dp</dimen>
+    <dimen name="fab_plus_icon_size">14dp</dimen>
+    <dimen name="fab_plus_icon_stroke">2dp</dimen>
+    <dimen name="fab_shadow_offset">3dp</dimen>
+    <dimen name="fab_shadow_radius">9dp</dimen>
+    <dimen name="fab_size_mini">40dp</dimen>
+    <dimen name="fab_size_normal">56dp</dimen>
+    <dimen name="fab_stroke_width">1dp</dimen>
+    <!-- From: file:/Users/chalup/src/android-floating-action-button/library/src/main/res/values/ids.xml -->
+    <eat-comment/>
+    <item name="fab_expand_menu_button" type="id"/>
+    <item name="fab_label" type="id"/>
+</resources>
\ 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 (file)
index 0000000..4bcebad
--- /dev/null
@@ -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
index 2fcc9f6..4a48a29 100644 (file)
@@ -3,7 +3,7 @@ buildscript {
         mavenCentral()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:1.2.3'
+        classpath 'com.android.tools.build:gradle:1.3.0'
     }
 }
 apply plugin: 'com.android.library'
index 5985ba9..4f9a752 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5985ba9a9fd9a208b2a09ee7809949874e0c3a97
+Subproject commit 4f9a7528cab0563cb234a8b817e8ee371dd6cc25
index b7cabdd..3b4370c 100644 (file)
@@ -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 (file)
index 25476cd..0000000
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 (file)
index a7fdc0d..0000000
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 (file)
index 86b54f4..0000000
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
new file mode 100644 (file)
index 0000000..164dcb5
Binary files /dev/null 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
new file mode 100644 (file)
index 0000000..330d7b9
Binary files /dev/null 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 (file)
index 0000000..ad72837
Binary files /dev/null and b/res/drawable-hdpi/ic_import.png differ
diff --git a/res/drawable-hdpi/ic_play_arrow.png b/res/drawable-hdpi/ic_play_arrow.png
new file mode 100644 (file)
index 0000000..57c9fa5
Binary files /dev/null and b/res/drawable-hdpi/ic_play_arrow.png differ
diff --git a/res/drawable-hdpi/ic_view_list.png b/res/drawable-hdpi/ic_view_list.png
new file mode 100644 (file)
index 0000000..64ad8e1
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 (file)
index 0000000..7982e38
Binary files /dev/null and b/res/drawable-hdpi/ic_view_module.png differ
index 6fe153b..2430c94 100644 (file)
Binary files a/res/drawable-hdpi/icon.png and b/res/drawable-hdpi/icon.png differ
diff --git a/res/drawable-hdpi/shared_via_link.png b/res/drawable-hdpi/shared_via_link.png
new file mode 100644 (file)
index 0000000..f4279f3
Binary files /dev/null and b/res/drawable-hdpi/shared_via_link.png differ
diff --git a/res/drawable-hdpi/shared_via_users.png b/res/drawable-hdpi/shared_via_users.png
new file mode 100644 (file)
index 0000000..9ec18ce
Binary files /dev/null and b/res/drawable-hdpi/shared_via_users.png differ
diff --git a/res/drawable-hdpi/shared_with_me.png b/res/drawable-hdpi/shared_with_me.png
deleted file mode 100644 (file)
index 9ec18ce..0000000
Binary files a/res/drawable-hdpi/shared_with_me.png and /dev/null differ
diff --git a/res/drawable-hdpi/sharedlink.png b/res/drawable-hdpi/sharedlink.png
deleted file mode 100644 (file)
index f4279f3..0000000
Binary files a/res/drawable-hdpi/sharedlink.png and /dev/null differ
diff --git a/res/drawable-hdpi/view_play.png b/res/drawable-hdpi/view_play.png
new file mode 100644 (file)
index 0000000..5371724
Binary files /dev/null and b/res/drawable-hdpi/view_play.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 (file)
index 2684c83..0000000
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 (file)
index bb9d855..0000000
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 (file)
index 47ef3f4..0000000
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 (file)
index 0000000..d4ca47c
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 (file)
index 0000000..99df274
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 (file)
index 0000000..3bc69d1
Binary files /dev/null and b/res/drawable-mdpi/ic_import.png differ
diff --git a/res/drawable-mdpi/ic_play_arrow.png b/res/drawable-mdpi/ic_play_arrow.png
new file mode 100644 (file)
index 0000000..c61e948
Binary files /dev/null and b/res/drawable-mdpi/ic_play_arrow.png differ
diff --git a/res/drawable-mdpi/ic_view_list.png b/res/drawable-mdpi/ic_view_list.png
new file mode 100644 (file)
index 0000000..4aca55c
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 (file)
index 0000000..f308a32
Binary files /dev/null and b/res/drawable-mdpi/ic_view_module.png differ
index 9008b9d..2d7ab66 100644 (file)
Binary files a/res/drawable-mdpi/icon.png and b/res/drawable-mdpi/icon.png differ
diff --git a/res/drawable-mdpi/shared_via_link.png b/res/drawable-mdpi/shared_via_link.png
new file mode 100644 (file)
index 0000000..1d27294
Binary files /dev/null and b/res/drawable-mdpi/shared_via_link.png differ
diff --git a/res/drawable-mdpi/shared_via_users.png b/res/drawable-mdpi/shared_via_users.png
new file mode 100644 (file)
index 0000000..0b17c76
Binary files /dev/null and b/res/drawable-mdpi/shared_via_users.png differ
diff --git a/res/drawable-mdpi/shared_with_me.png b/res/drawable-mdpi/shared_with_me.png
deleted file mode 100644 (file)
index 0b17c76..0000000
Binary files a/res/drawable-mdpi/shared_with_me.png and /dev/null differ
diff --git a/res/drawable-mdpi/sharedlink.png b/res/drawable-mdpi/sharedlink.png
deleted file mode 100644 (file)
index 1d27294..0000000
Binary files a/res/drawable-mdpi/sharedlink.png and /dev/null differ
diff --git a/res/drawable-mdpi/view_play.png b/res/drawable-mdpi/view_play.png
new file mode 100644 (file)
index 0000000..77b2027
Binary files /dev/null and b/res/drawable-mdpi/view_play.png differ
diff --git a/res/drawable-xhdpi/ic_checkbox_blank_outline.png b/res/drawable-xhdpi/ic_checkbox_blank_outline.png
new file mode 100644 (file)
index 0000000..05024eb
Binary files /dev/null and b/res/drawable-xhdpi/ic_checkbox_blank_outline.png differ
diff --git a/res/drawable-xhdpi/ic_checkbox_marked.png b/res/drawable-xhdpi/ic_checkbox_marked.png
new file mode 100644 (file)
index 0000000..3a2ca10
Binary files /dev/null and b/res/drawable-xhdpi/ic_checkbox_marked.png differ
diff --git a/res/drawable-xhdpi/ic_import.png b/res/drawable-xhdpi/ic_import.png
new file mode 100644 (file)
index 0000000..bf2f72e
Binary files /dev/null and b/res/drawable-xhdpi/ic_import.png differ
diff --git a/res/drawable-xhdpi/ic_play_arrow.png b/res/drawable-xhdpi/ic_play_arrow.png
new file mode 100644 (file)
index 0000000..a3c80e7
Binary files /dev/null and b/res/drawable-xhdpi/ic_play_arrow.png differ
diff --git a/res/drawable-xhdpi/ic_view_list.png b/res/drawable-xhdpi/ic_view_list.png
new file mode 100644 (file)
index 0000000..b81d910
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 (file)
index 0000000..b354853
Binary files /dev/null and b/res/drawable-xhdpi/ic_view_module.png differ
index 041efc6..a135cc2 100644 (file)
Binary files a/res/drawable-xhdpi/icon.png and b/res/drawable-xhdpi/icon.png differ
diff --git a/res/drawable-xhdpi/shared_via_link.png b/res/drawable-xhdpi/shared_via_link.png
new file mode 100644 (file)
index 0000000..11f8afa
Binary files /dev/null and b/res/drawable-xhdpi/shared_via_link.png differ
diff --git a/res/drawable-xhdpi/shared_via_users.png b/res/drawable-xhdpi/shared_via_users.png
new file mode 100644 (file)
index 0000000..ef7779c
Binary files /dev/null and b/res/drawable-xhdpi/shared_via_users.png differ
diff --git a/res/drawable-xhdpi/shared_with_me.png b/res/drawable-xhdpi/shared_with_me.png
deleted file mode 100644 (file)
index ef7779c..0000000
Binary files a/res/drawable-xhdpi/shared_with_me.png and /dev/null differ
diff --git a/res/drawable-xhdpi/sharedlink.png b/res/drawable-xhdpi/sharedlink.png
deleted file mode 100644 (file)
index 11f8afa..0000000
Binary files a/res/drawable-xhdpi/sharedlink.png and /dev/null differ
diff --git a/res/drawable-xhdpi/view_play.png b/res/drawable-xhdpi/view_play.png
new file mode 100644 (file)
index 0000000..8482788
Binary files /dev/null and b/res/drawable-xhdpi/view_play.png differ
diff --git a/res/drawable-xxhdpi/ic_checkbox_blank_outline.png b/res/drawable-xxhdpi/ic_checkbox_blank_outline.png
new file mode 100644 (file)
index 0000000..ffb1ea8
Binary files /dev/null and b/res/drawable-xxhdpi/ic_checkbox_blank_outline.png differ
diff --git a/res/drawable-xxhdpi/ic_checkbox_marked.png b/res/drawable-xxhdpi/ic_checkbox_marked.png
new file mode 100644 (file)
index 0000000..fba7e0c
Binary files /dev/null and b/res/drawable-xxhdpi/ic_checkbox_marked.png differ
diff --git a/res/drawable-xxhdpi/ic_import.png b/res/drawable-xxhdpi/ic_import.png
new file mode 100644 (file)
index 0000000..a4412aa
Binary files /dev/null and b/res/drawable-xxhdpi/ic_import.png differ
diff --git a/res/drawable-xxhdpi/ic_play_arrow.png b/res/drawable-xxhdpi/ic_play_arrow.png
new file mode 100644 (file)
index 0000000..547ef30
Binary files /dev/null and b/res/drawable-xxhdpi/ic_play_arrow.png differ
diff --git a/res/drawable-xxhdpi/ic_sort_variant.png b/res/drawable-xxhdpi/ic_sort_variant.png
new file mode 100644 (file)
index 0000000..2918126
Binary files /dev/null and b/res/drawable-xxhdpi/ic_sort_variant.png differ
diff --git a/res/drawable-xxhdpi/icon.png b/res/drawable-xxhdpi/icon.png
new file mode 100644 (file)
index 0000000..ad0fd25
Binary files /dev/null and b/res/drawable-xxhdpi/icon.png differ
diff --git a/res/drawable-xxhdpi/view_play.png b/res/drawable-xxhdpi/view_play.png
new file mode 100644 (file)
index 0000000..fea738b
Binary files /dev/null and b/res/drawable-xxhdpi/view_play.png differ
diff --git a/res/drawable-xxxhdpi/icon.png b/res/drawable-xxxhdpi/icon.png
new file mode 100644 (file)
index 0000000..c0ec25c
Binary files /dev/null and b/res/drawable-xxxhdpi/icon.png differ
diff --git a/res/drawable-xxxhdpi/view_play.png b/res/drawable-xxxhdpi/view_play.png
new file mode 100644 (file)
index 0000000..3786b4d
Binary files /dev/null and b/res/drawable-xxxhdpi/view_play.png differ
diff --git a/res/drawable/conflict_file_indicator.png b/res/drawable/conflict_file_indicator.png
new file mode 100644 (file)
index 0000000..fd580ca
Binary files /dev/null and b/res/drawable/conflict_file_indicator.png differ
diff --git a/res/drawable/fab_label_background.xml b/res/drawable/fab_label_background.xml
new file mode 100644 (file)
index 0000000..4460dab
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/black_semi_transparent"/>
+    <padding
+        android:left="@dimen/standard_padding"
+        android:top="4dp"
+        android:right="@dimen/standard_padding"
+        android:bottom="4dp"/>
+    <corners
+        android:radius="2dp"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/synchronizing_file_indicator.png b/res/drawable/synchronizing_file_indicator.png
new file mode 100644 (file)
index 0000000..947cba7
Binary files /dev/null and b/res/drawable/synchronizing_file_indicator.png differ
index 477011d..347568e 100644 (file)
@@ -95,7 +95,6 @@
                                                android:inputType="textUri"\r
                                                android:drawablePadding="5dp"\r
                                                android:paddingRight="55dp"\r
-                                               android:textColor="@color/primary"\r
                                                android:textColorHint="@color/login_text_hint_color"\r
                                                android:contentDescription="@string/auth_host_address"\r
                                                >\r
                                        android:text="@string/oauth2_url_endpoint_auth"\r
                                        android:singleLine="true"\r
                                        android:inputType="textUri"\r
-                                       android:textColor="@color/primary"\r
                                        android:textColorHint="@color/login_text_hint_color"\r
                                        android:visibility="gone">\r
                                </EditText>            \r
                                        android:text="@string/oauth2_url_endpoint_access"\r
                                        android:singleLine="true"\r
                                        android:inputType="textUri"\r
-                                       android:textColor="@color/primary"\r
                                        android:textColorHint="@color/login_text_hint_color"\r
                                        android:visibility="gone">\r
                                        <requestFocus />\r
                                        android:ems="10"\r
                                        android:hint="@string/auth_username"\r
                                        android:inputType="textNoSuggestions"\r
-                                       android:textColor="@color/primary"\r
                                        android:textColorHint="@color/login_text_hint_color"\r
                                        android:contentDescription="@string/auth_username"\r
                                        />\r
                                        android:hint="@string/auth_password"\r
                                        android:inputType="textPassword"\r
                                        android:drawablePadding="5dp"\r
-                                       android:textColor="@color/primary"\r
                                        android:textColorHint="@color/login_text_hint_color"\r
                                        />\r
                        \r
index bd4b0b6..d90fb8a 100644 (file)
         android:orientation="horizontal" >
 
         <!-- 'OK' / 'CANCEL' BUTTONS CHANGE THEIR ORDER FROM ANDROID 4.0 ; THANKS, GOOGLE -->
-        <Button
+        <android.support.v7.widget.AppCompatButton
             android:id="@+id/cancel"
+            android:theme="@style/Button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:text="@string/common_cancel" />
 
-               <Button
+        <android.support.v7.widget.AppCompatButton
                    android:id="@+id/ok"
+            android:theme="@style/Button.Primary"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
index 876d834..a555e2f 100644 (file)
@@ -82,7 +82,6 @@
                                android:inputType="textUri"\r
                                android:drawablePadding="5dp"\r
                                android:paddingRight="55dp"\r
-                android:textColor="@color/primary"\r
                 android:textColorHint="@color/login_text_hint_color"\r
                                android:contentDescription="@string/auth_host_address"\r
                 >\r
@@ -97,7 +96,6 @@
                            android:padding="0dp"\r
                            android:scaleType="fitCenter"\r
                            android:src="@drawable/ic_action_refresh_grey"\r
-               android:onClick="onRefreshClick"\r
                                android:visibility="gone"\r
                                android:background="@android:color/transparent"\r
                 android:contentDescription="@string/auth_refresh_button"\r
             android:layout_height="wrap_content"\r
             android:ems="10"\r
                        android:enabled="false"\r
-            android:textColor="@color/primary"\r
             android:textColorHint="@color/login_text_hint_color"\r
             android:text="@string/oauth2_url_endpoint_auth"\r
             android:singleLine="true"\r
             android:text="@string/oauth2_url_endpoint_access"\r
             android:singleLine="true"\r
             android:inputType="textUri"\r
-            android:textColor="@color/primary"\r
             android:textColorHint="@color/login_text_hint_color"\r
             android:visibility="gone"/>\r
 \r
             android:ems="10"\r
             android:hint="@string/auth_username"\r
             android:inputType="textNoSuggestions"\r
-            android:textColor="@color/primary"\r
             android:textColorHint="@color/login_text_hint_color"\r
             android:contentDescription="@string/auth_username"\r
             />\r
                    android:ems="10"\r
                    android:hint="@string/auth_password"\r
                    android:inputType="textPassword"\r
-            android:textColor="@color/primary"\r
             android:textColorHint="@color/login_text_hint_color"\r
                    android:contentDescription="@string/auth_password"\r
             />\r
index aacb1c6..485ff52 100644 (file)
             android:layout_width="fill_parent"
             android:layout_height="match_parent"
             android:background="@color/background_color"
-            android:divider="#eee"
+            android:divider="@color/list_divider_background"
             android:dividerHeight="1dp"
             android:paddingTop="100dp" />
 
         <LinearLayout
             android:layout_width="fill_parent"
             android:layout_height="100dp"
-            android:paddingTop="16dp"
-            android:paddingBottom="16dp"
+            android:paddingTop="@dimen/standard_padding"
+            android:paddingBottom="@dimen/standard_padding"
             android:background="@color/owncloud_blue_accent">
 
             <ImageView
                 android:id="@+id/itemIcon"
                 android:layout_width="24sp"
                 android:layout_height="24sp"
-                android:layout_marginLeft="16sp"
+                android:layout_marginLeft="@dimen/standard_padding"
                 android:layout_marginBottom="3dp"
                 android:layout_gravity="bottom"
                 android:src="@drawable/ic_account_circle"
@@ -93,7 +93,7 @@
                 android:text="@string/app_name"
                 android:textColor="#FFF"
                 android:paddingLeft="22dp"
-                android:paddingRight="16dp"
+                android:paddingRight="@dimen/standard_padding"
                 android:textSize="24sp"
                 android:ellipsize="end"
                 android:singleLine="true"
index 8c10610..25415ac 100644 (file)
     android:layout_alignParentLeft="true"
     android:orientation="horizontal"
     android:background="@color/background_color"
-    android:layout_marginTop="16dp"
-    android:layout_marginBottom="16dp"
+    android:layout_marginTop="@dimen/standard_margin"
+    android:layout_marginBottom="@dimen/standard_margin"
     android:minHeight="?android:attr/listPreferredItemHeight">
 
     <ImageView
         android:id="@+id/itemIcon"
         android:layout_width="24sp"
         android:layout_height="24sp"
-        android:layout_marginLeft="16sp"
+        android:layout_marginLeft="@dimen/standard_margin"
         android:layout_gravity="center_vertical"
         />
 
@@ -41,7 +41,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:paddingLeft="22dp"
-        android:paddingRight="16dp"
+        android:paddingRight="@dimen/standard_margin"
         android:textColor="@color/drawerMenuTextColor"
         android:text="@string/app_name"
         android:textStyle="normal"
index 726d057..3c4bbdb 100644 (file)
@@ -21,7 +21,7 @@
     android:layout_width="fill_parent"
     android:layout_height="56dp"
     android:gravity="center_vertical"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:textColor="#000"
+    android:paddingLeft="@dimen/standard_padding"
+    android:paddingRight="@dimen/standard_padding"
+    android:textColor="@color/black"
     android:textSize="18dp" />
\ No newline at end of file
diff --git a/res/layout/error_send.xml b/res/layout/error_send.xml
new file mode 100644 (file)
index 0000000..7a80166
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:weightSum="1" >
+
+    <ScrollView
+        android:id="@+id/scrollView1"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginBottom="@dimen/standard_margin"
+        android:layout_weight="1">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding">
+
+            <TextView
+                android:id="@+id/logTV"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:text="@string/empty"
+                android:typeface="monospace"/>
+        </LinearLayout>
+    </ScrollView>
+
+    <LinearLayout
+        android:id="@+id/historyButtonBar"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_marginBottom="@dimen/standard_margin"
+        android:layout_marginLeft="@dimen/standard_margin"
+        android:layout_marginRight="@dimen/standard_margin">
+
+    <Button
+        android:id="@+id/cancelErrorLogButton"
+        android:theme="@style/Button"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
+        android:layout_weight="1"
+        android:text="@string/error_log_exit" />
+
+    <android.support.v7.widget.AppCompatButton
+        android:id="@+id/sendErrorLogButton"
+        android:theme="@style/Button.Primary"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
+        android:layout_weight="1"
+        android:text="@string/error_log_send" />
+
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
index 0ad98e3..7a241b3 100644 (file)
@@ -32,9 +32,9 @@
                        android:id="@+id/fdFileHeaderContainer"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
-                       android:layout_marginLeft="16dp"
-                       android:layout_marginRight="16dp"
-                       android:layout_marginTop="4dp" >
+                       android:layout_marginLeft="@dimen/standard_margin"
+                       android:layout_marginRight="@dimen/standard_margin"
+                       android:layout_marginTop="@dimen/standard_margin">
        
                        <ImageView
                                android:id="@+id/fdIcon"
@@ -57,8 +57,9 @@
                        android:id="@+id/fdDetailsContainer"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
-                       android:layout_marginLeft="16dp"
-                       android:layout_marginRight="16dp"
+                       android:layout_marginLeft="@dimen/standard_margin"
+                       android:layout_marginRight="@dimen/standard_margin"
+                       android:layout_marginTop="@dimen/standard_margin"
                        android:layout_below="@id/fdFileHeaderContainer" >
                
                        <RelativeLayout
@@ -72,7 +73,6 @@
                                        android:id="@+id/fdTypeLabel"
                                        android:layout_width="wrap_content"
                                        android:layout_height="wrap_content"
-                                       android:layout_marginTop="24dp"
                                        android:text="@string/filedetails_type"
                                        android:textAppearance="?android:attr/textAppearanceMedium" />
                                        
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_alignParentTop="true"
-                               android:layout_marginLeft="12dp"
+                               android:layout_marginLeft="@dimen/standard_margin"
                                android:layout_toRightOf="@+id/fdLabelContainer" >
                                
                                <TextView
                                        android:id="@+id/fdType"
                                        android:layout_width="wrap_content"
                                        android:layout_height="wrap_content"
-                                       android:layout_marginTop="24dp"
                                        android:text="@string/placeholder_filetype"
                                        android:textAppearance="?android:attr/textAppearanceMedium" />
                                        
                        android:layout_height="wrap_content"
                        android:layout_below="@+id/fdDetailsContainer"
                        android:gravity="center_horizontal" 
-                       android:layout_margin="16dp"
+                       android:layout_margin="@dimen/standard_margin"
                        >
                        
-                       <CheckBox
+                       <android.support.v7.widget.AppCompatCheckBox
                                android:id="@+id/fdFavorite"
                                android:layout_width="wrap_content"
                                android:layout_height="wrap_content"
                                android:layout_centerHorizontal="true"
-                               android:text="@string/favorite" />
+                               android:text="@string/favorite"
+                               android:checked="false" />
 
                        <LinearLayout
                                android:layout_width="match_parent"
index f7a697a..685f2b5 100644 (file)
@@ -39,7 +39,7 @@
                android:id="@+id/image_preview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
-               android:layout_margin="16dp"
+               android:layout_margin="@dimen/standard_margin"
                android:layout_gravity="center"
                android:contentDescription="@string/preview_image_description"
                android:src="@drawable/logo" />
index 4fbec4a..0e334fd 100644 (file)
@@ -48,7 +48,7 @@
 
         <android.support.v7.widget.AppCompatButton
             android:id="@+id/folder_picker_btn_cancel"
-            style="@style/ownCloud.Button"
+            android:theme="@style/Button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"
@@ -56,7 +56,7 @@
 
         <android.support.v7.widget.AppCompatButton
                    android:id="@+id/folder_picker_btn_choose"
-            style="@style/ownCloud.Button"
+            android:theme="@style/Button.Primary"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
index f20c5f3..64c9ed0 100644 (file)
@@ -50,7 +50,7 @@
 
         <android.support.v7.widget.AppCompatButton
                    android:id="@+id/ok"
-            style="@style/ownCloud.Button"
+            android:theme="@style/Button.Primary"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
@@ -58,7 +58,7 @@
 
         <android.support.v7.widget.AppCompatButton
             android:id="@+id/cancel"
-            style="@style/ownCloud.Button"
+            android:theme="@style/Button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_weight="1"
index 383c615..9f93a3e 100644 (file)
             android:scaleType="centerCrop"\r
             android:src="@drawable/ic_menu_archive"/>\r
 \r
-        <LinearLayout\r
+        <ImageView\r
+            android:id="@+id/sharedIcon"\r
             android:layout_width="wrap_content"\r
             android:layout_height="wrap_content"\r
             android:layout_gravity="top|right"\r
-            android:orientation="vertical"\r
-            android:layout_margin="4dp">\r
-\r
-            <ImageView\r
-                android:id="@+id/sharedIcon"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_gravity="center"\r
-                android:layout_marginBottom="4dp"\r
-                android:src="@drawable/sharedlink" />\r
-\r
-            <ImageView\r
-                android:id="@+id/sharedWithMeIcon"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_gravity="center"\r
-                android:layout_marginTop="4dp"\r
-                android:src="@drawable/shared_with_me"\r
-                android:visibility="invisible" />\r
-        </LinearLayout>\r
+            android:layout_margin="4dp"\r
+            android:src="@drawable/shared_via_link" />\r
 \r
         <ImageView\r
             android:id="@+id/localFileIndicator"\r
             android:layout_marginBottom="4dp"\r
             android:layout_marginRight="4dp"\r
             android:src="@drawable/ic_favorite" />\r
+\r
+        <ImageView\r
+            android:id="@+id/custom_checkbox"\r
+            android:layout_width="wrap_content"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="center_vertical|bottom"\r
+            android:layout_marginLeft="4dp"\r
+            android:layout_marginRight="4dp"\r
+            android:gravity=""\r
+            android:src="@android:drawable/checkbox_off_background" />\r
     </FrameLayout>\r
 \r
 </LinearLayout>
\ No newline at end of file
index d0f3d0f..0f27f90 100644 (file)
             android:layout_marginRight="10dp"\r
             android:src="@drawable/ic_menu_archive" />\r
 \r
-        <LinearLayout\r
+        <ImageView\r
+            android:id="@+id/sharedIcon"\r
             android:layout_width="wrap_content"\r
             android:layout_height="wrap_content"\r
+            android:layout_margin="4dp"\r
             android:layout_gravity="top|right"\r
-            android:orientation="vertical"\r
-            android:layout_margin="2dp">\r
-\r
-            <ImageView\r
-                android:id="@+id/sharedIcon"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_gravity="center"\r
-                android:layout_marginBottom="2dp"\r
-                android:src="@drawable/sharedlink" />\r
-\r
-            <ImageView\r
-                android:id="@+id/sharedWithMeIcon"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_gravity="center"\r
-                android:layout_marginTop="2dp"\r
-                android:src="@drawable/shared_with_me"\r
-                android:visibility="invisible" />\r
-        </LinearLayout>\r
+            android:src="@drawable/shared_via_link" />\r
 \r
         <ImageView\r
             android:id="@+id/localFileIndicator"\r
             android:layout_marginRight="2dp"\r
             android:src="@drawable/ic_favorite" />\r
 \r
-\r
+        <ImageView\r
+            android:id="@+id/custom_checkbox"\r
+            android:layout_width="wrap_content"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="center_vertical|bottom"\r
+            android:layout_marginLeft="4dp"\r
+            android:layout_marginRight="4dp"\r
+            android:gravity=""\r
+            android:src="@android:drawable/checkbox_off_background"\r
+            android:elevation="30dp" />\r
 \r
     </FrameLayout>\r
 \r
index a8e8cc3..964b845 100644 (file)
     <TextView
         android:id="@+id/footerText"
         android:layout_width="match_parent"
-        android:layout_height="56dp"
+        android:layout_height="wrap_content"
+        android:padding="@dimen/standard_padding"
         android:layout_gravity="center"
         android:gravity="center"
-        android:textColor="@color/setup_text_hint"
+        android:textColor="@color/secondaryTextColor"
         />
 
 </LinearLayout> 
\ No newline at end of file
index 81b5210..bd8b12d 100644 (file)
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:fab="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
+    xmlns:fab="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_weight="1" >
+    android:layout_height="match_parent">
 
     <android.support.v4.widget.SwipeRefreshLayout
         android:id="@+id/swipe_containing_list"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" 
-        android:layout_weight="1"
+        android:layout_height="match_parent"
         android:footerDividersEnabled="false"
         android:visibility="visible" >
         
@@ -35,6 +39,8 @@
             android:id="@+id/list_root"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:divider="@color/list_divider_background"
+            android:dividerHeight="1px"
             android:visibility="visible" />
 
     </android.support.v4.widget.SwipeRefreshLayout>
             </ScrollView>
     </android.support.v4.widget.SwipeRefreshLayout>
 
-</FrameLayout>
\ No newline at end of file
+</FrameLayout>
+    <com.getbase.floatingactionbutton.FloatingActionsMenu
+        android:id="@+id/fab_main"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentEnd="true"
+        fab:fab_addButtonColorNormal="@color/owncloud_blue_accent"
+        fab:fab_addButtonColorPressed="@color/owncloud_blue"
+        fab:fab_addButtonPlusIconColor="@color/white"
+        fab:fab_labelStyle="@style/menu_labels_style"
+        android:layout_marginBottom="@dimen/standard_margin"
+        android:layout_marginRight="@dimen/standard_margin"
+        android:layout_marginEnd="@dimen/standard_margin"
+        android:visibility="gone">
+
+        <com.getbase.floatingactionbutton.FloatingActionButton
+            android:id="@+id/fab_upload"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            fab:fab_size="mini"
+            fab:fab_icon="@drawable/ic_action_upload"
+            fab:fab_colorNormal="@color/owncloud_blue_accent"
+            fab:fab_colorPressed="@color/owncloud_blue"
+            fab:fab_title=""/>
+
+        <com.getbase.floatingactionbutton.FloatingActionButton
+            android:id="@+id/fab_mkdir"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            fab:fab_size="mini"
+            fab:fab_icon="@drawable/ic_action_create_dir"
+            fab:fab_colorNormal="@color/owncloud_blue_accent"
+            fab:fab_colorPressed="@color/owncloud_blue"
+            fab:fab_title=""/>
+
+        <com.getbase.floatingactionbutton.FloatingActionButton
+            android:id="@+id/fab_upload_from_app"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            fab:fab_size="mini"
+            fab:fab_icon="@drawable/ic_import"
+            fab:fab_colorNormal="@color/owncloud_blue_accent"
+            fab:fab_colorPressed="@color/owncloud_blue"
+            fab:fab_title=""/>
+
+    </com.getbase.floatingactionbutton.FloatingActionsMenu>
+</RelativeLayout>
index be0b94e..cf09502 100644 (file)
@@ -22,7 +22,7 @@
     android:layout_width="match_parent"\r
     android:background="@drawable/list_selector"\r
     android:orientation="vertical"\r
-    android:layout_height="56dp">\r
+    android:layout_height="72dp">\r
 \r
     <LinearLayout\r
         android:layout_width="match_parent"\r
         android:orientation="horizontal">\r
 \r
         <FrameLayout\r
-            android:layout_width="56dp"\r
-            android:layout_height="56dp"\r
+            android:layout_width="60dp"\r
+            android:layout_height="72dp"\r
+            android:paddingLeft="12dp"\r
+            android:paddingBottom="@dimen/standard_padding"\r
+            android:paddingTop="@dimen/standard_padding"\r
+            android:paddingRight="4dp"\r
             android:focusable="false"\r
             android:focusableInTouchMode="false">\r
 \r
                 android:id="@+id/localFileIndicator"\r
                 android:layout_width="@dimen/file_icon_size"\r
                 android:layout_height="@dimen/file_icon_size"\r
-                android:layout_gravity="center_vertical"\r
-                android:layout_marginLeft="22dp"\r
+                android:layout_gravity="top|right"\r
+                android:layout_marginRight="4dp"\r
                 android:src="@drawable/local_file_indicator" />\r
 \r
             <ImageView\r
                 android:id="@+id/thumbnail"\r
                 android:layout_width="@dimen/file_icon_size"\r
                 android:layout_height="@dimen/file_icon_size"\r
-                android:layout_gravity="center_vertical"\r
-                android:layout_marginLeft="12dp"\r
+                android:layout_gravity="left|center_vertical"\r
                 android:src="@drawable/ic_menu_archive" />\r
 \r
             <ImageView\r
@@ -56,8 +59,7 @@
                 android:layout_width="wrap_content"\r
                 android:layout_height="wrap_content"\r
                 android:layout_gravity="bottom|right"\r
-                android:layout_marginBottom="10dp"\r
-                android:layout_marginRight="2dp"\r
+                android:layout_marginRight="4dp"\r
                 android:src="@drawable/ic_favorite" />\r
         </FrameLayout>\r
 \r
@@ -65,7 +67,8 @@
             android:layout_width="0dp"\r
             android:layout_height="match_parent"\r
             android:layout_weight="1"\r
-            android:gravity="center_vertical"\r
+            android:gravity="top"\r
+            android:paddingTop="@dimen/standard_padding"\r
             android:orientation="vertical" >\r
 \r
             <TextView\r
                 android:layout_width="wrap_content"\r
                 android:layout_height="wrap_content"\r
                 android:layout_gravity="center_vertical"\r
-                android:layout_marginLeft="4dp"\r
+                android:layout_marginLeft="0dp"\r
                 android:layout_marginRight="4dp"\r
                 android:ellipsize="middle"\r
                 android:singleLine="true"\r
                 android:text="TextView"\r
-                android:textColor="#303030"\r
-                android:textSize="16dip" />\r
+                android:textColor="@color/textColor"\r
+                android:textSize="@dimen/two_line_primary_text_size" />\r
 \r
             <LinearLayout\r
                 android:layout_width="match_parent"\r
                 android:layout_height="wrap_content"\r
-                android:layout_marginLeft="4dp"\r
+                android:layout_marginLeft="0dp"\r
                 android:layout_marginRight="4dp"\r
-                android:weightSum="1">\r
+                android:orientation="horizontal">\r
 \r
                 <TextView\r
-                    android:id="@+id/last_mod"\r
+                    android:id="@+id/file_size"\r
                     android:layout_width="wrap_content"\r
                     android:layout_height="wrap_content"\r
-                    android:text="TextView"\r
-                    android:layout_weight=".5"\r
+                    android:text="Size MB"\r
                     android:textColor="@color/list_item_lastmod_and_filesize_text"\r
-                    android:textSize="12dip"/>\r
+                    android:textSize="@dimen/two_line_secondary_text_size"/>\r
 \r
                 <TextView\r
-                    android:id="@+id/file_size"\r
+                    android:id="@+id/file_separator"\r
                     android:layout_width="wrap_content"\r
                     android:layout_height="wrap_content"\r
                     android:gravity="right"\r
-                    android:text="TextView"\r
+                    android:text=""\r
                     android:textColor="@color/list_item_lastmod_and_filesize_text"\r
-                    android:layout_weight=".5"\r
-                    android:textSize="12dip"/>\r
+                    android:textSize="@dimen/two_line_secondary_text_size"/>\r
+\r
+                <TextView\r
+                    android:id="@+id/last_mod"\r
+                    android:layout_width="wrap_content"\r
+                    android:layout_height="wrap_content"\r
+                    android:gravity="right"\r
+                    android:text="Mod Date"\r
+                    android:textColor="@color/list_item_lastmod_and_filesize_text"\r
+                    android:textSize="@dimen/two_line_secondary_text_size"/>\r
 \r
             </LinearLayout>\r
 \r
         </LinearLayout>\r
 \r
-        <LinearLayout\r
-            android:layout_width="25dp"\r
-            android:layout_height="match_parent"\r
-            android:gravity="center_vertical"\r
-            android:orientation="vertical">\r
-\r
-            <ImageView\r
-                android:id="@+id/sharedIcon"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_gravity="center"\r
-                android:layout_marginLeft="4dp"\r
-                android:layout_marginBottom="4dp"\r
-                android:layout_marginRight="4dp"\r
-                android:src="@drawable/sharedlink" />\r
-\r
-            <ImageView\r
-                android:id="@+id/sharedWithMeIcon"\r
-                android:layout_width="wrap_content"\r
-                android:layout_height="wrap_content"\r
-                android:layout_gravity="center"\r
-                android:layout_marginLeft="4dp"\r
-                android:layout_marginRight="4dp"\r
-                android:layout_marginTop="4dp"\r
-                android:src="@drawable/shared_with_me"\r
-                android:visibility="invisible" />\r
-\r
-        </LinearLayout>\r
+        <ImageView\r
+            android:id="@+id/sharedIcon"\r
+            android:layout_width="wrap_content"\r
+            android:layout_height="wrap_content"\r
+            android:layout_gravity="center"\r
+            android:layout_marginTop="4dp"\r
+            android:layout_marginLeft="4dp"\r
+            android:layout_marginBottom="4dp"\r
+            android:layout_marginRight="4dp"\r
+            android:src="@drawable/shared_via_link" />\r
 \r
         <ImageView\r
             android:id="@+id/custom_checkbox"\r
             android:layout_height="wrap_content"\r
             android:layout_gravity="center_vertical"\r
             android:layout_marginLeft="4dp"\r
-            android:layout_marginRight="4dp"\r
+            android:layout_marginRight="@dimen/standard_margin"\r
             android:gravity=""\r
-            android:src="@android:drawable/checkbox_off_background" />\r
+            android:src="@drawable/ic_checkbox_blank_outline" />\r
     </LinearLayout>\r
 \r
     <View\r
index 7d7a377..2bc5d66 100644 (file)
@@ -23,7 +23,7 @@
     android:clickable="true"
     android:orientation="vertical"
     android:background="#fff"
-    android:paddingLeft="16dp"
+    android:paddingLeft="@dimen/standard_padding"
     tools:context=".MainActivity" >
 
     <TextView
@@ -32,7 +32,7 @@
         android:layout_height="wrap_content"
         android:drawablePadding="5dp"
         android:gravity="center_vertical"
-        android:paddingLeft="16dp"
+        android:paddingLeft="@dimen/standard_padding"
         android:textSize="16dp" >
 
     </TextView>
index 753d738..ac71114 100644 (file)
@@ -24,7 +24,7 @@
     android:layout_height="56dp"
     android:layout_marginLeft="8dp"
     android:gravity="left"
-    android:paddingLeft="16dp"
+    android:paddingLeft="@dimen/standard_padding"
     android:paddingTop="8dp"
     android:textSize="16dp"
     android:groupIndicator="@android:color/transparent"
index 0dbb9ef..aeea08b 100644 (file)
     android:id="@+id/loadingLayout"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="horizontal" >
+    android:orientation="horizontal"
+    android:padding="@dimen/standard_padding">
 
     <ProgressBar
         android:id="@+id/loadingBar"
+        style="?android:attr/progressBarStyle"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginBottom="10dp"
-        android:layout_marginLeft="10dp"
-        android:layout_marginRight="5dp"
-        android:layout_marginTop="10dp" />
+        android:indeterminate="true"
+        android:indeterminateOnly="false"/>
 
     <TextView
         android:id="@+id/loadingText"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginRight="20dp"
+        android:layout_marginLeft="@dimen/standard_margin"
         android:text="TextView" />
 
 </LinearLayout>
index 2353b19..70169e5 100644 (file)
@@ -30,7 +30,6 @@
         android:textStyle="bold"
         android:textSize="22dp"
         android:textColor="#000000"
-        android:layout_marginTop="5dp"
-        android:layout_marginBottom="5dp" />
+        android:layout_marginBottom="@dimen/standard_margin" />
 
 </LinearLayout>
\ No newline at end of file
index 4f90772..921528e 100644 (file)
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
-    android:padding="10dp"
-    android:paddingLeft="8dp"
-    android:paddingRight="8dp"
     android:weightSum="1" >
 
     <ScrollView
         android:id="@+id/scrollView1"
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:layout_marginBottom="15dp"
-        android:layout_weight="1" >
+        android:layout_marginBottom="@dimen/standard_margin"
+        android:layout_weight="1">
 
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="vertical" >
+            android:orientation="vertical"
+            android:paddingLeft="@dimen/standard_padding"
+            android:paddingRight="@dimen/standard_padding">
 
             <TextView
                 android:id="@+id/logTV"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:text="@string/empty" />
+                android:text="@string/empty"
+                android:typeface="monospace"/>
         </LinearLayout>
     </ScrollView>
 
         android:id="@+id/historyButtonBar"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:orientation="horizontal" >
+        android:orientation="horizontal"
+        android:layout_marginBottom="@dimen/standard_margin"
+        android:layout_marginLeft="@dimen/standard_margin"
+        android:layout_marginRight="@dimen/standard_margin">
 
-    <android.support.v7.widget.AppCompatButton
+    <Button
         android:id="@+id/deleteLogHistoryButton"
-        style="@style/ownCloud.Button"
+        android:theme="@style/Button"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="bottom"
@@ -62,7 +65,7 @@
 
     <android.support.v7.widget.AppCompatButton
         android:id="@+id/sendLogHistoryButton"
-        style="@style/ownCloud.Button"
+        android:theme="@style/Button.Primary"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="bottom"
diff --git a/res/layout/migration_layout.xml b/res/layout/migration_layout.xml
new file mode 100644 (file)
index 0000000..84b5c22
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:gravity="center_vertical">
+
+    <ProgressBar
+        style="?android:attr/progressBarStyleHorizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/migrationProgress"
+        android:layout_gravity="center_horizontal"
+        android:progress="50"
+        android:paddingLeft="30dp"
+        android:paddingRight="30dp"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text=""
+        android:id="@+id/migrationText"
+        android:layout_gravity="center_horizontal"/>
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/drawer_close"
+        android:id="@+id/finishButton"
+        android:layout_gravity="center_horizontal"/>
+</LinearLayout>
\ No newline at end of file
index f3a0d01..14c3cf6 100644 (file)
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:oc="http://schemas.android.com/apk/res/com.owncloud.android"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:gravity="center_horizontal"
     android:orientation="vertical"
-    android:padding="20dp" >
+    android:padding="@dimen/standard_padding" >
 
 
     <TextView
@@ -33,6 +32,7 @@
         android:text="@string/pass_code_enter_pass_code"
         android:textColor="@android:color/black"
         android:gravity="center_horizontal"
+        android:textSize="16sp"
          />
 
     <TextView
@@ -42,6 +42,7 @@
         android:text="@string/pass_code_configure_your_pass_code_explanation"
         android:textAppearance="@android:style/TextAppearance.Small"
         android:gravity="center_horizontal"
+        android:textSize="14sp"
          />
     
     <LinearLayout
@@ -81,7 +82,7 @@
 
     <android.support.v7.widget.AppCompatButton
         android:id="@+id/cancel"
-        style="@style/ownCloud.Button"
+        android:theme="@style/Button.Primary"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="@string/common_cancel" />
diff --git a/res/layout/search_users_groups_layout.xml b/res/layout/search_users_groups_layout.xml
new file mode 100644 (file)
index 0000000..8eed34a
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:id="@+id/search_layout"
+    android:minWidth="200dp">
+
+    <SearchView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/searchView"
+        android:hint="@string/share_search"/>
+
+    <ListView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/searchUsersListView"
+        android:scrollbars="vertical"/>
+
+</LinearLayout>
diff --git a/res/layout/share_activity.xml b/res/layout/share_activity.xml
new file mode 100644 (file)
index 0000000..772b941
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.owncloud.android.ui.activity.ShareActivity">
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/share_fragment_container">
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/res/layout/share_file_layout.xml b/res/layout/share_file_layout.xml
new file mode 100644 (file)
index 0000000..feaddb3
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.owncloud.android.ui.fragment.ShareFileFragment">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/background_material_light"
+        android:orientation="vertical">
+
+        <RelativeLayout
+            android:id="@+id/shareHeaderContainer"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="6dp"
+            android:layout_marginBottom="6dp"
+            android:background="@color/background_color">
+
+            <ImageView
+                android:id="@+id/shareFileIcon"
+                android:layout_width="@dimen/file_icon_size"
+                android:layout_height="@dimen/file_icon_size"
+                android:src="@drawable/file"
+                android:layout_marginLeft="12dp"
+                android:layout_marginRight="12dp"
+                android:layout_gravity="center_vertical"
+                android:layout_marginTop="12dp"
+                android:layout_marginBottom="12dp"/>
+
+            <TextView
+                android:id="@+id/shareFileName"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/placeholder_filename"
+                android:textSize="16dip"
+                android:layout_gravity="center_vertical"
+                android:layout_marginLeft="4dp"
+                android:layout_marginRight="8dp"
+                android:layout_toRightOf="@+id/shareFileIcon"
+                android:layout_toEndOf="@+id/shareFileIcon"
+                android:singleLine="true"
+                android:ellipsize="middle"
+                android:layout_marginTop="12dp"/>
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textSize="12dip"
+                android:text="@string/placeholder_filesize"
+                android:id="@+id/shareFileSize"
+                android:layout_below="@+id/shareFileName"
+                android:layout_toRightOf="@+id/shareFileIcon"
+                android:layout_toEndOf="@+id/shareFileIcon"
+                android:layout_marginTop="4dp"
+                android:layout_marginLeft="4dp"
+                android:layout_marginBottom="12dp"
+                android:layout_gravity="center_vertical"/>
+
+        </RelativeLayout>
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:textSize="16dip"
+            android:text="@string/share_with_user_section_title"
+            android:id="@+id/shareWithUsersSectionTitle"
+            android:layout_gravity="left"
+            android:padding="8dp"
+            android:background="@color/actionbar_start_color"
+            android:textColor="@color/white"/>
+
+        <ListView
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:id="@+id/shareUsersList"
+            android:visibility="gone"
+            android:scrollbars="vertical"
+            android:layout_weight="1"/>
+
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:id="@+id/shareNoUsers"
+            android:text="@string/share_no_users"
+            android:textSize="12dip"
+            android:padding="12dp" />
+
+        <android.support.v7.widget.AppCompatButton
+            android:id="@+id/addUserButton"
+            style="@style/ownCloud.Button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:text="@string/share_add_user_or_group"
+            android:contentDescription="shareAddUserButton"/>
+
+    </LinearLayout>
+</FrameLayout>
diff --git a/res/layout/share_user_item.xml b/res/layout/share_user_item.xml
new file mode 100644 (file)
index 0000000..2bb8c28
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:weightSum="1"
+        android:longClickable="true">
+        <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.9"
+            android:textSize="16dip"
+            android:text="@string/username"
+            android:id="@+id/userOrGroupName"
+            android:layout_margin="12dp"
+            android:textColor="@color/textColor"
+            android:singleLine="true"
+            android:ellipsize="middle"/>
+
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="0.1"
+            android:id="@+id/unshareButton"
+            android:src="@drawable/ic_cancel"
+            android:layout_marginRight="8dp"
+            android:layout_marginLeft="4dp"
+            android:layout_gravity="center_horizontal"/>
+    </LinearLayout>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/list_divider_background"></View>
+</LinearLayout>
index 8ef7b13..8b6d502 100644 (file)
@@ -21,7 +21,7 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:gravity="center"
-       android:padding="16dp"
+       android:padding="@dimen/standard_padding"
     android:orientation="vertical" >
 
        <TextView
@@ -29,7 +29,7 @@
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="0"
-               android:paddingBottom="16dp"
+               android:paddingBottom="@dimen/standard_padding"
                android:text="@string/ssl_validator_header"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="@android:color/black"
                                    android:text=""
                                    android:textAppearance="?android:attr/textAppearanceSmall"
                                />
-                               
 
                                <TextView
                                android:id="@+id/label_signature"
                                android:text=""
                                android:textAppearance="?android:attr/textAppearanceSmall"
                        />
-                                                                                                                                                                                               
-                                                               
+
                                <TextView
-                               android:id="@+id/value_signature"
-                               android:layout_width="wrap_content"
-                               android:layout_height="wrap_content"
+                                       android:id="@+id/label_certificate_fingerprint"
+                                       android:layout_width="wrap_content"
+                                       android:layout_height="wrap_content"
                                        android:paddingBottom="5dp"
-                               android:text=""
-                               android:textAppearance="?android:attr/textAppearanceSmall"
-                       />
+                                       android:text="@string/ssl_validator_label_certificate_fingerprint"
+                                       android:textAppearance="?android:attr/textAppearanceSmall"
+                               />
+
+                               <TextView
+                                       android:id="@+id/value_certificate_fingerprint"
+                                       android:layout_width="wrap_content"
+                                       android:layout_height="wrap_content"
+                                       android:paddingBottom="5dp"
+                                       android:text=""
+                                       android:textAppearance="?android:attr/textAppearanceSmall"
+                               />
                                
                </LinearLayout>
                
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
                android:layout_weight="0"
-               android:paddingTop="16dp"
+               android:paddingTop="@dimen/standard_padding"
         android:text="@string/ssl_validator_question"
         android:textAppearance="?android:attr/textAppearanceMedium"
         >
index 4cbd46a..df14a35 100644 (file)
     android:layout_height="wrap_content"
     android:gravity="center"
     android:orientation="vertical"
-       android:padding="16dp">
+       android:padding="@dimen/standard_padding">
 
        <TextView
                android:id="@+id/header"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/ssl_validator_header"
-               android:paddingBottom="16dp"
+               android:paddingBottom="@dimen/standard_padding"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="@color/black"
                 />
         android:id="@+id/question"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-               android:paddingTop="16dp"
+               android:paddingTop="@dimen/standard_padding"
         android:text="@string/ssl_validator_question"
         android:textAppearance="?android:attr/textAppearanceMedium"
         >
index 95a3fb2..fbf9cee 100644 (file)
     <LinearLayout\r
         android:layout_width="match_parent"\r
         android:layout_height="wrap_content"\r
+        android:orientation="horizontal">\r
+\r
+        <ImageView\r
+            android:layout_width="match_parent"\r
+            android:layout_height="1dp"\r
+            android:src="@drawable/uploader_list_separator"/>\r
+\r
+    </LinearLayout>\r
+\r
+    <LinearLayout\r
+        android:orientation="horizontal"\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
+        android:paddingTop="8dp"\r
+        android:paddingLeft="16dp"\r
+        android:paddingRight="16dp">\r
+\r
+        <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"\r
+            android:id="@+id/drawer_radio_group"\r
+            android:layout_width="fill_parent"\r
+            android:layout_height="wrap_content"\r
+            android:gravity="center"\r
+            android:orientation="horizontal">\r
+\r
+            <RadioButton\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:text="@string/upload_copy_files"\r
+                android:id="@+id/upload_radio_copy"\r
+                android:paddingRight="8dp"\r
+                android:checked="false" />\r
+\r
+            <RadioButton\r
+                android:layout_width="wrap_content"\r
+                android:layout_height="wrap_content"\r
+                android:text="@string/upload_move_files"\r
+                android:id="@+id/upload_radio_move"\r
+                android:paddingRight="8dp"\r
+                android:checked="false" />\r
+        </RadioGroup>\r
+    </LinearLayout>\r
+\r
+    <LinearLayout\r
+        android:layout_width="match_parent"\r
+        android:layout_height="wrap_content"\r
         android:gravity="center"\r
-        android:orientation="horizontal" >\r
+        android:orientation="horizontal"\r
+        android:paddingLeft="16dp"\r
+        android:paddingRight="16dp"\r
+        android:paddingBottom="16dp">\r
 \r
         <android.support.v7.widget.AppCompatButton\r
             android:id="@+id/upload_files_btn_cancel"\r
-            style="@style/ownCloud.Button"\r
+            android:theme="@style/Button"\r
             android:layout_width="wrap_content"\r
             android:layout_height="wrap_content"\r
             android:layout_weight="1"\r
@@ -46,7 +94,7 @@
 \r
         <android.support.v7.widget.AppCompatButton\r
                    android:id="@+id/upload_files_btn_upload"\r
-            style="@style/ownCloud.Button"\r
+            android:theme="@style/Button.Primary"\r
                    android:layout_width="wrap_content"\r
                    android:layout_height="wrap_content"\r
                    android:layout_weight="1"\r
index 79b077d..51122ec 100644 (file)
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_height="wrap_content" android:orientation="vertical"
-       android:layout_width="wrap_content" android:background="#fefefe"
+       android:layout_height="wrap_content"
+       android:orientation="vertical"
+       android:layout_width="wrap_content"
+       android:background="@color/white"
        android:gravity="center">
 
-       <TextView android:layout_width="fill_parent"
-               android:text="@string/uploader_top_message"
-               android:layout_height="wrap_content"
-               android:id="@+id/drawer_username"
-               android:textColor="@android:color/black"
-               android:gravity="center_horizontal">
-       </TextView>
-
-       <FrameLayout android:layout_height="fill_parent"
+       <FrameLayout
+               android:layout_height="fill_parent"
                android:layout_width="fill_parent"
-               android:id="@+id/frameLayout1"
-               android:layout_below="@+id/drawer_username"
-               android:layout_above="@+id/linearLayout1">
+               android:id="@+id/upload_list"
+               android:layout_above="@+id/upload_actions">
 
-               <ListView android:id="@android:id/list"
+               <ListView
+                       android:id="@android:id/list"
                        android:layout_width="fill_parent"
                        android:layout_height="fill_parent"
-                       android:divider="@drawable/uploader_list_separator"
-                       android:dividerHeight="1dip">
+                       android:divider="@color/list_divider_background"
+                       android:dividerHeight="1dp">
                </ListView>
 
        </FrameLayout>
 
        <LinearLayout
-           android:id="@+id/linearLayout1"
+           android:id="@+id/upload_actions"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:orientation="horizontal" >
 
                <android.support.v7.widget.AppCompatButton
+                       android:theme="@style/Button"
                    android:id="@+id/uploader_cancel"
                        style="@style/ownCloud.Button"
                    android:layout_width="fill_parent"
@@ -63,7 +59,7 @@
 
                <android.support.v7.widget.AppCompatButton
                    android:id="@+id/uploader_choose_folder"
-                       style="@style/ownCloud.Button"
+                       android:theme="@style/Button.Primary"
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="bottom"
index f83608e..9f6f5ba 100644 (file)
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
  -->
-<LinearLayout
-       xmlns:android="http://schemas.android.com/apk/res/android"
-       android:layout_width="fill_parent"
-       android:background="#fefefe"
-       android:orientation="horizontal"
-       android:layout_height="56dp"  >
-  
-    <ImageView 
-        android:layout_width="20dp"
-        android:layout_height="20dp"
-        android:layout_gravity="center_vertical|center"
-        android:layout_margin="4dp"
-        android:src="@drawable/ic_menu_archive" 
-        android:id="@+id/thumbnail" />
-    
-    <TextView 
-        android:text="TextView" 
-        android:layout_width="fill_parent" 
-        android:id="@+id/filename"
-        android:layout_height="wrap_content" 
-        android:textColor="@android:color/black"
-               android:layout_gravity="center_vertical"
-        android:textSize="20dip"/>
-    
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="72dp"
+    android:background="@drawable/list_selector"
+    android:orientation="horizontal">
+
+    <LinearLayout
+        android:layout_width="60dp"
+        android:layout_height="72dp"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:id="@+id/thumbnail"
+            android:layout_width="@dimen/file_icon_size"
+            android:layout_height="@dimen/file_icon_size"
+            android:layout_gravity="center_vertical"
+            android:layout_marginLeft="12dp"
+            android:src="@drawable/ic_menu_archive" />
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="top"
+        android:paddingTop="@dimen/standard_padding"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/filename"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:layout_marginRight="4dp"
+            android:ellipsize="middle"
+            android:singleLine="true"
+            android:text="TextView"
+            android:textColor="@color/textColor"
+            android:textSize="16sp" />
+
+        <TextView
+            android:id="@+id/last_mod"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginRight="4dp"
+            android:text="TextView"
+            android:textColor="@color/list_item_lastmod_and_filesize_text"
+            android:textSize="14sp" />
+
+    </LinearLayout>
+
 </LinearLayout>
index 3e6f4cd..4d24759 100644 (file)
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
   ownCloud Android client application
 
   Copyright (C) 2012  Bartek Przybylski
         android:icon="@android:drawable/ic_menu_share"
         android:orderInCategory="1" />
     <item
+        android:id="@+id/action_stream_file"
+        android:title="@string/action_stream_file"
+        android:icon="@android:drawable/ic_menu_view"
+        android:orderInCategory="1" />
+    <item
         android:id="@+id/action_unshare_file"
         android:title="@string/action_unshare_file"
         android:icon="@android:drawable/ic_menu_share"
         android:orderInCategory="1" />
     <item
+        android:id="@+id/action_share_with_users"
+        android:title="@string/action_share_with_users"
+        android:orderInCategory="1" />
+
+    <item
         android:id="@+id/action_open_file_with"
         android:title="@string/actionbar_open_with"
         android:icon="@android:drawable/ic_menu_set_as"
         android:icon="@drawable/ic_action_refresh"
         android:orderInCategory="1" />
     <item
-        android:id="@+id/action_cancel_download"
-        android:title="@string/common_cancel_download"
-        android:icon="@android:drawable/ic_menu_close_clear_cancel"
-        android:orderInCategory="1" />
-    <item
-        android:id="@+id/action_cancel_upload"
-        android:title="@string/common_cancel_upload"
+        android:id="@+id/action_cancel_sync"
+        android:title="@string/common_cancel_sync"
         android:icon="@android:drawable/ic_menu_close_clear_cancel"
         android:orderInCategory="1" />
     <item
         android:icon="@android:drawable/ic_menu_set_as"
         android:orderInCategory="1" />
     <item
+        android:id="@+id/action_set_as_wallpaper"
+        android:title="@string/set_picture_as"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
         android:id="@+id/action_see_details"
         android:title="@string/actionbar_see_details"
         android:icon="@android:drawable/ic_menu_info_details"
index 236bfd6..097807a 100644 (file)
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <item
-        android:id="@+id/action_upload"
-        android:icon="@drawable/ic_action_upload"
-        android:orderInCategory="2"
-        app:showAsAction="always"
-        android:title="@string/actionbar_upload"
-        android:contentDescription="@string/actionbar_upload"/>
-    <item
         android:id="@+id/action_create_dir"
         android:icon="@drawable/ic_action_create_dir"
-        android:orderInCategory="2"
-        app:showAsAction="always"
+        android:orderInCategory="1"
+        app:showAsAction="never"
         android:title="@string/actionbar_mkdir"
         android:contentDescription="@string/actionbar_mkdir"/>
     <item
+        android:id="@+id/action_switch_view"
+        android:icon="@drawable/ic_view_module"
+        android:orderInCategory="2"
+        app:showAsAction="never"
+        android:title="@string/action_switch_grid_view" />
+    <item
         android:id="@+id/action_sync_account"
         android:icon="@drawable/ic_action_refresh"
-        android:orderInCategory="2"
+        android:orderInCategory="1"
         app:showAsAction="never"
         android:title="@string/actionbar_sync"
         android:contentDescription="@string/actionbar_sync"/>
        <item
         android:id="@+id/action_sort"
-        android:icon="@android:drawable/ic_menu_sort_by_size"
-        android:orderInCategory="2"
+        android:icon="@drawable/ic_sort_variant"
+        android:orderInCategory="1"
         app:showAsAction="never"
         android:title="@string/actionbar_sort"
         android:contentDescription="@string/actionbar_sort"/>
diff --git a/res/menu/multiple_file_actions_menu.xml b/res/menu/multiple_file_actions_menu.xml
new file mode 100644 (file)
index 0000000..fce1654
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ownCloud Android client application
+
+  Copyright (C) 2012  Bartek Przybylski
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/action_download_file"
+        android:title="@string/filedetails_download"
+        android:icon="@drawable/ic_action_download"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_move"
+        android:title="@string/actionbar_move"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_copy"
+        android:title="@android:string/copy"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_remove_file"
+        android:title="@string/common_remove"
+        android:icon="@android:drawable/ic_menu_delete"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_favorite_file"
+        android:title="@string/favorite"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+    <item
+        android:id="@+id/action_unfavorite_file"
+        android:title="@string/unfavorite"
+        android:icon="@android:drawable/ic_menu_set_as"
+        android:orderInCategory="1" />
+</menu>
diff --git a/res/menu/uploader_menu.xml b/res/menu/uploader_menu.xml
new file mode 100644 (file)
index 0000000..a721c7b
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  Copyright (C) 2012  Bartek Przybylski
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <item
+        android:id="@+id/action_sort"
+        android:icon="@android:drawable/ic_menu_sort_by_size"
+        android:orderInCategory="2"
+        app:showAsAction="always"
+        android:title="@string/actionbar_sort"
+        android:contentDescription="@string/actionbar_sort"/>
+</menu>
\ No newline at end of file
index be9f464..81613ea 100644 (file)
   <string name="filedetails_created">انشئ في :</string>
   <string name="filedetails_modified">عُدل في :</string>
   <string name="filedetails_download">تحميل</string>
-  <string name="filedetails_sync_file">تحديث الملف</string>
   <string name="filedetails_renamed_in_upload_msg">تم تغيير اسم الملف إلى  %1$s أثناء الرفع</string>
   <string name="action_share_file">شارك الرابط</string>
   <string name="action_unshare_file">الغاء مشاركة الرابط</string>
   <string name="common_yes">نعم</string>
   <string name="common_no">لا</string>
   <string name="common_ok">تم</string>
-  <string name="common_cancel_download">إلغاء التحميل</string>
-  <string name="common_cancel_upload">إلغاء الرفع</string>
   <string name="common_cancel">إلغاء</string>
   <string name="common_save_exit">حفظ + خروج</string>
   <string name="common_error">خطأ</string>
   <string name="favorite">المفضلة</string>
   <string name="common_rename">إعادة التسمية</string>
   <string name="common_remove">حذف</string>
-  <string name="confirmation_remove_alert">هل تريد حقاً حذف %1$s ؟</string>
+  <string name="confirmation_remove_file_alert">هل تريد حقاً حذف %1$s ؟</string>
   <string name="confirmation_remove_folder_alert">هل ترغب في حذف %1$s و جهات الإتصال التابعة له؟ </string>
   <string name="confirmation_remove_local">محليا فقط</string>
   <string name="confirmation_remove_folder_local">محليا فقط</string>
   <string name="folder_picker_choose_button_text">اختيار</string>
   <string name="prefs_category_security">الأمان</string>
   <string name="auth_host_address">عنوان الخادم</string>
+  <string name="share_dialog_title">مشاركة</string>
+  <string name="share_search">البحث</string>
 </resources>
index ed93bc2..d3cd832 100644 (file)
   <string name="filedetails_created">Yaradıldı:</string>
   <string name="filedetails_modified">Dəyişdirildi:</string>
   <string name="filedetails_download">Yüklə</string>
-  <string name="filedetails_sync_file">Faylı yenilə</string>
   <string name="filedetails_renamed_in_upload_msg">Yüklənmə müddətində fayl buna %1$s yeniləndi</string>
   <string name="action_share_file">Linki yayımla</string>
   <string name="action_unshare_file">Link yayımlanmasını dayandır</string>
   <string name="common_yes">Bəli</string>
   <string name="common_no">Xeyir</string>
   <string name="common_ok">Oldu</string>
-  <string name="common_cancel_download">Endirimi dayandır</string>
-  <string name="common_cancel_upload">Yüklənməni dayandır</string>
   <string name="common_cancel">Dayandır</string>
   <string name="common_save_exit">Saxla &amp; Çıx</string>
   <string name="common_error">Səhv</string>
@@ -184,7 +181,7 @@ Aşağıda göstərilən %5$s-də olan daxili və xarici fayl(lar) link edilmiş
   <string name="favorite">İstəkli</string>
   <string name="common_rename">Adı dəyiş</string>
   <string name="common_remove">Sil</string>
-  <string name="confirmation_remove_alert">Siz həqiqətən %1$s silmək istəyirsiniz?</string>
+  <string name="confirmation_remove_file_alert">Siz həqiqətən %1$s silmək istəyirsiniz?</string>
   <string name="confirmation_remove_folder_alert">Siz həqiqətəndə %1$s və onun kontentini silmək istəyirsiniz?</string>
   <string name="confirmation_remove_local">Yalnız daxili</string>
   <string name="confirmation_remove_folder_local">Yalnız daxili</string>
@@ -288,7 +285,9 @@ inzibatçınızla əlaqə saxlayasınız.</string>
   <string name="prefs_category_instant_uploading">Anında yükləmələr</string>
   <string name="prefs_category_security">Təhlükəsizlik</string>
   <string name="prefs_instant_video_upload_path_title">Video ünvanını yüklə</string>
-  <string name="download_folder_failed_content">Qovluğun endirilməsinin %1$s hissəsi tamamlana bilməz </string>
+  <string name="subject_user_shared_with_you">%1$s paylaşdı \"%2$s\" sizinlə</string>
   <string name="auth_refresh_button">Qoşulmanı yenilə</string>
   <string name="auth_host_address">Server ünvanı</string>
+  <string name="share_dialog_title">Paylaşılır</string>
+  <string name="share_search">Axtarış</string>
 </resources>
index 96334e4..eea53c9 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Създаден на:</string>
   <string name="filedetails_modified">Променен на:</string>
   <string name="filedetails_download">Изтегляне</string>
-  <string name="filedetails_sync_file">Обновяване на файла</string>
   <string name="filedetails_renamed_in_upload_msg">Файлът беше преименуван на %1$s по време на качването.</string>
   <string name="list_layout">Списък с изгледи</string>
   <string name="action_share_file">Връзка за споделяне</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">ОК</string>
-  <string name="common_cancel_download">Отказване на тегленето</string>
-  <string name="common_cancel_upload">Отказване на качването</string>
   <string name="common_cancel">Отказ</string>
   <string name="common_save_exit">Запазване и изход</string>
   <string name="common_error">Грешка</string>
   <string name="favorite">Любими</string>
   <string name="common_rename">Преименуване</string>
   <string name="common_remove">Премахване</string>
-  <string name="confirmation_remove_alert">Наистина ли искате да изтриете %1$s ?</string>
+  <string name="confirmation_remove_file_alert">Наистина ли искате да изтриете %1$s ?</string>
   <string name="confirmation_remove_folder_alert">Наистина ли искате да премахнете %1$s и съдържанието му?</string>
   <string name="confirmation_remove_local">Само локално</string>
   <string name="confirmation_remove_folder_local">Само локално</string>
   <string name="prefs_category_instant_uploading">Незабавно качване</string>
   <string name="prefs_category_security">Сигурност</string>
   <string name="prefs_instant_video_upload_path_title">Качване на видео път</string>
-  <string name="download_folder_failed_content">Свалянето на директорията %1$s не може да бъде завършено</string>
   <string name="shared_subject_header">споделен</string>
   <string name="with_you_subject_header">с теб</string>
-  <string name="subject_token">%1$s споделен \"%2$s\" с теб</string>
+  <string name="subject_user_shared_with_you">%1$s споделен \"%2$s\" с теб</string>
   <string name="auth_refresh_button">Обнови връзката</string>
   <string name="auth_host_address">Адрес на сървъра</string>
   <string name="common_error_out_memory">Няма достатъчно памет</string>
   <string name="file_list__footer__files">%1$d файла</string>
   <string name="file_list__footer__files_and_folder">%1$d файла, 1 папка</string>
   <string name="file_list__footer__files_and_folders">%1$d файла, %2$d папки</string>
+  <string name="share_dialog_title">Споделяне</string>
+  <string name="share_search">Търсене</string>
 </resources>
index d5833d3..49df5a6 100644 (file)
   <string name="filedetails_created">তৈরীর নির্ঘন্টঃ</string>
   <string name="filedetails_modified">পরিবর্তিতঃ</string>
   <string name="filedetails_download">ডাউনলোড</string>
-  <string name="filedetails_sync_file">ফাইল নবোদ্যম করুন</string>
   <string name="filedetails_renamed_in_upload_msg">আপলোডের সময় ফাইলের পূণঃনামকরণ করা হয়েছে %1$s</string>
   <string name="action_share_file">লিংক ভাগাভাগি করেন</string>
   <string name="action_unshare_file">লিংক ছিনন করেন</string>
   <string name="common_yes">হ্যাঁ</string>
   <string name="common_no">না</string>
   <string name="common_ok">তথাস্তু</string>
-  <string name="common_cancel_download">ডাউনলোড বাতিল করেন</string>
-  <string name="common_cancel_upload">আপলোড বাতিল কর</string>
   <string name="common_cancel">বাতিল</string>
   <string name="common_save_exit">সংরক্ষণ কর এবং &amp;প্রস্থান</string>
   <string name="common_error">সমস্যা</string>
   <string name="favorite">প্রিয়জন</string>
   <string name="common_rename">পূনঃনামকরণ</string>
   <string name="common_remove">অপসারণ</string>
-  <string name="confirmation_remove_alert">আপনি কি সত্যিই %1$s অপসারণ করতে চান?</string>
+  <string name="confirmation_remove_file_alert">আপনি কি সত্যিই %1$s অপসারণ করতে চান?</string>
   <string name="confirmation_remove_folder_alert">আপনি কি সত্যিই %1$s এবং এর কনটেন্ট অপসারণ করতে চান?</string>
   <string name="confirmation_remove_local">শুধুমাত্র লোকাল</string>
   <string name="confirmation_remove_folder_local">শুধুমাত্র লোকাল</string>
   <string name="move_file_not_found">সরাতে ব্যার্থ হলো। ফাইলটি রয়েছে কিনা দেখুন।</string>
   <string name="prefs_category_security">নিরাপত্তা</string>
   <string name="auth_host_address">সার্ভার ঠিকানা</string>
+  <string name="share_dialog_title">ভাগাভাগিরত</string>
+  <string name="share_search">অনুসন্ধান</string>
 </resources>
index d529561..87b4b20 100644 (file)
@@ -23,4 +23,5 @@
   <string name="common_rename">পুনঃনামকরণ</string>
   <string name="common_remove">সরান</string>
   <string name="empty"></string>
+  <string name="share_search">অনুসন্ধান</string>
 </resources>
index 8c01ccc..4ce4a45 100644 (file)
@@ -24,7 +24,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Ok</string>
-  <string name="common_cancel_upload">Prekini učitavanje</string>
   <string name="common_cancel">Odustani</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata greška</string>
@@ -39,4 +38,6 @@
   <string name="folder_picker_choose_button_text">Izaberite</string>
   <string name="prefs_category_security">Sigurnost</string>
   <string name="auth_host_address">Adresa servera</string>
+  <string name="share_dialog_title">Dijeljenje</string>
+  <string name="share_search">Potraži</string>
 </resources>
index 718efbf..b860271 100644 (file)
   <string name="filedetails_created">Creat:</string>
   <string name="filedetails_modified">Modificat:</string>
   <string name="filedetails_download">Baixa</string>
-  <string name="filedetails_sync_file">Actualitza el fitxer</string>
   <string name="filedetails_renamed_in_upload_msg">L\'arxiu s\'ha canviat de nom a %1$s durant la càrrega</string>
   <string name="action_share_file">Enllaç de compartició</string>
   <string name="action_unshare_file">Deixa de compartir l\'enllaç</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">D\'acord</string>
-  <string name="common_cancel_download">Cancelar la descàrrega</string>
-  <string name="common_cancel_upload">Cancel·la la pujada</string>
   <string name="common_cancel">Cancel·la</string>
   <string name="common_save_exit">Desa &amp; Surt</string>
   <string name="common_error">Error</string>
   <string name="favorite">Preferits</string>
   <string name="common_rename">Reanomena</string>
   <string name="common_remove">Elimina</string>
-  <string name="confirmation_remove_alert">Esteu segur que voleu eliminar %1$s?</string>
+  <string name="confirmation_remove_file_alert">Esteu segur que voleu eliminar %1$s?</string>
   <string name="confirmation_remove_folder_alert">Estàs segur que vols esborrar %1$s i els seus continguts?</string>
   <string name="confirmation_remove_local">Només local</string>
   <string name="confirmation_remove_folder_local">Només local</string>
   <string name="folder_picker_choose_button_text">Escull</string>
   <string name="prefs_category_security">Seguretat</string>
   <string name="auth_host_address">Adreça del servidor</string>
+  <string name="share_dialog_title">Compartir</string>
+  <string name="share_search">Cerca</string>
 </resources>
index 5147a57..5941be1 100644 (file)
   <string name="filedetails_created">Vytvořen:</string>
   <string name="filedetails_modified">Upraven:</string>
   <string name="filedetails_download">Stáhnout</string>
-  <string name="filedetails_sync_file">Obnovit soubor</string>
+  <string name="filedetails_sync_file">Synchronizovat</string>
   <string name="filedetails_renamed_in_upload_msg">Soubor byl v průběhu odesílání přejmenován na %1$s</string>
   <string name="list_layout">Náhled seznamu</string>
   <string name="action_share_file">Sdílet odkaz</string>
   <string name="action_unshare_file">Zrušit sdílení odkazu</string>
+  <string name="action_share_with_users">Sdílet s uživateli</string>
   <string name="common_yes">Ano</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Zrušit stahování</string>
-  <string name="common_cancel_upload">Zrušit odesílání</string>
+  <string name="common_cancel_sync">Zrušit synchronizaci</string>
   <string name="common_cancel">Zrušit</string>
   <string name="common_save_exit">Uložit a ukončit</string>
   <string name="common_error">Chyba</string>
   <string name="unfavorite">Odebrat z oblíbených</string>
   <string name="common_rename">Přejmenovat</string>
   <string name="common_remove">Odstranit</string>
-  <string name="confirmation_remove_alert">Opravdu chcete odstranit %1$s ?</string>
+  <string name="confirmation_remove_file_alert">Opravdu chcete odstranit %1$s ?</string>
   <string name="confirmation_remove_folder_alert">Opravdu chcete odstranit %1$s a jeho obsah?</string>
   <string name="confirmation_remove_local">Pouze místní</string>
   <string name="confirmation_remove_folder_local">Pouze místní</string>
-  <string name="confirmation_remove_remote">Ze serveru</string>
+  <string name="confirmation_remove_file_remote">Ze serveru</string>
   <string name="confirmation_remove_remote_and_local">Vzdálený &amp; místní</string>
   <string name="remove_success_msg">Úspěšně odstraněno</string>
   <string name="remove_fail_msg">Odstranění nelze dokončit</string>
   <string name="ssl_validator_label_validity_to">Pro:</string>
   <string name="ssl_validator_label_signature">Podpis:</string>
   <string name="ssl_validator_label_signature_algorithm">Alogritmus:</string>
+  <string name="digest_algorithm_not_available">Tento algoritmus není na vašem telefonu dostupný.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Otisk:</string>
+  <string name="certificate_load_problem">Došlo k problému s načtením certifikátu.</string>
   <string name="ssl_validator_null_cert">Certifikát nemohl být zobrazen.</string>
   <string name="ssl_validator_no_info_about_error">- Žádné informace o této chybě</string>
   <string name="placeholder_sentence">Zástupný text</string>
@@ -315,11 +318,11 @@ správce systému.</string>
   <string name="prefs_category_instant_uploading">Okamžitá odesílání</string>
   <string name="prefs_category_security">Zabezpečení</string>
   <string name="prefs_instant_video_upload_path_title">Cesta pro nahrávání videí</string>
-  <string name="download_folder_failed_content">Stažení adresáře %1$s nemohlo být dokončeno</string>
+  <string name="sync_folder_failed_content">Synchronizaci adresáře %1$s nelze dokončit</string>
   <string name="shared_subject_header">sdílené</string>
   <string name="with_you_subject_header">s vámi</string>
-  <string name="subject_token">%1$s s vámi sdílí \"%2$s\"</string>
-  <string name="saml_subject_token">\"%1$s\" ti byl nasdílen</string>
+  <string name="subject_user_shared_with_you">%1$s s vámi sdílí \"%2$s\"</string>
+  <string name="subject_shared_with_you">\"%1$s\" ti byl nasdílen</string>
   <string name="auth_refresh_button">Obnovit připojení</string>
   <string name="auth_host_address">Adresa serveru</string>
   <string name="common_error_out_memory">Nedostatek paměti</string>
@@ -332,4 +335,13 @@ správce systému.</string>
   <string name="file_list__footer__files">%1$d soubory(ů)</string>
   <string name="file_list__footer__files_and_folder">%1$d soubory(ů), 1 adresář</string>
   <string name="file_list__footer__files_and_folders">%1$d soubory(ů), %2$d adresáře(ů)</string>
+  <string name="share_dialog_title">Sdílení</string>
+  <string name="share_with_user_section_title">Sdílet s uživateli a skupinami</string>
+  <string name="share_no_users">Zatím nebyla s uživateli sdílena žádná data</string>
+  <string name="share_add_user_or_group">Přidat uživatele nebo skupinu</string>
+  <string name="share_search">Hledat</string>
+  <string name="search_users_and_groups_hint">Prohledat uživatele a skupiny</string>
+  <string name="share_group_clarification">%1$s (skupina)</string>
+  <string name="share_sharee_unavailable">Omlouváme se, verze vašeho serveru neumožňuje v klientské aplikaci sdílení dat mezi uživateli.
+\nKontaktujte prosím svého administrátora</string>
 </resources>
index e7e46fe..d3b885d 100644 (file)
@@ -42,8 +42,6 @@
   <string name="common_yes">Ie</string>
   <string name="common_no">Na</string>
   <string name="common_ok">Iawn</string>
-  <string name="common_cancel_download">Diddymu llwytho i lawr</string>
-  <string name="common_cancel_upload">Diddymu llwytho i fyny</string>
   <string name="common_cancel">Diddymu</string>
   <string name="common_save_exit">Cadw &amp; Gadael</string>
   <string name="common_error">Gwall</string>
   <string name="empty"></string>
   <string name="prefs_category_accounts">Cyfrifon</string>
   <string name="folder_picker_choose_button_text">Dewisiwch</string>
+  <string name="share_search">Chwilio</string>
 </resources>
index 80a6032..be4c942 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Oprettet:</string>
   <string name="filedetails_modified">Ændret:</string>
   <string name="filedetails_download">Hent</string>
-  <string name="filedetails_sync_file">Genopfrisk fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filen blev omdøbt til %1$s under upload</string>
   <string name="list_layout">Listevisning</string>
   <string name="action_share_file">Del link</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nej</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Afbryd download</string>
-  <string name="common_cancel_upload">Fortryd upload</string>
   <string name="common_cancel">Annuller</string>
   <string name="common_save_exit">Gem &amp; Afslut</string>
   <string name="common_error">Fejl</string>
   <string name="unfavorite">Fjern markering som foretrukket</string>
   <string name="common_rename">Omdøb</string>
   <string name="common_remove">Fjern</string>
-  <string name="confirmation_remove_alert">Er du sikker på at du vil fjerne %1$s ?</string>
+  <string name="confirmation_remove_file_alert">Er du sikker på at du vil fjerne %1$s ?</string>
   <string name="confirmation_remove_folder_alert">Ønsker du virkelig at slette %1$s og dets indhold?</string>
   <string name="confirmation_remove_local">Kun lokal</string>
   <string name="confirmation_remove_folder_local">Kun lokal</string>
-  <string name="confirmation_remove_remote">Fra server</string>
+  <string name="confirmation_remove_file_remote">Fra server</string>
   <string name="confirmation_remove_remote_and_local">Fjernbeliggende og lokalt</string>
   <string name="remove_success_msg">Vellykket fjernelse</string>
   <string name="remove_fail_msg">Fjernelse kunne ikke fuldføres</string>
   <string name="prefs_category_instant_uploading">Øjeblikkelige uploads</string>
   <string name="prefs_category_security">Sikkerhed</string>
   <string name="prefs_instant_video_upload_path_title">Sti til videoupload</string>
-  <string name="download_folder_failed_content">Download af %1$s mappe kunne ikke fuldføres</string>
   <string name="shared_subject_header">delt</string>
   <string name="with_you_subject_header">med dig</string>
-  <string name="subject_token">%1$s delte \"%2$s\" med dig</string>
-  <string name="saml_subject_token">\"%1$s\" er blevet delt med dig</string>
+  <string name="subject_user_shared_with_you">%1$s delte \"%2$s\" med dig</string>
+  <string name="subject_shared_with_you">\"%1$s\" er blevet delt med dig</string>
   <string name="auth_refresh_button">Genopfrisk forbindelsen</string>
   <string name="auth_host_address">Serveradresse</string>
   <string name="common_error_out_memory">Ikke tilstrækkelig hukommelse</string>
   <string name="file_list__footer__files">%1$d filer</string>
   <string name="file_list__footer__files_and_folder">%1$d filer, 1 mape</string>
   <string name="file_list__footer__files_and_folders">%1$d filer, %2$d mapper</string>
+  <string name="share_dialog_title">Deling</string>
+  <string name="share_search">Søg</string>
 </resources>
index a99ab89..4396346 100644 (file)
   <string name="filedetails_created">Erstellt am:</string>
   <string name="filedetails_modified">Verändert am:</string>
   <string name="filedetails_download">Herunterladen</string>
-  <string name="filedetails_sync_file">Datei neu laden</string>
   <string name="action_share_file">Link teilen</string>
   <string name="action_unshare_file">Link nicht mehr teilen</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Herunterladen abbrechen</string>
-  <string name="common_cancel_upload">Hochladen abbrechen</string>
   <string name="common_cancel">Abbrechen</string>
   <string name="common_save_exit">Speichern &amp; Schließen</string>
   <string name="common_error">Fehler</string>
index 2039297..375303f 100644 (file)
   <string name="common_remove">Löschen</string>
   <string name="confirmation_remove_local">Nur lokal</string>
   <string name="confirmation_remove_folder_local">Nur lokale Inhalte</string>
-  <string name="confirmation_remove_remote">Vom Server entfernen</string>
+  <string name="confirmation_remove_file_remote">Vom Server entfernen</string>
   <string name="confirmation_remove_remote_and_local">Lokal und auf dem Server</string>
   <string name="remove_success_msg">Erfolgreich gelöscht</string>
   <string name="remove_fail_msg">Der Löschvorgang konnte nicht beendet werden</string>
index 7fe556b..45e371e 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Erstellt:</string>
   <string name="filedetails_modified">Geändert:</string>
   <string name="filedetails_download">Herunterladen</string>
-  <string name="filedetails_sync_file">Datei aktualisieren</string>
   <string name="filedetails_renamed_in_upload_msg">Datei wurde wärend des Uploads zu %1$s umbenannt</string>
   <string name="list_layout">Listen-Layout</string>
   <string name="action_share_file">Link teilen</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Download abbrechen</string>
-  <string name="common_cancel_upload">Upload abbrechen</string>
   <string name="common_cancel">Abbrechen</string>
   <string name="common_save_exit">Speichern &amp; Schließen</string>
   <string name="common_error">Fehler</string>
   <string name="unfavorite">Nicht mehr favorisieren</string>
   <string name="common_rename">Umbenennen</string>
   <string name="common_remove">Löschen</string>
-  <string name="confirmation_remove_alert">Möchten Sie %1$s wirklich löschen?</string>
+  <string name="confirmation_remove_file_alert">Möchten Sie %1$s wirklich löschen?</string>
   <string name="confirmation_remove_folder_alert">Möchten Sie wirklich %1$s und dessen Inhalte entfernen?</string>
   <string name="confirmation_remove_local">Nur lokal</string>
   <string name="confirmation_remove_folder_local">Nur lokal</string>
   <string name="prefs_category_instant_uploading">Sofortiges Hochladen</string>
   <string name="prefs_category_security">Sicherheit</string>
   <string name="prefs_instant_video_upload_path_title">Verzeichnis zum Hochladen der Videos</string>
-  <string name="download_folder_failed_content">Herunterladen des %1$s - Ordners konnte nicht abgeschlossen werden</string>
   <string name="shared_subject_header">geteilt</string>
   <string name="with_you_subject_header">Mit Ihnen</string>
-  <string name="subject_token">%1$s hat \"%2$s\" mit Ihnen geteilt</string>
-  <string name="saml_subject_token">\"%1$s\" wurde mit dir geteilt</string>
+  <string name="subject_user_shared_with_you">%1$s hat \"%2$s\" mit Ihnen geteilt</string>
+  <string name="subject_shared_with_you">\"%1$s\" wurde mit dir geteilt</string>
   <string name="auth_refresh_button">Verbindung aktualisieren</string>
   <string name="auth_host_address">Serveradresse</string>
   <string name="common_error_out_memory">Nicht genügend Speicher</string>
   <string name="file_list__footer__files">%1$d Dateien</string>
   <string name="file_list__footer__files_and_folder">%1$d Dateien, 1 Ordner</string>
   <string name="file_list__footer__files_and_folders">%1$d Dateien, %2$d Ordner</string>
+  <string name="share_dialog_title">Teilen</string>
+  <string name="share_search">Suche</string>
 </resources>
index 562ee84..c84258d 100644 (file)
@@ -79,7 +79,6 @@
   <string name="filedetails_created">Erstellt:</string>
   <string name="filedetails_modified">Geändert:</string>
   <string name="filedetails_download">Herunterladen</string>
-  <string name="filedetails_sync_file">Datei aktualisieren</string>
   <string name="filedetails_renamed_in_upload_msg">Datei wurde wärend des Uploads zu %1$s umbenannt</string>
   <string name="list_layout">Listen-Layout</string>
   <string name="action_share_file">Link teilen</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nein</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Download abbrechen</string>
-  <string name="common_cancel_upload">Upload abbrechen</string>
   <string name="common_cancel">Abbrechen</string>
   <string name="common_save_exit">Speichern &amp; schließen</string>
   <string name="common_error">Fehler</string>
   <string name="unfavorite">Favorit entfernen</string>
   <string name="common_rename">Umbenennen</string>
   <string name="common_remove">Löschen</string>
-  <string name="confirmation_remove_alert">Möchtest Du %1$s wirklich löschen?</string>
+  <string name="confirmation_remove_file_alert">Möchtest Du %1$s wirklich löschen?</string>
   <string name="confirmation_remove_folder_alert">Möchtest Du wirklich %1$s und dessen Inhalte entfernen?</string>
   <string name="confirmation_remove_local">Nur lokal</string>
   <string name="confirmation_remove_folder_local">Nur lokal</string>
   <string name="prefs_category_instant_uploading">Sofortiges Hochladen</string>
   <string name="prefs_category_security">Sicherheit</string>
   <string name="prefs_instant_video_upload_path_title">Verzeichnis zum Hochladen der Videos</string>
-  <string name="download_folder_failed_content">Herunterladen des %1$s - Ordners konnte nicht abgeschlossen werden</string>
   <string name="shared_subject_header">geteilt</string>
   <string name="with_you_subject_header">Mit Dir</string>
-  <string name="subject_token">%1$s hat \"%2$s\" mit Dir geteilt</string>
-  <string name="saml_subject_token">\"%1$s\" wurde mit dir geteilt</string>
+  <string name="subject_user_shared_with_you">%1$s hat \"%2$s\" mit Dir geteilt</string>
+  <string name="subject_shared_with_you">\"%1$s\" wurde mit dir geteilt</string>
   <string name="auth_refresh_button">Verbindung aktualisieren</string>
   <string name="auth_host_address">Serveradresse</string>
   <string name="common_error_out_memory">Nicht genügend Speicher</string>
   <string name="file_list__footer__files">%1$d Dateien</string>
   <string name="file_list__footer__files_and_folder">%1$d Dateien, 1 Ordner</string>
   <string name="file_list__footer__files_and_folders">%1$d Dateien, %2$d Ordner</string>
+  <string name="share_dialog_title">Teilen</string>
+  <string name="share_search">Suche</string>
 </resources>
index 070d6f5..66df5fd 100644 (file)
   <string name="filedetails_created">Δημιουργήθηκε:</string>
   <string name="filedetails_modified">Τροποποιήθηκε:</string>
   <string name="filedetails_download">Λήψη</string>
-  <string name="filedetails_sync_file">Î\91νανέÏ\89Ï\83η Î±Ï\81Ï\87είοÏ\85</string>
+  <string name="filedetails_sync_file">ΣÏ\85γÏ\87Ï\81ονιÏ\83μÏ\8cÏ\82</string>
   <string name="filedetails_renamed_in_upload_msg">Το αρχείο μετονομάστηκε σε %1$s κατά τη μεταφόρτωση</string>
   <string name="list_layout">Διάταξη Λίστας</string>
   <string name="action_share_file">Διαμοιρασμός συνδέσμου</string>
   <string name="action_unshare_file">Ακύρωση διαμοιρασμού συνδέσμου</string>
+  <string name="action_share_with_users">Διαμοιρασμός με χρήστες</string>
   <string name="common_yes">Ναι</string>
   <string name="common_no">Όχι</string>
   <string name="common_ok">ΟΚ</string>
-  <string name="common_cancel_download">Ακύρωση λήψης</string>
-  <string name="common_cancel_upload">Ακύρωση μεταφόρτωσης</string>
+  <string name="common_cancel_sync">Ακύρωση συγχρονισμού</string>
   <string name="common_cancel">Άκυρο</string>
   <string name="common_save_exit">Αποθήκευση &amp; Έξοδος</string>
   <string name="common_error">Σφάλμα</string>
   <string name="unfavorite">Κατάργηση από τα αγαπημένα</string>
   <string name="common_rename">Μετονομασία</string>
   <string name="common_remove">Αφαίρεση</string>
-  <string name="confirmation_remove_alert">Θέλετε στ\' αλήθεια να αφαιρέσετε το  %1$s;</string>
+  <string name="confirmation_remove_file_alert">Θέλετε στ\' αλήθεια να αφαιρέσετε το  %1$s;</string>
   <string name="confirmation_remove_folder_alert">Θέλετε στ\' αλήθεια να διαγράψετε το %1$s και τα περιεχόμενά του;</string>
   <string name="confirmation_remove_local">Μόνο τοπικά</string>
   <string name="confirmation_remove_folder_local">Μόνο τοπικά</string>
-  <string name="confirmation_remove_remote">Από το διακομιστή</string>
+  <string name="confirmation_remove_file_remote">Από το διακομιστή</string>
   <string name="confirmation_remove_remote_and_local">Απομακρυσμένα &amp; τοπικά</string>
   <string name="remove_success_msg">Αφαίρεση επιτυχής</string>
   <string name="remove_fail_msg">Η αφαίρεση απέτυχε</string>
   <string name="ssl_validator_label_validity_to">Μέχρι:</string>
   <string name="ssl_validator_label_signature">Υπογραφή:</string>
   <string name="ssl_validator_label_signature_algorithm">Αλγόριθμος:</string>
+  <string name="digest_algorithm_not_available">Ο αλγόριθμος digest δεν είναι διαθέσιμος στο τηλέφωνό σας.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Ψηφιακό αποτύπωμα:</string>
+  <string name="certificate_load_problem">Πρόβλημα φόρτωσης του πιστοποιητικού.</string>
   <string name="ssl_validator_null_cert">Δεν μπορεί να εμφανιστεί το πιστοποιητικό.</string>
   <string name="ssl_validator_no_info_about_error">- Καμμία πληροφορία σχετικά με το σφάλμα</string>
   <string name="placeholder_sentence">Αυτό είναι ένα σημείο κράτησης θέσης</string>
   <string name="prefs_category_instant_uploading">Στιγμιαίες Μεταφορτώσεις</string>
   <string name="prefs_category_security">Ασφάλεια</string>
   <string name="prefs_instant_video_upload_path_title">Διαδρομή Μεταφόρτωσης Βίντεο</string>
-  <string name="download_folder_failed_content">Η λήψη του φακέλου %1$s δεν ολοκληρώθηκε με επιτυχία.</string>
+  <string name="sync_folder_failed_content">Ο συγχρονισμός του φακέλου %1$s δεν μπόρεσε να ολοκληρωθεί</string>
   <string name="shared_subject_header">διαμοιρασμένα</string>
   <string name="with_you_subject_header">με εσάς</string>
-  <string name="subject_token">Ο %1$s διαμοιράστηκε το \"%2$s\" με εσάς</string>
-  <string name="saml_subject_token">\"%1$s\" μοιράστηκε μαζί σας</string>
+  <string name="subject_user_shared_with_you">Ο %1$s διαμοιράστηκε το \"%2$s\" με εσάς</string>
+  <string name="subject_shared_with_you">\"%1$s\" μοιράστηκε μαζί σας</string>
   <string name="auth_refresh_button">Ανανέωση σύνδεσης</string>
   <string name="auth_host_address">Διεύθυνση διακομιστή</string>
   <string name="common_error_out_memory">Δεν υπάρχει αρκετή μνήμη</string>
   <string name="file_list__footer__files">%1$d αρχεία</string>
   <string name="file_list__footer__files_and_folder">%1$d αρχεία, 1 φάκελος</string>
   <string name="file_list__footer__files_and_folders">%1$d αρχεία, %2$d φάκελοι</string>
+  <string name="share_dialog_title">Διαμοιρασμός</string>
+  <string name="share_with_user_section_title">Διαμοιρασμός με χρήστες και ομάδες</string>
+  <string name="share_no_users">Δεν έχουν διαμοιραστεί ακόμα δεδομένα με τους χρήστες</string>
+  <string name="share_add_user_or_group">Προσθήκη χρήστη ή ομάδας</string>
+  <string name="share_search">Αναζήτηση</string>
+  <string name="search_users_and_groups_hint">Αναζήτηση χρηστών και ομάδων</string>
+  <string name="share_group_clarification">%1$s (ομάδα)</string>
+  <string name="share_sharee_unavailable">Δεν επιτρέπεται ο διαμοιρασμός μεταξύ χρηστών μέσω εφαρμογής, σε αυτή την έκδοση.
+\nΕπικοινωνήστε με το διαχειριστή του συστήματος</string>
 </resources>
index f0c7acd..5fc8dfd 100644 (file)
   <string name="filedetails_created">Created:</string>
   <string name="filedetails_modified">Modified:</string>
   <string name="filedetails_download">Download</string>
-  <string name="filedetails_sync_file">Refresh file</string>
   <string name="filedetails_renamed_in_upload_msg">File was renamed to %1$s during upload</string>
   <string name="action_share_file">Share link</string>
   <string name="action_unshare_file">Unshare link</string>
   <string name="common_yes">Yes</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Cancel download</string>
-  <string name="common_cancel_upload">Cancel upload</string>
   <string name="common_cancel">Cancel</string>
   <string name="common_save_exit">Save &amp; Exit</string>
   <string name="common_error">Error</string>
   <string name="unfavorite">Unfavourite</string>
   <string name="common_rename">Rename</string>
   <string name="common_remove">Remove</string>
-  <string name="confirmation_remove_alert">Do you really want to remove %1$s?</string>
+  <string name="confirmation_remove_file_alert">Do you really want to remove %1$s?</string>
   <string name="confirmation_remove_folder_alert">Do you really want to remove %1$s and its contents?</string>
   <string name="confirmation_remove_local">Local only</string>
   <string name="confirmation_remove_folder_local">Local only</string>
   <string name="prefs_category_instant_uploading">Instant Uploads</string>
   <string name="prefs_category_security">Security</string>
   <string name="prefs_instant_video_upload_path_title">Upload Video Path</string>
-  <string name="download_folder_failed_content">Download of %1$s folder could not be completed</string>
+  <string name="subject_user_shared_with_you">%1$s shared \"%2$s\" with you</string>
   <string name="auth_refresh_button">Refresh connection</string>
   <string name="auth_host_address">Server address</string>
   <string name="common_error_out_memory">Not enough memory</string>
+  <string name="share_dialog_title">Sharing</string>
+  <string name="share_search">Search</string>
 </resources>
index 7c9473b..4d98b49 100644 (file)
@@ -53,8 +53,6 @@
   <string name="common_yes">Jes</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Akcepti</string>
-  <string name="common_cancel_download">Nuligi elŝuton</string>
-  <string name="common_cancel_upload">Nuligi alŝuton</string>
   <string name="common_cancel">Nuligi</string>
   <string name="common_save_exit">Konservi kaj forlasi</string>
   <string name="common_error">Eraro</string>
   <string name="unfavorite">Nefavoratigi</string>
   <string name="common_rename">Alinomigi</string>
   <string name="common_remove">Forigi</string>
-  <string name="confirmation_remove_alert">Ĉu vi vere volas forigi %1$s?</string>
+  <string name="confirmation_remove_file_alert">Ĉu vi vere volas forigi %1$s?</string>
   <string name="confirmation_remove_folder_alert">Ĉu vi vere volas forigi %1$s kaj ĝia enhavo?</string>
   <string name="confirmation_remove_local">Nur loka</string>
   <string name="confirmation_remove_folder_local">Nur loka</string>
   <string name="auth_host_address">Servila adreso</string>
   <string name="file_list__footer__file">1 dosiero</string>
   <string name="file_list__footer__files">%1$d dosieroj</string>
+  <string name="share_dialog_title">Kunhavigo</string>
+  <string name="share_search">Serĉi</string>
 </resources>
index f159bce..6165582 100644 (file)
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
   <string name="action_share_file">Compartir vínculo</string>
   <string name="action_unshare_file">Dejar de compartir vínculo</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar descarga</string>
-  <string name="common_cancel_upload">Cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar y salir</string>
   <string name="common_error">Error</string>
   <string name="favorite">Favorito</string>
   <string name="common_rename">Renombrar</string>
   <string name="common_remove">Borrar</string>
-  <string name="confirmation_remove_alert">¿Realmente quieres eliminar %1$s?</string>
+  <string name="confirmation_remove_file_alert">¿Realmente quieres eliminar %1$s?</string>
   <string name="confirmation_remove_folder_alert">¿Realmente deseas eliminar %1$s y todo su contenido?</string>
   <string name="confirmation_remove_local">Sólo local</string>
   <string name="confirmation_remove_folder_local">Sólo local</string>
   <string name="prefs_category_instant_uploading">Subida Instantánea </string>
   <string name="prefs_category_security">Seguridad</string>
   <string name="prefs_instant_video_upload_path_title">Dirección de subida del video</string>
-  <string name="download_folder_failed_content">La descarga de la carpeta %1$s no pudo ser completada</string>
   <string name="auth_host_address">Dirección del servidor</string>
+  <string name="share_dialog_title">Compartiendo</string>
+  <string name="share_search">Buscar</string>
 </resources>
index e4288f1..441831c 100644 (file)
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">refrescar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado a %1$s durante la subida</string>
   <string name="common_yes">Si</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">cancelar bajada</string>
-  <string name="common_cancel_upload">cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar&amp;Salir</string>
   <string name="common_error">Error</string>
   <string name="auth_unauthorized">usuario o clave incorrecta</string>
   <string name="common_rename">Renombrar</string>
   <string name="common_remove">Remover</string>
-  <string name="confirmation_remove_alert">¿Realmente desea eliminar %1$s?</string>
+  <string name="confirmation_remove_file_alert">¿Realmente desea eliminar %1$s?</string>
   <string name="confirmation_remove_folder_alert">¿Realmente desea eliminar el archivo %1$s y su contenido?</string>
   <string name="confirmation_remove_local">Solo local</string>
   <string name="confirmation_remove_folder_local">Solo local</string>
index 84ab10c..dc31f88 100644 (file)
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar archivo</string>
   <string name="filedetails_renamed_in_upload_msg">El archivo fue renombrado como %1$s durante la subida</string>
   <string name="action_share_file">Enlace compartido</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar descarga</string>
-  <string name="common_cancel_upload">Cancelar subida</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar &amp; Salir</string>
   <string name="common_error">Error</string>
   <string name="folder_picker_choose_button_text">Seleccionar</string>
   <string name="prefs_category_security">Seguridad</string>
   <string name="auth_host_address">Dirección del servidor</string>
+  <string name="share_dialog_title">Compartiendo</string>
+  <string name="share_search">Buscar</string>
 </resources>
index 1ae5c99..0f77b14 100644 (file)
@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">hace segundos</string>
   <string name="file_list_empty">No hay nada aquí. ¡Suba algo!</string>
   <string name="file_list_loading">Cargando...</string>
+  <string name="file_list_no_app_for_file_type">¡No se encontró una aplicación para el tipo de archivo!</string>
   <string name="local_file_list_empty">No hay archivos en esta carpeta.</string>
   <string name="filedetails_select_file">Pulsa sobre un archivo para mostrar información adicional.</string>
   <string name="filedetails_size">Tamaño:</string>
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar archivo</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">El fichero fue renombrado como %1$s durante la subida</string>
   <string name="list_layout">Diseño de lista</string>
   <string name="action_share_file">Compartir con enlace</string>
   <string name="action_unshare_file">Dejar de compartir</string>
+  <string name="action_share_with_users">Compartir con usuarios</string>
   <string name="common_yes">Sí</string>
   <string name="common_no">No</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar descarga</string>
-  <string name="common_cancel_upload">Cancelar subida</string>
+  <string name="common_cancel_sync">Cancelar sincronización</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar &amp; Salir</string>
   <string name="common_error">Error</string>
   <string name="unfavorite">No-favorito</string>
   <string name="common_rename">Renombrar</string>
   <string name="common_remove">Borrar</string>
-  <string name="confirmation_remove_alert">¿Realmente desea eliminar %1$s?</string>
+  <string name="confirmation_remove_file_alert">¿Realmente desea eliminar %1$s?</string>
   <string name="confirmation_remove_folder_alert">¿Realmente desea eliminar %1$s y todo su contenido?</string>
   <string name="confirmation_remove_local">Sólo local</string>
   <string name="confirmation_remove_folder_local">Sólo local</string>
-  <string name="confirmation_remove_remote">Desde el servidor</string>
+  <string name="confirmation_remove_file_remote">Desde el servidor</string>
   <string name="confirmation_remove_remote_and_local">Remoto &amp; local</string>
   <string name="remove_success_msg">Borrado correctamente</string>
   <string name="remove_fail_msg">El borrado no pudo ser completado</string>
   <string name="ssl_validator_label_validity_to">A:</string>
   <string name="ssl_validator_label_signature">Firma:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritmo:</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Firma:</string>
+  <string name="certificate_load_problem">Existe un problema al cargar el certificado.</string>
   <string name="ssl_validator_null_cert">No se ha podido mostrar el certificado</string>
   <string name="ssl_validator_no_info_about_error">- No hay información acerca del error</string>
   <string name="placeholder_sentence">Esto es un marcador de posición</string>
   <string name="prefs_category_instant_uploading">Subidas instantáneas</string>
   <string name="prefs_category_security">Seguridad</string>
   <string name="prefs_instant_video_upload_path_title">Guardar videos subidos en la carpeta:</string>
-  <string name="download_folder_failed_content">La descarga de la carpeta %1$s no ha podido ser completada</string>
+  <string name="sync_folder_failed_content">La sincronización de la carpeta %1$s no se pudo completar</string>
   <string name="shared_subject_header">compartido</string>
   <string name="with_you_subject_header">con usted</string>
-  <string name="subject_token">%1$s compartió \"%2$s\" conmigo</string>
-  <string name="saml_subject_token">\"%1$s\" ha sido compartido con usted.</string>
+  <string name="subject_user_shared_with_you">%1$s compartió \"%2$s\" conmigo</string>
+  <string name="subject_shared_with_you">\"%1$s\" ha sido compartido con usted.</string>
   <string name="auth_refresh_button">Refrescar la conexión</string>
   <string name="auth_host_address">Dirección del servidor</string>
   <string name="common_error_out_memory">No hay suficiente memoria</string>
   <string name="file_list__footer__files">%1$d archivos</string>
   <string name="file_list__footer__files_and_folder">%1$d archivos, 1 carpeta</string>
   <string name="file_list__footer__files_and_folders">%1$d archivos, %2$d carpetas</string>
+  <string name="share_dialog_title">Compartiendo</string>
+  <string name="share_with_user_section_title">Compartir con Usuarios y Grupos</string>
+  <string name="share_no_users">Aún no se ha compartido con ningún usuario.</string>
+  <string name="share_add_user_or_group">Añadir usuario o grupo</string>
+  <string name="share_search">Buscar</string>
+  <string name="search_users_and_groups_hint">Buscar usuarios y grupos</string>
+  <string name="share_group_clarification">%1$s (grupo)</string>
+  <string name="share_sharee_unavailable">Lo siento, compartir no está disponible en su servidor.\nPor favor, contacte con su administrador</string>
 </resources>
index a4841a4..7167dc5 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Loodud:</string>
   <string name="filedetails_modified">Muudetud:</string>
   <string name="filedetails_download">Lae alla</string>
-  <string name="filedetails_sync_file">Värskenda faili</string>
   <string name="filedetails_renamed_in_upload_msg">Fail nimetati üleslaadimise käigus ümber %1$ </string>
   <string name="list_layout">Nimekirja paigutus</string>
   <string name="action_share_file">Jaga linki</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Jah</string>
   <string name="common_no">Ei</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Tühista allalaadimine</string>
-  <string name="common_cancel_upload">Tühista üleslaadimine</string>
   <string name="common_cancel">Loobu</string>
   <string name="common_save_exit">Salvesta &amp; Välju</string>
   <string name="common_error">Viga</string>
@@ -202,11 +199,11 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
   <string name="unfavorite">Eemalda lemmik</string>
   <string name="common_rename">Nimeta ümber</string>
   <string name="common_remove">Eemalda</string>
-  <string name="confirmation_remove_alert">Oled sa kindel, et soovid %1$s eemaldada?</string>
+  <string name="confirmation_remove_file_alert">Oled sa kindel, et soovid %1$s eemaldada?</string>
   <string name="confirmation_remove_folder_alert">Kas sa tõesti soovid eemaldada %1$s ja selle sisu?</string>
   <string name="confirmation_remove_local">Ainult kohalik</string>
   <string name="confirmation_remove_folder_local">Ainult kohalik</string>
-  <string name="confirmation_remove_remote">Serverist</string>
+  <string name="confirmation_remove_file_remote">Serverist</string>
   <string name="confirmation_remove_remote_and_local">Kaugfail &amp; kohalik</string>
   <string name="remove_success_msg">Eemaldamine oli edukas</string>
   <string name="remove_fail_msg">Eemaldamine ebaõnnestus</string>
@@ -319,11 +316,10 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
   <string name="prefs_category_instant_uploading">Kohesed üleslaadimised</string>
   <string name="prefs_category_security">Turvalisus</string>
   <string name="prefs_instant_video_upload_path_title">Video üleslaadimise asukoht</string>
-  <string name="download_folder_failed_content">Kausta %1$s  allalaadimine ei õnnestunud</string>
   <string name="shared_subject_header">jagatud</string>
   <string name="with_you_subject_header">sinuga</string>
-  <string name="subject_token">%1$s jagas sinuga \"%2$s\"</string>
-  <string name="saml_subject_token">\"%1$s\" on sinuga jagatud</string>
+  <string name="subject_user_shared_with_you">%1$s jagas sinuga \"%2$s\"</string>
+  <string name="subject_shared_with_you">\"%1$s\" on sinuga jagatud</string>
   <string name="auth_refresh_button">Värskenda ühendust</string>
   <string name="auth_host_address">Serveri aadress</string>
   <string name="common_error_out_memory">Mälu pole piisavalt</string>
@@ -336,4 +332,6 @@ Allpool on loend kohalikest failidest ning serveris asuvatest failidest %5$s, mi
   <string name="file_list__footer__files">%1$d faili</string>
   <string name="file_list__footer__files_and_folder">%1$d faili, 1 kaust</string>
   <string name="file_list__footer__files_and_folders">%1$d faili, %2$d kausta</string>
+  <string name="share_dialog_title">Jagamine</string>
+  <string name="share_search">Otsi</string>
 </resources>
index a532d2c..7cb8302 100644 (file)
   <string name="filedetails_created">Sortuta:</string>
   <string name="filedetails_modified">Aldatuta:</string>
   <string name="filedetails_download">Deskargatu</string>
-  <string name="filedetails_sync_file">Freskatu fitxaegia</string>
   <string name="filedetails_renamed_in_upload_msg">Fitxategiaren izena %1$sra aldatu da igotzean</string>
   <string name="action_share_file">Elkarbanatu lotura</string>
   <string name="action_unshare_file">Lotura partekatzeari utzi</string>
   <string name="common_yes">Bai</string>
   <string name="common_no">Ez</string>
   <string name="common_ok">Ados</string>
-  <string name="common_cancel_download">Utzi deskarga bertan behera </string>
-  <string name="common_cancel_upload">Ezeztatu igoera</string>
   <string name="common_cancel">Ezeztatu</string>
   <string name="common_save_exit">Gorde eta Irten</string>
   <string name="common_error">Errorea</string>
@@ -177,7 +174,7 @@ Mesedez, baimendu berriz</string>
   <string name="favorite">Gogokoa</string>
   <string name="common_rename">Berrizendatu</string>
   <string name="common_remove">Ezabatu</string>
-  <string name="confirmation_remove_alert">Ziur zaude %1$s ezabatu nahi duzula?</string>
+  <string name="confirmation_remove_file_alert">Ziur zaude %1$s ezabatu nahi duzula?</string>
   <string name="confirmation_remove_folder_alert">Ziru zaude %1$s eta bere edukiak ezabatu nahi dituzula?</string>
   <string name="confirmation_remove_local">Bertakoa bakarrik</string>
   <string name="confirmation_remove_folder_local">Bertakoa bakarrik</string>
@@ -278,6 +275,7 @@ Mesedez, baimendu berriz</string>
   <string name="prefs_category_instant_uploading">Berehalako Igoerak</string>
   <string name="prefs_category_security">Segurtasuna</string>
   <string name="prefs_instant_video_upload_path_title">Bideo Igoera Bidea</string>
-  <string name="download_folder_failed_content">%1$s karpetaren deskarga ezin izan da burutu</string>
   <string name="auth_host_address">Zerbitzariaren helbidea</string>
+  <string name="share_dialog_title">Partekatzea</string>
+  <string name="share_search">Bilatu</string>
 </resources>
index 3f833b3..35696da 100644 (file)
   <string name="filedetails_created">ایجاد شده توسط:</string>
   <string name="filedetails_modified">تغییر یافته توسط:</string>
   <string name="filedetails_download">بارگیری</string>
-  <string name="filedetails_sync_file">بازنمایی فایل</string>
   <string name="filedetails_renamed_in_upload_msg">فایل در هنگام بارگزاری به %1$s تغییر نام یافت</string>
   <string name="action_share_file">اشتراک گذاشتن لینک</string>
   <string name="action_unshare_file">لغو اشتراک گذاشتن لینک</string>
   <string name="common_yes">بله</string>
   <string name="common_no">نه</string>
   <string name="common_ok">باشه</string>
-  <string name="common_cancel_download">قطع دانلود</string>
-  <string name="common_cancel_upload">متوقف کردن بار گذاری</string>
   <string name="common_cancel">منصرف شدن</string>
   <string name="common_save_exit">ذخیره سازی و خروج</string>
   <string name="common_error">خطا</string>
   <string name="prefs_category_instant_uploading">آپلودهای فوری</string>
   <string name="prefs_category_security">امنیت</string>
   <string name="prefs_instant_video_upload_path_title">مسیر آپلود ویدئو</string>
-  <string name="download_folder_failed_content">امکان تکمیل دانلود پوشه  %1$s وجود ندارد</string>
   <string name="shared_subject_header">به اشتراک گذاشته شد</string>
   <string name="with_you_subject_header">با تو</string>
-  <string name="subject_token">\"%2$s\" توسط %1$s با شما به اشتراک گذاشته شد</string>
-  <string name="saml_subject_token">\"%1$s\" با شما به اشتراک گذاشته شد</string>
+  <string name="subject_user_shared_with_you">\"%2$s\" توسط %1$s با شما به اشتراک گذاشته شد</string>
+  <string name="subject_shared_with_you">\"%1$s\" با شما به اشتراک گذاشته شد</string>
   <string name="auth_refresh_button">بروزرسانی ارتباط</string>
   <string name="auth_host_address">آدرس سرور</string>
   <string name="common_error_out_memory">حافظه کافی وجود ندارد</string>
   <string name="file_list__footer__files">%1$d  فایل</string>
   <string name="file_list__footer__files_and_folder">%1$d فایل، 1 پوشه</string>
   <string name="file_list__footer__files_and_folders">%1$d فایل, %2$d پوشه</string>
+  <string name="share_dialog_title">اشتراک گذاری</string>
+  <string name="share_search">جست‌و‌جو</string>
 </resources>
index 59a6ec1..7db8066 100644 (file)
   <string name="filedetails_created">Luotu:</string>
   <string name="filedetails_modified">Muokattu:</string>
   <string name="filedetails_download">Lataa</string>
-  <string name="filedetails_sync_file">Päivitä tiedosto</string>
+  <string name="filedetails_sync_file">Synkronoi</string>
   <string name="filedetails_renamed_in_upload_msg">Tiedoston nimeksi muutettiin %1$s siirron yhteydessä</string>
   <string name="list_layout">Luettelon asettelu</string>
   <string name="action_share_file">Jaa linkki</string>
   <string name="action_unshare_file">Poista linkin jako</string>
+  <string name="action_share_with_users">Jaa käyttäjien kanssa</string>
   <string name="common_yes">Kyllä</string>
   <string name="common_no">Ei</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Peru lataus</string>
-  <string name="common_cancel_upload">Peru lähetys</string>
+  <string name="common_cancel_sync">Peru synkronointi</string>
   <string name="common_cancel">Peru</string>
   <string name="common_save_exit">Tallenna ja poistu</string>
   <string name="common_error">Virhe</string>
   <string name="unfavorite">Poista suosikeista</string>
   <string name="common_rename">Nimeä uudelleen</string>
   <string name="common_remove">Poista</string>
-  <string name="confirmation_remove_alert">Haluatko varmasti poistaa kohteen %1$s?</string>
+  <string name="confirmation_remove_file_alert">Haluatko varmasti poistaa kohteen %1$s?</string>
   <string name="confirmation_remove_folder_alert">Haluatko varmasti poistaa kohteen %1$s ja sen sisällön?</string>
   <string name="confirmation_remove_local">Vain paikallinen</string>
   <string name="confirmation_remove_folder_local">Vain paikallinen</string>
-  <string name="confirmation_remove_remote">Palvelimelta</string>
+  <string name="confirmation_remove_file_remote">Palvelimelta</string>
   <string name="confirmation_remove_remote_and_local">Etä ja paikallinen</string>
   <string name="remove_success_msg">Poistettu onnistuneesti</string>
   <string name="remove_fail_msg">Poistamista ei voitu suorittaa loppuun asti</string>
   <string name="ssl_validator_label_validity_to">Päättyen:</string>
   <string name="ssl_validator_label_signature">Allekirjoitus:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritmi:</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Sormenjälki:</string>
+  <string name="certificate_load_problem">Varmennetta ladatessa ilmeni ongelmia.</string>
   <string name="ssl_validator_null_cert">Varmennetta ei voi näyttää.</string>
   <string name="ssl_validator_no_info_about_error">- Ei lisätietoja virheestä</string>
   <string name="placeholder_filetype">PNG-kuva</string>
   <string name="copy_file_error">Tätä tiedostoa tai kansiota kopioitaessa tapahtui virhe</string>
   <string name="prefs_category_instant_uploading">Välittömät lähetykset</string>
   <string name="prefs_category_security">Tietoturva</string>
+  <string name="prefs_instant_video_upload_path_title">Videoiden lähetyspolku</string>
+  <string name="sync_folder_failed_content">Kansion %1$s synkronointia ei voitu suorittaa kokonaan</string>
   <string name="shared_subject_header">jaettu</string>
   <string name="with_you_subject_header">kanssasi</string>
-  <string name="subject_token">%1$s jakoi kohteen \"%2$s\" kanssasi</string>
-  <string name="saml_subject_token">\"%1$s\" on jaettu kanssasi</string>
+  <string name="subject_user_shared_with_you">%1$s jakoi kohteen \"%2$s\" kanssasi</string>
+  <string name="subject_shared_with_you">\"%1$s\" on jaettu kanssasi</string>
   <string name="auth_refresh_button">Päivitä yhteys</string>
   <string name="auth_host_address">Palvelimen osoite</string>
   <string name="common_error_out_memory">Muistia ei ole riittävästi</string>
   <string name="file_list__footer__files">%1$d tiedostoa</string>
   <string name="file_list__footer__files_and_folder">%1$d tiedostoa, 1 kansio</string>
   <string name="file_list__footer__files_and_folders">%1$d tiedostoa, %2$d kansiota</string>
+  <string name="share_dialog_title">Jakaminen</string>
+  <string name="share_with_user_section_title">Jaa käyttäjien tai ryhmien kanssa</string>
+  <string name="share_add_user_or_group">Lisää käyttäjä tai ryhmä</string>
+  <string name="share_search">Etsi</string>
+  <string name="search_users_and_groups_hint">Etsi käyttäjiä ja ryhmiä</string>
+  <string name="share_group_clarification">%1$s (ryhmä)</string>
 </resources>
index 4d72b39..260ffbd 100644 (file)
@@ -74,22 +74,22 @@ Téléchargez-le ici : %2$s</string>
   <string name="file_list_loading">Chargement...</string>
   <string name="file_list_no_app_for_file_type">Aucune app trouvée pour ce type de fichier !</string>
   <string name="local_file_list_empty">Aucun fichier n\'est présent dans ce dossier.</string>
-  <string name="filedetails_select_file">Appuyez sur un fichier pour afficher des informations supplémentaires</string>
+  <string name="filedetails_select_file">Sélectionnez un fichier pour afficher des informations supplémentaires</string>
   <string name="filedetails_size">Taille :</string>
   <string name="filedetails_type">Type :</string>
   <string name="filedetails_created">Créé le :</string>
   <string name="filedetails_modified">Modifié le :</string>
   <string name="filedetails_download">Télécharger</string>
-  <string name="filedetails_sync_file">Actualiser le fichier</string>
+  <string name="filedetails_sync_file">Synchroniser</string>
   <string name="filedetails_renamed_in_upload_msg">Le fichier a été renommé en %s pendant le téléversement</string>
   <string name="list_layout">Affichage en liste</string>
   <string name="action_share_file">Partager le lien</string>
   <string name="action_unshare_file">Ne plus partager ce lien</string>
+  <string name="action_share_with_users">Partager avec des utilisateurs</string>
   <string name="common_yes">Oui</string>
   <string name="common_no">Non</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Annuler le téléchargement</string>
-  <string name="common_cancel_upload">Annuler le téléversement</string>
+  <string name="common_cancel_sync">Annuler la synchronisation</string>
   <string name="common_cancel">Annuler</string>
   <string name="common_save_exit">Sauvegarder &amp; Quitter</string>
   <string name="common_error">Erreur</string>
@@ -204,11 +204,11 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
   <string name="unfavorite">Retirer des favoris</string>
   <string name="common_rename">Renommer</string>
   <string name="common_remove">Supprimer</string>
-  <string name="confirmation_remove_alert">Voulez-vous vraiment supprimer %1$s ?</string>
+  <string name="confirmation_remove_file_alert">Voulez-vous vraiment supprimer %1$s ?</string>
   <string name="confirmation_remove_folder_alert">Voulez-vous vraiment supprimer %1$s et son contenu ?</string>
   <string name="confirmation_remove_local">Local seulement</string>
   <string name="confirmation_remove_folder_local">Local seulement</string>
-  <string name="confirmation_remove_remote">Depuis le serveur</string>
+  <string name="confirmation_remove_file_remote">Depuis le serveur</string>
   <string name="confirmation_remove_remote_and_local">Distant &amp; local</string>
   <string name="remove_success_msg">Suppression effectuée avec succès</string>
   <string name="remove_fail_msg">Suppression impossible</string>
@@ -250,6 +250,9 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
   <string name="ssl_validator_label_validity_to">Au :</string>
   <string name="ssl_validator_label_signature">Signature :</string>
   <string name="ssl_validator_label_signature_algorithm">Algorithme :</string>
+  <string name="digest_algorithm_not_available">Cet algorithme de hachage n\'est pas disponible sur votre téléphone.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Empreinte numérique :</string>
+  <string name="certificate_load_problem">Le chargement du certificat pose problème.</string>
   <string name="ssl_validator_null_cert">Impossible d\'afficher le certificat.</string>
   <string name="ssl_validator_no_info_about_error">- Aucune information sur l\'erreur</string>
   <string name="placeholder_sentence">Ceci est un espace réservé</string>
@@ -320,11 +323,11 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
   <string name="prefs_category_instant_uploading">Téléversement immédiat</string>
   <string name="prefs_category_security">Sécurité</string>
   <string name="prefs_instant_video_upload_path_title">Répertoire de téléversement des vidéos</string>
-  <string name="download_folder_failed_content">Le téléchargement du dossier %1$s n\'a pas pu être achevé</string>
+  <string name="sync_folder_failed_content">La synchronisation du dossier %1$s n\'a pas pu être terminée</string>
   <string name="shared_subject_header">a partagé</string>
   <string name="with_you_subject_header">avec vous</string>
-  <string name="subject_token">%1$s a partagé \"%2$s\" avec vous</string>
-  <string name="saml_subject_token">\"%1$s\" a été partagé avec vous</string>
+  <string name="subject_user_shared_with_you">%1$s a partagé \"%2$s\" avec vous</string>
+  <string name="subject_shared_with_you">\"%1$s\" a été partagé avec vous</string>
   <string name="auth_refresh_button">Actualiser la connexion</string>
   <string name="auth_host_address">Adresse du serveur</string>
   <string name="common_error_out_memory">Mémoire insuffisante</string>
@@ -337,4 +340,13 @@ Ci-dessous la liste des fichiers locaux, et les fichiers distants dans %5$s auxq
   <string name="file_list__footer__files">%1$d fichiers</string>
   <string name="file_list__footer__files_and_folder">%1$d fichiers, 1 dossier</string>
   <string name="file_list__footer__files_and_folders">%1$d fichiers, %2$d dossiers</string>
+  <string name="share_dialog_title">Partage</string>
+  <string name="share_with_user_section_title">Partager avec des Utilisateurs et des Groupes</string>
+  <string name="share_no_users">Aucune donnée partagée avec des utilisateurs pour le moment</string>
+  <string name="share_add_user_or_group">Ajouter un Utilisateur ou un Groupe</string>
+  <string name="share_search">Rechercher</string>
+  <string name="search_users_and_groups_hint">Chercher parmi les utilisateurs et groupes</string>
+  <string name="share_group_clarification">%1$s (groupe)</string>
+  <string name="share_sharee_unavailable">Désolé, la version du serveur ne permet pas aux applications d\'initier des partage avec d\'autres utilisateurs.
+\nVeuillez contacter votre administrateur</string>
 </resources>
index 51aa4a4..68ad0a4 100644 (file)
@@ -72,6 +72,7 @@ Descárgueo de aquí: %2$s</string>
   <string name="file_list_seconds_ago">segundos atrás</string>
   <string name="file_list_empty">Aquí non hai nada. Envíe algo!</string>
   <string name="file_list_loading">Cargando...</string>
+  <string name="file_list_no_app_for_file_type">Non se atopou un App para este tipo de ficheiro!</string>
   <string name="local_file_list_empty">Non hai ficheiros neste cartafol.</string>
   <string name="filedetails_select_file">Prema nun ficheiro para que amose a información adicional.</string>
   <string name="filedetails_size">Tamaño:</string>
@@ -79,16 +80,16 @@ Descárgueo de aquí: %2$s</string>
   <string name="filedetails_created">Creado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Descargar</string>
-  <string name="filedetails_sync_file">Actualizar o ficheiro</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado a %1$s durante o envío</string>
   <string name="list_layout">Deseño da lista</string>
   <string name="action_share_file">Ligazón para compartir</string>
   <string name="action_unshare_file">Deixar de compartir a ligazón</string>
+  <string name="action_share_with_users">Compartir con usuarios</string>
   <string name="common_yes">Si</string>
   <string name="common_no">Non</string>
   <string name="common_ok">Aceptar</string>
-  <string name="common_cancel_download">Cancelar a descarga</string>
-  <string name="common_cancel_upload">Cancelar o envío</string>
+  <string name="common_cancel_sync">Parar a sincronización</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Gardar e saír</string>
   <string name="common_error">Erro</string>
@@ -199,10 +200,11 @@ Descárgueo de aquí: %2$s</string>
   <string name="unfavorite">Retirar de favoritos</string>
   <string name="common_rename">Renomear</string>
   <string name="common_remove">Retirar</string>
-  <string name="confirmation_remove_alert">Confirma que quere retirar %1$s?</string>
+  <string name="confirmation_remove_file_alert">Confirma que quere retirar %1$s?</string>
   <string name="confirmation_remove_folder_alert">Confirma que quere retirar %1$s e o seu contido?</string>
   <string name="confirmation_remove_local">Só local</string>
   <string name="confirmation_remove_folder_local">Só local</string>
+  <string name="confirmation_remove_remote">Desde servidor</string>
   <string name="confirmation_remove_remote_and_local">Remoto e local</string>
   <string name="remove_success_msg">Retirado correctamente</string>
   <string name="remove_fail_msg">Non foi posíbel retiralo</string>
@@ -307,15 +309,19 @@ Descárgueo de aquí: %2$s</string>
   <string name="move_file_invalid_overwrite">Este ficheiro xa existe no cartafol de destino</string>
   <string name="move_file_error">Produciuse un erro ao tentar mover este ficheiro ou cartafol.</string>
   <string name="forbidden_permissions_move">para mover este ficheiro</string>
+  <string name="copy_file_not_found">Non se puido copiar. Por favor comprobe que o ficheiro existe</string>
+  <string name="copy_file_invalid_into_descendent">Non é posible copiar un cartafol nun descendente seu</string>
   <string name="copy_file_invalid_overwrite">Este ficheiro xa existe no cartafol de destino</string>
+  <string name="copy_file_error">Oconteceu un erro mentras se intentaba copiar este ficheiro ou cartafol</string>
+  <string name="forbidden_permissions_copy">copiar este ficheiro</string>
   <string name="prefs_category_instant_uploading">Envío instantáneo</string>
   <string name="prefs_category_security">Seguridade</string>
   <string name="prefs_instant_video_upload_path_title">Enviar a ruta do vídeo</string>
-  <string name="download_folder_failed_content">Non foi posíbel completar a descarga do cartafol %1$s</string>
+  <string name="sync_folder_failed_content">A sincronización do cartafol %1$s non se completou</string>
   <string name="shared_subject_header">compartido</string>
   <string name="with_you_subject_header">con vostede</string>
-  <string name="subject_token">%1$s compartiu «%2$s» con vostede</string>
-  <string name="saml_subject_token">«%1$s» foi compartido con vostede</string>
+  <string name="subject_user_shared_with_you">%1$s compartiu «%2$s» con vostede</string>
+  <string name="subject_shared_with_you">«%1$s» foi compartido con vostede</string>
   <string name="auth_refresh_button">Actualizar a conexión</string>
   <string name="auth_host_address">Enderezo do servidor</string>
   <string name="common_error_out_memory">Non hai memoria abondo</string>
@@ -328,4 +334,13 @@ Descárgueo de aquí: %2$s</string>
   <string name="file_list__footer__files">%1$d ficheiros</string>
   <string name="file_list__footer__files_and_folder">%1$d ficheiros, 1 cartafol</string>
   <string name="file_list__footer__files_and_folders">%1$d ficheiros, %2$d cartafoles</string>
+  <string name="share_dialog_title">Compartindo</string>
+  <string name="share_with_user_section_title">Compartir con Usuarios e Grupos</string>
+  <string name="share_no_users">Aínda non hai datos compartidos con usuarios</string>
+  <string name="share_add_user_or_group">Engadir Usuario ou Grupo</string>
+  <string name="share_search">Buscar</string>
+  <string name="search_users_and_groups_hint">Buscar usuarios e grupos</string>
+  <string name="share_group_clarification">%1$s (grupo)</string>
+  <string name="share_sharee_unavailable">Sentímolo, pero a versión do seu servidor non permite compartir con usuarios desde o cliente.
+\nPor favor contacte co seu administrador</string>
 </resources>
index 1a62cc2..14c8156 100644 (file)
   <string name="filedetails_created">מועד היצירה:</string>
   <string name="filedetails_modified">מועד השינוי:</string>
   <string name="filedetails_download">הורדה</string>
-  <string name="filedetails_sync_file">רענון קובץ</string>
   <string name="filedetails_renamed_in_upload_msg">שם הקובץ השתנה ל־ %1$s במהלך ההעלאה</string>
   <string name="action_share_file">קישור לשיתוף</string>
   <string name="action_unshare_file">ביטול קישור לשיתוף</string>
   <string name="common_yes">כן</string>
   <string name="common_no">לא</string>
   <string name="common_ok">אישור</string>
-  <string name="common_cancel_download">ביטול ההורדה</string>
-  <string name="common_cancel_upload">ביטול ההעלאה</string>
   <string name="common_cancel">ביטול</string>
   <string name="common_save_exit">לשמור ולצאת</string>
   <string name="common_error">שגיאה</string>
   <string name="favorite">מועדף</string>
   <string name="common_rename">שינוי שם</string>
   <string name="common_remove">הסרה</string>
-  <string name="confirmation_remove_alert">האם באמת להסיר %1$s?</string>
+  <string name="confirmation_remove_file_alert">האם באמת להסיר %1$s?</string>
   <string name="confirmation_remove_folder_alert">האם באמת להסיר %1$s ואת כל התכולה?</string>
   <string name="confirmation_remove_local">מקומי בלבד</string>
   <string name="confirmation_remove_folder_local">מקומי בלבד</string>
   <string name="folder_picker_choose_button_text">בחירה</string>
   <string name="prefs_category_security">אבטחה</string>
   <string name="auth_host_address">כתובת שרת</string>
+  <string name="share_dialog_title">שיתוף</string>
+  <string name="share_search">חיפוש</string>
 </resources>
index 12e7ef4..6fba8ee 100644 (file)
@@ -47,7 +47,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">U redu</string>
-  <string name="common_cancel_upload">Prekini upload</string>
   <string name="common_cancel">Odustani</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata pogreška</string>
@@ -66,4 +65,6 @@
   <string name="folder_picker_choose_button_text">Odaberite</string>
   <string name="prefs_category_security">Sigurnost</string>
   <string name="auth_host_address">Adresa poslužitelja</string>
+  <string name="share_dialog_title">Dijeljenje zajedničkih resursa</string>
+  <string name="share_search">pretraži</string>
 </resources>
index 2746202..25967de 100644 (file)
@@ -45,6 +45,7 @@
   <string name="prefs_recommend">Ajánlja egy barátjának</string>
   <string name="prefs_feedback">Visszajelzés</string>
   <string name="prefs_imprint">Impresszum</string>
+  <string name="prefs_remember_last_share_location">Emlékezzen a megosztás helyére</string>
   <string name="recommend_subject">Próbálja ki %1$s-t az okostelefonján!</string>
   <string name="auth_check_server">Szerver állapot ellenörzés</string>
   <string name="auth_host_url">Kiszolgáló címe https://...</string>
   <string name="filedetails_created">Készült:</string>
   <string name="filedetails_modified">Módosítva:</string>
   <string name="filedetails_download">Letöltés</string>
-  <string name="filedetails_sync_file">File frissítése</string>
+  <string name="filedetails_sync_file">Szinkronizálás</string>
   <string name="filedetails_renamed_in_upload_msg">A feltöltés során az állmányt erre neveztük át: %1$s</string>
+  <string name="list_layout">Lista Elrendezés</string>
   <string name="action_share_file">Megosztás hivatkozással</string>
   <string name="action_unshare_file">Megosztás visszavonása</string>
   <string name="common_yes">Igen</string>
   <string name="common_no">Nem</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">A letöltés megszakítása</string>
-  <string name="common_cancel_upload">A feltöltés megszakítása</string>
+  <string name="common_cancel_sync">Szinkronizálás megállítása</string>
   <string name="common_cancel">Mégsem</string>
   <string name="common_save_exit">Mentés &amp; Kilépés</string>
   <string name="common_error">Hiba</string>
   <string name="auth_no_net_conn_title">Nincs hálózati kapcsolat</string>
   <string name="auth_nossl_plain_ok_title">Nem érhető el biztonságos kapcsolat.</string>
   <string name="auth_connection_established">A kapcsolat létrejött</string>
+  <string name="auth_testing_connection">Kapcsolat ellenőrzése</string>
   <string name="auth_not_configured_title">Hibás a kiszolgáló beállítása</string>
   <string name="auth_account_not_new">Egy bejelentkezési beállítás már létezik ugyanehhez a kiszolgálóhoz és felhasználóhoz</string>
   <string name="auth_account_not_the_same">A megadott felhasználó nem azonos ezzel a belépési jogosultsággal</string>
   <string name="unfavorite">Nem kedvenc</string>
   <string name="common_rename">Átnevezés</string>
   <string name="common_remove">Eltávolítás</string>
-  <string name="confirmation_remove_alert">Tényleg el akarod távolítani %1$s?</string>
+  <string name="confirmation_remove_file_alert">Tényleg el akarod távolítani %1$s?</string>
   <string name="confirmation_remove_folder_alert">Tényleg el akarod távolítani a %1$s és tartalmát?</string>
   <string name="confirmation_remove_local">Csak a helyi példány</string>
   <string name="confirmation_remove_folder_local">Csak a helyi példány</string>
   <string name="sync_file_nothing_to_do_msg">Az állományok már szinkonizálva vannak</string>
   <string name="create_dir_fail_msg">A könyvtárt nem lehet létrehozni</string>
   <string name="filename_forbidden_characters">Nem megendedett karakterek: / \\ &lt; &gt; : \" | ? *</string>
+  <string name="filename_forbidden_charaters_from_server">A fájlnév legalább egy érvénytelen karaktert tartalmaz!</string>
   <string name="filename_empty">A fájl név nem lehet üres</string>
   <string name="wait_a_moment">Egy pillanat...</string>
   <string name="filedisplay_unexpected_bad_get_content">Váratlan hiba; válassza ki a fájlt más programból</string>
   <string name="preview_image_description">Előnézeti kép</string>
   <string name="preview_image_error_unknown_format">Ez a kép nem jeleníthető meg</string>
   <string name="error__upload__local_file_not_copied">%1$s nem lehet másolni a %2$s helyi könyvtárba</string>
+  <string name="prefs_instant_upload_path_title">Feltöltési Elérési Út</string>
   <string name="share_link_file_error">Hiba lépett fel a mappa megosztásakor</string>
   <string name="unshare_link_file_error">Hiba lépett fel a mappa megosztásának visszavonásakor</string>
   <string name="share_link_password_title">Jelszó beírása</string>
   <string name="file_list__footer__files">%1$d fájl</string>
   <string name="file_list__footer__files_and_folder">%1$d fájl, 1 könyvtár</string>
   <string name="file_list__footer__files_and_folders">%1$d fájl, %2$d könyvtár</string>
+  <string name="share_dialog_title">Megosztás</string>
+  <string name="share_search">Keresés</string>
 </resources>
index 64bbe0b..1ed5516 100644 (file)
@@ -1,5 +1,6 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <resources>
+  <string name="about_version">տարբերակ %1$s</string>
   <string name="actionbar_upload_files">Ֆայլեր</string>
   <string name="actionbar_mkdir">Նոր պանակ</string>
   <string name="actionbar_send_file">Ուղարկել</string>
   <!--<string name="drawer_item_accounts">Accounts</string>-->
   <!--TODO re-enable when "On Device" is available
     <string name="drawer_item_on_device">On device</string>-->
+  <string name="drawer_close">Փակել</string>
   <string name="drawer_open">Բացել</string>
   <string name="auth_password">Գաղտնաբառ</string>
   <string name="sync_string_files">Ֆայլեր</string>
   <string name="uploader_btn_new_folder_text">Նոր պանակ</string>
+  <string name="file_list_seconds_ago">վրկ. առաջ</string>
+  <string name="filedetails_size">Չափս.</string>
   <string name="filedetails_download">Բեռնել</string>
   <string name="action_share_file">Կիսվել հղմամբ</string>
+  <string name="common_yes">Այո</string>
+  <string name="common_no">Ոչ</string>
   <string name="common_cancel">Չեղարկել</string>
   <string name="common_rename">Վերանվանել</string>
   <string name="ssl_validator_label_C">Երկիր.</string>
+  <string name="ssl_validator_label_validity_from">Ումից.</string>
+  <string name="ssl_validator_label_validity_to">Ում.</string>
+  <string name="placeholder_filesize">389 ԿԲ</string>
   <string name="activity_chooser_send_file_title">Ուղարկել</string>
   <string name="empty"></string>
+  <string name="file_list__footer__folder">1 պանակ</string>
+  <string name="file_list__footer__folders">%1$d պանակ</string>
+  <string name="file_list__footer__file">1 ֆայլ</string>
+  <string name="file_list__footer__file_and_folder">1 ֆայլ, 1 պանակ</string>
+  <string name="file_list__footer__file_and_folders">1 ֆայլ, %1$d պանակ</string>
+  <string name="file_list__footer__files">%1$d ֆայլ</string>
+  <string name="file_list__footer__files_and_folder">%1$d ֆայլ, 1 պանակ</string>
+  <string name="file_list__footer__files_and_folders">%1$d ֆայլ, %2$d պանակ</string>
 </resources>
index efb3d3d..666c923 100644 (file)
   <string name="common_yes">Si</string>
   <string name="common_no">No</string>
   <string name="common_ok">Ok</string>
-  <string name="common_cancel_download">Cancellar discarga</string>
   <string name="common_cancel">Cancellar</string>
   <string name="common_error">Error</string>
   <string name="common_error_unknown">Error Incognite</string>
+  <string name="about_title">A proposito</string>
   <string name="change_password">Cambiar contrasigno</string>
   <string name="delete_account">Deler conto</string>
   <string name="uploader_info_dirname">Nomine de dossier</string>
@@ -45,4 +45,5 @@
   <string name="prefs_category_accounts">Contos</string>
   <string name="saml_authentication_wrong_pass">Contrasigno errate</string>
   <string name="folder_picker_choose_button_text">Seliger</string>
+  <string name="share_search">Cercar</string>
 </resources>
index 5ed18fa..f1f7d9f 100644 (file)
@@ -79,7 +79,6 @@
   <string name="filedetails_created">Dibuat:</string>
   <string name="filedetails_modified">Diubah:</string>
   <string name="filedetails_download">Unduh</string>
-  <string name="filedetails_sync_file">Segarkan berkas</string>
   <string name="filedetails_renamed_in_upload_msg">Berkas diubah namanya menjadi %1$s saat pengunggahan</string>
   <string name="list_layout">Daftar Tata Letak</string>
   <string name="action_share_file">Bagikan tautan</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">Ya</string>
   <string name="common_no">Tidak</string>
   <string name="common_ok">Oke</string>
-  <string name="common_cancel_download">Batal mengunduh</string>
-  <string name="common_cancel_upload">Batal mengunggah</string>
   <string name="common_cancel">Batal</string>
   <string name="common_save_exit">Simpan &amp; Keluar</string>
   <string name="common_error">Kesalahan</string>
   <string name="unfavorite">Hapus favorit</string>
   <string name="common_rename">Ubah nama</string>
   <string name="common_remove">Hapus</string>
-  <string name="confirmation_remove_alert">Apakah Anda yakin ingin menghapus %1$s?</string>
+  <string name="confirmation_remove_file_alert">Apakah Anda yakin ingin menghapus %1$s?</string>
   <string name="confirmation_remove_folder_alert">Apakah Anda yakin ingin menghapus %1$s dan isinya?</string>
   <string name="confirmation_remove_local">Lokal saja</string>
   <string name="confirmation_remove_folder_local">Lokal saja</string>
-  <string name="confirmation_remove_remote">Dari server</string>
+  <string name="confirmation_remove_file_remote">Dari server</string>
   <string name="confirmation_remove_remote_and_local">Remot &amp; lokal</string>
   <string name="remove_success_msg">Penghapusan berhasil</string>
   <string name="remove_fail_msg">Penghapusan gagal</string>
   <string name="prefs_category_instant_uploading">Unggah Cepat</string>
   <string name="prefs_category_security">Keamanan</string>
   <string name="prefs_instant_video_upload_path_title">Unggah Lokasi Video</string>
-  <string name="download_folder_failed_content">Mengunduh folder %1$s  tidak selesai</string>
   <string name="shared_subject_header">dibagikan</string>
   <string name="with_you_subject_header">kepada Anda</string>
-  <string name="subject_token">%1$s dibagikan \"%2$s\" kepada Anda</string>
-  <string name="saml_subject_token">\"%1$s\" telah membagikan dengan Anda</string>
+  <string name="subject_user_shared_with_you">%1$s dibagikan \"%2$s\" kepada Anda</string>
+  <string name="subject_shared_with_you">\"%1$s\" telah membagikan dengan Anda</string>
   <string name="auth_refresh_button">Menyegarkan sambungan</string>
   <string name="auth_host_address">Alamat server</string>
   <string name="common_error_out_memory">Memori tidak cukup</string>
   <string name="file_list__footer__files">%1$d berkas</string>
   <string name="file_list__footer__files_and_folder">%1$d berkas, 1 folder</string>
   <string name="file_list__footer__files_and_folders">%1$d berkas, %2$d folder</string>
+  <string name="share_dialog_title">Berbagi</string>
+  <string name="share_with_user_section_title">Bagikan dengan Pengguna dan Grup</string>
+  <string name="share_no_users">Tidak ada data yang dibagikan dengan pengguna</string>
+  <string name="share_add_user_or_group">Tambah Pengguna atau Grup</string>
+  <string name="share_search">Cari</string>
 </resources>
index 2d50d6f..046a796 100644 (file)
@@ -24,7 +24,6 @@
   <string name="common_yes">Já</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">Í lagi</string>
-  <string name="common_cancel_upload">Hætta við innsendingu</string>
   <string name="common_cancel">Hætta við</string>
   <string name="common_error"><strong>Villa</strong></string>
   <string name="change_password">Breyta lykilorði</string>
@@ -36,4 +35,5 @@
   <string name="actionbar_move">Færa</string>
   <string name="folder_picker_choose_button_text">Veldu</string>
   <string name="auth_host_address">Host nafn netþjóns</string>
+  <string name="share_search">Leita</string>
 </resources>
index 49fd528..3a2e02c 100644 (file)
   <string name="filedetails_created">Creato:</string>
   <string name="filedetails_modified">Modificato:</string>
   <string name="filedetails_download">Scarica</string>
-  <string name="filedetails_sync_file">Aggiorna file</string>
+  <string name="filedetails_sync_file">Sincronizza</string>
   <string name="filedetails_renamed_in_upload_msg">Il file è stato rinominato in %1$s durante il caricamento</string>
   <string name="list_layout">Struttura elenco</string>
   <string name="action_share_file">Condividi collegamento</string>
   <string name="action_unshare_file">Rimuovi condivisione collegamento</string>
+  <string name="action_share_with_users">Condividi con utenti</string>
   <string name="common_yes">Sì</string>
   <string name="common_no">No</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Annulla lo scaricamento</string>
-  <string name="common_cancel_upload">Annulla caricamento</string>
+  <string name="common_cancel_sync">Annulla sincronizzazione</string>
   <string name="common_cancel">Annulla</string>
   <string name="common_save_exit">Salva ed esci</string>
   <string name="common_error">Errore</string>
   <string name="unfavorite">Rimuovi dai preferiti</string>
   <string name="common_rename">Rinomina</string>
   <string name="common_remove">Rimuovi</string>
-  <string name="confirmation_remove_alert">Vuoi davvero rimuovere %1$s?</string>
+  <string name="confirmation_remove_file_alert">Vuoi davvero rimuovere %1$s?</string>
   <string name="confirmation_remove_folder_alert">Vuoi davvero rimuovere %1$s e il suo contenuto?</string>
   <string name="confirmation_remove_local">Solo localmente</string>
   <string name="confirmation_remove_folder_local">Solo locale</string>
-  <string name="confirmation_remove_remote">Dal server</string>
+  <string name="confirmation_remove_file_remote">Dal server</string>
   <string name="confirmation_remove_remote_and_local">Remota e locale</string>
   <string name="remove_success_msg">Rimozione effettuata con successo</string>
   <string name="remove_fail_msg">La rimozione non può essere completata</string>
   <string name="ssl_validator_label_validity_to">A:</string>
   <string name="ssl_validator_label_signature">Firma:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritmo:</string>
+  <string name="digest_algorithm_not_available">Questo algoritmo digest non è disponibile sul tuo telefono.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Impronta digitale:</string>
+  <string name="certificate_load_problem">Si è verificato un problema durante il caricamento del certificato.</string>
   <string name="ssl_validator_null_cert">Il certificato non può essere mostrato.</string>
   <string name="ssl_validator_no_info_about_error">- Nessuna informazione sull\'errore</string>
   <string name="placeholder_sentence">Questo è un segnaposto</string>
   <string name="prefs_category_instant_uploading">Caricamenti istantanei</string>
   <string name="prefs_category_security">Protezione</string>
   <string name="prefs_instant_video_upload_path_title">Percorso di caricamento video</string>
-  <string name="download_folder_failed_content">Lo scaricamento della cartella %1$s non può essere completato</string>
+  <string name="sync_folder_failed_content">La sincronizzazione della cartella %1$s non può essere completata</string>
   <string name="shared_subject_header">condiviso</string>
   <string name="with_you_subject_header">con te</string>
-  <string name="subject_token">%1$s ha condiviso \"%2$s\" con te</string>
-  <string name="saml_subject_token">\"%1$s\" è stato condiviso con te</string>
+  <string name="subject_user_shared_with_you">%1$s ha condiviso \"%2$s\" con te</string>
+  <string name="subject_shared_with_you">\"%1$s\" è stato condiviso con te</string>
   <string name="auth_refresh_button">Aggiorna la connessione</string>
   <string name="auth_host_address">Indirizzo del server</string>
   <string name="common_error_out_memory">Memoria insufficiente</string>
   <string name="file_list__footer__files">%1$d file</string>
   <string name="file_list__footer__files_and_folder">%1$d file, 1 cartella</string>
   <string name="file_list__footer__files_and_folders">%1$d file, %2$d cartelle</string>
+  <string name="share_dialog_title">Condivisione</string>
+  <string name="share_with_user_section_title">Condividi con utenti e gruppi</string>
+  <string name="share_no_users">Ancora nessun dato condiviso con gli utenti </string>
+  <string name="share_add_user_or_group">Aggiungi utente o gruppo</string>
+  <string name="share_search">Cerca</string>
+  <string name="search_users_and_groups_hint">Cerca utenti e gruppi</string>
+  <string name="share_group_clarification">%1$s (gruppo)</string>
+  <string name="share_sharee_unavailable">Spiacenti, la versione del tuo server non consente la condivisione con utenti dai client.
+\nContatta il tuo amministratore.</string>
 </resources>
index b51e644..d17876a 100644 (file)
@@ -72,6 +72,7 @@
   <string name="file_list_seconds_ago">数秒前</string>
   <string name="file_list_empty">ここには何もありません。何かアップロードしてください。</string>
   <string name="file_list_loading">読込中...</string>
+  <string name="file_list_no_app_for_file_type">この種類のファイルに対応するアプリはありません!</string>
   <string name="local_file_list_empty">このフォルダーにはファイルがありません。</string>
   <string name="filedetails_select_file">ファイルをタップすると追加情報が表示されます。</string>
   <string name="filedetails_size">サイズ:</string>
   <string name="list_layout">リストレイアウト</string>
   <string name="action_share_file">URLで共有</string>
   <string name="action_unshare_file">未共有のリンク</string>
+  <string name="action_share_with_users">ユーザーと共有</string>
   <string name="common_yes">はい</string>
   <string name="common_no">いいえ</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">ダウンロードをキャンセル</string>
-  <string name="common_cancel_upload">アップロードをキャンセル</string>
+  <string name="common_cancel_sync">同期をキャンセル</string>
   <string name="common_cancel">キャンセル</string>
   <string name="common_save_exit">保存して終了</string>
   <string name="common_error">エラー</string>
   <string name="unfavorite">お気に入りを解除</string>
   <string name="common_rename">名前を変更</string>
   <string name="common_remove">削除</string>
-  <string name="confirmation_remove_alert">本当に %1$s を削除しますか?</string>
+  <string name="confirmation_remove_file_alert">本当に %1$s を削除しますか?</string>
   <string name="confirmation_remove_folder_alert">本当に %1$s およびそのコンテンツを削除してもよろしいですか?</string>
   <string name="confirmation_remove_local">ローカルのみ</string>
   <string name="confirmation_remove_folder_local">ローカルのみ</string>
+  <string name="confirmation_remove_remote">サーバーから</string>
+  <string name="confirmation_remove_remote_and_local">リモートとローカルの両方</string>
   <string name="remove_success_msg">削除に成功しました</string>
   <string name="remove_fail_msg">削除を完了できませんでした</string>
   <string name="rename_dialog_title">新しい名前を入力</string>
   <string name="ssl_validator_label_validity_to">先:</string>
   <string name="ssl_validator_label_signature">署名:</string>
   <string name="ssl_validator_label_signature_algorithm">アルゴリズム:</string>
+  <string name="digest_algorithm_not_available">このスマートフォンでは、ダイジェストアルゴリズムが利用できません。</string>
+  <string name="ssl_validator_label_certificate_fingerprint">フィンガープリント:</string>
+  <string name="certificate_load_problem">証明書の読み込みに問題がありました。</string>
   <string name="ssl_validator_null_cert">証明書が表示できません。</string>
   <string name="ssl_validator_no_info_about_error">-エラーについての詳細情報はありません</string>
   <string name="placeholder_sentence">これはプレースホルダです</string>
   <string name="conflict_title">ファイルが競合</string>
   <string name="conflict_message">どちらのファイルを保存したいですか?両方のバージョンを選択した場合は、ファイル名の後ろに数字を追加したファイルのコピーを作成します。</string>
   <string name="conflict_keep_both">両方を保持</string>
+  <string name="conflict_use_local_version">ローカルのもの</string>
+  <string name="conflict_use_server_version">サーバーのもの</string>
   <string name="preview_image_description">イメージプレビュー</string>
   <string name="preview_image_error_unknown_format">この画像は表示できません</string>
   <string name="error__upload__local_file_not_copied">%1$s は、ローカルフォルダー %2$s  にコピーできませんでした。</string>
   <string name="move_file_invalid_overwrite">そのファイルは宛先フォルダーにすでに存在します。</string>
   <string name="move_file_error">このファイルまたはフォルダーを移動する際にエラーが発生しました</string>
   <string name="forbidden_permissions_move">このファイルを移動</string>
+  <string name="copy_file_not_found">コピーできません。ファイルがあるか確認してください。</string>
+  <string name="copy_file_invalid_into_descendent">フォルダーを子フォルダーへコピーすることはできません。</string>
   <string name="copy_file_invalid_overwrite">そのファイルは宛先フォルダーにすでに存在します。</string>
+  <string name="copy_file_error">このファイルまたはフォルダーをコピーする際にエラーが発生しました</string>
+  <string name="forbidden_permissions_copy">このファイルをコピー</string>
   <string name="prefs_category_instant_uploading">自動アップロード</string>
   <string name="prefs_category_security">セキュリティ</string>
   <string name="prefs_instant_video_upload_path_title">動画のアップロードパス</string>
-  <string name="download_folder_failed_content">%1$s フォルダーのダウンロードが完了しませんでした</string>
+  <string name="sync_folder_failed_content">%1$s フォルダーの同期が完了しませんでした。</string>
   <string name="shared_subject_header">共有中</string>
   <string name="with_you_subject_header">あなたと</string>
-  <string name="subject_token">%1$s は \"%2$s\" をあなたと共有しました</string>
-  <string name="saml_subject_token">\"%1$s\" があなたと共有しました</string>
+  <string name="subject_user_shared_with_you">%1$s は \"%2$s\" をあなたと共有しました</string>
+  <string name="subject_shared_with_you">\"%1$s\" があなたと共有しました</string>
   <string name="auth_refresh_button">再接続中</string>
   <string name="auth_host_address">サーバーアドレス</string>
   <string name="common_error_out_memory">十分なメモリがありません</string>
   <string name="file_list__footer__files">%1$d ファイル</string>
   <string name="file_list__footer__files_and_folder">%1$d ファイル、1 フォルダー</string>
   <string name="file_list__footer__files_and_folders">%1$d ファイル、%2$d フォルダー</string>
+  <string name="share_dialog_title">共有</string>
+  <string name="share_with_user_section_title">ユーザーまたはグループに共有</string>
+  <string name="share_no_users">ユーザーと共有されているデータはありません</string>
+  <string name="share_add_user_or_group">ユーザーまたはグループを追加</string>
+  <string name="share_search">検索</string>
+  <string name="search_users_and_groups_hint">ユーザーとグループを検索</string>
+  <string name="share_group_clarification">%1$s (グループ)</string>
+  <string name="share_sharee_unavailable">申し訳ありませんが、このサーバーのバージョンではこのクライアントアプリ上で他のユーザーと共有することができません。
+        \n管理者に相談してしてください。</string>
 </resources>
index 0d7d860..06bf89b 100644 (file)
@@ -46,8 +46,6 @@
   <string name="common_yes">კი</string>
   <string name="common_no">არა</string>
   <string name="common_ok">დიახ</string>
-  <string name="common_cancel_download">ჩამოტვირთვის შეჩერება</string>
-  <string name="common_cancel_upload">ატვირთვის გაუქმება</string>
   <string name="common_cancel">გაუქმება</string>
   <string name="common_save_exit">შენახვა &amp;გამოსვლა</string>
   <string name="common_error">შეცდომა</string>
   <string name="folder_picker_choose_button_text">არჩევა</string>
   <string name="prefs_category_security">უსაფრთხოება</string>
   <string name="auth_host_address">სერვერის მისამართი</string>
+  <string name="share_dialog_title">გაზიარება</string>
+  <string name="share_search">ძებნა</string>
 </resources>
index 68b3921..1c9ef99 100644 (file)
@@ -58,8 +58,6 @@
   <string name="common_yes">ព្រម</string>
   <string name="common_no">ទេ</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">បោះបង់ការទាញយក</string>
-  <string name="common_cancel_upload">បោះបង់​ការ​ផ្ទុកឡើង</string>
   <string name="common_cancel">លើកលែង</string>
   <string name="common_save_exit">រក្សាទុក &amp; ចាកចេញ</string>
   <string name="common_error">កំហុស</string>
   <string name="folder_picker_choose_button_text">ជ្រើស</string>
   <string name="prefs_category_security">សុវត្ថិភាព</string>
   <string name="auth_host_address">អាសយដ្ឋាន​ម៉ាស៊ីន​បម្រើ</string>
+  <string name="share_dialog_title">ការ​ចែក​រំលែក</string>
+  <string name="share_search">ស្វែង​រក</string>
 </resources>
index ef5e51c..4ca45b1 100644 (file)
@@ -25,7 +25,6 @@
   <string name="common_yes">ಹೌದು</string>
   <string name="common_no">ಇಲ್ಲ</string>
   <string name="common_ok">ಸರಿ</string>
-  <string name="common_cancel_upload">ವರ್ಗಾವಣೆ ರದ್ದು ಮಾಡಿ</string>
   <string name="common_cancel">ರದ್ದು</string>
   <string name="common_error">ತಪ್ಪಾಗಿದೆ</string>
   <string name="common_error_unknown">ಗೊತ್ತಿಲ್ಲದ ದೋಷ</string>
@@ -40,4 +39,6 @@
   <string name="folder_picker_choose_button_text">ಆಯ್ಕೆ</string>
   <string name="prefs_category_security">ಭದ್ರತೆ</string>
   <string name="auth_host_address">ಪರಿಚಾರಕ ಗಣಕಯಂತ್ರದ ವಿಳಾಸ</string>
+  <string name="share_dialog_title">ಹಂಚಿಕೆ</string>
+  <string name="share_search">ಹುಡುಕು</string>
 </resources>
index 1876c65..c856bf3 100644 (file)
@@ -79,7 +79,6 @@
   <string name="filedetails_created">만든 날짜:</string>
   <string name="filedetails_modified">수정한 날짜:</string>
   <string name="filedetails_download">다운로드</string>
-  <string name="filedetails_sync_file">파일 새로 고침</string>
   <string name="filedetails_renamed_in_upload_msg">업로드 중 파일 이름을 %1$s(으)로 변경하였습니다</string>
   <string name="list_layout">목록 레이아웃</string>
   <string name="action_share_file">링크 공유</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">예</string>
   <string name="common_no">아니요</string>
   <string name="common_ok">확인</string>
-  <string name="common_cancel_download">다운로드 취소</string>
-  <string name="common_cancel_upload">업로드 취소</string>
   <string name="common_cancel">취소</string>
   <string name="common_save_exit">저장하고 끝내기</string>
   <string name="common_error">오류</string>
   <string name="unfavorite">책갈피 해제</string>
   <string name="common_rename">이름 바꾸기</string>
   <string name="common_remove">삭제</string>
-  <string name="confirmation_remove_alert">%1$s을(를) 삭제하시겠습니까?</string>
+  <string name="confirmation_remove_file_alert">%1$s을(를) 삭제하시겠습니까?</string>
   <string name="confirmation_remove_folder_alert">%1$s 및 포함된 내용을 삭제하시겠습니까?</string>
   <string name="confirmation_remove_local">로컬만</string>
   <string name="confirmation_remove_folder_local">로컬만</string>
   <string name="prefs_category_instant_uploading">즉시 업로드</string>
   <string name="prefs_category_security">보안</string>
   <string name="prefs_instant_video_upload_path_title">동영상 업로드 경로</string>
-  <string name="download_folder_failed_content">폴더 %1$s을(를) 다운로드할 수 없음</string>
   <string name="shared_subject_header">공유됨</string>
   <string name="with_you_subject_header">여러분과</string>
-  <string name="subject_token">%1$s 님이 \"%2$s\" 항목을 여러분과 공유하였습니다</string>
-  <string name="saml_subject_token">\"%1$s\"을(를) 여러분과 공유하였습니다</string>
+  <string name="subject_user_shared_with_you">%1$s 님이 \"%2$s\" 항목을 여러분과 공유하였습니다</string>
+  <string name="subject_shared_with_you">\"%1$s\"을(를) 여러분과 공유하였습니다</string>
   <string name="auth_refresh_button">연결 새로 고침</string>
   <string name="auth_host_address">서버 주소</string>
   <string name="common_error_out_memory">메모리 부족</string>
   <string name="file_list__footer__files">파일 %1$d개</string>
   <string name="file_list__footer__files_and_folder">파일 %1$d개, 폴더 1개</string>
   <string name="file_list__footer__files_and_folders">파일 %1$d개, 폴더 %2$d개</string>
+  <string name="share_dialog_title">공유</string>
+  <string name="share_with_user_section_title">Share with Users and Groups</string>
+  <string name="share_no_users">No data shared with users yet</string>
+  <string name="share_add_user_or_group">Add User or Group</string>
+  <string name="share_search">검색</string>
 </resources>
index af1edac..e03d080 100644 (file)
@@ -37,4 +37,5 @@
   <string name="empty"></string>
   <string name="prefs_category_accounts">هەژمارەکان</string>
   <string name="auth_host_address">ناونیشانی ڕاژه</string>
+  <string name="share_search">بگەڕێ</string>
 </resources>
index 80ccbff..1c958f3 100644 (file)
   <string name="filedetails_created">Erstallt:</string>
   <string name="filedetails_modified">Geännert:</string>
   <string name="filedetails_download">Eroflueden</string>
-  <string name="filedetails_sync_file">Fichier opfrëschen</string>
   <string name="action_share_file">Link deelen</string>
   <string name="common_yes">Jo</string>
   <string name="common_no">Nee</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Eroflueden ofbriechen</string>
-  <string name="common_cancel_upload">Eroplueden ofbriechen</string>
   <string name="common_cancel">Ofbriechen</string>
   <string name="common_save_exit">Späicheren an Zoumaachen</string>
   <string name="common_error">Feeler</string>
   <string name="auth_unsupported_auth_method">De Server ënnerstëtzt dës Authentifizéierungsmethod net</string>
   <string name="common_rename">Ëmbenennen</string>
   <string name="common_remove">Läschen</string>
-  <string name="confirmation_remove_alert">Wëlls du %1$s wierklech läschen?</string>
+  <string name="confirmation_remove_file_alert">Wëlls du %1$s wierklech läschen?</string>
   <string name="confirmation_remove_folder_alert">Wëlls du %1$s an de ganzen Inhalt wierklech läschen?</string>
   <string name="confirmation_remove_local">Nemme lokal</string>
   <string name="confirmation_remove_folder_local">Nemme lokal</string>
   <string name="prefs_category_instant_uploading">Direkt eropgeluede Fichieren</string>
   <string name="prefs_category_security">Sécherheet</string>
   <string name="prefs_instant_video_upload_path_title">Pad fir d\'Eropluede vun de Videoen</string>
-  <string name="download_folder_failed_content">D\'Erofluede vum %1$s-Dossier konnt net ofgeschloss ginn</string>
+  <string name="subject_user_shared_with_you">%1$s huet \"%2$s\" mat dir gedeelt</string>
   <string name="auth_refresh_button">Connectioun opfrëschen</string>
   <string name="auth_host_address">Server-Adress</string>
+  <string name="share_search">Sichen</string>
 </resources>
index fe17441..87c1a8b 100644 (file)
@@ -8,4 +8,5 @@
     <string name="drawer_item_on_device">On device</string>-->
   <string name="common_error_unknown">ຂໍ້ຜິດພາດທີ່ບໍ່ຮູ້ສາເຫດ</string>
   <string name="empty"></string>
+  <string name="share_dialog_title">ການແບ່ງປັນ</string>
 </resources>
index 855116d..1459761 100644 (file)
@@ -79,7 +79,7 @@
   <string name="filedetails_created">Sukurta:</string>
   <string name="filedetails_modified">Modifikuota:</string>
   <string name="filedetails_download">Atsisiųsti</string>
-  <string name="filedetails_sync_file">Atnaujinti failą</string>
+  <string name="filedetails_sync_file">Sinchronizuojama</string>
   <string name="filedetails_renamed_in_upload_msg">Įkėlimo metu failas buvo pervadintas į %1$s</string>
   <string name="list_layout">Sąrašo išdėstymas</string>
   <string name="action_share_file">Dalintis nuoroda</string>
@@ -87,8 +87,7 @@
   <string name="common_yes">Taip</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Gerai</string>
-  <string name="common_cancel_download">Atšaukti parsiuntimą</string>
-  <string name="common_cancel_upload">Atšaukti siuntimą</string>
+  <string name="common_cancel_sync">Atšaukti sinchronizavimą</string>
   <string name="common_cancel">Atšaukti</string>
   <string name="common_save_exit">Išsaugoti ir Išeiti</string>
   <string name="common_error">Klaida</string>
   <string name="sync_fail_in_favourites_content">Nepavyko sinchronizuoti %1$d failų turinio (%2$d konfliktų)</string>
   <string name="sync_foreign_files_forgotten_ticker">Keli vietiniai failai buvo užmiršti</string>
   <string name="sync_foreign_files_forgotten_content">%1$d failai iš %2$s aplanko negali būti nukopijuoti</string>
+  <string name="sync_foreign_files_forgotten_explanation">Iki 1.3.16 versijos, iš šio įrenginio įkelti failai nukopijuoti į vietinį %1$s aplanką, siekiant išvengti duomenų praradimo kai vienas failas sinchronizuojamas su keletu įrenginių.\n\nTodėl visi failai įkelti su ankstesne versija nukopijuoti į %2$s aplanką. Dėja kopijavimas nepavuko dėl klaidos sinchronizuojant paskyrą. Galita palikti failus ir pašalinti ryšį su %3$s, arba perkelti failą(us) į %1$s aplanką ir palikti ryšį su %4$s.\n\nŽemiau pateikti vietiniai failai ir aplankas(ai), bei nutolę failai susieti per  %5$s.</string>
   <string name="sync_current_folder_was_removed">Aplankas %1$s nebeegzistuoja</string>
   <string name="foreign_files_move">Perkelti visus</string>
   <string name="foreign_files_success">Visi failai buvo perkelti</string>
   <string name="unfavorite">Nebemėgti</string>
   <string name="common_rename">Pervadinti</string>
   <string name="common_remove">Pašalinti</string>
-  <string name="confirmation_remove_alert">Ar tikrai norite pašalinti %1$s?</string>
+  <string name="confirmation_remove_file_alert">Ar tikrai norite pašalinti %1$s?</string>
   <string name="confirmation_remove_folder_alert">Ar tikrai norite pašalinti %1$s ir ten esantį turinį?</string>
   <string name="confirmation_remove_local">Tik vietiniai</string>
   <string name="confirmation_remove_folder_local">Tik vietiniai</string>
   <string name="prefs_category_instant_uploading">Momentinis įkėlimas</string>
   <string name="prefs_category_security">Saugumas</string>
   <string name="prefs_instant_video_upload_path_title">Vaizdo įrašų įkėlimo kelias</string>
-  <string name="download_folder_failed_content">Nepavyko baigti %1$s atsiuntimo</string>
+  <string name="sync_folder_failed_content">%1$s sinchronizavimas negali būti užbaigtas.</string>
   <string name="shared_subject_header">Dalinamasi</string>
   <string name="with_you_subject_header">su jumis</string>
-  <string name="subject_token">%1$s dalinamasi \"%2$s\" su jumis</string>
-  <string name="saml_subject_token">\"%1$s\" dalinamasi su jumis</string>
+  <string name="subject_user_shared_with_you">%1$s dalinamasi \"%2$s\" su jumis</string>
+  <string name="subject_shared_with_you">\"%1$s\" dalinamasi su jumis</string>
   <string name="auth_refresh_button">Atnaujinti sujungimą</string>
   <string name="auth_host_address">Serverio adresas</string>
   <string name="common_error_out_memory">Nepakanka atminties</string>
   <string name="file_list__footer__files">%1$d failai</string>
   <string name="file_list__footer__files_and_folder">%1$d failai, 1 aplankas</string>
   <string name="file_list__footer__files_and_folders">%1$d failai, %2$d aplankai</string>
+  <string name="share_dialog_title">Dalijimasis</string>
+  <string name="share_search">Ieškoti</string>
 </resources>
index ea13b1b..42cb5bb 100644 (file)
        <item>Biggest - Smallest</item>-->
   <!--TODO re-enable when "Accounts" is available in Navigation Drawer-->
   <!--<string name="drawer_item_accounts">Accounts</string>-->
+  <string name="drawer_item_all_files">Visas datnes</string>
   <!--TODO re-enable when "On Device" is available
     <string name="drawer_item_on_device">On device</string>-->
+  <string name="drawer_item_settings">Iestatījumi</string>
+  <string name="drawer_close">Aizvērt</string>
   <string name="drawer_open">Atvērt</string>
   <string name="prefs_category_general">Vispārīgi</string>
   <string name="prefs_category_more">Vairāk</string>
@@ -40,6 +43,8 @@
   <string name="prefs_help">Palīdzība</string>
   <string name="prefs_recommend">Ieteikt draugam</string>
   <string name="prefs_feedback">Atsauksmes</string>
+  <string name="recommend_subject">Izmēģini %1$s uz savu viedtālruni!</string>
+  <string name="auth_check_server">Pārbaudīt serveri</string>
   <string name="auth_username">Lietotājvārds</string>
   <string name="auth_password">Parole</string>
   <string name="sync_string_files">Datnes</string>
@@ -56,6 +61,7 @@
   <string name="uploader_info_uploading">Augšupielādē</string>
   <string name="file_list_seconds_ago">sekundes atpakaļ</string>
   <string name="file_list_empty">Te vēl nekas nav. Rīkojies, sāc augšupielādēt!</string>
+  <string name="file_list_loading">Ielādē…</string>
   <string name="local_file_list_empty">Šajā mapē nav failu</string>
   <string name="filedetails_select_file">Uzsitiet uz datnes, lai redzētu papildinformāciju.</string>
   <string name="filedetails_size">Izmērs:</string>
   <string name="filedetails_created">Izveidota:</string>
   <string name="filedetails_modified">Modificēta:</string>
   <string name="filedetails_download">Lejupielādēt</string>
-  <string name="filedetails_sync_file">Atsvaidzināt failu</string>
   <string name="filedetails_renamed_in_upload_msg">Datne tika pārsaukta uz %1$s augšupielādes laikā</string>
+  <string name="action_share_file">Dalīt saiti</string>
+  <string name="action_unshare_file">Pārtraukt dalīt saiti</string>
   <string name="common_yes">Jā</string>
   <string name="common_no">Nē</string>
   <string name="common_ok">Labi</string>
-  <string name="common_cancel_download">Atcelt lejupielādi</string>
-  <string name="common_cancel_upload">Atcelt augšupielādi</string>
   <string name="common_cancel">Atcelt</string>
   <string name="common_save_exit">Saglabāt un iziet</string>
   <string name="common_error">Kļūda</string>
   <string name="common_remove">Izņemt</string>
   <string name="confirmation_remove_local">Tikai lokālos</string>
   <string name="confirmation_remove_folder_local">Tikai lokālos</string>
+  <string name="confirmation_remove_remote">No servera</string>
   <string name="remove_success_msg">Veiksmīgi izņemts</string>
   <string name="remove_fail_msg">Neizdevās izņemt</string>
   <string name="rename_dialog_title">Ievadīt jaunu nosaukumu</string>
   <string name="rename_server_fail_msg">Nevarēja pabeigt pārsaukšanu</string>
   <string name="sync_file_fail_msg">Nevarēja atzīmēt attālinātas datnes</string>
   <string name="sync_file_nothing_to_do_msg">Datnes saturs jau ir sinhronizēts</string>
+  <string name="create_dir_fail_msg">Mapi nevarēja izveidot</string>
   <string name="wait_a_moment">Uzgaidīt brīdi</string>
   <string name="filedisplay_unexpected_bad_get_content">Negaidīta problēma; lūdzu, izvēlieties datni no citas lietotnes</string>
   <string name="filedisplay_no_file_selected">Netika izvēlēta neviena datne</string>
   <string name="ssl_validator_label_validity_to">Kam:</string>
   <string name="ssl_validator_label_signature">Paraksts:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritms:</string>
+  <string name="placeholder_filetype">PNG attēls</string>
   <string name="instant_upload_on_wifi">Attēlus augšupielādēt tikai caur WiFi</string>
   <string name="instant_upload_path">/TūlītējaAugšupielāde</string>
   <string name="conflict_keep_both">Paturēt abas</string>
+  <string name="preview_image_error_unknown_format">Šo attēlu nevar attēlot</string>
+  <string name="share_link_password_title">Ievadiet paroli</string>
+  <string name="share_link_empty_password">Jums ir jāievada paroli</string>
   <string name="activity_chooser_send_file_title">Sūtīt</string>
+  <string name="copy_link">Kopēt saiti</string>
   <string name="empty"></string>
+  <string name="forbidden_permissions_rename">lai pārsauktu šo datni</string>
+  <string name="forbidden_permissions_delete">lai dzēstu šo datni</string>
+  <string name="share_link_forbidden_permissions">lai dalītu šo datni</string>
+  <string name="unshare_link_forbidden_permissions">lai pārtrauktu šis datnes dalīšanu</string>
+  <string name="forbidden_permissions_create">lai izveidotu datni</string>
   <string name="prefs_category_accounts">Konti</string>
+  <string name="prefs_add_account">Pievienot kontu</string>
+  <string name="log_progress_dialog_text">Ielādē datus…</string>
   <string name="saml_authentication_wrong_pass">Nepareiza parole</string>
+  <string name="actionbar_move">Pārvietot</string>
+  <string name="file_list_empty_moving">Šeit nekā nav. Jūs varat pievienot mapi!</string>
   <string name="folder_picker_choose_button_text">Izvēlieties</string>
+  <string name="forbidden_permissions_move">lai pārvietotu šo datni</string>
+  <string name="forbidden_permissions_copy">lai kopētu šo datni</string>
   <string name="prefs_category_security">Drošība</string>
+  <string name="shared_subject_header">koplietots</string>
+  <string name="with_you_subject_header">ar jums</string>
   <string name="auth_host_address">Servera adrese</string>
+  <string name="username">Lietotājvārds</string>
+  <string name="file_list__footer__folder">1 mape</string>
+  <string name="file_list__footer__file">1 datne</string>
+  <string name="share_dialog_title">Dalīšanās</string>
+  <string name="share_search">Meklēt</string>
 </resources>
index 1c6f96f..a2708d3 100644 (file)
   <string name="filedetails_created">Создадено:</string>
   <string name="filedetails_modified">Изменето:</string>
   <string name="filedetails_download">Преземање</string>
-  <string name="filedetails_sync_file">Освежи ја датотеката</string>
   <string name="filedetails_renamed_in_upload_msg">Датотеката беше преименувана во %1$s за време на префрлањето</string>
   <string name="action_share_file">Сподели ја врската</string>
   <string name="action_unshare_file">Тргнете го споделувањето на врската</string>
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">Во ред</string>
-  <string name="common_cancel_download">Откажи превземање</string>
-  <string name="common_cancel_upload">Откажи прикачување</string>
   <string name="common_cancel">Откажи</string>
   <string name="common_save_exit">Сними &amp; Излез</string>
   <string name="common_error">Грешка</string>
   <string name="auth_account_does_not_exist">Сметката сеуште не постои на овој уред</string>
   <string name="common_rename">Преименувај</string>
   <string name="common_remove">Отстрани</string>
-  <string name="confirmation_remove_alert">Дали навистина сакаш да ја отстраниш %1$s?</string>
+  <string name="confirmation_remove_file_alert">Дали навистина сакаш да ја отстраниш %1$s?</string>
   <string name="confirmation_remove_folder_alert">Дали навистина сакаш да го отстранам %1$s и неговата содржина?</string>
   <string name="confirmation_remove_local">Само локално</string>
   <string name="confirmation_remove_folder_local">Само локално</string>
   <string name="prefs_category_instant_uploading">Инстант прикачувања</string>
   <string name="prefs_category_security">Безбедност</string>
   <string name="prefs_instant_video_upload_path_title">Прикачи патека на видео</string>
-  <string name="download_folder_failed_content">Превземањето на папката %1$s не може да се заврши</string>
+  <string name="subject_user_shared_with_you">%1$s сподели \"%2$s\" со тебе</string>
   <string name="auth_refresh_button">Освежи ја конекцијата</string>
   <string name="auth_host_address">Адреса на сервер</string>
+  <string name="share_dialog_title">Споделување</string>
+  <string name="share_search">Барај</string>
 </resources>
index 92ace9c..50f7a44 100644 (file)
@@ -18,4 +18,5 @@
   <string name="common_remove">Устгах</string>
   <string name="empty"></string>
   <string name="prefs_category_security">Аюулгүй байдал</string>
+  <string name="share_dialog_title">Түгээлт</string>
 </resources>
index 4ac4d95..910ed90 100644 (file)
@@ -41,7 +41,6 @@
   <string name="common_yes">Ya</string>
   <string name="common_no">Tidak</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_upload">Batal muat naik</string>
   <string name="common_cancel">Batal</string>
   <string name="common_save_exit">Simpan &amp; Keluar</string>
   <string name="common_error">Ralat</string>
@@ -61,4 +60,5 @@
   <string name="empty"></string>
   <string name="prefs_category_accounts">Akaun</string>
   <string name="auth_host_address">Alamat pelayan</string>
+  <string name="share_search">Cari</string>
 </resources>
index bbf1061..95ad2e5 100644 (file)
@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">for få sekunder siden</string>
   <string name="file_list_empty">Ingenting her. Last opp noe!</string>
   <string name="file_list_loading">Laster...</string>
+  <string name="file_list_no_app_for_file_type">Ingen app funnet for filtypen!</string>
   <string name="local_file_list_empty">Det er ingen filer i denne mappen.</string>
   <string name="filedetails_select_file">Trykk på en fil for å vise ekstra informasjon.</string>
   <string name="filedetails_size">Størrelse:</string>
@@ -78,7 +79,6 @@
   <string name="filedetails_created">Opprettet:</string>
   <string name="filedetails_modified">Endret:</string>
   <string name="filedetails_download">Last ned</string>
-  <string name="filedetails_sync_file">Oppdater fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filnavnet ble endret til  %1$s under opplasting</string>
   <string name="list_layout">Listeoppsett</string>
   <string name="action_share_file">Del lenke</string>
@@ -86,8 +86,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Avbryt nedlasting</string>
-  <string name="common_cancel_upload">Avbryt opplasting</string>
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Lagre og avslutt</string>
   <string name="common_error">Feil</string>
   <string name="unfavorite">Fjern favoritt</string>
   <string name="common_rename">Endre navn</string>
   <string name="common_remove">Fjern</string>
-  <string name="confirmation_remove_alert">Vil du virkelig fjerne %1$s?</string>
+  <string name="confirmation_remove_file_alert">Vil du virkelig fjerne %1$s?</string>
   <string name="confirmation_remove_folder_alert">Vil du virkelig fjerne %1$s inkludert innholdet?</string>
   <string name="confirmation_remove_local">Kun lokalt</string>
   <string name="confirmation_remove_folder_local">Kun lokalt</string>
-  <string name="confirmation_remove_remote">Fra server</string>
+  <string name="confirmation_remove_file_remote">Fra server</string>
   <string name="confirmation_remove_remote_and_local">Ekstern &amp; lokal</string>
   <string name="remove_success_msg">Fjerning var vellykket</string>
   <string name="remove_fail_msg">Fjerning mislyktes</string>
   <string name="prefs_category_instant_uploading">Umiddelbare opplastinger</string>
   <string name="prefs_category_security">Sikkerhet</string>
   <string name="prefs_instant_video_upload_path_title">Sti til video-opplasting</string>
-  <string name="download_folder_failed_content">Nedlasting av %1$s mappen kunne ikke fullføres</string>
   <string name="shared_subject_header">delte</string>
   <string name="with_you_subject_header">med deg</string>
-  <string name="subject_token">%1$s delte \"%2$s\" med deg</string>
-  <string name="saml_subject_token">\"%1$s\" er blitt delt med deg</string>
+  <string name="subject_user_shared_with_you">%1$s delte \"%2$s\" med deg</string>
+  <string name="subject_shared_with_you">\"%1$s\" er blitt delt med deg</string>
   <string name="auth_refresh_button">Oppfrisk forbindelse</string>
   <string name="auth_host_address">Server-adresse</string>
   <string name="common_error_out_memory">Ikke nok minne</string>
   <string name="file_list__footer__files">%1$d filer</string>
   <string name="file_list__footer__files_and_folder">%1$d filer, 1 mappe</string>
   <string name="file_list__footer__files_and_folders">%1$d filer, %2$d mapper</string>
+  <string name="share_dialog_title">Deling</string>
+  <string name="share_with_user_section_title">Del med brukere og grupper</string>
+  <string name="share_no_users">Ingen data delt med brukere ennå</string>
+  <string name="share_add_user_or_group">Legg til bruker eller gruppe</string>
+  <string name="share_search">Søk</string>
 </resources>
index 5d35f01..9a3fa84 100644 (file)
@@ -80,16 +80,16 @@ Download hier: %2$s</string>
   <string name="filedetails_created">Aangemaakt:</string>
   <string name="filedetails_modified">Aangepast:</string>
   <string name="filedetails_download">Download</string>
-  <string name="filedetails_sync_file">Bestand verversen</string>
+  <string name="filedetails_sync_file">Synchroniseren</string>
   <string name="filedetails_renamed_in_upload_msg">Bestand is tijdens het uploaden hernoemd naar %1$s</string>
   <string name="list_layout">Lijst layout</string>
   <string name="action_share_file">Deel link</string>
   <string name="action_unshare_file">Link niet meer delen</string>
+  <string name="action_share_with_users">Delen met gebruiker</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nee</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Annuleer download</string>
-  <string name="common_cancel_upload">Upload afbreken</string>
+  <string name="common_cancel_sync">Annuleren synchronisatie</string>
   <string name="common_cancel">Annuleren</string>
   <string name="common_save_exit">Opslaan &amp; Afsluiten</string>
   <string name="common_error">Fout</string>
@@ -202,11 +202,11 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <string name="unfavorite">Niet meer favoriet</string>
   <string name="common_rename">Hernoemen</string>
   <string name="common_remove">Verwijderen</string>
-  <string name="confirmation_remove_alert">Wilt u %1$s werkelijk verwijderen?</string>
+  <string name="confirmation_remove_file_alert">Wilt u %1$s werkelijk verwijderen?</string>
   <string name="confirmation_remove_folder_alert">Wilt u %1$s en de inhoud ervan werkelijk verwijderen?</string>
   <string name="confirmation_remove_local">Alleen lokaal</string>
   <string name="confirmation_remove_folder_local">Alleen lokaal</string>
-  <string name="confirmation_remove_remote">Van server</string>
+  <string name="confirmation_remove_file_remote">Van server</string>
   <string name="confirmation_remove_remote_and_local">Extern &amp; lokaal</string>
   <string name="remove_success_msg">Succesvol verwijderd</string>
   <string name="remove_fail_msg">Verwijdering kon niet voltooid worden</string>
@@ -248,6 +248,9 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <string name="ssl_validator_label_validity_to">Aan:</string>
   <string name="ssl_validator_label_signature">Handtekening:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritme:</string>
+  <string name="digest_algorithm_not_available">Dit digest algoritme is niet beschikbaar op uw telefoon.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Vingerafdruk:</string>
+  <string name="certificate_load_problem">Er is een probleem met het laden van het certificaat.</string>
   <string name="ssl_validator_null_cert">Het certificaat kon niet worden getoond.</string>
   <string name="ssl_validator_no_info_about_error">- Geen informatie over de fout</string>
   <string name="placeholder_sentence">Dit is een plaatshouder</string>
@@ -303,7 +306,7 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <string name="log_progress_dialog_text">Laden data...</string>
   <string name="saml_authentication_required_text">Authenticatie vereist</string>
   <string name="saml_authentication_wrong_pass">Onjuist wachtwoord</string>
-  <string name="actionbar_move">verplaatsen</string>
+  <string name="actionbar_move">Verplaatsen</string>
   <string name="file_list_empty_moving">Niets hier. U kunt een map toevoegen!</string>
   <string name="folder_picker_choose_button_text">Kies</string>
   <string name="move_file_not_found">Kan niet verplaatsen. Ga na of het bestand wel bestaat</string>
@@ -319,11 +322,11 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <string name="prefs_category_instant_uploading">Directe uploads</string>
   <string name="prefs_category_security">Beveiliging</string>
   <string name="prefs_instant_video_upload_path_title">Upload Video Pad</string>
-  <string name="download_folder_failed_content">Download van %1$s map kon niet worden voltooid</string>
+  <string name="sync_folder_failed_content">Synchronisatie van map %1$s kon niet worden voltooid</string>
   <string name="shared_subject_header">gedeeld</string>
   <string name="with_you_subject_header">met u</string>
-  <string name="subject_token">%1$s deelde \"%2$s\" met u</string>
-  <string name="saml_subject_token">\"%1$s\" is gedeeld met u</string>
+  <string name="subject_user_shared_with_you">%1$s deelde \"%2$s\" met u</string>
+  <string name="subject_shared_with_you">\"%1$s\" is gedeeld met u</string>
   <string name="auth_refresh_button">Verversen verbinding</string>
   <string name="auth_host_address">Serveradres</string>
   <string name="common_error_out_memory">Niet voldoende geheugen</string>
@@ -336,4 +339,13 @@ Hieronder staan de lokale bestanden en de externe bestanden in %5$s waar ze naar
   <string name="file_list__footer__files">%1$d bestanden</string>
   <string name="file_list__footer__files_and_folder">%1$d bestanden, 1 map</string>
   <string name="file_list__footer__files_and_folders">%1$d bestanden, %2$d mappen</string>
+  <string name="share_dialog_title">Delen</string>
+  <string name="share_with_user_section_title">Delen met gebruikers en groepen</string>
+  <string name="share_no_users">Nog geen gegevens met gebruikers gedeeld</string>
+  <string name="share_add_user_or_group">Toevoegen gebruiker of groep</string>
+  <string name="share_search">Zoeken</string>
+  <string name="search_users_and_groups_hint">Zoeken naar gebruikers en groepen</string>
+  <string name="share_group_clarification">%1$s (groep)</string>
+  <string name="share_sharee_unavailable">Sorry, uw serverversie staat niet toe om binnen de clients te delen met gebruikers.
+Neem contact op met uw beheerder</string>
 </resources>
index 2a12cc0..aa846e3 100644 (file)
@@ -62,8 +62,6 @@
   <string name="common_yes">Ja</string>
   <string name="common_no">Nei</string>
   <string name="common_ok">Greitt</string>
-  <string name="common_cancel_download">Avbryt nedlasting</string>
-  <string name="common_cancel_upload">Avbryt opplasting</string>
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Lagra &amp; avslutt</string>
   <string name="common_error">Feil</string>
   <string name="folder_picker_choose_button_text">Vel</string>
   <string name="prefs_category_security">Tryggleik</string>
   <string name="auth_host_address">Tenaradresse</string>
+  <string name="share_dialog_title">Deling</string>
+  <string name="share_search">Søk</string>
 </resources>
index c50bc37..5ba832c 100644 (file)
@@ -72,6 +72,7 @@ Telecargatz-lo aicí : %2$s</string>
   <string name="file_list_seconds_ago">i a qualques segondas</string>
   <string name="file_list_empty">I a pas res aicí ! Mandatz doncas quicòm :)</string>
   <string name="file_list_loading">Cargament...</string>
+  <string name="file_list_no_app_for_file_type">Cap d\'aplicacion pas trobada per aqueste tipe de fichièr !</string>
   <string name="local_file_list_empty">Cap de fichièr es pas present dins aqueste dorsièr.</string>
   <string name="filedetails_select_file">Quichatz sus un fichièr per afichar las informacions suplementàrias</string>
   <string name="filedetails_size">Talha :</string>
@@ -79,16 +80,16 @@ Telecargatz-lo aicí : %2$s</string>
   <string name="filedetails_created">Creat lo :</string>
   <string name="filedetails_modified">Modificat lo :</string>
   <string name="filedetails_download">Telecargar</string>
-  <string name="filedetails_sync_file">Actualizar lo fichièr</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">Lo fichièr es estat renomenat en %s pendent lo mandadís</string>
   <string name="list_layout">Afichatge en lista</string>
   <string name="action_share_file">Partejar lo ligam</string>
   <string name="action_unshare_file">Partejar pas mai aqueste ligam</string>
+  <string name="action_share_with_users">Partejar amb d\'Utilizaires</string>
   <string name="common_yes">Òc</string>
   <string name="common_no">Non</string>
   <string name="common_ok">D\'acòrdi</string>
-  <string name="common_cancel_download">Anullar lo telecargament</string>
-  <string name="common_cancel_upload">Anullar lo mandadís</string>
+  <string name="common_cancel_sync">Anullar la sincronizacion</string>
   <string name="common_cancel">Anullar</string>
   <string name="common_save_exit">Salvar &amp; Quitar</string>
   <string name="common_error">Error</string>
@@ -203,11 +204,11 @@ En rason d\'aquesta modificacion, totes los fichièrs mandats amb de versions an
   <string name="unfavorite">Suprimir dels favorits</string>
   <string name="common_rename">Renomenar</string>
   <string name="common_remove">Suprimir</string>
-  <string name="confirmation_remove_alert">Sètz segur que volètz suprimir %1$s ?</string>
+  <string name="confirmation_remove_file_alert">Sètz segur que volètz suprimir %1$s ?</string>
   <string name="confirmation_remove_folder_alert">Sètz segur que volètz suprimir %1$s e son contengut ?</string>
   <string name="confirmation_remove_local">Local solament</string>
   <string name="confirmation_remove_folder_local">Local solament</string>
-  <string name="confirmation_remove_remote">Dempuèi lo servidor</string>
+  <string name="confirmation_remove_file_remote">Dempuèi lo servidor</string>
   <string name="confirmation_remove_remote_and_local">Distant &amp; local</string>
   <string name="remove_success_msg">Supression efectuada amb succès</string>
   <string name="remove_fail_msg">Supression impossibla</string>
@@ -319,11 +320,11 @@ En rason d\'aquesta modificacion, totes los fichièrs mandats amb de versions an
   <string name="prefs_category_instant_uploading">Mandadís immediat</string>
   <string name="prefs_category_security">Seguretat</string>
   <string name="prefs_instant_video_upload_path_title">Repertòri de mandadís de las vidèos</string>
-  <string name="download_folder_failed_content">Lo telecargament del dorsièr %1$s a pas pogut èsser acabat</string>
+  <string name="sync_folder_failed_content">La sincronizacion del dorsièr %1$s a pas pogut èsser acabad</string>
   <string name="shared_subject_header">a partejat</string>
   <string name="with_you_subject_header">amb vos</string>
-  <string name="subject_token">%1$s a partejat \"%2$s\" amb vos</string>
-  <string name="saml_subject_token">\"%1$s\" es estat partejat amb vos</string>
+  <string name="subject_user_shared_with_you">%1$s a partejat \"%2$s\" amb vos</string>
+  <string name="subject_shared_with_you">\"%1$s\" es estat partejat amb vos</string>
   <string name="auth_refresh_button">Actualizar la connexion</string>
   <string name="auth_host_address">Adreça del servidor</string>
   <string name="common_error_out_memory">Memòria insufisenta</string>
@@ -336,4 +337,10 @@ En rason d\'aquesta modificacion, totes los fichièrs mandats amb de versions an
   <string name="file_list__footer__files">%1$d fichièrs</string>
   <string name="file_list__footer__files_and_folder">%1$d fichièrs, 1 dorsièr</string>
   <string name="file_list__footer__files_and_folders">%1$d fichièrs, %2$d dorsièrs</string>
+  <string name="share_dialog_title">Partiment</string>
+  <string name="share_with_user_section_title">Partejar amb d\'utilizaires e de gropes</string>
+  <string name="share_no_users">Cap de donada es pas partejada amb d\'utilizaires pel moment</string>
+  <string name="share_add_user_or_group">Apondre un utilizaire o un grop</string>
+  <string name="share_search">Recercar</string>
+  <string name="search_users_and_groups_hint">Recercar d\'utilizaires e de gropes</string>
 </resources>
index f68a9c6..35a3769 100644 (file)
   <string name="filedetails_created">ਬਣਾਈ:</string>
   <string name="filedetails_modified">ਸੋਧ ਕੀਤੀ:</string>
   <string name="filedetails_download">ਡਾਊਨਲੋਡ</string>
-  <string name="filedetails_sync_file">ਫਾਇਲ ਤਾਜ਼ਾ ਕਰੋ</string>
   <string name="common_yes">ਹਾਂ</string>
   <string name="common_no">ਨਹੀਂ</string>
   <string name="common_ok">ਠੀਕ ਹੈ</string>
-  <string name="common_cancel_download">ਡਾਊਨਲੋਡ ਕਰਨਾ ਰੱਦ ਕਰੋ</string>
-  <string name="common_cancel_upload">ਅੱਪਲੋਡ ਰੱਦ ਕਰੋ</string>
   <string name="common_cancel">ਰੱਦ ਕਰੋ</string>
   <string name="common_save_exit">ਸੰਭਾਲੋ ਅਤੇ ਬੰਦ ਕਰੋ</string>
   <string name="common_error">ਗਲਤੀ</string>
   <string name="prefs_category_accounts">ਅਕਾਊਂਟ</string>
   <string name="folder_picker_choose_button_text">ਚੁਣੋ</string>
   <string name="auth_host_address">ਸਰਵਰ ਐਡਰੈਸ</string>
+  <string name="share_search">ਖੋਜ</string>
 </resources>
index 95168bd..f6a6f45 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Utworzono:</string>
   <string name="filedetails_modified">Zmodyfikowano:</string>
   <string name="filedetails_download">Pobierz</string>
-  <string name="filedetails_sync_file">Odśwież plik</string>
   <string name="filedetails_renamed_in_upload_msg">Podczas wysyłania nazwa pliku została zmieniona na %1$s</string>
   <string name="list_layout">Lista szablonów wyglądu</string>
   <string name="action_share_file">Udostępnij link</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Tak</string>
   <string name="common_no">Nie</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Anuluj pobieranie</string>
-  <string name="common_cancel_upload">Anuluj wysyłanie</string>
   <string name="common_cancel">Anuluj</string>
   <string name="common_save_exit">Zapisz i wyjdź</string>
   <string name="common_error">Błąd</string>
   <string name="unfavorite">Usuń z ulubionych</string>
   <string name="common_rename">Zmień nazwę</string>
   <string name="common_remove">Usuń</string>
-  <string name="confirmation_remove_alert">Czy naprawdę chcesz usunąć %1$s?</string>
+  <string name="confirmation_remove_file_alert">Czy naprawdę chcesz usunąć %1$s?</string>
   <string name="confirmation_remove_folder_alert">Czy naprawdę chcesz usunąć %1$s i jego zawartość?</string>
   <string name="confirmation_remove_local">Tylko lokalnie</string>
   <string name="confirmation_remove_folder_local">Tylko lokalnie</string>
-  <string name="confirmation_remove_remote">Z serwera</string>
+  <string name="confirmation_remove_file_remote">Z serwera</string>
   <string name="remove_success_msg">Usunięto</string>
   <string name="remove_fail_msg">Nie można usunąć</string>
   <string name="rename_dialog_title">Wprowadź nową nazwę</string>
   <string name="prefs_category_instant_uploading">Automatyczne wysyłanie</string>
   <string name="prefs_category_security">Bezpieczeństwo</string>
   <string name="prefs_instant_video_upload_path_title">Katalog wysyłania dla wideo</string>
-  <string name="download_folder_failed_content">Pobieranie %1$s katalogu nie może zostać ukończone</string>
   <string name="shared_subject_header">udostępniony</string>
   <string name="with_you_subject_header">z tobą</string>
+  <string name="subject_user_shared_with_you">%1$s wspólne \"%2$s\" z tobą</string>
   <string name="auth_refresh_button">Odśwież połączenie</string>
   <string name="auth_host_address">Adres Serwera</string>
   <string name="common_error_out_memory">Brak wystarczającej pamięci</string>
   <string name="file_list__footer__folders">%1$d folderów</string>
   <string name="file_list__footer__file">1 plik</string>
   <string name="file_list__footer__file_and_folder">1 plik , 1 folder</string>
+  <string name="share_dialog_title">Udostępnianie</string>
+  <string name="share_search">Wyszukaj</string>
 </resources>
index 302e83e..7b494cd 100644 (file)
   <string name="filedetails_created">Criado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Baixar</string>
-  <string name="filedetails_sync_file">Atualizar arquivo</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">Arquivo foi renomeado para %1$s durante o envio</string>
   <string name="list_layout">Lista de Layout</string>
   <string name="action_share_file">Compartilhar link</string>
   <string name="action_unshare_file">Descompartilhar o link</string>
+  <string name="action_share_with_users">Compartilhado com usuários</string>
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Cancelar o download</string>
-  <string name="common_cancel_upload">Cancelar envio</string>
+  <string name="common_cancel_sync">Cancelar a sincronização</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Salvar &amp; Sair</string>
   <string name="common_error">Erro</string>
   <string name="unfavorite">Nãofavorito</string>
   <string name="common_rename">Renomear</string>
   <string name="common_remove">Remover</string>
-  <string name="confirmation_remove_alert">Você realmente deseja remover %1$s?</string>
+  <string name="confirmation_remove_file_alert">Você realmente deseja remover %1$s?</string>
   <string name="confirmation_remove_folder_alert">Você realmente deseja remover %1$s e seus conteúdos?</string>
   <string name="confirmation_remove_local">Somente local</string>
   <string name="confirmation_remove_folder_local">Somente local</string>
-  <string name="confirmation_remove_remote">Do servidor</string>
+  <string name="confirmation_remove_file_remote">Do servidor</string>
   <string name="confirmation_remove_remote_and_local">Remoto &amp; local</string>
   <string name="remove_success_msg">Removido com sucesso</string>
   <string name="remove_fail_msg">Erro ao remover</string>
   <string name="ssl_validator_label_validity_to">Para:</string>
   <string name="ssl_validator_label_signature">Assinatura:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritmo:</string>
+  <string name="digest_algorithm_not_available">Este algoritmo de resumo não está disponível no seu telefone.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Impressão digital:</string>
+  <string name="certificate_load_problem">Existe um problema ao carregar o certificado.</string>
   <string name="ssl_validator_null_cert">O certificado não pode ser mostrado.</string>
   <string name="ssl_validator_no_info_about_error">- Nenhuma informação sobre o erro</string>
   <string name="placeholder_sentence">Este é um espaço reservado</string>
   <string name="prefs_category_instant_uploading">Envios Instantâneos</string>
   <string name="prefs_category_security">Segurança</string>
   <string name="prefs_instant_video_upload_path_title">Enviar o Caminho do Vídeo</string>
-  <string name="download_folder_failed_content">Baixar %1$s da pasta não pode ser completado</string>
+  <string name="sync_folder_failed_content">A sincronização da pasta %1$s não pode ser finalizada</string>
   <string name="shared_subject_header">compartilhado</string>
   <string name="with_you_subject_header">com você</string>
-  <string name="subject_token">%1$s compartilhado \"%2$s\" com você</string>
-  <string name="saml_subject_token">\"%1$s\" foi compartilhado com você</string>
+  <string name="subject_user_shared_with_you">%1$s compartilhado \"%2$s\" com você</string>
+  <string name="subject_shared_with_you">\"%1$s\" foi compartilhado com você</string>
   <string name="auth_refresh_button">Reinicializar conexão</string>
   <string name="auth_host_address">Endereço do servidor</string>
   <string name="common_error_out_memory">Não há memoria suficiente</string>
   <string name="file_list__footer__files">%1$d arquivos</string>
   <string name="file_list__footer__files_and_folder">%1$d arquivos, 1 pasta</string>
   <string name="file_list__footer__files_and_folders">%1$d arquivos, %2$d pastas</string>
+  <string name="share_dialog_title">Compartilhamento</string>
+  <string name="share_with_user_section_title">Compartilhar com Usuários e Grupos</string>
+  <string name="share_no_users">Ainda não existe nenhum dado compartilhado com usuários</string>
+  <string name="share_add_user_or_group">Adicionar Usuário ou Grupo</string>
+  <string name="share_search">Perquisar</string>
+  <string name="search_users_and_groups_hint">Pesquisar usuários e grupos</string>
+  <string name="share_group_clarification">%1$s (grupo)</string>
+  <string name="share_sharee_unavailable">Desculpe, sua versão do servidor não permite compartilhamento com usuários que também são clientes.
+        \nEntre em contato com o administrador</string>
 </resources>
index 628b53a..a1adba9 100644 (file)
@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">segundos atrás</string>
   <string name="file_list_empty">Aqui não existe nada. Envie alguma coisa!</string>
   <string name="file_list_loading">A carregar...</string>
+  <string name="file_list_no_app_for_file_type">Nenhuma App encontrada por tipo de ficheiro!</string>
   <string name="local_file_list_empty">Não existem ficheiros nesta pasta.</string>
   <string name="filedetails_select_file">Toque num ficheiro para visualizar a informação adicional.</string>
   <string name="filedetails_size">Tamanho:</string>
@@ -78,7 +79,7 @@
   <string name="filedetails_created">Criado:</string>
   <string name="filedetails_modified">Modificado:</string>
   <string name="filedetails_download">Transferir</string>
-  <string name="filedetails_sync_file">Atualizar ficheiro</string>
+  <string name="filedetails_sync_file">Sincronizar</string>
   <string name="filedetails_renamed_in_upload_msg">O ficheiro foi renomeado para %1$s durante o envio.</string>
   <string name="list_layout">Apresentação da Lista</string>
   <string name="action_share_file">Partilhar a hiperligação</string>
@@ -86,8 +87,7 @@
   <string name="common_yes">Sim</string>
   <string name="common_no">Não</string>
   <string name="common_ok">ACEITAR</string>
-  <string name="common_cancel_download">Cancelar a transferência</string>
-  <string name="common_cancel_upload">Cancelar o envio</string>
+  <string name="common_cancel_sync">Cancelar sincronização</string>
   <string name="common_cancel">Cancelar</string>
   <string name="common_save_exit">Guardar &amp; Sair</string>
   <string name="common_error">Erro</string>
   <string name="unfavorite">Retirar Favorito</string>
   <string name="common_rename">Renomear</string>
   <string name="common_remove">Remover</string>
-  <string name="confirmation_remove_alert">Tem a certeza que deseja remover %1$s ?</string>
+  <string name="confirmation_remove_file_alert">Tem a certeza que deseja remover %1$s ?</string>
   <string name="confirmation_remove_folder_alert">Deseja realmente remover %1$s e o seu conteúdo?</string>
   <string name="confirmation_remove_local">Apenas localmente</string>
   <string name="confirmation_remove_folder_local">Apenas localmente</string>
-  <string name="confirmation_remove_remote">Do servidor</string>
+  <string name="confirmation_remove_file_remote">Do servidor</string>
   <string name="confirmation_remove_remote_and_local">Remoto &amp; local</string>
   <string name="remove_success_msg">Removido com sucesso</string>
   <string name="remove_fail_msg">Não foi possível remover</string>
   <string name="prefs_category_instant_uploading">Envios Instantâneos</string>
   <string name="prefs_category_security">Segurança</string>
   <string name="prefs_instant_video_upload_path_title">Envio do Caminho do Vídeo</string>
-  <string name="download_folder_failed_content">Não foi possível completar o download da pasta %1$s</string>
+  <string name="sync_folder_failed_content">Não foi possível completar a sincronização da pasta %1$s</string>
   <string name="shared_subject_header">partilhado</string>
   <string name="with_you_subject_header">consigo</string>
-  <string name="subject_token">%1$s partilhou \"%2$s\" consigo</string>
-  <string name="saml_subject_token">\"%1$s\" foi partilhado consigo</string>
+  <string name="subject_user_shared_with_you">%1$s partilhou \"%2$s\" consigo</string>
+  <string name="subject_shared_with_you">\"%1$s\" foi partilhado consigo</string>
   <string name="auth_refresh_button">Recarregar ligação</string>
   <string name="auth_host_address">Endereço do servidor</string>
   <string name="common_error_out_memory">Falta de memória</string>
   <string name="file_list__footer__files">%1$d ficheiros</string>
   <string name="file_list__footer__files_and_folder">%1$d ficheiros, 1 pasta</string>
   <string name="file_list__footer__files_and_folders">%1$d ficheiros, %2$d pastas</string>
+  <string name="share_dialog_title">Partilha</string>
+  <string name="share_with_user_section_title">Partilhar com Utilizadores e Grupos</string>
+  <string name="share_no_users">Ainda não foram partilhados os dados com os utilizadores</string>
+  <string name="share_add_user_or_group">Adicionar Utilziador ou Grupo</string>
+  <string name="share_search">Procurar</string>
 </resources>
index e539924..b997bc9 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Creat:</string>
   <string name="filedetails_modified">Modificat:</string>
   <string name="filedetails_download">Descarcă</string>
-  <string name="filedetails_sync_file">Împrospătare fișier</string>
   <string name="filedetails_renamed_in_upload_msg">Fișierul a fost redenumit %1$s în timpul încărcării</string>
   <string name="list_layout">Aspect listă</string>
   <string name="action_share_file">Partajază legătură</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Nu</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Anulează descărcarea</string>
-  <string name="common_cancel_upload">Anulează încărcarea</string>
   <string name="common_cancel">Anulează</string>
   <string name="common_save_exit">Salvare și ieșire</string>
   <string name="common_error">Eroare</string>
   <string name="unfavorite">Defavoritați</string>
   <string name="common_rename">Redenumește</string>
   <string name="common_remove">Elimină</string>
-  <string name="confirmation_remove_alert">Doriti sigur sa stergeti %1$s?</string>
+  <string name="confirmation_remove_file_alert">Doriti sigur sa stergeti %1$s?</string>
   <string name="confirmation_remove_folder_alert">Sigur vrei să elimini %1$s și conținutul său?</string>
   <string name="confirmation_remove_local">Doar local</string>
   <string name="confirmation_remove_folder_local">Doar local</string>
-  <string name="confirmation_remove_remote">De pe server</string>
+  <string name="confirmation_remove_file_remote">De pe server</string>
   <string name="confirmation_remove_remote_and_local">Ambele</string>
   <string name="remove_success_msg">Eliminat cu succes</string>
   <string name="remove_fail_msg">Eliminarea nu a reușit</string>
   <string name="prefs_category_instant_uploading">Încărcări instante</string>
   <string name="prefs_category_security">Securitate</string>
   <string name="prefs_instant_video_upload_path_title">Calea de încărcare Video</string>
-  <string name="download_folder_failed_content">Descărcarea fișierului %1$s nu s-a finisat</string>
   <string name="shared_subject_header">partajat</string>
   <string name="with_you_subject_header">cu tine</string>
-  <string name="subject_token">%1$s a partajat fișierul \"%2$s\" cu tine</string>
-  <string name="saml_subject_token">„%1$s” a fost partajat cu dumneavoastră</string>
+  <string name="subject_user_shared_with_you">%1$s a partajat fișierul \"%2$s\" cu tine</string>
+  <string name="subject_shared_with_you">„%1$s” a fost partajat cu dumneavoastră</string>
   <string name="auth_refresh_button">Reîmprospătează conexiunea</string>
   <string name="auth_host_address">Adresa server-ului</string>
   <string name="common_error_out_memory">Memorie insuficientă </string>
   <string name="file_list__footer__files">%1$d fișiere</string>
   <string name="file_list__footer__files_and_folder">%1$d fișiere, 1 folder</string>
   <string name="file_list__footer__files_and_folders">%1$d fișiere, %2$d foldere</string>
+  <string name="share_dialog_title">Partajare</string>
+  <string name="share_search">Căutare</string>
 </resources>
index 6675918..cfbee73 100644 (file)
   <string name="fd_keep_in_sync">Обновлять файл</string>
   <string name="common_rename">Переименовать</string>
   <string name="common_remove">Удалить</string>
-  <string name="confirmation_remove_alert">Вы действительно хотите удалить %1$s?</string>
+  <string name="confirmation_remove_file_alert">Вы действительно хотите удалить %1$s?</string>
   <string name="confirmation_remove_folder_alert">Вы действительно хотите удалить %1$s и все содержимое ?</string>
   <string name="confirmation_remove_local">Только локально</string>
   <string name="confirmation_remove_folder_local">Только локальное содержимое</string>
-  <string name="confirmation_remove_remote">Удалить с сервера</string>
+  <string name="confirmation_remove_file_remote">Удалить с сервера</string>
   <string name="confirmation_remove_remote_and_local">Оба, удаленный и локальный</string>
   <string name="remove_success_msg">Успешное удаление</string>
   <string name="remove_fail_msg">Удаление не может быть завершено</string>
index a0128b5..5f12453 100644 (file)
@@ -72,6 +72,7 @@
   <string name="file_list_seconds_ago">несколько секунд назад</string>
   <string name="file_list_empty">Здесь ничего нет. Загрузите что-нибудь!</string>
   <string name="file_list_loading">Загрузка...</string>
+  <string name="file_list_no_app_for_file_type">Не найдено приложений для этого типа файла.</string>
   <string name="local_file_list_empty">В этом каталоге нет файлов.</string>
   <string name="filedetails_select_file">Нажмите на файл для отображения дополнительной информации.</string>
   <string name="filedetails_size">Размер:</string>
@@ -79,7 +80,6 @@
   <string name="filedetails_created">Создан:</string>
   <string name="filedetails_modified">Изменён:</string>
   <string name="filedetails_download">Скачать</string>
-  <string name="filedetails_sync_file">Обновить файл</string>
   <string name="filedetails_renamed_in_upload_msg">Файл был переименован в %1$s во время загрузки</string>
   <string name="list_layout">Макет списка</string>
   <string name="action_share_file">Поделиться ссылкой</string>
@@ -87,8 +87,6 @@
   <string name="common_yes">Да</string>
   <string name="common_no">Нет</string>
   <string name="common_ok">ОК</string>
-  <string name="common_cancel_download">Отменить скачивание</string>
-  <string name="common_cancel_upload">Отменить загрузку</string>
   <string name="common_cancel">Отмена</string>
   <string name="common_save_exit">Сохранить и выйти</string>
   <string name="common_error">Ошибка</string>
   <string name="unfavorite">Убрать из избранного</string>
   <string name="common_rename">Переименовать</string>
   <string name="common_remove">Удалить</string>
-  <string name="confirmation_remove_alert">Вы действительно хотите удалить %1$s?</string>
+  <string name="confirmation_remove_file_alert">Вы действительно хотите удалить %1$s?</string>
   <string name="confirmation_remove_folder_alert">Вы действительно хотите удалить %1$s и его содержимое?</string>
   <string name="confirmation_remove_local">Только локально</string>
   <string name="confirmation_remove_folder_local">Только локально</string>
   <string name="prefs_category_instant_uploading">Мгновенные загрузки</string>
   <string name="prefs_category_security">Безопасность</string>
   <string name="prefs_instant_video_upload_path_title">Путь для загрузки Видео</string>
-  <string name="download_folder_failed_content">Не удалось завершить скачивание каталога %1$s</string>
   <string name="shared_subject_header">поделился</string>
   <string name="with_you_subject_header">с вами</string>
-  <string name="subject_token">%1$s предоставил вам доступ к \"%2$s\"</string>
-  <string name="saml_subject_token">Вам предоставлен доступ к \"%1$s\"</string>
+  <string name="subject_user_shared_with_you">%1$s предоставил вам доступ к \"%2$s\"</string>
+  <string name="subject_shared_with_you">Вам предоставлен доступ к \"%1$s\"</string>
   <string name="auth_refresh_button">Обновить соединение</string>
   <string name="auth_host_address">Адрес сервера</string>
   <string name="common_error_out_memory">Недостаточно памяти</string>
   <string name="file_list__footer__files">%1$d файлов</string>
   <string name="file_list__footer__files_and_folder">%1$d файлов, 1 каталог</string>
   <string name="file_list__footer__files_and_folders">%1$d файлов, %2$d каталогов</string>
+  <string name="share_dialog_title">Общий доступ</string>
+  <string name="share_with_user_section_title">Поделиться с пользователями или группами</string>
+  <string name="share_no_users">Нет данных используемых совместно с другими пользователями</string>
+  <string name="share_add_user_or_group">Добавить пользователя или группу</string>
+  <string name="share_search">Найти</string>
 </resources>
index 8116b72..7ecb8cc 100644 (file)
@@ -36,7 +36,6 @@
   <string name="common_yes">ඔව්</string>
   <string name="common_no">එපා</string>
   <string name="common_ok">හරි</string>
-  <string name="common_cancel_upload">උඩුගත කිරීම අත් හරින්න</string>
   <string name="common_cancel">එපා</string>
   <string name="common_save_exit">සුරැක &amp; පිටවන්න</string>
   <string name="common_error">දෝශය</string>
@@ -79,4 +78,6 @@
   <string name="prefs_category_accounts">ගිණුම්</string>
   <string name="folder_picker_choose_button_text">තෝරන්න</string>
   <string name="auth_host_address">සේවාදායකයේ ලිපිනය</string>
+  <string name="share_dialog_title">හුවමාරු කිරීම</string>
+  <string name="share_search">සොයන්න</string>
 </resources>
index 66ac426..b48dc6e 100644 (file)
@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">pred sekundami</string>
   <string name="file_list_empty">Žiadny súbor. Nahrajte niečo!</string>
   <string name="file_list_loading">Načítavam...</string>
+  <string name="file_list_no_app_for_file_type">Nenašla sa aplikácia pre tento typ súboru!</string>
   <string name="local_file_list_empty">V tomto priečinku nie sú žiadne súbory.</string>
   <string name="filedetails_select_file">Viac informácií získate kliknutím na súbor.</string>
   <string name="filedetails_size">Veľkosť:</string>
   <string name="filedetails_created">Vytvorený:</string>
   <string name="filedetails_modified">Zmenený:</string>
   <string name="filedetails_download">Stiahnuť</string>
-  <string name="filedetails_sync_file">Obnoviť súbor</string>
+  <string name="filedetails_sync_file">Synchronizovať</string>
   <string name="filedetails_renamed_in_upload_msg">Súbor bol premenovaný na %1$s počas nahrávania</string>
   <string name="list_layout">Rozvrhnutie zoznamu</string>
   <string name="action_share_file">Zdieľať linku</string>
   <string name="action_unshare_file">Zrušiť zdieľanie odkazu</string>
+  <string name="action_share_with_users">Zdieľať s používateľmi</string>
   <string name="common_yes">Áno</string>
   <string name="common_no">Nie</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Zrušiť sťahovanie</string>
-  <string name="common_cancel_upload">Zrušiť odosielanie</string>
+  <string name="common_cancel_sync">Zrušiť synchronizáciu</string>
   <string name="common_cancel">Zrušiť</string>
   <string name="common_save_exit">Uložiť a ukončiť</string>
   <string name="common_error">Chyba</string>
   <string name="unfavorite">Odobrať z obľúbených</string>
   <string name="common_rename">Premenuj</string>
   <string name="common_remove">Odober</string>
-  <string name="confirmation_remove_alert">Naozaj chcete odstrániť %1$s?</string>
+  <string name="confirmation_remove_file_alert">Naozaj chcete odstrániť %1$s?</string>
   <string name="confirmation_remove_folder_alert">Naozaj chcete odstrániť %1$s a jeho obsah?</string>
   <string name="confirmation_remove_local">Iba lokálne</string>
   <string name="confirmation_remove_folder_local">Iba lokálne</string>
-  <string name="confirmation_remove_remote">Zo servera</string>
+  <string name="confirmation_remove_file_remote">Zo servera</string>
   <string name="confirmation_remove_remote_and_local">Vzdialene aj lokálne</string>
   <string name="remove_success_msg">Úspešne odstránené</string>
   <string name="remove_fail_msg">Odstránenie zlyhalo</string>
   <string name="ssl_validator_label_validity_to">Do: </string>
   <string name="ssl_validator_label_signature">Podpis:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritmus:</string>
+  <string name="digest_algorithm_not_available">Algoritmus digest nie je na vašom telefóne dostupný.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Odtlačok:</string>
+  <string name="certificate_load_problem">Nastal problém s načítaním certifikátu.</string>
   <string name="ssl_validator_null_cert">Certifikát nemohol byť zobrazený.</string>
   <string name="ssl_validator_no_info_about_error">- Žiadne informácie o tejto chybe</string>
   <string name="placeholder_sentence">Toto je \"placeholder\"</string>
   <string name="prefs_category_instant_uploading">Okamžité nahratie</string>
   <string name="prefs_category_security">Zabezpečenie</string>
   <string name="prefs_instant_video_upload_path_title">Cesta pre nahrávanie videí</string>
-  <string name="download_folder_failed_content">Sťahovanie %1$s priečinka nebolo dokončené</string>
+  <string name="sync_folder_failed_content">Synchronizáciu priečinka %1$s nebolo možné dokončiť</string>
   <string name="shared_subject_header">zdieľané</string>
   <string name="with_you_subject_header">s vami</string>
-  <string name="subject_token">%1$s vám zdieľal \"%2$s\"</string>
-  <string name="saml_subject_token">\"%1$s\" bol s vami nazdieľaný</string>
+  <string name="subject_user_shared_with_you">%1$s vám zdieľal \"%2$s\"</string>
+  <string name="subject_shared_with_you">\"%1$s\" bol s vami nazdieľaný</string>
   <string name="auth_refresh_button">Obnoviť pripojenie</string>
   <string name="auth_host_address">Adresa servera</string>
   <string name="common_error_out_memory">Nedostatok pamäte</string>
   <string name="file_list__footer__files">%1$d súb.</string>
   <string name="file_list__footer__files_and_folder">%1$d súb., 1 priečinok</string>
   <string name="file_list__footer__files_and_folders">%1$d súb., %2$d prieč.</string>
+  <string name="share_dialog_title">Zdieľanie</string>
+  <string name="share_with_user_section_title">Zdieľať s používateľmi alebo skupinami</string>
+  <string name="share_no_users">Zatiaľ s používateľmi nezdieľate žiadne dáta.</string>
+  <string name="share_add_user_or_group">Pridať používateľa alebo skupinu</string>
+  <string name="share_search">Hľadať</string>
+  <string name="search_users_and_groups_hint">Vyhľadať používateľov alebo skupiny</string>
+  <string name="share_group_clarification">%1$s (skupina)</string>
+  <string name="share_sharee_unavailable">Je nám ľúto, vaša verzia servera neumožňuje zdieľanie s používateľmi alebo skupinami.
+\nProsím, obráťte sa na svojho správcu</string>
 </resources>
index e58ba5b..0b5a4a6 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Ustvarjeno:</string>
   <string name="filedetails_modified">Spremenjeno:</string>
   <string name="filedetails_download">Prejmi</string>
-  <string name="filedetails_sync_file">Osveži datoteko</string>
   <string name="filedetails_renamed_in_upload_msg">Datoteka je bila med nalaganjem preimenovana v %1$s</string>
   <string name="list_layout">Postavitev seznama</string>
   <string name="action_share_file">Povezava za souporabo</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">V redu</string>
-  <string name="common_cancel_download">Prekliči prejem</string>
-  <string name="common_cancel_upload">Prekliči pošiljanje</string>
   <string name="common_cancel">Prekliči</string>
   <string name="common_save_exit">Shrani in končaj</string>
   <string name="common_error">Napaka</string>
   <string name="unfavorite">Odstrani priljubljeno</string>
   <string name="common_rename">Preimenuj</string>
   <string name="common_remove">Odstrani</string>
-  <string name="confirmation_remove_alert">Ali res želite odstraniti %1$s?</string>
+  <string name="confirmation_remove_file_alert">Ali res želite odstraniti %1$s?</string>
   <string name="confirmation_remove_folder_alert">Ali res želite odstraniti %1$s skupaj s celotno vsebino?</string>
   <string name="confirmation_remove_local">Le krajevno</string>
   <string name="confirmation_remove_folder_local">Le krajevno</string>
-  <string name="confirmation_remove_remote">S strežnika</string>
+  <string name="confirmation_remove_file_remote">S strežnika</string>
   <string name="confirmation_remove_remote_and_local">Oddaljeno &amp; krajevno</string>
   <string name="remove_success_msg">Odstranitev je uspešno končana</string>
   <string name="remove_fail_msg">Odstranjevanje je spodletelo</string>
   <string name="prefs_category_instant_uploading">Takojšnje pošiljanje v oblak</string>
   <string name="prefs_category_security">Varnost</string>
   <string name="prefs_instant_video_upload_path_title">Pot videa za pošiljanje</string>
-  <string name="download_folder_failed_content">Imenika %1$s  ni mogoče prejeti v celoti</string>
   <string name="shared_subject_header">v souporabi</string>
   <string name="with_you_subject_header">z vami</string>
-  <string name="subject_token">Uporabnik %1$s je omogočil souporabo \"%2$s\" z vami</string>
-  <string name="saml_subject_token">\"%1$s\" je oddan v souporabo z vami</string>
+  <string name="subject_user_shared_with_you">Uporabnik %1$s je omogočil souporabo \"%2$s\" z vami</string>
+  <string name="subject_shared_with_you">\"%1$s\" je oddan v souporabo z vami</string>
   <string name="auth_refresh_button">Osveži povezavo</string>
   <string name="auth_host_address">Naslov strežnika</string>
   <string name="common_error_out_memory">Ni dovolj pomnilnika</string>
   <string name="file_list__footer__files">%1$d datotek</string>
   <string name="file_list__footer__files_and_folder">%1$d datotek, 1 mapa</string>
   <string name="file_list__footer__files_and_folders">%1$d datotek, %2$d map</string>
+  <string name="share_dialog_title">Souporaba</string>
+  <string name="share_search">Poišči</string>
 </resources>
index 0bde9ed..c4a9dec 100644 (file)
   <string name="filedetails_created">Krijuar më:</string>
   <string name="filedetails_modified">Ndryshuar më:</string>
   <string name="filedetails_download">Shkarkoje</string>
-  <string name="filedetails_sync_file">Rifreskoje kartelën</string>
+  <string name="filedetails_sync_file">Njëkohëso</string>
   <string name="filedetails_renamed_in_upload_msg">Kartela u riemërtua si %1$s gjatë ngarkimit</string>
   <string name="list_layout">Skemë Liste</string>
   <string name="action_share_file">Ndajeni lidhjen me të tjerët</string>
   <string name="action_unshare_file">Zhbëjeni ndarjen e lidhjes me të tjerët</string>
+  <string name="action_share_with_users">Ndajeni me përdoruesit</string>
   <string name="common_yes">Po</string>
   <string name="common_no">Jo</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Anulojeni shkarkimin</string>
-  <string name="common_cancel_upload">Anulojeni ngarkimin</string>
+  <string name="common_cancel_sync">Anuloje njëkohësimin</string>
   <string name="common_cancel">Anuloje</string>
   <string name="common_save_exit">Ruaje &amp; Dil</string>
   <string name="common_error">Gabim</string>
   <string name="ssl_validator_label_validity_to">Deri më:</string>
   <string name="ssl_validator_label_signature">Nënshkrim:</string>
   <string name="ssl_validator_label_signature_algorithm">Algoritëm:</string>
+  <string name="digest_algorithm_not_available">Ky algoritëm digest s’është i passhëm në telefonin tuaj.</string>
+  <string name="ssl_validator_label_certificate_fingerprint">Shenja gishtash:</string>
+  <string name="certificate_load_problem">Pati një problem gjatë ngarkimit të dëshmisë.</string>
   <string name="ssl_validator_null_cert">Dëshmia s\’u shfaq dot.</string>
   <string name="ssl_validator_no_info_about_error">- Pa të dhëna rreth gabimit</string>
   <string name="placeholder_sentence">Kjo është një vendmbajtëse</string>
   <string name="prefs_category_instant_uploading">Ngarkime të Menjëhershme</string>
   <string name="prefs_category_security">Siguri</string>
   <string name="prefs_instant_video_upload_path_title">Shteg Ngarkimi Videosh</string>
-  <string name="download_folder_failed_content">S\’u plotësua dot shkarkimi i dosjes %1$s</string>
+  <string name="sync_folder_failed_content">Njëkohësimi i dosjes %1$s s’u plotësua dot</string>
   <string name="shared_subject_header">ndarë</string>
   <string name="with_you_subject_header">me ju</string>
-  <string name="subject_token">%1$s ndau me ju \"%2$s\"</string>
-  <string name="saml_subject_token">\"%1$s\" është ndarë me ju</string>
+  <string name="subject_user_shared_with_you">%1$s ndau me ju \"%2$s\"</string>
+  <string name="subject_shared_with_you">\"%1$s\" është ndarë me ju</string>
   <string name="auth_refresh_button">Rifreskoni lidhjen</string>
   <string name="auth_host_address">Adresë shërbyesi</string>
   <string name="common_error_out_memory">Pa kujtesë të mjaftueshme</string>
   <string name="file_list__footer__files">%1$d kartelë</string>
   <string name="file_list__footer__files_and_folder">%1$d kartela, 1 dosje</string>
   <string name="file_list__footer__files_and_folders">%1$d kartela, %2$d dosje</string>
+  <string name="share_dialog_title">Ndarje me të tjerët</string>
+  <string name="share_with_user_section_title">Ndani me Përdorues dhe Grupe</string>
+  <string name="share_no_users">Ende pa të dhëna të ndara me përdorues</string>
+  <string name="share_add_user_or_group">Shtoni Përdorues ose Grup</string>
+  <string name="share_search">Kërko</string>
+  <string name="search_users_and_groups_hint">Kërkoni për grupe dhe përdorues</string>
+  <string name="share_group_clarification">%1$s (grup)</string>
+  <string name="share_sharee_unavailable">Na ndjeni, versioni juaj i shërbyesit nuk lejon ndarje me përdorues brenda klientësh.
+        \nJu lutemi, lidhuni me përgjegjësin tuaj</string>
 </resources>
index a820097..cde6c3d 100644 (file)
@@ -34,7 +34,6 @@
   <string name="common_yes">Da</string>
   <string name="common_no">Ne</string>
   <string name="common_ok">Ok</string>
-  <string name="common_cancel_upload">Otkaži otpremanje</string>
   <string name="common_cancel">Otkaži</string>
   <string name="common_error">Greška</string>
   <string name="common_error_unknown">Nepoznata greška</string>
@@ -73,4 +72,5 @@
   <string name="empty"></string>
   <string name="prefs_category_accounts">Nalozi</string>
   <string name="folder_picker_choose_button_text">Izaberi</string>
+  <string name="share_search">Traži</string>
 </resources>
index 469676f..f38facb 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Направљен:</string>
   <string name="filedetails_modified">Измењен:</string>
   <string name="filedetails_download">Преузми</string>
-  <string name="filedetails_sync_file">Освежи фајл</string>
   <string name="filedetails_renamed_in_upload_msg">Фајл је преименован у %1$s током отпремања</string>
   <string name="list_layout">Распоред листе</string>
   <string name="action_share_file">Веза дељења</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Да</string>
   <string name="common_no">Не</string>
   <string name="common_ok">У реду</string>
-  <string name="common_cancel_download">Откажи преузимање</string>
-  <string name="common_cancel_upload">Откажи отпремање</string>
   <string name="common_cancel">Откажи</string>
   <string name="common_save_exit">Сачувај и изађи</string>
   <string name="common_error">Грешка</string>
   <string name="unfavorite">Неомиљени</string>
   <string name="common_rename">Преименуј</string>
   <string name="common_remove">Уклони</string>
-  <string name="confirmation_remove_alert">Желите да уклоните %1$s?</string>
+  <string name="confirmation_remove_file_alert">Желите да уклоните %1$s?</string>
   <string name="confirmation_remove_folder_alert">Желите да уклоните %1$s и њен садржај?</string>
   <string name="confirmation_remove_local">Само локално</string>
   <string name="confirmation_remove_folder_local">Само локално</string>
   <string name="prefs_category_instant_uploading">Тренутна отпремања</string>
   <string name="prefs_category_security">Безбедност</string>
   <string name="prefs_instant_video_upload_path_title">Путања отпремања видеа</string>
-  <string name="download_folder_failed_content">Преузимање фасцикле %1$s не може бити довршено</string>
   <string name="shared_subject_header">дељено</string>
   <string name="with_you_subject_header">са вама</string>
-  <string name="subject_token">%1$s подели „%2$s“ са вама</string>
+  <string name="subject_user_shared_with_you">%1$s подели „%2$s“ са вама</string>
   <string name="auth_refresh_button">Освежи везу</string>
   <string name="auth_host_address">Адреса сервера</string>
   <string name="common_error_out_memory">Нема довољно меморије</string>
   <string name="file_list__footer__files">%1$d фајлова</string>
   <string name="file_list__footer__files_and_folder">%1$d фајлова, 1 фасцикла</string>
   <string name="file_list__footer__files_and_folders">%1$d фајлова, %2$d фасцикли</string>
+  <string name="share_dialog_title">Дељење</string>
+  <string name="share_search">Тражи</string>
 </resources>
index 5a6cdba..6766749 100644 (file)
   <string name="filedetails_created">Skapad:</string>
   <string name="filedetails_modified">Ändrad:</string>
   <string name="filedetails_download">Ladda ner</string>
-  <string name="filedetails_sync_file">Ladda om fil</string>
   <string name="filedetails_renamed_in_upload_msg">Filen bytte namn till %1$s under uppladdningen</string>
   <string name="action_share_file">Dela länk</string>
   <string name="action_unshare_file">Sluta dela länk</string>
   <string name="common_yes">Ja</string>
   <string name="common_no">Nej</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Avbryt nedladdning</string>
-  <string name="common_cancel_upload">Avbryt uppladdning</string>
   <string name="common_cancel">Avbryt</string>
   <string name="common_save_exit">Spara &amp; Avsluta</string>
   <string name="common_error">Fel</string>
   <string name="unfavorite">Avfavoritisera</string>
   <string name="common_rename">Byt namn</string>
   <string name="common_remove">Radera</string>
-  <string name="confirmation_remove_alert">Vill du verkligen ta bort %1$s?</string>
+  <string name="confirmation_remove_file_alert">Vill du verkligen ta bort %1$s?</string>
   <string name="confirmation_remove_folder_alert">Vill du verkligen ta bort %1$s och dess innehåll?</string>
   <string name="confirmation_remove_local">Endast lokalt</string>
   <string name="confirmation_remove_folder_local">Endast lokalt</string>
   <string name="prefs_category_instant_uploading">Direktuppladning</string>
   <string name="prefs_category_security">Säkerhet</string>
   <string name="prefs_instant_video_upload_path_title">Uppladdnings-sökväg för video</string>
-  <string name="download_folder_failed_content">Neddladning utav %1$s mappen kunde inte slutföras</string>
+  <string name="subject_user_shared_with_you">%1$s delade \"%2$s\" med dig</string>
   <string name="auth_host_address">Serveradress</string>
+  <string name="share_dialog_title">Dela</string>
+  <string name="share_search">Sök</string>
 </resources>
index 2f30505..1937439 100644 (file)
@@ -42,8 +42,6 @@
   <string name="common_yes">ஆம்</string>
   <string name="common_no">இல்லை</string>
   <string name="common_ok">சரி </string>
-  <string name="common_cancel_download">பதிவிறக்கலை இரத்துசெய்க</string>
-  <string name="common_cancel_upload">பதிவேற்றலை இரத்து செய்க</string>
   <string name="common_cancel">இரத்து செய்க</string>
   <string name="common_save_exit">சேமிக்க மற்றும் amp; வெளியேறு</string>
   <string name="common_error">வழு</string>
   <string name="prefs_category_accounts">கணக்குகள்</string>
   <string name="folder_picker_choose_button_text">தெரிவுசெய்க </string>
   <string name="auth_host_address">சேவையக முகவரி</string>
+  <string name="share_search">தேடுதல்</string>
 </resources>
index adefdc8..562b39e 100644 (file)
   <string name="filedetails_created">สร้างเมื่อ:</string>
   <string name="filedetails_modified">แก้ไขเมื่อ:</string>
   <string name="filedetails_download">ดาวน์โหลด</string>
-  <string name="filedetails_sync_file">à¸\9fืà¹\89à¸\99à¸\9fูà¹\84à¸\9fลà¹\8c</string>
+  <string name="filedetails_sync_file">à¸\9bระสาà¸\99à¸\82à¹\89อมูล</string>
   <string name="filedetails_renamed_in_upload_msg">ไฟล์ได้ถูกเปลี่ยนชื่อเป็น %1$s ในระหว่างการอัพโหลด</string>
   <string name="list_layout">เค้าโครงรายการ</string>
   <string name="action_share_file">แชร์ลิงค์</string>
   <string name="action_unshare_file">ยกเลิกการแชร์ลิงค์</string>
+  <string name="action_share_with_users">แชร์กับผู้ใช้</string>
   <string name="common_yes">ตกลง</string>
   <string name="common_no">ไม่ตกลง</string>
   <string name="common_ok">ตกลง</string>
-  <string name="common_cancel_download">ยกเลิกการดาวน์โหลด</string>
-  <string name="common_cancel_upload">ยกเลิกการอัพโหลด</string>
+  <string name="common_cancel_sync">ยกเลิกการประสานข้อมูล</string>
   <string name="common_cancel">ยกเลิก</string>
   <string name="common_save_exit">บันทึก &amp; ออก</string>
   <string name="common_error">ข้อผิดพลาด</string>
   <string name="unfavorite">ออกจากรายการโปรด</string>
   <string name="common_rename">เปลี่ยนชื่อ</string>
   <string name="common_remove">ลบออก</string>
-  <string name="confirmation_remove_alert">คุณต้องการที่จะลบ %1$s?</string>
+  <string name="confirmation_remove_file_alert">คุณต้องการที่จะลบ %1$s?</string>
   <string name="confirmation_remove_folder_alert">คุณต้องการที่จะลบ %1$s และเนื้อหาของมัน?</string>
   <string name="confirmation_remove_local">เฉพาะต้นทางเท่านั้น</string>
   <string name="confirmation_remove_folder_local">เฉพาะต้นทางเท่านั้น</string>
-  <string name="confirmation_remove_remote">จากเซิฟเวอร์</string>
+  <string name="confirmation_remove_file_remote">จากเซิฟเวอร์</string>
   <string name="confirmation_remove_remote_and_local">รีโมท &amp; ต้นทาง</string>
   <string name="remove_success_msg">ลบเรียบร้อยแล้ว</string>
   <string name="remove_fail_msg">ไม่สามารถลบได้</string>
   <string name="ssl_validator_label_validity_to">ถึง:</string>
   <string name="ssl_validator_label_signature">ลายเซ็นต์:</string>
   <string name="ssl_validator_label_signature_algorithm">อัลกอริทึ่ม:</string>
+  <string name="digest_algorithm_not_available">อัลกอริทึมย่อยนี้ไม่สามารถใช้งานบนโทรศัพท์ของคุณ</string>
+  <string name="ssl_validator_label_certificate_fingerprint">ลายนิ้วมือ:</string>
+  <string name="certificate_load_problem">มีปัญหาในการโหลดใบรับรอง</string>
   <string name="ssl_validator_null_cert">ไม่สามารถแสดงใบรับรอง</string>
   <string name="ssl_validator_no_info_about_error">- ไม่มีข้อมูลเกี่ยวกับข้อผิดพลาด</string>
   <string name="placeholder_sentence">นี่คือ placeholder</string>
   <string name="prefs_category_instant_uploading">อัพโหลดทันที</string>
   <string name="prefs_category_security">ความปลอดภัย</string>
   <string name="prefs_instant_video_upload_path_title">อัพโหลดเส้นทางวิดีโอ</string>
-  <string name="download_folder_failed_content">การดาวน์โหลดโฟลเดอร์ %1$s อาจไม่สำเร็จ</string>
+  <string name="sync_folder_failed_content">ประสานข้อมูลโฟลเดอร์ %1$s ไม่สำเร็จ</string>
   <string name="shared_subject_header">ถูกแชร์</string>
   <string name="with_you_subject_header">กับคุณ</string>
-  <string name="subject_token">%1$s ได้แชร์ \"%2$s\" กับคุณ</string>
-  <string name="saml_subject_token">\"%1$s\" ได้ถูกแชร์กับคุณ</string>
+  <string name="subject_user_shared_with_you">%1$s ได้แชร์ \"%2$s\" กับคุณ</string>
+  <string name="subject_shared_with_you">\"%1$s\" ได้ถูกแชร์กับคุณ</string>
   <string name="auth_refresh_button">ฟื้นฟูการเชื่อมต่อ</string>
   <string name="auth_host_address">ที่อยู่เซิร์ฟเวอร์</string>
   <string name="common_error_out_memory">หน่วยความจำไม่พอ</string>
   <string name="file_list__footer__files">%1$d ไฟล์</string>
   <string name="file_list__footer__files_and_folder">%1$d ไฟล์, 1 โฟลเดอร์</string>
   <string name="file_list__footer__files_and_folders">%1$d ไฟล์, %2$d โฟลเดอร์</string>
+  <string name="share_dialog_title">การแชร์ข้อมูล</string>
+  <string name="share_with_user_section_title">แชร์ไปยังผู้ใช้หรือกลุ่ม</string>
+  <string name="share_no_users">ยังไม่มีข้อมูลที่แชร์กับผู้ใช้ในตอนนี้</string>
+  <string name="share_add_user_or_group">เพิ่มผู้ใช่หรือกลุ่ม</string>
+  <string name="share_search">ค้นหา</string>
+  <string name="search_users_and_groups_hint">ค้นหาผู้ใช้และกลุ่ม</string>
+  <string name="share_group_clarification">%1$s (กลุ่ม)</string>
+  <string name="share_sharee_unavailable">ขออภัย รุ่นเซิร์ฟเวอร์ของคุณไม่อนุญาตให้แชร์กับผู้ใช้ภายในไคลเอนต์
+\nกรุณาติดต่อผู้ดูแลระบบ</string>
 </resources>
index 0ad4cfc..918e5e3 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">Oluşturulma:</string>
   <string name="filedetails_modified">Değiştirilme:</string>
   <string name="filedetails_download">İndir</string>
-  <string name="filedetails_sync_file">Dosyayı yenile</string>
   <string name="filedetails_renamed_in_upload_msg">Dosya adı, yükleme sırasında %1$s olarak değiştirildi</string>
   <string name="list_layout">Liste Yerleşimi</string>
   <string name="action_share_file">Paylaşma bağlantısı</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">Evet</string>
   <string name="common_no">Hayır</string>
   <string name="common_ok">Tamam</string>
-  <string name="common_cancel_download">İndirmeyi iptal et</string>
-  <string name="common_cancel_upload">Yüklemeyi iptal et</string>
   <string name="common_cancel">İptal</string>
   <string name="common_save_exit">Kaydet ve Çık</string>
   <string name="common_error">Hata</string>
   <string name="unfavorite">Favoriden kaldır</string>
   <string name="common_rename">Yeniden adlandır</string>
   <string name="common_remove">Kaldır</string>
-  <string name="confirmation_remove_alert">Gerçekten %1$s dosyasını kaldırmak istiyor musunuz?</string>
+  <string name="confirmation_remove_file_alert">Gerçekten %1$s dosyasını kaldırmak istiyor musunuz?</string>
   <string name="confirmation_remove_folder_alert">Gerçekten %1$s ve içeriğini kaldırmak istediğinizden emin misiniz?</string>
   <string name="confirmation_remove_local">Sadece yerel</string>
   <string name="confirmation_remove_folder_local">Sadece yerel</string>
-  <string name="confirmation_remove_remote">Sunucudan</string>
+  <string name="confirmation_remove_file_remote">Sunucudan</string>
   <string name="confirmation_remove_remote_and_local">Uzak ve yerel</string>
   <string name="remove_success_msg">Kaldırma başarılı</string>
   <string name="remove_fail_msg">Kaldırma başarısız</string>
   <string name="prefs_category_instant_uploading">Anında Yüklemeler</string>
   <string name="prefs_category_security">Güvenlik</string>
   <string name="prefs_instant_video_upload_path_title">Video Yükleme Yolu</string>
-  <string name="download_folder_failed_content">%1$s klasörün indirilmesi tamamlanamadı</string>
   <string name="shared_subject_header">sizinle</string>
   <string name="with_you_subject_header">paylaştı</string>
-  <string name="subject_token">%1$s, sizinle \"%2$s\" paylaşımını yaptı</string>
-  <string name="saml_subject_token">\"%1$s\" sizinle paylaşıldı</string>
+  <string name="subject_user_shared_with_you">%1$s, sizinle \"%2$s\" paylaşımını yaptı</string>
+  <string name="subject_shared_with_you">\"%1$s\" sizinle paylaşıldı</string>
   <string name="auth_refresh_button">Bağlantıyı yenile</string>
   <string name="auth_host_address">Sunucu adresi</string>
   <string name="common_error_out_memory">Yeterli hafıza yok</string>
   <string name="file_list__footer__files">%1$d dosya</string>
   <string name="file_list__footer__files_and_folder">%1$d dosya, 1 klasör</string>
   <string name="file_list__footer__files_and_folders">%1$d dosya, %2$d klasör</string>
+  <string name="share_dialog_title">Paylaşım</string>
+  <string name="share_search">Ara</string>
 </resources>
diff --git a/res/values-tzl/strings.xml b/res/values-tzl/strings.xml
deleted file mode 100644 (file)
index 37e6152..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>
-<resources>
-  <!--TODO re-enable when server-side folder size calculation is available   
-       <item>Biggest - Smallest</item>-->
-  <!--TODO re-enable when "Accounts" is available in Navigation Drawer-->
-  <!--<string name="drawer_item_accounts">Accounts</string>-->
-  <!--TODO re-enable when "On Device" is available
-    <string name="drawer_item_on_device">On device</string>-->
-  <string name="empty"></string>
-</resources>
index 4573d71..7d64b16 100644 (file)
@@ -36,7 +36,6 @@
   <string name="common_yes">ھەئە</string>
   <string name="common_no">ياق</string>
   <string name="common_ok">جەزملە</string>
-  <string name="common_cancel_upload">يۈكلەشتىن ۋاز كەچ</string>
   <string name="common_cancel">ۋاز كەچ</string>
   <string name="common_save_exit">ساقلاپ چېكىن</string>
   <string name="common_error">خاتالىق</string>
@@ -52,4 +51,6 @@
   <string name="prefs_category_accounts">ھېساباتلار</string>
   <string name="prefs_category_security">بىخەتەرلىك</string>
   <string name="auth_host_address">مۇلازىمېتىر ئادرىسى</string>
+  <string name="share_dialog_title">ھەمبەھىر</string>
+  <string name="share_search">ئىزدە</string>
 </resources>
index 062efeb..fed88ce 100644 (file)
@@ -71,6 +71,7 @@
   <string name="file_list_seconds_ago">секунди тому</string>
   <string name="file_list_empty">Тут нічого немає. Відвантажте що-небудь!</string>
   <string name="file_list_loading">Завантаження…</string>
+  <string name="file_list_no_app_for_file_type">Застосунку для цього типу файла не знайдено!</string>
   <string name="local_file_list_empty">В цій теці немає файлів.</string>
   <string name="filedetails_select_file">Натисніть на файлі для відображення додаткової інформації</string>
   <string name="filedetails_size">Розмір:</string>
   <string name="filedetails_created">Створено:</string>
   <string name="filedetails_modified">Змінено:</string>
   <string name="filedetails_download">Завантажити</string>
-  <string name="filedetails_sync_file">Оновити файл</string>
   <string name="filedetails_renamed_in_upload_msg">Файл був переіменований в %1$s протягом вивантаження</string>
+  <string name="list_layout">Вигляд списку</string>
   <string name="action_share_file">Опублікувати посилання</string>
   <string name="action_unshare_file">Видалити посилання</string>
   <string name="common_yes">Так</string>
   <string name="common_no">Ні</string>
   <string name="common_ok">OK</string>
-  <string name="common_cancel_download">Скасувати завантаження</string>
-  <string name="common_cancel_upload">Перервати завантаження</string>
   <string name="common_cancel">Відмінити</string>
   <string name="common_save_exit">Зберегти &amp; Вихід</string>
   <string name="common_error">Помилка</string>
   <string name="auth_can_not_auth_against_server">Аутентифікація на цьому сервері неможлива</string>
   <string name="auth_account_does_not_exist">Користвача в пристрої не існуе</string>
   <string name="favorite">Улюблений</string>
+  <string name="unfavorite">Прибрати з вибраного</string>
   <string name="common_rename">Перейменувати</string>
   <string name="common_remove">Видалити</string>
-  <string name="confirmation_remove_alert">Ви дійсно бажаєте видалити %1$s?</string>
+  <string name="confirmation_remove_file_alert">Ви дійсно бажаєте видалити %1$s?</string>
   <string name="confirmation_remove_folder_alert">Ви дійсно бажаєте видалити %1$s та весь вміст?</string>
   <string name="confirmation_remove_local">Лише локально</string>
   <string name="confirmation_remove_folder_local">Лише локально</string>
   <string name="move_file_error">Виникла помилка при спробі перемістити файл або теку</string>
   <string name="forbidden_permissions_move">перемістити цей файл</string>
   <string name="copy_file_not_found">Неможливо скопіювати. Будь ласка, перевірте, чи існує файл</string>
+  <string name="copy_file_invalid_into_descendent">Неможливо копіювати теку до підтеки</string>
   <string name="copy_file_invalid_overwrite">Файл вже існує в теці призначення</string>
   <string name="copy_file_error">Виникла помилка під час спроби скопіювати даний файл чи папку</string>
   <string name="forbidden_permissions_copy">скопіювати даний файл</string>
   <string name="prefs_category_instant_uploading">Миттєво завантаження</string>
   <string name="prefs_category_security">Безпека</string>
   <string name="prefs_instant_video_upload_path_title">Шлях завантаження відео</string>
-  <string name="download_folder_failed_content">Скачування теки %1$s не може бути завершено</string>
+  <string name="shared_subject_header">поширений</string>
   <string name="with_you_subject_header">з Вами</string>
-  <string name="subject_token">%1$s поділився \"%2$s\" з вами</string>
+  <string name="subject_user_shared_with_you">%1$s поділився \"%2$s\" з вами</string>
+  <string name="subject_shared_with_you">З Вами поділилися \"%1$s\"</string>
   <string name="auth_refresh_button">Оновити з\'єднання</string>
   <string name="auth_host_address">Ареса серверу</string>
   <string name="common_error_out_memory">Недостатньо пам\'яті</string>
   <string name="file_list__footer__files">%1$d файлів</string>
   <string name="file_list__footer__files_and_folder">%1$d файлів, 1 тека</string>
   <string name="file_list__footer__files_and_folders">%1$d файлів, %2$d тек</string>
+  <string name="share_dialog_title">Спільний доступ</string>
+  <string name="share_search">Пошук</string>
 </resources>
index 3e97d3f..111a866 100644 (file)
@@ -26,4 +26,5 @@
   <string name="activity_chooser_send_file_title">بھجیں</string>
   <string name="empty"></string>
   <string name="folder_picker_choose_button_text">منتخب کریں</string>
+  <string name="share_search">تلاش</string>
 </resources>
index 00fe7ca..4fdc212 100644 (file)
@@ -1,10 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
-       
-       <style name="Theme.ownCloud.ButtonStyle" parent="@android:style/Widget.Holo.Light.Button">
-               <item name="android:background">@android:drawable/btn_default</item>
-               <item name="android:textColor">@color/button_text_color</item>
-       </style>
 
        <!-- Notifications -->
        <style  name="Theme.ownCloud.NotificationText.Title" 
index c017442..04d9ac9 100644 (file)
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
        <style name="ProgressDialogTheme" parent="ownCloud.Dialog">
        </style>
+    <style name="Theme.ownCloud.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+    </style>
 </resources>
\ No newline at end of file
index bdccc82..6ec7515 100644 (file)
   <string name="filedetails_created">Đã tạo:</string>
   <string name="filedetails_modified">Đã chỉnh sửa:</string>
   <string name="filedetails_download">Tải về</string>
-  <string name="filedetails_sync_file">Cập nhật lại tập tin</string>
   <string name="filedetails_renamed_in_upload_msg">Tập tin đã bị đổi tên thành %1$s trong quá trình tải lên</string>
   <string name="action_share_file">Chia sẻ liên kết</string>
   <string name="action_unshare_file">Liên kết không chia sẻ</string>
   <string name="common_yes">Yes</string>
   <string name="common_no">Không</string>
   <string name="common_ok">Chấp nhận</string>
-  <string name="common_cancel_download">Hủy tải về</string>
-  <string name="common_cancel_upload">Hủy upload</string>
   <string name="common_cancel">Hủy</string>
   <string name="common_save_exit">Lưu &amp; Thoát</string>
   <string name="common_error">Lỗi</string>
   <string name="prefs_category_accounts">Tài khoản</string>
   <string name="folder_picker_choose_button_text">Chọn</string>
   <string name="auth_host_address">Địa chỉ máy chủ</string>
+  <string name="share_dialog_title">Chia sẻ</string>
+  <string name="share_search">Tìm kiếm</string>
 </resources>
index 74eb868..39d4ea9 100644 (file)
@@ -79,7 +79,6 @@
   <string name="filedetails_created">创建于:</string>
   <string name="filedetails_modified">修改于:</string>
   <string name="filedetails_download">下载</string>
-  <string name="filedetails_sync_file">刷新文件</string>
   <string name="filedetails_renamed_in_upload_msg">上传过程中文件被更名为了 %1$s</string>
   <string name="list_layout">列表布局</string>
   <string name="action_share_file">分享链接</string>
@@ -87,8 +86,6 @@
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">确定</string>
-  <string name="common_cancel_download">取消下载</string>
-  <string name="common_cancel_upload">取消上传</string>
   <string name="common_cancel">取消</string>
   <string name="common_save_exit">保存并退出</string>
   <string name="common_error">错误</string>
   <string name="unfavorite">取消收藏</string>
   <string name="common_rename">重命名</string>
   <string name="common_remove">删除</string>
-  <string name="confirmation_remove_alert">你确定要删除 %1$s 吗?</string>
+  <string name="confirmation_remove_file_alert">你确定要删除 %1$s 吗?</string>
   <string name="confirmation_remove_folder_alert">您确定要删除 %1$s 及其内容吗?</string>
   <string name="confirmation_remove_local">仅本地</string>
   <string name="confirmation_remove_folder_local">仅本地</string>
-  <string name="confirmation_remove_remote">来自服务器</string>
+  <string name="confirmation_remove_file_remote">来自服务器</string>
   <string name="confirmation_remove_remote_and_local">远程 &amp; 本地</string>
   <string name="remove_success_msg">成功删除</string>
   <string name="remove_fail_msg">无法完成删除</string>
   <string name="prefs_category_instant_uploading">即时上传</string>
   <string name="prefs_category_security">安全</string>
   <string name="prefs_instant_video_upload_path_title">视频上传路径</string>
-  <string name="download_folder_failed_content">%1$s 文件夹的下载无法完成</string>
   <string name="shared_subject_header">已共享</string>
   <string name="with_you_subject_header">与你</string>
-  <string name="subject_token">%1$s和你分享了“%2$s”</string>
-  <string name="saml_subject_token">已与你分享“%1$s”</string>
+  <string name="subject_user_shared_with_you">%1$s和你分享了“%2$s”</string>
+  <string name="subject_shared_with_you">已与你分享“%1$s”</string>
   <string name="auth_refresh_button">刷新连接</string>
   <string name="auth_host_address">服务器地址</string>
   <string name="common_error_out_memory">内存不足</string>
   <string name="file_list__footer__files">%1$d 个文件</string>
   <string name="file_list__footer__files_and_folder">%1$d 个文件,1 个文件夹</string>
   <string name="file_list__footer__files_and_folders">%1$d 个文件,%2$d 个文件夹</string>
+  <string name="share_dialog_title">共享</string>
+  <string name="share_search">搜索</string>
 </resources>
index 7810b88..50f708a 100644 (file)
@@ -43,8 +43,6 @@
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">確定</string>
-  <string name="common_cancel_download">取消下戴</string>
-  <string name="common_cancel_upload">取消上戴</string>
   <string name="common_cancel">取消</string>
   <string name="common_save_exit">儲存並離開</string>
   <string name="common_error">錯誤</string>
@@ -79,4 +77,6 @@
   <string name="saml_authentication_wrong_pass">密碼錯誤</string>
   <string name="prefs_category_security">安全</string>
   <string name="auth_host_address">伺服器地址</string>
+  <string name="share_dialog_title">分享</string>
+  <string name="share_search">尋找</string>
 </resources>
index db564b1..c783957 100644 (file)
@@ -78,7 +78,6 @@
   <string name="filedetails_created">建立:</string>
   <string name="filedetails_modified">修改:</string>
   <string name="filedetails_download">下載</string>
-  <string name="filedetails_sync_file">更新檔案列表</string>
   <string name="filedetails_renamed_in_upload_msg">檔案名稱在上傳時已被更改為 %1$s</string>
   <string name="list_layout">列表版型</string>
   <string name="action_share_file">分享連結</string>
@@ -86,8 +85,6 @@
   <string name="common_yes">是</string>
   <string name="common_no">否</string>
   <string name="common_ok">好</string>
-  <string name="common_cancel_download">取消下載</string>
-  <string name="common_cancel_upload">取消上傳</string>
   <string name="common_cancel">取消</string>
   <string name="common_save_exit">儲存並離開</string>
   <string name="common_error">錯誤</string>
   <string name="unfavorite">不喜愛的</string>
   <string name="common_rename">重新命名</string>
   <string name="common_remove">移除</string>
-  <string name="confirmation_remove_alert">您真的要移除 %1$s ?</string>
+  <string name="confirmation_remove_file_alert">您真的要移除 %1$s ?</string>
   <string name="confirmation_remove_folder_alert">您真的要移除 %1$s 與裡頭的檔案?</string>
   <string name="confirmation_remove_local">只有本地</string>
   <string name="confirmation_remove_folder_local">只有本地</string>
-  <string name="confirmation_remove_remote">來自伺服器</string>
+  <string name="confirmation_remove_file_remote">來自伺服器</string>
   <string name="confirmation_remove_remote_and_local">遠端 &amp; 本地</string>
   <string name="remove_success_msg">成功地移除</string>
   <string name="remove_fail_msg">刪除失敗</string>
   <string name="prefs_category_instant_uploading">即時上傳</string>
   <string name="prefs_category_security">安全性</string>
   <string name="prefs_instant_video_upload_path_title">影片上傳路徑</string>
-  <string name="download_folder_failed_content">%1$s 目錄的下載未完成</string>
   <string name="shared_subject_header">以分享的</string>
   <string name="with_you_subject_header">與你</string>
-  <string name="subject_token">%1$s 分享了 \"%2$s\" 給您</string>
-  <string name="saml_subject_token">\"%1$s\" 已經與您分享</string>
+  <string name="subject_user_shared_with_you">%1$s 分享了 \"%2$s\" 給您</string>
+  <string name="subject_shared_with_you">\"%1$s\" 已經與您分享</string>
   <string name="auth_refresh_button">重新連線</string>
   <string name="auth_host_address">伺服器位址</string>
   <string name="common_error_out_memory">記憶體不足</string>
   <string name="file_list__footer__files">%1$d 個檔案</string>
   <string name="file_list__footer__files_and_folder">%1$d 個檔案, 1 個資料夾</string>
   <string name="file_list__footer__files_and_folders">%1$d 個檔案, %2$d 個資料夾</string>
+  <string name="share_dialog_title">分享</string>
+  <string name="share_with_user_section_title">與用戶或群組分享</string>
+  <string name="share_no_users">目前沒有任何您分享的內容</string>
+  <string name="share_add_user_or_group">新增使用者或是群組</string>
+  <string name="share_search">搜尋</string>
 </resources>
index 800a4b6..7d80983 100644 (file)
 
        </declare-styleable>
 
+       <string-array name="pref_behaviour_entries">
+               <item>@string/pref_behaviour_entries_do_nothing</item>
+               <item>@string/pref_behaviour_entries_copy</item>
+               <item>@string/pref_behaviour_entries_move</item>
+               <item>@string/pref_behaviour_entries_delete</item>
+       </string-array>
+
+       <string-array name="pref_behaviour_entryValues">
+               <item>NOTHING</item>
+               <item>COPY</item>
+               <item>MOVE</item>
+               <item>DELETE</item>
+       </string-array>
 </resources>
\ No newline at end of file
index 8ca0a4e..694e231 100644 (file)
 -->
 <resources>
 
-    <color name="owncloud_blue">#1D2D44</color>
+    <color name="owncloud_blue">@color/actionbar_start_color</color>
     <color name="owncloud_blue_accent">#35537A</color>
     <color name="owncloud_blue_bright">#00ddff</color>
 
-    <color name="list_item_lastmod_and_filesize_text">#989898</color>
+    <color name="list_item_lastmod_and_filesize_text">@color/secondaryTextColor</color>
     <color name="black">#000000</color>
     <color name="white">#FFFFFF</color>
-    <color name="textColor">#303030</color>
+    <color name="fab_white">#fafafa</color>
+    <color name="white_pressed">#f1f1f1</color>
+    <color name="half_black">#808080</color>
+    <color name="black_semi_transparent">#B2000000</color>
+    <color name="textColor">@color/black</color>
     <color name="drawerMenuTextColor">#000000</color>
-    <color name="list_divider_background">#fff0f0f0</color>
+    <color name="list_divider_background">#eee</color>
     <color name="filelist_icon_backgorund">#DDDDDD</color>
     <color name="dark_background_text_color">#EEEEEE</color>
     <color name="login_text_color">#757575</color>
@@ -36,6 +40,9 @@
     <color name="primary_button_color">@color/owncloud_blue_accent</color>
     <color name="secondary_button_color">#D6D7D7</color>
     <color name="transparent">#00000000</color>
+    <color name="secondaryTextColor">#a0a0a0</color>
+    <color name="listItemHighlighted">#f8f8f8</color>
+    <color name="highlightTextColor">#55739a</color>
 
     <!-- Colors -->
     <color name="color_accent">@color/owncloud_blue_accent</color>
index 76bdd9f..b23f7b1 100644 (file)
@@ -1,14 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <!-- App name  and other strings-->
-    <string name="app_name">ownCloud</string>
-    <string name="account_type">owncloud</string>      <!-- better if was a domain name; but changing it now would require migrate accounts when the app is updated -->
-    <string name="authority">org.owncloud</string>     <!-- better if was the app package with ".provider" appended ; it identifies the provider -->
+    <string name="app_name">ownCloud beta</string>
+    <string name="account_type">owncloud.beta</string> <!-- better if was a domain name; but changing it now would require migrate accounts when the app is updated -->
+    <string name="authority">org.owncloud.beta.provider</string>       <!-- better if was the app package with ".provider" appended ; it identifies the provider -->
+    <string name="authorityCache">org.owncloud.beta.imageCache.provider</string>
     <string name ="db_file">owncloud.db</string>
     <string name ="db_name">ownCloud</string>
-    <string name ="data_folder">owncloud</string>
+    <string name ="data_folder">owncloud-beta</string>
     <string name ="log_name">Owncloud_</string>
-    <string name ="default_display_name_for_root_folder">ownCloud</string>
+    <string name ="default_display_name_for_root_folder">ownCloud beta</string>
     <string name ="user_agent">Mozilla/5.0 (Android) ownCloud-android/%1$s</string>
     
     <!-- URLs and flags related -->
@@ -30,7 +31,7 @@
     <!-- Colors -->
     <color name="login_background_color">#FFFFFF</color>
     <color name="login_logo_background_color">#FFFFFF</color>
-    <color name="background_color">#F7F7F7</color>
+    <color name="background_color">#FFFFFF</color>
     <color name="actionbar_start_color">#1D2D44</color>
     <color name="actionbar_end_color">#1D2D44</color>
     
@@ -46,6 +47,7 @@
     <bool name="recommend_enabled">true</bool>
     <bool name="feedback_enabled">true</bool>
     <string name="url_help">http://owncloud.com/mobile/help</string>
+    <string name="beta_link">https://github.com/owncloud/android/raw/beta/apks/owncloud-beta-</string>
     <string name="url_imprint"></string>
     <string name="mail_recommend">"mailto:"</string>
     <string name="mail_feedback">"mailto:apps@owncloud.com"</string>
index c35fd99..3750f61 100644 (file)
@@ -61,7 +61,7 @@
     <string name="setup_btn_connect">Connect</string>
     <string name="uploader_btn_upload_text">Upload</string>
     <string name="uploader_btn_new_folder_text">New folder</string>
-    <string name="uploader_top_message">Choose upload folder:</string>
+    <string name="uploader_top_message">Choose upload folder</string>
     <string name="uploader_wrn_no_account_title">No account found</string>
     <string name="uploader_wrn_no_account_text">There are no %1$s accounts on your device. Please setup an account first.</string>
     <string name="uploader_wrn_no_account_setup_btn_text">Setup</string>
     <string name="filedetails_created">Created:</string>
     <string name="filedetails_modified">Modified:</string>
     <string name="filedetails_download">Download</string>
-    <string name="filedetails_sync_file">Refresh file</string>
+    <string name="filedetails_sync_file">Synchronize</string>
     <string name="filedetails_renamed_in_upload_msg">File was renamed to %1$s during upload</string>
     <string name="list_layout">List Layout</string>
     <string name="action_share_file">Share link</string>
     <string name="action_unshare_file">Unshare link</string>
+    <string name="action_share_with_users">Share with users</string>
     <string name="common_yes">Yes</string>
     <string name="common_no">No</string>
     <string name="common_ok">OK</string>
-    <string name="common_cancel_download">Cancel download</string>
-    <string name="common_cancel_upload">Cancel upload</string>
+    <string name="common_cancel_sync">Cancel synchronization</string>
     <string name="common_cancel">Cancel</string>
     <string name="common_save_exit">Save &amp; Exit</string>
     <string name="common_error">Error</string>
     <string name="unfavorite">Unfavorite</string>
     <string name="common_rename">Rename</string>
     <string name="common_remove">Remove</string>
-    <string name="confirmation_remove_alert">"Do you really want to remove %1$s?"</string>
+    <string name="confirmation_remove_file_alert">"Do you really want to remove %1$s?"</string>
     <string name="confirmation_remove_folder_alert">"Do you really want to remove %1$s and its contents?"</string>
     <string name="confirmation_remove_local">Local only</string>
     <string name="confirmation_remove_folder_local">Local only</string>
-    <string name="confirmation_remove_remote">From server</string>
+    <string name="confirmation_remove_file_remote">From server</string>
     <string name="confirmation_remove_remote_and_local">Remote &amp; local</string>
     <string name="remove_success_msg">"Removal succeeded"</string>
     <string name="remove_fail_msg">"Removal failed"</string>
     <string name="ssl_validator_label_validity_to">To:</string>
     <string name="ssl_validator_label_signature">Signature:</string>
     <string name="ssl_validator_label_signature_algorithm">Algorithm:</string>
+    <string name="digest_algorithm_not_available">This digest algorithm is not available on your phone.</string>
+    <string name="ssl_validator_label_certificate_fingerprint">Fingerprint:</string>
+    <string name="certificate_load_problem">There is a problem loading the certificate.</string>
     <string name="ssl_validator_null_cert">The certificate could not be shown.</string>
     <string name="ssl_validator_no_info_about_error">- No information about the error</string>
 
     <string name="placeholder_filesize">389 KB</string>
     <string name="placeholder_timestamp">2012/05/18 12:23 PM</string>
     <string name="placeholder_media_time">12:23:45</string>
-
-    <string name="instant_upload_on_wifi">Upload pictures via WiFi only</string>
-    <string name="instant_video_upload_on_wifi">Upload videos via WiFi only</string>
+    
+    <string name="instant_upload_on_wifi">Upload pictures via wifi only</string>
+    <string name="instant_upload_on_charging">Upload when charging only</string>
+    <string name="instant_video_upload_on_wifi">Upload videos via wifi only</string>
+    <string name="instant_video_upload_on_charging">Upload when charging only</string>
     <string name="instant_upload_path">/InstantUpload</string>
     <string name="conflict_title">File conflict</string>
     <string name="conflict_message">Which files do you want to keep? If you select both versions, the local file will have a number added to its name.</string>
     <string name="preview_image_error_unknown_format">This image cannot be shown</string>
 
     <string name="error__upload__local_file_not_copied">%1$s could not be copied to %2$s local folder</string>
-    <string name="prefs_instant_upload_path_title">Upload Path</string>
+    <string name="prefs_instant_upload_path_title">Upload path</string>
 
        <string name="share_link_no_support_share_api">Sorry, sharing is not enabled on your server. Please contact your
                administrator.</string>
     <string name="uploader_upload_forbidden_permissions">to upload in this folder</string>
     <string name="downloader_download_file_not_found">The file is no longer available on the server</string>
 
+    <string name="file_migration_finish_button">Finish</string>
+    <string name="file_migration_preparing">Preparing for migration...</string>
+    <string name="file_migration_checking_destination">Checking destination...</string>
+    <string name="file_migration_saving_accounts_configuration">Saving accounts configuration...</string>
+    <string name="file_migration_waiting_for_unfinished_sync">Waiting for unfinished synchronizations...</string>
+    <string name="file_migration_migrating">Moving data...</string>
+    <string name="file_migration_updating_index">Updating index...</string>
+    <string name="file_migration_cleaning">Cleaning...</string>
+    <string name="file_migration_restoring_accounts_configuration">Restoring accounts configuration...</string>
+    <string name="file_migration_ok_finished">Finished</string>
+    <string name="file_migration_failed_not_enough_space">ERROR: Not enough space</string>
+    <string name="file_migration_failed_not_writable">ERROR: File is not writable</string>
+    <string name="file_migration_failed_not_readable">ERROR: File is not readable</string>
+    <string name="file_migration_failed_dir_already_exists">ERROR: owncloud directory already exists</string>
+    <string name="file_migration_failed_while_coping">ERROR: While migrating</string>
+    <string name="file_migration_failed_while_updating_index">ERROR: While updating index</string>
+
     <string name="prefs_category_accounts">Accounts</string>
     <string name="prefs_add_account">Add account</string>
     <string name="auth_redirect_non_secure_connection_title">Secure connection is redirected through an unsecured route.</string>
     <string name="prefs_category_instant_uploading">Instant Uploads</string>
        <string name="prefs_category_security">Security</string>
 
-       <string name="prefs_instant_video_upload_path_title">Upload Video Path</string>
+       <string name="prefs_instant_video_upload_path_title">Upload video path</string>
     <string name="download_folder_failed_content">Download of %1$s folder could not be completed</string>
+    <string name="sync_folder_failed_content">Synchronization of %1$s folder could not be completed</string>
 
        <string name="shared_subject_header">shared</string>
        <string name="with_you_subject_header">with you</string>
     
-       <string name="subject_token">%1$s shared \"%2$s\" with you</string>
-    <string name="saml_subject_token">\"%1$s\" has been shared with you</string>
+       <string name="subject_user_shared_with_you">%1$s shared \"%2$s\" with you</string>
+    <string name="subject_shared_with_you">\"%1$s\" has been shared with you</string>
 
     <string name="auth_refresh_button">Refresh connection</string>
     <string name="auth_host_address">Server address</string>
     <string name="file_list__footer__files">%1$d files</string>
     <string name="file_list__footer__files_and_folder">%1$d files, 1 folder</string>
     <string name="file_list__footer__files_and_folders">%1$d files, %2$d folders</string>
+    <string name="action_switch_grid_view">Switch to grid view</string>
+    <string name="action_switch_list_view">Switch to list view</string>
+    <string name="common_category">Common</string>
+    <string name="pref_cache_size">Cache size</string>
+    <string name="prefs_instant_behaviour_dialogTitle">Upload file to server and ...</string>
+    <string name="prefs_instant_behaviour_title">Behaviour</string>
+    <string name="upload_copy_files">Copy file</string>
+    <string name="upload_move_files">Move file</string>
+    <string name="prefs_storage_path">Storage path</string>
+    <string name="prefs_common">Common</string>
+
+    <string name="pref_behaviour_entries_do_nothing">do nothing</string>
+    <string name="pref_behaviour_entries_copy">copy file to OC folder</string>
+    <string name="pref_behaviour_entries_move">move file to OC folder</string>
+    <string name="pref_behaviour_entries_delete">delete origin file</string>
+    <string name="confirmation_remove_files_alert">Do you really want to remove selected items?</string>
+    <string name="confirmation_remove_folders_alert">Do you really want to remove a folder and its content?</string>
+    <string name="confirmation_remove_files">selected items</string>
+    <string name="error_log_exit">Exit</string>
+    <string name="error_log_send">Send Log</string>
+    <string name="error_log_title">Error Log</string>
+    <string name="action_stream_file">Stream file with external player</string>
+    <string name="stream_expose_password">Do you want to stream this file with an external app?\n\nCAUTION: This may expose your password!</string>
+    <string name="set_picture_as">Set picture as</string>
+
+    <string name="share_dialog_title">Sharing</string>
+    <string name="share_with_user_section_title">Share with Users and Groups</string>
+    <string name="share_no_users">No data shared with users yet</string>
+    <string name="share_add_user_or_group">Add User or Group</string>
+    <string name="share_search">Search</string>
+
+    <string name="search_users_and_groups_hint">Search users and groups</string>
+    <string name="share_group_clarification">%1$s (group)</string>
+
+    <string name="share_sharee_unavailable">Sorry, your server version does not allow share with users within clients.
+        \nPlease contact your administrator</string>
+    <string name="changelog">https://github.com/owncloud/android/raw/beta/CHANGELOG.md</string>
 
 </resources>
index 54e5225..934b755 100644 (file)
        <style name="Theme.ownCloud" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:actionBarStyle">@style/Theme.ownCloud.Widget.ActionBar</item>
        <item name="actionBarStyle">@style/Theme.ownCloud.Widget.ActionBar</item>
-       <item name="android:buttonStyle">@style/Theme.ownCloud.ButtonStyle</item>
                <item name="colorPrimary">@color/primary</item>
                <item name="colorPrimaryDark">@color/primary_dark</item>
                <item name="colorAccent">@color/color_accent</item>
                <item name="android:alertDialogTheme">@style/Theme.ownCloud.Dialog</item>
                <item name="alertDialogTheme">@style/ownCloud.AlertDialog</item>
-               <item name="colorButtonNormal">@color/background_color</item>
-               <item name="colorControlActivated">@color/primary_dark</item>
-               <item name="colorControlHighlight">@color/color_accent</item>
        </style>
 
        <!-- seperate action bar style for activities without an action bar -->
        <style name="Theme.ownCloud.noActionBar" parent="Theme.AppCompat.Light.DarkActionBar">
-               <item name="android:buttonStyle">@style/Theme.ownCloud.ButtonStyle</item>
                <item name="windowNoTitle">true</item>
                <item name="windowActionBar">false</item>
                <item name="colorPrimary">@color/primary</item>
@@ -45,9 +40,6 @@
                <item name="colorAccent">@color/color_accent</item>
                <item name="android:alertDialogTheme">@style/Theme.ownCloud.Dialog</item>
                <item name="alertDialogTheme">@style/ownCloud.AlertDialog</item>
-               <item name="colorButtonNormal">@color/background_color</item>
-               <item name="colorControlActivated">@color/primary_dark</item>
-               <item name="colorControlHighlight">@color/color_accent</item>
     </style>
 
        <style name="Theme.ownCloud.noActionBar.Login" parent="Theme.ownCloud.noActionBar">
@@ -59,7 +51,9 @@
                <item name="android:textColorPrimary">@color/primary</item>
        </style>
 
-       <style name="ownCloud.Dialog" parent="Theme.AppCompat.Light.Dialog" />
+       <style name="ownCloud.Dialog" parent="Theme.AppCompat.Light.Dialog">
+               <item name="colorAccent">@color/color_accent</item>
+       </style>
 
        <style name="ProgressDialogTheme" parent="ownCloud.Dialog">
                <item name="colorAccent">@color/color_accent</item>
 
        <style name="Theme.ownCloud.Fullscreen" parent="style/Theme.AppCompat">
         <item name="android:windowFullscreen">true</item>
+               <item name="colorAccent">@color/color_accent</item>
     </style>
        
        
                <item name="buttonBarStyle">@style/Theme.ownCloud.Dialog.ButtonBar</item>
        </style>
 
+       <style name="menu_labels_style">
+               <item name="android:background">@drawable/fab_label_background</item>
+               <item name="android:textColor">@color/fab_white</item>
+       </style>
+
        <!-- Button Bar hack due to Lollipop bug:
                https://code.google.com/p/android/issues/detail?id=78302
        fix see:
                
        <color name="setup_text_hint">#777777</color>
        <color name="setup_text_typed">#000000</color>
+    <style name="Theme.ownCloud.NoActionBar">
+        <item name="windowActionBar">false</item>
+        <item name="windowNoTitle">true</item>
+    </style>
+    <style name="Theme.ownCloud.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
+    <style name="Theme.ownCloud.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
 </resources>
\ No newline at end of file
index fc5c292..660e0fd 100644 (file)
@@ -1,12 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
-       
-    <!-- Buttons -->
-       <style name="Theme.ownCloud.ButtonStyle" parent="@android:style/Widget.Button">
-               <item name="android:background">@android:drawable/btn_default</item>
-               <item name="android:textColor">@color/button_text_color</item>
-       </style>
-       
+
        <!-- DropDown -->
        <style name="Theme.ownCloud.DropDownStyle"
                parent="style/Widget.AppCompat.Spinner.DropDown.ActionBar">
index 4823a83..3972e9e 100644 (file)
@@ -3,7 +3,7 @@
   ownCloud Android client application
 
   Copyright (C) 2012  Bartek Przybylski
-  Copyright (C) 2015 ownCloud Inc.
+  Copyright (C) 2012-2013 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,
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 -->
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+       <PreferenceCategory android:title="@string/prefs_category_general">
+               <com.owncloud.android.ui.PreferenceWithLongSummary
+                       android:title="@string/prefs_storage_path"
+                       android:key="storage_path" />
+       </PreferenceCategory>
     <PreferenceCategory android:title="@string/prefs_category_accounts" android:key="accounts_category">
     </PreferenceCategory>
-    
+
        <PreferenceCategory android:title="@string/prefs_category_security">
-           <android.preference.CheckBoxPreference android:title="@string/prefs_passcode" android:key="set_pincode" />
+               <android.preference.CheckBoxPreference android:title="@string/prefs_passcode" android:key="set_pincode" />
        </PreferenceCategory>
 
     <PreferenceCategory android:title="@string/prefs_category_instant_uploading" android:key="instant_uploading_category">
-         <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
+         <com.owncloud.android.ui.dialog.OwnCloudListPreference android:key="prefs_instant_behaviour"
+                        android:dialogTitle="@string/prefs_instant_behaviour_dialogTitle"
+                        android:title="@string/prefs_instant_behaviour_title"
+                        android:entries="@array/pref_behaviour_entries"
+                        android:entryValues="@array/pref_behaviour_entryValues"
+                        android:defaultValue="NOTHING"
+                        android:summary="%s"
+                        />
+
+               <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_uploading"
                                android:title="@string/prefs_instant_upload"
                                android:summary="@string/prefs_instant_upload_summary"/>
          <com.owncloud.android.ui.PreferenceWithLongSummary
                                                        android:title="@string/prefs_instant_upload_path_title"
                                                        android:key="instant_upload_path" />
            <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
-                                               android:title="@string/instant_upload_on_wifi"
-                                               android:key="instant_upload_on_wifi"/>
-           <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle android:key="instant_video_uploading"
-                               android:title="@string/prefs_instant_video_upload"
-                               android:summary="@string/prefs_instant_video_upload_summary" />
+                       android:dependency="instant_uploading"
+                       android:disableDependentsState="true"
+               android:title="@string/instant_upload_on_wifi"
+               android:key="instant_upload_on_wifi"/>
+               <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
+                       android:dependency="instant_uploading"
+                       android:disableDependentsState="true"
+                       android:title="@string/instant_upload_on_charging"
+                       android:key="instant_upload_on_charging"/>
+
+               <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
+                       android:key="instant_video_uploading"
+               android:title="@string/prefs_instant_video_upload"
+               android:summary="@string/prefs_instant_video_upload_summary" />
            <com.owncloud.android.ui.PreferenceWithLongSummary
-                                                       android:title="@string/prefs_instant_video_upload_path_title"
-                                                       android:key="instant_video_upload_path" />
+                       android:dependency="instant_video_uploading"
+                       android:disableDependentsState="true"
+                       android:title="@string/prefs_instant_video_upload_path_title"
+                       android:key="instant_video_upload_path" />
            <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
-                                               android:title="@string/instant_video_upload_on_wifi"
-                                               android:key="instant_video_upload_on_wifi"/>
-           <!-- DISABLED FOR RELEASE UNTIL FIXED
+                       android:dependency="instant_video_uploading"
+                       android:disableDependentsState="true"
+               android:title="@string/instant_video_upload_on_wifi"
+               android:key="instant_video_upload_on_wifi"/>
+               <com.owncloud.android.ui.CheckBoxPreferenceWithLongTitle
+                       android:dependency="instant_video_uploading"
+                       android:disableDependentsState="true"
+                       android:title="@string/instant_video_upload_on_charging"
+                       android:key="instant_video_upload_on_charging"/>
+       </PreferenceCategory>
+
+       <PreferenceCategory android:title="@string/common_category" android:key="common_category">
+               <EditTextPreference android:title="@string/pref_cache_size"
+                                                       android:key="pref_cache_size"
+                                                       android:digits="0123456789"/>
+       </PreferenceCategory>
+
+       <PreferenceCategory android:title="@string/prefs_category_more" android:key="more">
+               <!-- DISABLED FOR RELEASE UNTIL FIXED
            CheckBoxPreference android:key="log_to_file"
                                android:title="@string/prefs_log_title"
                                android:summary="@string/prefs_log_summary"/>
                <Preference             android:key="log_history"
                                android:title="@string/prefs_log_title_history"
                                android:summary="@string/prefs_log_summary_history"/ -->
-                        
-    </PreferenceCategory>
-       
-       <PreferenceCategory android:title="@string/prefs_category_more" android:key="more">
     <Preference android:title="@string/prefs_help" android:key="help" />
     <Preference android:title="@string/prefs_recommend" android:key="recommend" />
     <Preference android:title="@string/prefs_feedback" android:key="feedback" />
     <Preference android:title="@string/prefs_imprint" android:key="imprint" />
-                        
-       <Preference             android:id="@+id/about_app" 
-                                       android:title="@string/about_title" 
+
+       <Preference             android:id="@+id/about_app"
+                                       android:title="@string/about_title"
                                        android:key="about_app" />
-       </PreferenceCategory>
-    
 
+       <Preference android:id="@+id/beta_link"
+                               android:title="Download latest beta version"
+                               android:key="beta_link" />
+
+       <Preference android:id="@+id/changelog_link"
+               android:title="Changelog beta version"
+               android:key="changelog_link" />
+
+       </PreferenceCategory>
 </PreferenceScreen>
diff --git a/res/xml/users_and_groups_searchable.xml b/res/xml/users_and_groups_searchable.xml
new file mode 100644 (file)
index 0000000..9eadd56
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  @author David A. Velasco
+  Copyright (C) 2015 ownCloud Inc.
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License version 2,
+  as published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<!-- Searchable configuration to search users & groups in an OC server -->
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+    android:label="@string/app_name"
+    android:hint="@string/search_users_and_groups_hint"
+    android:searchSuggestAuthority="com.owncloud.android.providers.UsersAndGroupsSearchProvider"
+    android:searchSuggestIntentAction="com.owncloud.android.providers.UsersAndGroupsSearchProvider.action.SHARE_WITH"
+    android:searchSuggestThreshold="1" >
+</searchable>
\ No newline at end of file
index 8ccfeee..b0fef5e 100644 (file)
@@ -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
index 76ba2a3..6ca3a85 100755 (executable)
@@ -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
index 250b7ae..401f607 100644 (file)
@@ -23,16 +23,21 @@ package com.owncloud.android;
 import android.app.Activity;
 import android.app.Application;
 import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Environment;
+import android.preference.PreferenceManager;
 
 import com.owncloud.android.authentication.PassCodeManager;
 import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
 import com.owncloud.android.lib.common.OwnCloudClientManagerFactory.Policy;
 import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.utils.ExceptionHandler;
 
 
 /**
@@ -54,13 +59,24 @@ public class MainApp extends Application {
 
     private static Context mContext;
 
+    private static String storagePath;
+
     private static boolean mOnlyOnDevice = false;
 
     
     public void onCreate(){
         super.onCreate();
         MainApp.mContext = getApplicationContext();
+
+        // Setup handler for uncaught exceptions.
+        Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
         
+
+        SharedPreferences appPrefs =
+                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+        MainApp.storagePath = appPrefs.getString("storage_path", Environment.
+                              getExternalStorageDirectory().getAbsolutePath());
+
         boolean isSamlAuth = AUTH_ON.equals(getString(R.string.auth_method_saml_web_sso));
 
         OwnCloudClientManagerFactory.setUserAgent(getUserAgent());
@@ -80,7 +96,7 @@ public class MainApp extends Application {
             // Set folder for store logs
             Log_OC.setLogDataFolder(dataFolder);
 
-            Log_OC.startLogging();
+            Log_OC.startLogging(MainApp.storagePath);
             Log_OC.d("Debug", "start logging");
         }
 
@@ -133,6 +149,14 @@ public class MainApp extends Application {
         return MainApp.mContext;
     }
 
+    public static String getStoragePath(){
+        return MainApp.storagePath;
+    }
+
+    public static void setStoragePath(String path){
+        MainApp.storagePath = path;
+    }
+
     // Methods to obtain Strings referring app_name 
     //   From AccountAuthenticator 
     //   public static final String ACCOUNT_TYPE = "owncloud";    
index 87766b5..2f05a3e 100644 (file)
@@ -289,4 +289,15 @@ public class AccountUtils {
         return serverVersion;\r
     }\r
 \r
+    public static boolean hasSearchUsersSupport(Account account){\r
+        OwnCloudVersion serverVersion = null;\r
+        if (account != null) {\r
+            AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());\r
+            String serverVersionStr = accountMgr.getUserData(account, Constants.KEY_OC_VERSION);\r
+            if (serverVersionStr != null) {\r
+                serverVersion = new OwnCloudVersion(serverVersionStr);\r
+            }\r
+        }\r
+        return (serverVersion != null ? serverVersion.isSearchUsersSupported() : false);\r
+    }\r
 }\r
index 02ab3c7..4173ca4 100644 (file)
@@ -176,7 +176,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     private EditText mUsernameInput;\r
     private EditText mPasswordInput;\r
     private View mOkButton;\r
-    private View mCenteredRefreshButton;\r
     private TextView mAuthStatusView;\r
 \r
     private int mAuthStatusText = 0, mAuthStatusIcon = 0;\r
@@ -261,16 +260,22 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             }\r
         });\r
 \r
-        mCenteredRefreshButton = findViewById(R.id.centeredRefreshButton);\r
-        mCenteredRefreshButton.setOnClickListener(new View.OnClickListener() {\r
+        findViewById(R.id.centeredRefreshButton).setOnClickListener(new View.OnClickListener() {\r
 \r
             @Override\r
             public void onClick(View v) {\r
                 checkOcServer();\r
             }\r
         });\r
-        \r
-        mOkButton = findViewById(R.id.buttonOK);\r
+\r
+        findViewById(R.id.embeddedRefreshButton).setOnClickListener(new View.OnClickListener() {\r
+\r
+            @Override\r
+            public void onClick(View v) {\r
+                checkOcServer();\r
+            }\r
+        });\r
+\r
 \r
         /// initialize block to be moved to single Fragment to check server and get info about it \r
         initServerPreFragment(savedInstanceState);\r
@@ -702,7 +707,7 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
         \r
         mHostUrlInput.removeTextChangedListener(mHostUrlInputWatcher);\r
         mHostUrlInput.setOnFocusChangeListener(null);\r
-        \r
+\r
         super.onPause();\r
     }\r
     \r
@@ -811,8 +816,8 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
             Intent getServerInfoIntent = new Intent();\r
             getServerInfoIntent.setAction(OperationsService.ACTION_GET_SERVER_INFO);\r
             getServerInfoIntent.putExtra(\r
-                OperationsService.EXTRA_SERVER_URL,\r
-                normalizeUrlSuffix(uri)\r
+                    OperationsService.EXTRA_SERVER_URL,\r
+                    normalizeUrlSuffix(uri)\r
             );\r
             if (mOperationsServiceBinder != null) {\r
                 mWaitingForOpId = mOperationsServiceBinder.queueNewOperation(getServerInfoIntent);\r
@@ -1625,18 +1630,6 @@ public class AuthenticatorActivity extends AccountAuthenticatorActivity
     }\r
 \r
     /**\r
-     * Called when the refresh button in the input field for ownCloud host is clicked.\r
-     * \r
-     * Performs a new check on the URL in the input field.\r
-     * \r
-     * @param view      Refresh 'button'\r
-     */\r
-    public void onRefreshClick(View view) {\r
-        checkOcServer();\r
-    }\r
-\r
-\r
-    /**\r
      * Called when the eye icon in the password field is clicked.\r
      * \r
      * Toggles the visibility of the password in the field. \r
index e60233d..5fcccba 100644 (file)
@@ -74,7 +74,7 @@ public class PassCodeManager {
                 ){
 
             Intent i = new Intent(MainApp.getAppContext(), PassCodeActivity.class);
-            i.setAction(PassCodeActivity.ACTION_REQUEST);
+            i.setAction(PassCodeActivity.ACTION_CHECK);
             i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
             activity.startActivity(i);
 
index f2223d4..cef10bc 100644 (file)
@@ -24,8 +24,10 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.Vector;
 
 import android.accounts.Account;
@@ -45,17 +47,12 @@ import android.provider.MediaStore;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
+import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.utils.FileStorageUtils;
 
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
 public class FileDataStorageManager {
 
     public static final int ROOT_PARENT_ID = 0;
@@ -88,18 +85,10 @@ public class FileDataStorageManager {
         return mAccount;
     }
 
-    public void setContentResolver(ContentResolver cr) {
-        mContentResolver = cr;
-    }
-
     public ContentResolver getContentResolver() {
         return mContentResolver;
     }
 
-    public void setContentProviderClient(ContentProviderClient cp) {
-        mContentProviderClient = cp;
-    }
-
     public ContentProviderClient getContentProviderClient() {
         return mContentProviderClient;
     }
@@ -178,15 +167,14 @@ public class FileDataStorageManager {
         boolean overriden = false;
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
-        cv.put( 
-            ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
-            file.getModificationTimestampAtLastSyncForData()
+        cv.put(
+                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                file.getModificationTimestampAtLastSyncForData()
         );
         cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
         cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
         cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
         cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
-        //if (file.getParentId() != DataStorageManager.ROOT_PARENT_ID)
         cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
         cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
         if (!file.isFolder())
@@ -196,17 +184,20 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
         cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
-        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
         cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
         cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
         cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
-        
+        cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
+
         boolean sameRemotePath = fileExists(file.getRemotePath());
-        if (sameRemotePath ||                fileExists(file.getFileId())) {           // for renamed files; no more delete and create
+        if (sameRemotePath ||
+                fileExists(file.getFileId())) {  // for renamed files; no more delete and create
 
-            OCFile oldFile = null;
+            OCFile oldFile;
             if (sameRemotePath) {
                 oldFile = getFileByPath(file.getRemotePath());
                 file.setFileId(oldFile.getFileId());
@@ -252,12 +243,6 @@ public class FileDataStorageManager {
             }
         }
 
-//        if (file.isFolder()) {
-//            updateFolderSize(file.getFileId());
-//        } else {
-//            updateFolderSize(file.getParentId());
-//        }
-
         return overriden;
     }
 
@@ -274,12 +259,12 @@ public class FileDataStorageManager {
      */
     public void saveFolder(
             OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
-        ) {
-        
-        Log_OC.d(TAG,  "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() 
+    ) {
+
+        Log_OC.d(TAG,  "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size()
                 + " children and " + filesToRemove.size() + " files to remove");
 
-        ArrayList<ContentProviderOperation> operations = 
+        ArrayList<ContentProviderOperation> operations =
                 new ArrayList<ContentProviderOperation>(updatedFiles.size());
 
         // prepare operations to insert or update files to save in the given folder
@@ -287,8 +272,8 @@ public class FileDataStorageManager {
             ContentValues cv = new ContentValues();
             cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
             cv.put(
-                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
-                file.getModificationTimestampAtLastSyncForData()
+                    ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                    file.getModificationTimestampAtLastSyncForData()
             );
             cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
             cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
@@ -305,12 +290,14 @@ public class FileDataStorageManager {
             cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
             cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
-            cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
+            cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
+            cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
             cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
             cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
             cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
             cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
+            cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
@@ -335,15 +322,14 @@ public class FileDataStorageManager {
         for (OCFile file : filesToRemove) {
             if (file.getParentId() == folder.getFileId()) {
                 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
-                //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
                 if (file.isFolder()) {
                     operations.add(ContentProviderOperation.newDelete(
                             ContentUris.withAppendedId(
                                     ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
                             )
                     ).withSelection(where, whereArgs).build());
-                    
-                    File localFolder = 
+
+                    File localFolder =
                             new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
                     if (localFolder.exists()) {
                         removeLocalFolder(localFolder);
@@ -368,8 +354,8 @@ public class FileDataStorageManager {
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
         cv.put(
-            ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
-            folder.getModificationTimestampAtLastSyncForData()
+                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                folder.getModificationTimestampAtLastSyncForData()
         );
         cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
         cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
@@ -382,7 +368,8 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
         cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isFavorite() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
-        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
         cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
@@ -432,43 +419,9 @@ public class FileDataStorageManager {
             }
         }
 
-        //updateFolderSize(folder.getFileId());
-
     }
 
 
-//    /**
-//     * 
-//     * @param id
-//     */
-//    private void updateFolderSize(long id) {
-//        if (id > FileDataStorageManager.ROOT_PARENT_ID) {
-//            Log_OC.d(TAG, "Updating size of " + id);
-//            if (getContentResolver() != null) {
-//                getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, 
-//                        new ContentValues(),    
-                            // won't be used, but cannot be null; crashes in KLP
-//                        ProviderTableMeta._ID + "=?",
-//                        new String[] { String.valueOf(id) });
-//            } else {
-//                try {
-//                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, 
-//                            new ContentValues(),    
-                                // won't be used, but cannot be null; crashes in KLP
-//                            ProviderTableMeta._ID + "=?",
-//                            new String[] { String.valueOf(id) });
-//                    
-//                } catch (RemoteException e) {
-//                    Log_OC.e(
-//    TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
-//                }
-//            }
-//        } else {
-//            Log_OC.e(TAG,  "not updating size for folder " + id);
-//        }
-//    }
-
-
     public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
         boolean success = true;
         if (file != null) {
@@ -477,9 +430,12 @@ public class FileDataStorageManager {
 
             } else {
                 if (removeDBData) {
-                    //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
-                    Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
-                    String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+                    //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE,
+                    // ""+file.getFileId());
+                    Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE,
+                            file.getFileId());
+                    String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
+                            ProviderTableMeta.FILE_PATH + "=?";
                     String[] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                     int deleted = 0;
                     if (getContentProviderClient() != null) {
@@ -503,6 +459,7 @@ public class FileDataStorageManager {
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
                         file.setStoragePath(null);
                         saveFile(file);
+                        saveConflict(file, null);
                     }
                 }
             }
@@ -527,7 +484,7 @@ public class FileDataStorageManager {
     private boolean removeFolderInDb(OCFile folder) {
         Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" +
                 folder.getFileId());   // URI for recursive deletion
-        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + 
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " +
                 ProviderTableMeta.FILE_PATH + "=?";
         String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
         int deleted = 0;
@@ -593,7 +550,7 @@ public class FileDataStorageManager {
         return success;
     }
 
-    
+
     /**
      * Updates database and file system for a file or folder that was moved to a different location.
      *
@@ -606,7 +563,8 @@ public class FileDataStorageManager {
 
             OCFile targetParent = getFileByPath(targetParentPath);
             if (targetParent == null) {
-                throw new IllegalStateException("Parent folder of the target path does not exist!!");
+                throw new IllegalStateException(
+                        "Parent folder of the target path does not exist!!");
             }
 
             /// 1. get all the descendants of the moved element in a single QUERY
@@ -663,12 +621,12 @@ public class FileDataStorageManager {
                         // update link to downloaded content - but local move is not done here!
                         String targetLocalPath = defaultSavePath + targetPath +
                                 child.getStoragePath().substring(lengthOfOldStoragePath);
-                        
+
                         cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath);
-                        
+
                         originalPathsToTriggerMediaScan.add(child.getStoragePath());
                         newPathsToTriggerMediaScan.add(targetLocalPath);
-                        
+
                     }
                     if (child.getRemotePath().equals(file.getRemotePath())) {
                         cv.put(
@@ -699,7 +657,8 @@ public class FileDataStorageManager {
                 }
 
             } catch (Exception e) {
-                Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e);
+                Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database",
+                        e);
             }
 
             /// 4. move in local file system 
@@ -745,42 +704,74 @@ public class FileDataStorageManager {
                 if (!targetFolder.exists()) {
                     targetFolder.mkdirs();
                 }
-                copied = copyFile(localFile, targetFile);
+                copied = FileStorageUtils.copyFile(localFile, targetFile);
             }
             Log_OC.d(TAG, "Local file COPIED : " + copied);
         }
     }
 
-    private boolean copyFile(File src, File target) {
-        boolean ret = true;
+    public void migrateStoredFiles(String srcPath, String dstPath) throws Exception {
+        Cursor c = null;
+        if (getContentResolver() != null) {
+            c = getContentResolver().query(ProviderTableMeta.CONTENT_URI_FILE,
+                    null,
+                    ProviderTableMeta.FILE_STORAGE_PATH  + " IS NOT NULL",
+                    null,
+                    null);
+
+        } else {
+            try {
+                c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_FILE,
+                        new String[]{ProviderTableMeta._ID, ProviderTableMeta.FILE_STORAGE_PATH},
+                        ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL",
+                        null,
+                        null);
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, e.getMessage());
+                throw e;
+            }
+        }
 
-        InputStream in = null;
-        OutputStream out = null;
+        ArrayList<ContentProviderOperation> operations =
+                new ArrayList<ContentProviderOperation>(c.getCount());
+        if (c.moveToFirst()) {
+            do {
+                ContentValues cv = new ContentValues();
+                long fileId = c.getLong(c.getColumnIndex(ProviderTableMeta._ID));
+                String oldFileStoragePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH));
 
+                if (oldFileStoragePath.startsWith(srcPath)) {
+
+                    cv.put(
+                            ProviderTableMeta.FILE_STORAGE_PATH,
+                            oldFileStoragePath.replaceFirst(srcPath, dstPath));
+
+                    operations.add(
+                            ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+                                    withValues(cv).
+                                    withSelection(
+                                            ProviderTableMeta._ID + "=?",
+                                            new String[]{String.valueOf(fileId)}
+                                    )
+                                    .build());
+                }
+
+            } while (c.moveToNext());
+        }
+        c.close();
+
+        /// 3. apply updates in batch
         try {
-            in = new FileInputStream(src);
-            out = new FileOutputStream(target);
-            byte[] buf = new byte[1024];
-            int len;
-            while ((len = in.read(buf)) > 0) {
-                out.write(buf, 0, len);
-            }
-        } catch (IOException ex) {
-            ret = false;
-        } finally {
-            if (in != null) try {
-                in.close();
-            } catch (IOException e) {
-                e.printStackTrace(System.err);
-            }
-            if (out != null) try {
-                out.close();
-            } catch (IOException e) {
-                e.printStackTrace(System.err);
+            if (getContentResolver() != null) {
+                getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+
+            } else {
+                getContentProviderClient().applyBatch(operations);
             }
-        }
 
-        return ret;
+        } catch (Exception e) {
+            throw e;
+        }
     }
 
     
@@ -929,8 +920,10 @@ public class FileDataStorageManager {
             file.setFavorite(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
             file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
-            file.setShareByLink(c.getInt(
-                    c.getColumnIndex(ProviderTableMeta.FILE_SHARE_BY_LINK)) == 1 ? true : false);
+            file.setShareViaLink(c.getInt(
+                    c.getColumnIndex(ProviderTableMeta.FILE_SHARED_VIA_LINK)) == 1 ? true : false);
+            file.setShareWithSharee(c.getInt(
+                    c.getColumnIndex(ProviderTableMeta.FILE_SHARED_WITH_SHAREE)) == 1 ? true : false);
             file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
             file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS)));
             file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
@@ -938,44 +931,12 @@ public class FileDataStorageManager {
                     c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
             file.setDownloading(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
-                    
-        }
-        return file;
-    }
-
-    /**
-     * Returns if the file/folder is shared by link or not
-     *
-     * @param path Path of the file/folder
-     * @return
-     */
-    public boolean isShareByLink(String path) {
-        Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
-        OCFile file = null;
-        if (c.moveToFirst()) {
-            file = createFileInstance(c);
-        }
-        c.close();
-        return file.isShareByLink();
-    }
+            file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT)));
 
-    /**
-     * Returns the public link of the file/folder
-     *
-     * @param path Path of the file/folder
-     * @return
-     */
-    public String getPublicLink(String path) {
-        Cursor c = getCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path);
-        OCFile file = null;
-        if (c.moveToFirst()) {
-            file = createFileInstance(c);
         }
-        c.close();
-        return file.getPublicLink();
+        return file;
     }
 
-
     // Methods for Shares
     public boolean saveShare(OCShare share) {
         boolean overriden = false;
@@ -990,15 +951,15 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
         cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
         cv.put(
-            ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, 
-            share.getSharedWithDisplayName()
+                ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
+                share.getSharedWithDisplayName()
         );
         cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
         cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
         cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
         cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
 
-        if (shareExists(share.getIdRemoteShared())) {           // for renamed files; no more delete and create
+        if (shareExists(share.getIdRemoteShared())) {// for renamed files; no more delete and create
             overriden = true;
             if (getContentResolver() != null) {
                 getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv,
@@ -1041,26 +1002,29 @@ public class FileDataStorageManager {
     }
 
 
-    public OCShare getFirstShareByPathAndType(String path, ShareType type) {
+    public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) {
         Cursor c = null;
+
+        String selection = ProviderTableMeta.OCSHARES_PATH + "=? AND "
+                + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
+                + ProviderTableMeta.OCSHARES_SHARE_WITH + "=? AND "
+                + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" ;
+
+        String [] selectionArgs =  new String[]{path, Integer.toString(type.getValue()),
+                shareWith, mAccount.name};
+
         if (getContentResolver() != null) {
             c = getContentResolver().query(
                     ProviderTableMeta.CONTENT_URI_SHARE,
                     null,
-                    ProviderTableMeta.OCSHARES_PATH + "=? AND "
-                            + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
-                            + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
-                    new String[]{path, Integer.toString(type.getValue()), mAccount.name},
+                    selection, selectionArgs,
                     null);
         } else {
             try {
                 c = getContentProviderClient().query(
                         ProviderTableMeta.CONTENT_URI_SHARE,
                         null,
-                        ProviderTableMeta.OCSHARES_PATH + "=? AND "
-                                + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? AND "
-                                + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?",
-                        new String[]{path, Integer.toString(type.getValue()), mAccount.name},
+                        selection, selectionArgs,
                         null);
 
             } catch (RemoteException e) {
@@ -1086,6 +1050,8 @@ public class FileDataStorageManager {
                     .getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE)));
             share.setShareType(ShareType.fromValue(c.getInt(c
                     .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE))));
+            share.setShareWith(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH)));
             share.setPermissions(c.getInt(c
                     .getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS)));
             share.setSharedDate(c.getLong(c
@@ -1099,7 +1065,8 @@ public class FileDataStorageManager {
             share.setIsFolder(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1);
             share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
-            share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
+            share.setIdRemoteShared(c.getLong(
+                    c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
         }
         return share;
     }
@@ -1138,9 +1105,10 @@ public class FileDataStorageManager {
         return shareExists(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId));
     }
 
-    private void cleanSharedFiles() {
+    private void resetShareFlagsInAllFiles() {
         ContentValues cv = new ContentValues();
-        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, false);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, false);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
         String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
         String[] whereArgs = new String[]{mAccount.name};
@@ -1150,29 +1118,54 @@ public class FileDataStorageManager {
 
         } else {
             try {
-                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where,
+                        whereArgs);
             } catch (RemoteException e) {
-                Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
+                Log_OC.e(TAG, "Exception in resetShareFlagsInAllFiles" + e.getMessage());
             }
         }
     }
 
-    private void cleanSharedFilesInFolder(OCFile folder) {
+    private void resetShareFlagsInFolder(OCFile folder) {
         ContentValues cv = new ContentValues();
-        cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, false);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, false);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
         String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
                 ProviderTableMeta.FILE_PARENT + "=?";
         String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
-        
+
         if (getContentResolver() != null) {
             getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
 
         } else {
             try {
-                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where,
+                        whereArgs);
             } catch (RemoteException e) {
-                Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage());
+                Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage());
+            }
+        }
+    }
+
+    private void resetShareFlagInAFile(String filePath){
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, false);
+        cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, false);
+        cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
+                ProviderTableMeta.FILE_PATH+ "=?";
+        String [] whereArgs = new String[] { mAccount.name , filePath };
+
+        if (getContentResolver() != null) {
+            getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+
+        } else {
+            try {
+                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where,
+                        whereArgs);
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage());
             }
         }
     }
@@ -1186,7 +1179,8 @@ public class FileDataStorageManager {
 
         } else {
             try {
-                getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
+                getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where,
+                        whereArgs);
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
             }
@@ -1196,7 +1190,7 @@ public class FileDataStorageManager {
     public void saveShares(Collection<OCShare> shares) {
         cleanShares();
         if (shares != null) {
-            ArrayList<ContentProviderOperation> operations = 
+            ArrayList<ContentProviderOperation> operations =
                     new ArrayList<ContentProviderOperation>(shares.size());
 
             // prepare operations to insert or update files to save in the given folder
@@ -1212,8 +1206,8 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
                 cv.put(
-                    ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, 
-                    share.getSharedWithDisplayName()
+                        ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
+                        share.getSharedWithDisplayName()
                 );
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
@@ -1224,16 +1218,16 @@ public class FileDataStorageManager {
                     // updating an existing file
                     operations.add(
                             ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
-                            withValues(cv).
-                            withSelection(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
-                                    new String[]{String.valueOf(share.getIdRemoteShared())})
-                            .build());
+                                    withValues(cv).
+                                    withSelection(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?",
+                                            new String[]{String.valueOf(share.getIdRemoteShared())})
+                                    .build());
                 } else {
                     // adding a new file
                     operations.add(
                             ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
-                            withValues(cv).
-                            build()
+                                    withValues(cv).
+                                    build()
                     );
                 }
             }
@@ -1242,11 +1236,12 @@ public class FileDataStorageManager {
             if (operations.size() > 0) {
                 @SuppressWarnings("unused")
                 ContentProviderResult[] results = null;
-                Log_OC.d(TAG, "Sending " + operations.size() + 
+                Log_OC.d(TAG, "Sending " + operations.size() +
                         " operations to FileContentProvider");
                 try {
                     if (getContentResolver() != null) {
-                        results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+                        results = getContentResolver().applyBatch(MainApp.getAuthority(),
+                                operations);
                     } else {
                         results = getContentProviderClient().applyBatch(operations);
                     }
@@ -1263,10 +1258,10 @@ public class FileDataStorageManager {
     }
 
     public void updateSharedFiles(Collection<OCFile> sharedFiles) {
-        cleanSharedFiles();
+        resetShareFlagsInAllFiles();
 
         if (sharedFiles != null) {
-            ArrayList<ContentProviderOperation> operations = 
+            ArrayList<ContentProviderOperation> operations =
                     new ArrayList<ContentProviderOperation>(sharedFiles.size());
 
             // prepare operations to insert or update files to save in the given folder
@@ -1274,8 +1269,8 @@ public class FileDataStorageManager {
                 ContentValues cv = new ContentValues();
                 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
                 cv.put(
-                    ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
-                    file.getModificationTimestampAtLastSyncForData()
+                        ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
+                        file.getModificationTimestampAtLastSyncForData()
                 );
                 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
                 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
@@ -1289,40 +1284,42 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
                 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
                 cv.put(
-                    ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, 
-                    file.getLastSyncDateForData()
+                        ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
+                        file.getLastSyncDateForData()
                 );
                 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
-                cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
+                cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
+                cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
                 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
                 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
                 cv.put(
-                    ProviderTableMeta.FILE_UPDATE_THUMBNAIL, 
-                    file.needsUpdateThumbnail() ? 1 : 0
+                        ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
+                        file.needsUpdateThumbnail() ? 1 : 0
                 );
                 cv.put(
                         ProviderTableMeta.FILE_IS_DOWNLOADING,
                         file.isDownloading() ? 1 : 0
                 );
+                cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
 
                 boolean existsByPath = fileExists(file.getRemotePath());
                 if (existsByPath || fileExists(file.getFileId())) {
                     // updating an existing file
                     operations.add(
                             ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
-                            withValues(cv).
-                            withSelection(ProviderTableMeta._ID + "=?",
-                                    new String[]{String.valueOf(file.getFileId())})
-                            .build());
+                                    withValues(cv).
+                                    withSelection(ProviderTableMeta._ID + "=?",
+                                            new String[]{String.valueOf(file.getFileId())})
+                                    .build());
 
                 } else {
                     // adding a new file
                     operations.add(
                             ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
-                            withValues(cv).
-                            build()
+                                    withValues(cv).
+                                    build()
                     );
                 }
             }
@@ -1331,7 +1328,7 @@ public class FileDataStorageManager {
             if (operations.size() > 0) {
                 @SuppressWarnings("unused")
                 ContentProviderResult[] results = null;
-                Log_OC.d(TAG, "Sending " + operations.size() + 
+                Log_OC.d(TAG, "Sending " + operations.size() +
                         " operations to FileContentProvider");
                 try {
                     if (getContentResolver() != null) {
@@ -1354,8 +1351,8 @@ public class FileDataStorageManager {
     public void removeShare(OCShare share) {
         Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
         String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " +
-                ProviderTableMeta.FILE_PATH + "=?";
-        String [] whereArgs = new String[]{mAccount.name, share.getPath()};
+                ProviderTableMeta._ID + "=?";
+        String [] whereArgs = new String[]{mAccount.name, Long.toString(share.getId())};
         if (getContentProviderClient() != null) {
             try {
                 getContentProviderClient().delete(share_uri, where, whereArgs);
@@ -1368,38 +1365,108 @@ public class FileDataStorageManager {
     }
 
     public void saveSharesDB(ArrayList<OCShare> shares) {
-        saveShares(shares);
-
-        ArrayList<OCFile> sharedFiles = new ArrayList<OCFile>();
+        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
 
-        for (OCShare share : shares) {
-            // Get the path
-            String path = share.getPath();
-            if (share.isFolder()) {
-                path = path + FileUtils.PATH_SEPARATOR;
+        // Reset flags & Remove shares for this files
+        String filePath = "";
+        for (OCShare share: shares) {
+            if (filePath != share.getPath()){
+                filePath = share.getPath();
+                resetShareFlagInAFile(filePath);
+                operations = prepareRemoveSharesInFile(filePath, operations);
             }
+        }
+
+       // Add operations to insert shares
+       operations = prepareInsertShares(shares, operations);
 
-            // Update OCFile with data from share: ShareByLink  and publicLink
-            OCFile file = getFileByPath(path);
-            if (file != null) {
-                if (share.getShareType().equals(ShareType.PUBLIC_LINK)) {
-                    file.setShareByLink(true);
-                    sharedFiles.add(file);
+        // apply operations in batch
+        if (operations.size() > 0) {
+            Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+            try {
+                if (getContentResolver() != null) {
+                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+
+                } else {
+                    getContentProviderClient().applyBatch(operations);
                 }
+
+            } catch (OperationApplicationException e) {
+                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
             }
         }
 
-        updateSharedFiles(sharedFiles);
+//        // TODO: review if it is needed
+//        // Update shared files
+//        ArrayList<OCFile> sharedFiles = new ArrayList<OCFile>();
+//
+//        for (OCShare share : shares) {
+//            // Get the path
+//            String path = share.getPath();
+//            if (share.isFolder()) {
+//                path = path + FileUtils.PATH_SEPARATOR;
+//            }
+//
+//            // Update OCFile with data from share: ShareByLink, publicLink and
+//            OCFile file = getFileByPath(path);
+//            if (file != null) {
+//                if (share.getShareType().equals(ShareType.PUBLIC_LINK)) {
+//                    file.setShareViaLink(true);
+//                    sharedFiles.add(file);
+//                }
+//            }
+//        }
+//
+//        // TODO: Review
+//        updateSharedFiles(sharedFiles);
     }
 
 
     public void saveSharesInFolder(ArrayList<OCShare> shares, OCFile folder) {
-        cleanSharedFilesInFolder(folder);
+        resetShareFlagsInFolder(folder);
         ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
         operations = prepareRemoveSharesInFolder(folder, operations);
 
         if (shares != null) {
             // prepare operations to insert or update files to save in the given folder
+            operations = prepareInsertShares(shares, operations);
+        }
+
+        // apply operations in batch
+        if (operations.size() > 0) {
+            Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+            try {
+                if (getContentResolver() != null) {
+                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+
+                } else {
+                    getContentProviderClient().applyBatch(operations);
+                }
+
+            } catch (OperationApplicationException e) {
+                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+
+            } catch (RemoteException e) {
+
+            }
+        }
+
+    }
+
+    /**
+     * Prepare operations to insert or update files to save in the given folder
+     * @param shares        List of shares to insert
+     * @param operations    List of operations
+     * @return
+     */
+    private ArrayList<ContentProviderOperation> prepareInsertShares(
+            ArrayList<OCShare> shares, ArrayList<ContentProviderOperation> operations) {
+
+        if (shares != null) {
+            // prepare operations to insert or update files to save in the given folder
             for (OCShare share : shares) {
                 ContentValues cv = new ContentValues();
                 cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource());
@@ -1412,58 +1479,23 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
                 cv.put(
-                    ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, 
-                    share.getSharedWithDisplayName()
+                        ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
+                        share.getSharedWithDisplayName()
                 );
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
                 cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
 
-                /*
-                if (shareExists(share.getIdRemoteShared())) {
-                    // updating an existing share resource
-                    operations.add(
-                            ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
-                            withValues(cv).
-                            withSelection(  ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
-                                    new String[] { String.valueOf(share.getIdRemoteShared()) })
-                                    .build());
-
-                } else {
-                */
                 // adding a new share resource
                 operations.add(
                         ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
-                        withValues(cv).
-                        build()
+                                withValues(cv).
+                                build()
                 );
-                //}
             }
         }
-
-        // apply operations in batch
-        if (operations.size() > 0) {
-            @SuppressWarnings("unused")
-            ContentProviderResult[] results = null;
-            Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
-            try {
-                if (getContentResolver() != null) {
-                    results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
-
-                } else {
-                    results = getContentProviderClient().applyBatch(operations);
-                }
-
-            } catch (OperationApplicationException e) {
-                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
-
-            } catch (RemoteException e) {
-                Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
-            }
-        }
-        //}
-
+        return operations;
     }
 
     private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(
@@ -1479,53 +1511,73 @@ public class FileDataStorageManager {
                 whereArgs[0] = file.getRemotePath();
                 preparedOperations.add(
                         ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
-                        withSelection(where, whereArgs).
-                        build()
+                                withSelection(where, whereArgs).
+                                build()
                 );
             }
         }
         return preparedOperations;
-        
-        /*
-        if (operations.size() > 0) {
-            try {
-                if (getContentResolver() != null) {
-                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
 
-                } else {
-                    getContentProviderClient().applyBatch(operations);
-                }
+    }
 
-            } catch (OperationApplicationException e) {
-                Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
+    private ArrayList<ContentProviderOperation> prepareRemoveSharesInFile(
+            String filePath, ArrayList<ContentProviderOperation> preparedOperations) {
+
+        String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
+                + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
+        String[] whereArgs = new String[]{filePath, mAccount.name};
+
+        preparedOperations.add(
+                ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
+                        withSelection(where, whereArgs).
+                        build()
+        );
+
+        return preparedOperations;
+
+    }
+
+    public ArrayList<OCShare> getSharesWithForAFile(String filePath, String accountName){
+        // Condition
+        String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND "
+                + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"+ "AND"
+                + " (" + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR "
+                + ProviderTableMeta.OCSHARES_SHARE_TYPE +  "=? ) ";
+        String [] whereArgs = new String[]{ filePath, accountName ,
+                Integer.toString(ShareType.USER.getValue()),
+                Integer.toString(ShareType.GROUP.getValue()) };
+
+        Cursor c = null;
+        if (getContentResolver() != null) {
+            c = getContentResolver().query(
+                    ProviderTableMeta.CONTENT_URI_SHARE,
+                    null, where, whereArgs, null);
+        } else {
+            try {
+                c = getContentProviderClient().query(
+                        ProviderTableMeta.CONTENT_URI_SHARE,
+                        null, where, whereArgs, null);
 
             } catch (RemoteException e) {
-                Log_OC.e(TAG, "Exception in batch of operations  " + e.getMessage());
+                Log_OC.e(TAG, "Could not get list of shares with: " + e.getMessage());
+                c = null;
             }
-        }            
-        */
-            
-            /*
-            if (getContentResolver() != null) {
-                
-                getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, 
-                                            where,
-                                            whereArgs);
-            } else {
-                try {
-                    getContentProviderClient().delete(  ProviderTableMeta.CONTENT_URI_SHARE, 
-                                                        where,
-                                                        whereArgs);
+        }
+        ArrayList<OCShare> shares = new ArrayList<OCShare>();
+        OCShare share = null;
+        if (c.moveToFirst()) {
+            do {
+                share = createShareInstance(c);
+                shares.add(share);
+                // }
+            } while (c.moveToNext());
+        }
+        c.close();
 
-                } catch (RemoteException e) {
-                    Log_OC.e(TAG, "Exception deleting shares in a folder " + e.getMessage());
-                }
-            }
-            */
-        //}
+        return shares;
     }
 
-    public void triggerMediaScan(String path) {
+    public static void triggerMediaScan(String path) {
         Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
         intent.setData(Uri.fromFile(new File(path)));
         MainApp.getAppContext().sendBroadcast(intent);
@@ -1573,4 +1625,317 @@ public class FileDataStorageManager {
 
     }
 
+    public void saveConflict(OCFile file, String etagInConflict) {
+        if (!file.isDown()) {
+            etagInConflict = null;
+        }
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, etagInConflict);
+        int updated = 0;
+        if (getContentResolver() != null) {
+            updated = getContentResolver().update(
+                    ProviderTableMeta.CONTENT_URI_FILE,
+                    cv,
+                    ProviderTableMeta._ID + "=?",
+                    new String[] { String.valueOf(file.getFileId())}
+            );
+        } else {
+            try {
+                updated = getContentProviderClient().update(
+                        ProviderTableMeta.CONTENT_URI_FILE,
+                        cv,
+                        ProviderTableMeta._ID + "=?",
+                        new String[]{String.valueOf(file.getFileId())}
+                );
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
+            }
+        }
+
+        Log_OC.d(TAG, "Number of files updated with CONFLICT: " + updated);
+
+        if (updated > 0) {
+            if (etagInConflict != null) {
+                /// set conflict in all ancestor folders
+
+                long parentId = file.getParentId();
+                Set<String> ancestorIds = new HashSet<String>();
+                while (parentId != FileDataStorageManager.ROOT_PARENT_ID) {
+                    ancestorIds.add(Long.toString(parentId));
+                    parentId = getFileById(parentId).getParentId();
+                }
+
+                if (ancestorIds.size() > 0) {
+                    StringBuffer whereBuffer = new StringBuffer();
+                    whereBuffer.append(ProviderTableMeta._ID).append(" IN (");
+                    for (int i = 0; i < ancestorIds.size() - 1; i++) {
+                        whereBuffer.append("?,");
+                    }
+                    whereBuffer.append("?");
+                    whereBuffer.append(")");
+
+                    if (getContentResolver() != null) {
+                        updated = getContentResolver().update(
+                                ProviderTableMeta.CONTENT_URI_FILE,
+                                cv,
+                                whereBuffer.toString(),
+                                ancestorIds.toArray(new String[]{})
+                        );
+                    } else {
+                        try {
+                            updated = getContentProviderClient().update(
+                                    ProviderTableMeta.CONTENT_URI_FILE,
+                                    cv,
+                                    whereBuffer.toString(),
+                                    ancestorIds.toArray(new String[]{})
+                            );
+                        } catch (RemoteException e) {
+                            Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
+                        }
+                    }
+                } // else file is ROOT folder, no parent to set in conflict
+
+            } else {
+                /// update conflict in ancestor folders
+                // (not directly unset; maybe there are more conflicts below them)
+                String parentPath = file.getRemotePath();
+                if (parentPath.endsWith(OCFile.PATH_SEPARATOR)) {
+                    parentPath = parentPath.substring(0, parentPath.length() - 1);
+                }
+                parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1);
+
+                Log_OC.d(TAG, "checking parents to remove conflict; STARTING with " + parentPath);
+                while (parentPath.length() > 0) {
+
+                    String where =
+                            ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " IS NOT NULL AND " +
+                                    ProviderTableMeta.FILE_CONTENT_TYPE + " != 'DIR' AND " +
+                                    ProviderTableMeta.FILE_ACCOUNT_OWNER + " = ? AND " +
+                                    ProviderTableMeta.FILE_PATH + " LIKE ?";
+                    Cursor descendentsInConflict = getContentResolver().query(
+                            ProviderTableMeta.CONTENT_URI_FILE,
+                            new String[]{ProviderTableMeta._ID},
+                            where,
+                            new String[]{mAccount.name, parentPath + "%"},
+                            null
+                    );
+                    if (descendentsInConflict == null || descendentsInConflict.getCount() == 0) {
+                        Log_OC.d(TAG, "NO MORE conflicts in " + parentPath);
+                        if (getContentResolver() != null) {
+                            updated = getContentResolver().update(
+                                    ProviderTableMeta.CONTENT_URI_FILE,
+                                    cv,
+                                    ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
+                                            ProviderTableMeta.FILE_PATH + "=?",
+                                    new String[]{mAccount.name, parentPath}
+                            );
+                        } else {
+                            try {
+                                updated = getContentProviderClient().update(
+                                        ProviderTableMeta.CONTENT_URI_FILE,
+                                        cv,
+                                        ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " +
+                                                ProviderTableMeta.FILE_PATH + "=?"
+                                        , new String[]{mAccount.name, parentPath}
+                                );
+                            } catch (RemoteException e) {
+                                Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage());
+                            }
+                        }
+
+                    } else {
+                        Log_OC.d(TAG, "STILL " + descendentsInConflict.getCount() + " in " + parentPath);
+                    }
+
+                    if (descendentsInConflict != null) {
+                        descendentsInConflict.close();
+                    }
+
+                    parentPath = parentPath.substring(0, parentPath.length() - 1);  // trim last /
+                    parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1);
+                    Log_OC.d(TAG, "checking parents to remove conflict; NEXT " + parentPath);
+                }
+            }
+        }
+
+    }
+
+    public OCCapability saveCapabilities(OCCapability capability){
+
+        // Prepare capabilities data
+        ContentValues cv = new ContentValues();
+        cv.put(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME, mAccount.name);
+        cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR, capability.getVersionMayor());
+        cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MINOR, capability.getVersionMinor());
+        cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MICRO, capability.getVersionMicro());
+        cv.put(ProviderTableMeta.CAPABILITIES_VERSION_STRING, capability.getVersionString());
+        cv.put(ProviderTableMeta.CAPABILITIES_VERSION_EDITION, capability.getVersionEdition());
+        cv.put(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL, capability.getCorePollinterval());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED, capability.getFilesSharingApiEnabled().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED,
+                capability.getFilesSharingPublicEnabled().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED,
+                capability.getFilesSharingPublicPasswordEnforced().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED,
+                capability.getFilesSharingPublicExpireDateEnabled().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS,
+                capability.getFilesSharingPublicExpireDateDays());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED,
+                capability.getFilesSharingPublicExpireDateEnforced().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL,
+                capability.getFilesSharingPublicSendMail().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD,
+                capability.getFilesSharingPublicUpload().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL,
+                capability.getFilesSharingUserSendMail().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING, capability.getFilesSharingResharing().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING,
+                capability.getFilesSharingFederationOutgoing().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING,
+                capability.getFilesSharingFederationIncoming().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING, capability.getFilesBigFileChuncking().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE, capability.getFilesUndelete().getValue());
+        cv.put(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING, capability.getFilesVersioning().getValue());
+
+        if (capabilityExists(mAccount.name)) {
+            if (getContentResolver() != null) {
+                getContentResolver().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv,
+                        ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?",
+                        new String[]{mAccount.name});
+            } else {
+                try {
+                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES,
+                            cv, ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?",
+                            new String[]{mAccount.name});
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG,
+                            "Fail to insert insert file to database "
+                                    + e.getMessage());
+                }
+            }
+        } else {
+            Uri result_uri = null;
+            if (getContentResolver() != null) {
+                result_uri = getContentResolver().insert(
+                        ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv);
+            } else {
+                try {
+                    result_uri = getContentProviderClient().insert(
+                            ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv);
+                } catch (RemoteException e) {
+                    Log_OC.e(TAG,
+                            "Fail to insert insert capability to database "
+                                    + e.getMessage());
+                }
+            }
+            if (result_uri != null) {
+                long new_id = Long.parseLong(result_uri.getPathSegments()
+                        .get(1));
+                capability.setId(new_id);
+                capability.setAccountName(mAccount.name);
+            }
+        }
+
+        return capability;
+    }
+
+    private boolean capabilityExists(String accountName) {
+        Cursor c = getCapabilityCursorForAccount(accountName);
+        boolean exists = false;
+        if (c != null) {
+            exists = c.moveToFirst();
+            c.close();
+        }
+        return exists;
+    }
+
+    private Cursor getCapabilityCursorForAccount(String accountName){
+        Cursor c = null;
+        if (getContentResolver() != null) {
+            c = getContentResolver()
+                    .query(ProviderTableMeta.CONTENT_URI_CAPABILITIES,
+                            null,
+                            ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ",
+                            new String[]{accountName}, null);
+        } else {
+            try {
+                c = getContentProviderClient().query(
+                        ProviderTableMeta.CONTENT_URI_CAPABILITIES,
+                        null,
+                        ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ",
+                        new String[]{accountName}, null);
+            } catch (RemoteException e) {
+                Log_OC.e(TAG,
+                        "Couldn't determine capability existance, assuming non existance: "
+                                + e.getMessage());
+            }
+        }
+
+        return c;
+
+    }
+    public OCCapability getCapability(String accountName){
+        OCCapability capability = null;
+        Cursor c = getCapabilityCursorForAccount(accountName);
+
+        if (c.moveToFirst()) {
+            capability = createCapabilityInstance(c);
+        }
+        c.close();
+        return capability;
+    }
+
+    private OCCapability createCapabilityInstance(Cursor c) {
+        OCCapability capability = null;
+        if (c != null) {
+            capability = new OCCapability();
+            capability.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID)));
+            capability.setAccountName(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)));
+            capability.setVersionMayor(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)));
+            capability.setVersionMinor(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MINOR)));
+            capability.setVersionMicro(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MICRO)));
+            capability.setVersionString(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_STRING)));
+            capability.setVersionEdition(c.getString(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_EDITION)));
+            capability.setCorePollinterval(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL)));
+            capability.setFilesSharingApiEnabled(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED))));
+            capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED))));
+            capability.setFilesSharingPublicPasswordEnforced(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED))));
+            capability.setFilesSharingPublicExpireDateEnabled(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED))));
+            capability.setFilesSharingPublicExpireDateDays(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS)));
+            capability.setFilesSharingPublicExpireDateEnforced(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED))));
+            capability.setFilesSharingPublicSendMail(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL))));
+            capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD))));
+            capability.setFilesSharingUserSendMail(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL))));
+            capability.setFilesSharingResharing(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING))));
+            capability.setFilesSharingFederationOutgoing(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING))));
+            capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING))));
+            capability.setFilesBigFileChuncking(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING))));
+            capability.setFilesUndelete(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE))));
+            capability.setFilesVersioning(CapabilityBooleanType.fromValue(c.getInt(c
+                    .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING))));
+
+        }
+        return capability;
+    }
 }
index 4baf1ea..8cbb95e 100644 (file)
@@ -1,6 +1,8 @@
 /**
  *   ownCloud Android client application
  *
+ *   @author Bartek Przybylski
+ *   @author David A. Velasco
  *   Copyright (C) 2012  Bartek Przybylski
  *   Copyright (C) 2015 ownCloud Inc.
  *
@@ -20,6 +22,8 @@
 
 package com.owncloud.android.datamodel;
 
+import android.content.ContentResolver;
+import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.webkit.MimeTypeMap;
@@ -31,18 +35,18 @@ import java.io.File;
 import third_parties.daveKoeller.AlphanumComparator;
 public class OCFile implements Parcelable, Comparable<OCFile> {
 
-    public static final Parcelable.Creator<OCFile> CREATOR = new Parcelable.Creator<OCFile>() {
-        @Override
+    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
         public OCFile createFromParcel(Parcel source) {
             return new OCFile(source);
         }
 
-        @Override
         public OCFile[] newArray(int size) {
             return new OCFile[size];
         }
     };
 
+    private final static String PERMISSION_SHARED_WITH_ME = "S";    // TODO move to better location
+
     public static final String PATH_SEPARATOR = "/";
     public static final String ROOT_PATH = PATH_SEPARATOR;
 
@@ -74,6 +78,18 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
 
     private boolean mIsDownloading;
 
+    private boolean mShowGridView;
+
+    private String mEtagInConflict;    // Save file etag in the server, when there is a conflict. No conflict =  null
+
+    private boolean mShareWithSharee;
+
+    /**
+     * URI to the local path of the file contents, if stored in the device; cached after first call
+     * to {@link #getStorageUri()}
+     */
+    private Uri mLocalUri;
+
 
     /**
      * Create new {@link OCFile} with given path.
@@ -115,8 +131,10 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mPublicLink = source.readString();
         mPermissions = source.readString();
         mRemoteId = source.readString();
-        mNeedsUpdateThumbnail = source.readInt() == 0;
-        mIsDownloading = source.readInt() == 0;
+        mNeedsUpdateThumbnail = source.readInt() == 1;
+        mIsDownloading = source.readInt() == 1;
+        mEtagInConflict = source.readString();
+        mShareWithSharee = source.readInt() == 1;
 
     }
 
@@ -142,6 +160,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         dest.writeString(mRemoteId);
         dest.writeInt(mNeedsUpdateThumbnail ? 1 : 0);
         dest.writeInt(mIsDownloading ? 1 : 0);
+        dest.writeString(mEtagInConflict);
+        dest.writeInt(mShareWithSharee ? 1 : 0);
     }
 
     /**
@@ -204,12 +224,31 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     }
 
     /**
+     * The URI to the file contents, if stored locally
+     *
+     * @return A URI to the local copy of the file, or NULL if not stored in the device
+     */
+    public Uri getStorageUri() {
+        if (mLocalPath == null || mLocalPath.length() == 0) {
+            return null;
+        }
+        if (mLocalUri == null) {
+            Uri.Builder builder = new Uri.Builder();
+            builder.scheme(ContentResolver.SCHEME_FILE);
+            builder.path(mLocalPath);
+            mLocalUri = builder.build();
+        }
+        return mLocalUri;
+    }
+
+    /**
      * Can be used to set the path where the file is stored
      *
      * @param storage_path to set
      */
     public void setStoragePath(String storage_path) {
         mLocalPath = storage_path;
+        mLocalUri = null;
     }
 
     /**
@@ -316,24 +355,6 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     }
 
     /**
-     * Adds a file to this directory. If this file is not a directory, an
-     * exception gets thrown.
-     *
-     * @param file to add
-     * @throws IllegalStateException if you try to add a something and this is
-     *                               not a directory
-     */
-    public void addFile(OCFile file) throws IllegalStateException {
-        if (isFolder()) {
-            file.mParentId = mId;
-            mNeedsUpdating = true;
-            return;
-        }
-        throw new IllegalStateException(
-                "This is not a directory where you can add stuff to!");
-    }
-
-    /**
      * Used internally. Reset all file properties
      */
     private void resetData() {
@@ -357,6 +378,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mRemoteId = null;
         mNeedsUpdateThumbnail = false;
         mIsDownloading = false;
+        mEtagInConflict = null;
+        mShareWithSharee = false;
     }
 
     /**
@@ -498,15 +521,15 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     }
 
     public void setEtag(String etag) {
-        this.mEtag = etag;
+        this.mEtag = (etag != null ? etag : "");
     }
 
 
-    public boolean isShareByLink() {
+    public boolean isSharedViaLink() {
         return mShareByLink;
     }
 
-    public void setShareByLink(boolean shareByLink) {
+    public void setShareViaLink(boolean shareByLink) {
         this.mShareByLink = shareByLink;
     }
 
@@ -598,8 +621,24 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         this.mIsDownloading = isDownloading;
     }
 
-    public boolean isSynchronizing() {
-        // TODO real implementation
-        return false;
+    public String getEtagInConflict() {
+        return mEtagInConflict;
+    }
+
+    public void setEtagInConflict(String etagInConflict) {
+        mEtagInConflict = etagInConflict;
+    }
+
+    public boolean isSharedWithSharee() {
+        return mShareWithSharee;
+    }
+
+    public void setShareWithSharee(boolean shareWithSharee) {
+        this.mShareWithSharee = shareWithSharee;
+    }
+
+    public boolean isSharedWithMe() {
+        String permissions = getPermissions();
+        return (permissions != null && permissions.contains(PERMISSION_SHARED_WITH_ME));
     }
 }
index f0ecf76..70730fd 100644 (file)
@@ -24,23 +24,34 @@ package com.owncloud.android.datamodel;
 import java.io.File;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
+import java.net.FileNameMap;
+import java.net.URLConnection;
 
 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.Canvas;
+import android.graphics.Paint;
 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;
@@ -53,6 +64,7 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.ui.adapter.DiskLruImageCache;
 import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.FileStorageUtils;
 
 /**
  * Manager for concurrent access to thumbnails cache.
@@ -140,13 +152,40 @@ public class ThumbnailsCacheManager {
         return null;
     }
 
+    /**
+     * Sets max size of cache
+     * @param maxSize in MB
+     * @return
+     */
+    public static boolean setMaxSize(long maxSize){
+        if (mThumbnailCache != null){
+            mThumbnailCache.setMaxSize(maxSize * 1024 * 1024);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Shows max cache size
+     * @return max cache size in MB.
+     */
+    public static long getMaxSize(){
+        if (mThumbnailCache != null) {
+            return mThumbnailCache.getMaxSize() / 1024 / 1024;
+        } else {
+            return -1l;
+        }
+    }
+
     public static class ThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
         private final WeakReference<ImageView> mImageViewReference;
+        private WeakReference<ProgressBar> 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 +196,12 @@ public class ThumbnailsCacheManager {
             mAccount = account;
         }
 
+        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
+                                       Account account, ProgressBar progressWheel) {
+        this(imageView, storageManager, account);
+        mProgressWheelRef = new WeakReference<ProgressBar>(progressWheel);
+        }
+
         public ThumbnailGenerationTask(ImageView imageView) {
             // Use a WeakReference to ensure the ImageView can be garbage collected
             mImageViewReference = new WeakReference<ImageView>(imageView);
@@ -175,11 +220,24 @@ public class ThumbnailsCacheManager {
                 }
 
                 mFile = params[0];
+                mIsThumbnail = (Boolean) params[1];
+
                 
                 if (mFile instanceof OCFile) {
-                    thumbnail = doOCFileInBackground();
+                    thumbnail = doOCFileInBackground(mIsThumbnail);
+
+                    if (((OCFile) mFile).isVideo()){
+                        thumbnail = addVideoOverlay(thumbnail);
+                    }
                 }  else if (mFile instanceof File) {
-                    thumbnail = doFileInBackground();
+                    thumbnail = doFileInBackground(mIsThumbnail);
+
+                    String url = ((File) mFile).getAbsolutePath();
+                    String mMimeType = FileStorageUtils.getMimeTypeFromName(url);
+
+                    if (mMimeType != null && mMimeType.startsWith("video/")){
+                        thumbnail = addVideoOverlay(thumbnail);
+                    }
                 //} else {  do nothing
                 }
 
@@ -206,7 +264,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 +282,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 +309,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 +370,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 +442,39 @@ public class ThumbnailsCacheManager {
             return resultBitmap;
         }
 
-        private Bitmap doFileInBackground() {
+        private Bitmap doFileInBackground(Boolean mIsThumbnail) {
             File file = (File)mFile;
 
-            final String imageKey = String.valueOf(file.hashCode());
+            // distinguish between thumbnail and resized image
+            String temp = String.valueOf(file.hashCode());
+            if (mIsThumbnail){
+                temp = "t" + temp;
+            } else {
+                temp = "r" + temp;
+            }
+
+            final String imageKey = temp;
 
             // Check disk cache in background thread
             Bitmap 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;
@@ -382,6 +512,51 @@ public class ThumbnailsCacheManager {
         return null;
     }
 
+    public static Bitmap addVideoOverlay(Bitmap thumbnail){
+        Bitmap playButton = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
+                R.drawable.view_play);
+
+        Bitmap resizedPlayButton = Bitmap.createScaledBitmap(playButton,
+                (int) (thumbnail.getWidth() * 0.3),
+                (int) (thumbnail.getHeight() * 0.3), true);
+
+        Bitmap resultBitmap = Bitmap.createBitmap(thumbnail.getWidth(),
+                thumbnail.getHeight(),
+                Bitmap.Config.ARGB_8888);
+
+        Canvas c = new Canvas(resultBitmap);
+
+        // compute visual center of play button, according to resized image
+        int x1 = resizedPlayButton.getWidth();
+        int y1 = resizedPlayButton.getHeight() / 2;
+        int x2 = 0;
+        int y2 = resizedPlayButton.getWidth();
+        int x3 = 0;
+        int y3 = 0;
+
+        double ym = ( ((Math.pow(x3,2) - Math.pow(x1,2) + Math.pow(y3,2) - Math.pow(y1,2)) *
+                    (x2 - x1)) - (Math.pow(x2,2) - Math.pow(x1,2) + Math.pow(y2,2) -
+                    Math.pow(y1,2)) * (x3 - x1) )  /  (2 * ( ((y3 - y1) * (x2 - x1)) -
+                    ((y2 - y1) * (x3 - x1)) ));
+        double xm = ( (Math.pow(x2,2) - Math.pow(x1,2)) + (Math.pow(y2,2) - Math.pow(y1,2)) -
+                    (2*ym*(y2 - y1)) ) / (2*(x2 - x1));
+
+        // offset to top left
+        double ox = - xm;
+        double oy = thumbnail.getHeight() - ym;
+
+
+        c.drawBitmap(thumbnail, 0, 0, null);
+
+        Paint p = new Paint();
+        p.setAlpha(230);
+
+        c.drawBitmap(resizedPlayButton, (float) ((thumbnail.getWidth() / 2) + ox),
+                                        (float) ((thumbnail.getHeight() / 2) - ym), p);
+
+        return resultBitmap;
+    }
+
     public static class AsyncDrawable extends BitmapDrawable {
         private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
 
index 25e8fbd..1c67433 100644 (file)
@@ -31,7 +31,7 @@ import com.owncloud.android.MainApp;
 public class ProviderMeta {\r
 \r
     public static final String DB_NAME = "filelist";\r
-    public static final int DB_VERSION = 10;\r
+    public static final int DB_VERSION = 13;\r
 \r
     private ProviderMeta() {\r
     }\r
@@ -39,6 +39,7 @@ public class ProviderMeta {
     static public class ProviderTableMeta implements BaseColumns {\r
         public static final String FILE_TABLE_NAME = "filelist";\r
         public static final String OCSHARES_TABLE_NAME = "ocshares";\r
+        public static final String CAPABILITIES_TABLE_NAME = "capabilities";\r
         public static final Uri CONTENT_URI = Uri.parse("content://"\r
                 + MainApp.getAuthority() + "/");\r
         public static final Uri CONTENT_URI_FILE = Uri.parse("content://"\r
@@ -47,6 +48,8 @@ public class ProviderMeta {
                 + MainApp.getAuthority() + "/dir");\r
         public static final Uri CONTENT_URI_SHARE = Uri.parse("content://"\r
                 + MainApp.getAuthority() + "/shares");\r
+        public static final Uri CONTENT_URI_CAPABILITIES = Uri.parse("content://"\r
+                + MainApp.getAuthority() + "/capabilities");\r
 \r
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.owncloud.file";\r
         public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.owncloud.file";\r
@@ -62,16 +65,18 @@ public class ProviderMeta {
         public static final String FILE_STORAGE_PATH = "media_path";\r
         public static final String FILE_PATH = "path";\r
         public static final String FILE_ACCOUNT_OWNER = "file_owner";\r
-        public static final String FILE_LAST_SYNC_DATE = "last_sync_date";  // _for_properties, but let's keep it as it is\r
+        public static final String FILE_LAST_SYNC_DATE = "last_sync_date";// _for_properties, but let's keep it as it is\r
         public static final String FILE_LAST_SYNC_DATE_FOR_DATA = "last_sync_date_for_data";\r
         public static final String FILE_KEEP_IN_SYNC = "keep_in_sync";\r
         public static final String FILE_ETAG = "etag";\r
-        public static final String FILE_SHARE_BY_LINK = "share_by_link";\r
+        public static final String FILE_SHARED_VIA_LINK = "share_by_link";\r
+        public static final String FILE_SHARED_WITH_SHAREE = "shared_via_users";\r
         public static final String FILE_PUBLIC_LINK = "public_link";\r
         public static final String FILE_PERMISSIONS = "permissions";\r
         public static final String FILE_REMOTE_ID = "remote_id";\r
         public static final String FILE_UPDATE_THUMBNAIL = "update_thumbnail";\r
         public static final String FILE_IS_DOWNLOADING= "is_downloading";\r
+        public static final String FILE_ETAG_IN_CONFLICT = "etag_in_conflict";\r
 \r
         public static final String FILE_DEFAULT_SORT_ORDER = FILE_NAME\r
                 + " collate nocase asc";\r
@@ -94,7 +99,35 @@ public class ProviderMeta {
         \r
         public static final String OCSHARES_DEFAULT_SORT_ORDER = OCSHARES_FILE_SOURCE \r
                 + " collate nocase asc";\r
-        \r
 \r
+        // Columns of capabilities table\r
+        public static final String CAPABILITIES_ACCOUNT_NAME = "account";\r
+        public static final String CAPABILITIES_VERSION_MAYOR = "version_mayor";\r
+        public static final String CAPABILITIES_VERSION_MINOR = "version_minor";\r
+        public static final String CAPABILITIES_VERSION_MICRO = "version_micro";\r
+        public static final String CAPABILITIES_VERSION_STRING = "version_string";\r
+        public static final String CAPABILITIES_VERSION_EDITION = "version_edition";\r
+        public static final String CAPABILITIES_CORE_POLLINTERVAL = "core_pollinterval";\r
+        public static final String CAPABILITIES_SHARING_API_ENABLED = "sharing_api_enabled";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_ENABLED = "sharing_public_enabled";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED = "sharing_public_password_enforced";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED =\r
+                "sharing_public_expire_date_enabled";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS =\r
+                "sharing_public_expire_date_days";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED =\r
+                "sharing_public_expire_date_enforced";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_SEND_MAIL = "sharing_public_send_mail";\r
+        public static final String CAPABILITIES_SHARING_PUBLIC_UPLOAD = "sharing_public_upload";\r
+        public static final String CAPABILITIES_SHARING_USER_SEND_MAIL = "sharing_user_send_mail";\r
+        public static final String CAPABILITIES_SHARING_RESHARING = "sharing_resharing";\r
+        public static final String CAPABILITIES_SHARING_FEDERATION_OUTGOING = "sharing_federation_outgoing";\r
+        public static final String CAPABILITIES_SHARING_FEDERATION_INCOMING = "sharing_federation_incoming";\r
+        public static final String CAPABILITIES_FILES_BIGFILECHUNKING = "files_bigfilechunking";\r
+        public static final String CAPABILITIES_FILES_UNDELETE = "files_undelete";\r
+        public static final String CAPABILITIES_FILES_VERSIONING = "files_versioning";\r
+\r
+        public static final String CAPABILITIES_DEFAULT_SORT_ORDER = CAPABILITIES_ACCOUNT_NAME\r
+                + " collate nocase asc";\r
     }\r
 }\r
index f7fee62..0b7eb81 100644 (file)
@@ -29,12 +29,14 @@ import android.view.Menu;
 import android.view.MenuItem;
 
 import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
-import com.owncloud.android.services.OperationsService;
+import com.owncloud.android.lib.resources.status.CapabilityBooleanType;
+import com.owncloud.android.lib.resources.status.OCCapability;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.activity.ComponentsGetter;
 
@@ -58,7 +60,8 @@ public class FileMenuFilter {
      *                          {@link FileUploader} and {@link FileDownloader} services
      * @param context           Android {@link Context}, needed to access build setup resources.
      */
-    public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg, Context context) {
+    public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg,
+                          Context context) {
         mFile = targetFile;
         mAccount = account;
         mComponentsGetter = cg;
@@ -106,21 +109,25 @@ public class FileMenuFilter {
      * @param toHide            List to save the options that must be shown in the menu.
      */
     private void filter(List<Integer> toShow, List <Integer> toHide) {
-        boolean downloading = false;
-        boolean uploading = false;
+        boolean synchronizing = false;
         if (mComponentsGetter != null && mFile != null && mAccount != null) {
-            FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder();
-            downloading = (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile));
             OperationsServiceBinder opsBinder = mComponentsGetter.getOperationsServiceBinder();
-            downloading |= (opsBinder != null && opsBinder.isSynchronizing(mAccount, mFile.getRemotePath()));
             FileUploaderBinder uploaderBinder = mComponentsGetter.getFileUploaderBinder();
-            uploading = (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile));
+            FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder();
+            synchronizing = (
+                // comparing local and remote
+                (opsBinder != null && opsBinder.isSynchronizing(mAccount, mFile.getRemotePath())) ||
+                // downloading
+                (downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFile)) ||
+                // uploading
+                (uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFile))
+            );
         }
 
         /// decision is taken for each possible action on a file in the menu
 
         // DOWNLOAD 
-        if (mFile == null || mFile.isDown() || downloading || uploading) {
+        if (mFile == null || mFile.isDown() || mFile.isFolder() || synchronizing) {
             toHide.add(R.id.action_download_file);
 
         } else {
@@ -128,7 +135,7 @@ public class FileMenuFilter {
         }
 
         // RENAME
-        if (mFile == null || downloading || uploading) {
+        if (mFile == null || synchronizing) {
             toHide.add(R.id.action_rename_file);
 
         } else {
@@ -136,7 +143,7 @@ public class FileMenuFilter {
         }
 
         // MOVE & COPY
-        if (mFile == null || downloading || uploading) {
+        if (mFile == null || synchronizing) {
             toHide.add(R.id.action_move);
             toHide.add(R.id.action_copy);
         } else {
@@ -145,7 +152,7 @@ public class FileMenuFilter {
         }
 
         // REMOVE
-        if (mFile == null || downloading || uploading) {
+        if (mFile == null || synchronizing) {
             toHide.add(R.id.action_remove_file);
 
         } else {
@@ -153,36 +160,30 @@ public class FileMenuFilter {
         }
 
         // OPEN WITH (different to preview!)
-        if (mFile == null || mFile.isFolder() || !mFile.isDown() || downloading || uploading) {
+        if (mFile == null || mFile.isFolder() || !mFile.isDown() || synchronizing) {
             toHide.add(R.id.action_open_file_with);
 
         } else {
             toShow.add(R.id.action_open_file_with);
         }
 
+        // CANCEL SYNCHRONIZATION
+        if (mFile == null || !synchronizing) {
+            toHide.add(R.id.action_cancel_sync);
 
-        // CANCEL DOWNLOAD
-        if (mFile == null || !downloading) {
-            toHide.add(R.id.action_cancel_download);
-        } else {
-            toShow.add(R.id.action_cancel_download);
-        }
-
-        // CANCEL UPLOAD
-        if (mFile == null || !uploading || mFile.isFolder()) {
-            toHide.add(R.id.action_cancel_upload);
         } else {
-            toShow.add(R.id.action_cancel_upload);
+            toShow.add(R.id.action_cancel_sync);
         }
 
-        // SYNC FILE CONTENTS
-        if (mFile == null || mFile.isFolder() || !mFile.isDown() || downloading || uploading) {
+        // SYNC CONTENTS (BOTH FILE AND FOLDER)
+        if (mFile == null || (!mFile.isFolder() && !mFile.isDown()) || synchronizing) {
             toHide.add(R.id.action_sync_file);
+
         } else {
             toShow.add(R.id.action_sync_file);
         }
 
-        // SHARE FILE 
+        // SHARE FILE
         // TODO add check on SHARE available on server side?
         boolean shareAllowed = (mContext != null  &&
                 mContext.getString(R.string.share_feature).equalsIgnoreCase("on"));
@@ -192,14 +193,25 @@ public class FileMenuFilter {
             toShow.add(R.id.action_share_file);
         }
 
-        // UNSHARE FILE  
+        // UNSHARE FILE
         // TODO add check on SHARE available on server side?
-        if ( !shareAllowed || (mFile == null || !mFile.isShareByLink())) {
+        if ( !shareAllowed || (mFile == null || !mFile.isSharedViaLink())) {
             toHide.add(R.id.action_unshare_file);
         } else {
             toShow.add(R.id.action_unshare_file);
         }
 
+        // SHARE FILE, with Users
+        OCCapability capability = mComponentsGetter.getStorageManager().getCapability(mAccount.name);
+        boolean shareApiEnabled  = capability != null &&
+                (capability.getFilesSharingApiEnabled().isTrue() || capability.getFilesSharingApiEnabled().isUnknown());
+        if (!shareAllowed ||  mFile == null || !shareApiEnabled ) {
+            toHide.add(R.id.action_share_with_users);
+        } else {
+            toShow.add(R.id.action_share_with_users);
+        }
+
+
         // SEE DETAILS
         if (mFile == null || mFile.isFolder()) {
             toHide.add(R.id.action_see_details);
@@ -210,26 +222,40 @@ public class FileMenuFilter {
         // SEND
         boolean sendAllowed = (mContext != null &&
                 mContext.getString(R.string.send_files_to_other_apps).equalsIgnoreCase("on"));
-        if (mFile == null || !sendAllowed || mFile.isFolder() || uploading || downloading) {
+        if (mFile == null || !sendAllowed || mFile.isFolder() || synchronizing) {
             toHide.add(R.id.action_send_file);
         } else {
             toShow.add(R.id.action_send_file);
         }
 
         // FAVORITES
-        if (mFile == null || downloading || uploading || mFile.isFolder() || mFile.isFavorite()) {
+        if (mFile == null || synchronizing || mFile.isFolder() || mFile.isFavorite()) {
             toHide.add(R.id.action_favorite_file);
         } else {
             toShow.add(R.id.action_favorite_file);
         }
 
         // UNFAVORITES
-        if (mFile == null || downloading || uploading || mFile.isFolder() || !mFile.isFavorite()) {
+        if (mFile == null || synchronizing || mFile.isFolder() || !mFile.isFavorite()) {
             toHide.add(R.id.action_unfavorite_file);
         } else {
             toShow.add(R.id.action_unfavorite_file);
         }
 
+        // STREAM
+        if (mFile != null && !mFile.isDown() && (mFile.isAudio() || mFile.isVideo())){
+            toShow.add(R.id.action_stream_file);
+        } else {
+            toHide.add(R.id.action_stream_file);
+        }
+
+        // SET PICTURE AS
+        if (mFile == null || !mFile.isImage()){
+            toHide.add(R.id.action_set_as_wallpaper);
+        } else {
+            toShow.add(R.id.action_set_as_wallpaper);
+        }
+
     }
 
 }
index fba6209..362cada 100644 (file)
@@ -25,28 +25,47 @@ import android.accounts.Account;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
 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;
 import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.ShareType;
 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.activity.ShareActivity;
 import com.owncloud.android.ui.dialog.ShareLinkToDialog;
 
 import org.apache.http.protocol.HTTP;
 
+import java.io.File;
+import java.util.List;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.http.protocol.HTTP;
+
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -74,7 +93,8 @@ public class FileOperationsHelper {
             String encodedStoragePath = WebdavUtils.encodePath(storagePath);
 
             Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
-            intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
+            intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath),
+                    file.getMimetype());
             intentForSavedMimeType.setFlags(
                     Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
             );
@@ -86,9 +106,12 @@ public class FileOperationsHelper {
                 );
                 if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
                     intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
-                    intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
+                    intentForGuessedMimeType.
+                            setDataAndType(Uri.parse("file://"+ encodedStoragePath),
+                                    guessedMimeType);
                     intentForGuessedMimeType.setFlags(
-                            Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                            Intent.FLAG_GRANT_READ_URI_PERMISSION |
+                                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                     );
                 }
             }
@@ -140,7 +163,8 @@ public class FileOperationsHelper {
                 String link = "https://fake.url";
                 Intent intent = createShareWithLinkIntent(link);
                 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
-                DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file);
+                DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent,
+                        packagesToExclude, file);
                 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
 
             } else {
@@ -150,7 +174,8 @@ public class FileOperationsHelper {
         } else {
             // Show a Message
             Toast t = Toast.makeText(
-                    mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG
+                    mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
+                    Toast.LENGTH_LONG
             );
             t.show();
         }
@@ -160,10 +185,11 @@ public class FileOperationsHelper {
     public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) {
         
         if (file != null) {
-            mFileActivity.showLoadingDialog();
+            mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                    getString(R.string.wait_a_moment));
 
             Intent service = new Intent(mFileActivity, OperationsService.class);
-            service.setAction(OperationsService.ACTION_CREATE_SHARE);
+            service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
             service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
             service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
             service.putExtra(OperationsService.EXTRA_PASSWORD_SHARE, password);
@@ -185,6 +211,33 @@ public class FileOperationsHelper {
 
 
     /**
+     * Helper method to share a file with a know sharee. Starts a request to do it in {@link OperationsService}
+     *
+     * @param file          The file to share.
+     * @param shareeName    Name (user name or group name) of the target sharee.
+     * @param shareType     The share type determines the sharee type.
+     */
+    public void shareFileWithSharee(OCFile file, String shareeName, ShareType shareType) {
+        if (file != null) {
+            // TODO check capability?
+            mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                    getString(R.string.wait_a_moment));
+
+            Intent service = new Intent(mFileActivity, OperationsService.class);
+            service.setAction(OperationsService.ACTION_CREATE_SHARE_WITH_SHAREE);
+            service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+            service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+            service.putExtra(OperationsService.EXTRA_SHARE_WITH, shareeName);
+            service.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
+            mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
+
+        } else {
+            Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
+        }
+    }
+
+
+    /**
      * @return 'True' if the server supports the Share API
      */
     public boolean isSharedSupported() {
@@ -198,24 +251,75 @@ public class FileOperationsHelper {
 
     public void unshareFileWithLink(OCFile file) {
 
+        // Unshare the file: Create the intent
+        Intent unshareService = new Intent(mFileActivity, OperationsService.class);
+        unshareService.setAction(OperationsService.ACTION_UNSHARE);
+        unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+        unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+        unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, ShareType.PUBLIC_LINK);
+        unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, "");
+
+        unshareFile(unshareService);
+    }
+
+    public void unshareFileWithUserOrGroup(OCFile file, ShareType shareType, String userOrGroup){
+
+        // Unshare the file: Create the intent
+        Intent unshareService = new Intent(mFileActivity, OperationsService.class);
+        unshareService.setAction(OperationsService.ACTION_UNSHARE);
+        unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+        unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+        unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
+        unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, userOrGroup);
+
+        unshareFile(unshareService);
+    }
+
+
+    private void unshareFile(Intent unshareService){
         if (isSharedSupported()) {
             // Unshare the file
-            Intent service = new Intent(mFileActivity, OperationsService.class);
-            service.setAction(OperationsService.ACTION_UNSHARE);
-            service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
-            service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
-            mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
-            
-            mFileActivity.showLoadingDialog();
+            mWaitingForOpId = mFileActivity.getOperationsServiceBinder().
+                    queueNewOperation(unshareService);
+
+            mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                    getString(R.string.wait_a_moment));
 
         } else {
             // Show a Message
-            Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
+            Toast t = Toast.makeText(mFileActivity,
+                    mFileActivity.getString(R.string.share_link_no_support_share_api),
+                    Toast.LENGTH_LONG);
             t.show();
 
         }
     }
 
+    /**
+     * Show an instance of {@link ShareType} for sharing or unsharing the {@OCFile} received as parameter.
+     *
+     * @param file  File to share or unshare.
+     */
+    public void showShareFile(OCFile file){
+        Intent intent = new Intent(mFileActivity, ShareActivity.class);
+        intent.putExtra(mFileActivity.EXTRA_FILE, file);
+        intent.putExtra(mFileActivity.EXTRA_ACCOUNT, mFileActivity.getAccount());
+        mFileActivity.startActivity(intent);
+
+    }
+
+
+    /**
+     * @return 'True' if the server supports the Search Users API
+     */
+    public boolean isSearchUsersSupportedSupported() {
+        if (mFileActivity.getAccount() != null) {
+            OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
+            return (serverVersion != null && serverVersion.isSearchUsersSupported());
+        }
+        return false;
+    }
+
     public void sendDownloadedFile(OCFile file) {
         if (file != null) {
             String storagePath = file.getStoragePath();
@@ -228,7 +332,8 @@ public class FileOperationsHelper {
 
             // Show dialog, without the own app
             String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
-            DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file);
+            DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent,
+                    packagesToExclude, file);
             chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
 
         } else {
@@ -236,9 +341,70 @@ public class FileOperationsHelper {
         }
     }
 
+    public void setPictureAs(OCFile file) {
+        if (file != null){
+            if (file.isDown()) {
+                File externalFile = new File(file.getStoragePath());
+                Uri sendUri = Uri.fromFile(externalFile);
+                Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
+                intent.setDataAndType(sendUri, file.getMimetype());
+                intent.putExtra("mimeType", file.getMimetype());
+                mFileActivity.startActivityForResult(Intent.createChooser(intent, "Set As"), 200);
+            } else {
+                // TODO re-enable after resized images is available
+                Uri sendUri = Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + file.getRemotePath());
+                Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
+                intent.setDataAndType(sendUri, file.getMimetype());
+                intent.putExtra("mimeType", file.getMimetype());
+                mFileActivity.startActivityForResult(Intent.createChooser(intent, "Set As"), 200);
+
+//                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 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
 
-    public void syncFile(OCFile file) {
+            // 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 syncFiles(ArrayList<OCFile> files) {
+        for (OCFile file: files) {
+            syncFile(file);
+        }
+    }
+
+    /**
+     * Request the synchronization of a file or folder with the OC server, including its contents.
+     *
+     * @param file          The file or folder to synchronize
+     */
+    public void syncFile(OCFile file) {
         if (!file.isFolder()){
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_SYNC_FILE);
@@ -246,7 +412,8 @@ public class FileOperationsHelper {
             intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
             intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
-            mFileActivity.showLoadingDialog();
+            mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                    getString(R.string.wait_a_moment));
             
         } else {
             Intent intent = new Intent(mFileActivity, OperationsService.class);
@@ -254,6 +421,13 @@ public class FileOperationsHelper {
             intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
             intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
             mFileActivity.startService(intent);
+
+        }
+    }
+
+    public void toggleFavorites(ArrayList<OCFile> files, boolean isFavorite){
+        for (OCFile file: files) {
+            toggleFavorite(file, isFavorite);
         }
     }
 
@@ -284,7 +458,8 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
         
-        mFileActivity.showLoadingDialog();
+        mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                getString(R.string.wait_a_moment));
     }
 
 
@@ -297,7 +472,8 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
         
-        mFileActivity.showLoadingDialog();
+        mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                getString(R.string.wait_a_moment));
     }
 
 
@@ -310,7 +486,8 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
         
-        mFileActivity.showLoadingDialog();
+        mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                getString(R.string.wait_a_moment));
     }
 
     /**
@@ -320,7 +497,8 @@ public class FileOperationsHelper {
     public void cancelTransference(OCFile file) {
         Account account = mFileActivity.getAccount();
         if (file.isFolder()) {
-            OperationsService.OperationsServiceBinder opsBinder = mFileActivity.getOperationsServiceBinder();
+            OperationsService.OperationsServiceBinder opsBinder =
+                    mFileActivity.getOperationsServiceBinder();
             if (opsBinder != null) {
                 opsBinder.cancel(account, file);
             }
@@ -328,19 +506,11 @@ public class FileOperationsHelper {
 
         // for both files and folders
         FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
-        FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
         if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
             downloaderBinder.cancel(account, file);
-
-            // TODO - review why is this here, and solve in a better way
-            // Remove etag for parent, if file is a favorite
-            if (file.isFavorite()) {
-                OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId());
-                parent.setEtag("");
-                mFileActivity.getStorageManager().saveFile(parent);
-            }
-
-        } else if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
+        }
+        FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
+        if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
             uploaderBinder.cancel(account, file);
         }
     }
@@ -360,7 +530,9 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
 
-        mFileActivity.showLoadingDialog();
+        // TODO Tobi loading dialog?
+//        mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+//                getString(R.string.wait_a_moment));
     }
 
     /**
@@ -378,7 +550,8 @@ public class FileOperationsHelper {
         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
 
-        mFileActivity.showLoadingDialog();
+        mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
+                getString(R.string.wait_a_moment));
     }
 
     public long getOpIdWaitingFor() {
@@ -395,7 +568,8 @@ public class FileOperationsHelper {
      */
     public boolean isVersionWithForbiddenCharacters() {
         if (mFileActivity.getAccount() != null) {
-            OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
+            OwnCloudVersion serverVersion =
+                    AccountUtils.getServerVersion(mFileActivity.getAccount());
             return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
         }
         return false;
index 47f7127..e152daf 100644 (file)
@@ -29,14 +29,16 @@ 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.content.SharedPreferences;
 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 +60,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 +105,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 +112,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;
         }
 
@@ -122,6 +126,25 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
         i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
         i.putExtra(FileUploader.KEY_MIME_TYPE, mime_type);
         i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
+
+        // instant upload behaviour
+        SharedPreferences appPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+        String behaviour = appPreferences.getString("prefs_instant_behaviour", "NOTHING");
+
+        if (behaviour.equalsIgnoreCase("NOTHING")) {
+            Log_OC.d(TAG, "upload file and do nothing");
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_FORGET);
+        } else if (behaviour.equalsIgnoreCase("COPY")) {
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_COPY);
+            Log_OC.d(TAG, "upload file and copy file to oc folder");
+        } else if (behaviour.equalsIgnoreCase("MOVE")) {
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
+            Log_OC.d(TAG, "upload file and move file to oc folder");
+        } else if (behaviour.equalsIgnoreCase("DELETE")){
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_REMOVE);
+            Log_OC.d(TAG, "upload file and delete file in original place");
+        }
+
         context.startService(i);
     }
 
@@ -155,8 +178,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;
         }
 
@@ -167,23 +198,64 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
         i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
         i.putExtra(FileUploader.KEY_MIME_TYPE, mime_type);
         i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
+
+        // instant upload behaviour
+        SharedPreferences appPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+        String behaviour = appPreferences.getString("prefs_instant_behaviour", "NOTHING");
+
+        if (behaviour.equalsIgnoreCase("NOTHING")) {
+            Log_OC.d(TAG, "upload file and do nothing");
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_FORGET);
+        } else if (behaviour.equalsIgnoreCase("COPY")) {
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_COPY);
+            Log_OC.d(TAG, "upload file and copy file to oc folder");
+        } else if (behaviour.equalsIgnoreCase("MOVE")) {
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
+            Log_OC.d(TAG, "upload file and move file to oc folder");
+        } else if (behaviour.equalsIgnoreCase("DELETE")){
+            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_REMOVE);
+            Log_OC.d(TAG, "upload file and delete file in original place");
+        }
+
         context.startService(i);
 
     }
 
     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 (instantPictureUploadViaWiFiOnly(context) && !isConnectedViaWiFi(context)){
+            Account account = AccountUtils.getCurrentOwnCloudAccount(context);
+            if (account == null) {
+                Log_OC.w(TAG, "No owncloud account found for instant upload, aborting");
+                return;
+            }
+
+            Intent i = new Intent(context, FileUploader.class);
+            i.putExtra(FileUploader.KEY_ACCOUNT, account);
+            i.putExtra(FileUploader.KEY_CANCEL_ALL, true);
+            context.startService(i);
+        }
+
         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()) {
                 do {
+                    if (instantPictureUploadViaWiFiOnly(context) &&
+                            !isConnectedViaWiFi(context)){
+                        break;
+                    }
+
                     String account_name = c.getString(c.getColumnIndex("account"));
                     String file_path = c.getString(c.getColumnIndex("path"));
                     File f = new File(file_path);
@@ -207,6 +279,25 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
                         i.putExtra(FileUploader.KEY_REMOTE_FILE, FileStorageUtils.getInstantUploadFilePath(context, f.getName()));
                         i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
                         i.putExtra(FileUploader.KEY_INSTANT_UPLOAD, true);
+
+                        // instant upload behaviour
+                        SharedPreferences appPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+                        String behaviour = appPreferences.getString("prefs_instant_behaviour", "NOTHING");
+
+                        if (behaviour.equalsIgnoreCase("NOTHING")) {
+                            Log_OC.d(TAG, "upload file and do nothing");
+                            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_FORGET);
+                        } else if (behaviour.equalsIgnoreCase("COPY")) {
+                            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_COPY);
+                            Log_OC.d(TAG, "upload file and copy file to oc folder");
+                        } else if (behaviour.equalsIgnoreCase("MOVE")) {
+                            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_MOVE);
+                            Log_OC.d(TAG, "upload file and move file to oc folder");
+                        } else if (behaviour.equalsIgnoreCase("DELETE")){
+                            i.putExtra(FileUploader.KEY_LOCAL_BEHAVIOUR, FileUploader.LOCAL_BEHAVIOUR_REMOVE);
+                            Log_OC.d(TAG, "upload file and delete file in original place");
+                        }
+
                         context.startService(i);
 
                     } else {
@@ -217,7 +308,6 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver {
             c.close();
             db.close();
         }
-
     }
 
     public static boolean isOnline(Context context) {
@@ -231,6 +321,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 +349,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);
+    }
 }
index f6d3b50..b6f21a5 100644 (file)
 package com.owncloud.android.files.services;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.AbstractList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Vector;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AuthenticatorActivity;
@@ -54,7 +52,6 @@ import com.owncloud.android.utils.ErrorMessageAdapter;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AccountsException;
 import android.accounts.OnAccountsUpdateListener;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -153,7 +150,7 @@ public class FileDownloader extends Service
 
     /**
      * Entry point to add one or several files to the queue of downloads.
-     * <p/>
+     *
      * New downloads are added calling to startService(), resulting in a call to this method.
      * This ensures the service will keep on working although the caller activity goes away.
      */
@@ -169,12 +166,6 @@ public class FileDownloader extends Service
         } else {
             final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
             final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
-
-            /*Log_OC.v(
-                    "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Received request to download file"
-            );*/
-
             AbstractList<String> requestedDownloads = new Vector<String>();
             try {
                 DownloadFileOperation newDownload = new DownloadFileOperation(account, file);
@@ -185,20 +176,6 @@ public class FileDownloader extends Service
                 );
                 String downloadKey = putResult.first;
                 requestedDownloads.add(downloadKey);
-                    /*Log_OC.v(
-                        "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Download on " + file.getRemotePath() + " added to queue"
-                    );*/
-
-                // Store file on db with state 'downloading'
-                    /*
-                    TODO - check if helps with UI responsiveness,
-                    letting only folders use FileDownloaderBinder to check
-                    FileDataStorageManager storageManager =
-                    new FileDataStorageManager(account, getContentResolver());
-                    file.setDownloading(true);
-                    storageManager.saveFile(file);
-                    */
 
                 sendBroadcastNewDownload(newDownload, putResult.second);
 
@@ -275,34 +252,23 @@ public class FileDownloader extends Service
          * @param file    A file in the queue of pending downloads
          */
         public void cancel(Account account, OCFile file) {
-            /*Log_OC.v(
-                    "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Received request to cancel download of " + file.getRemotePath()
-            );
-            Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                    "Removing download of " + file.getRemotePath());*/
-            Pair<DownloadFileOperation, String> removeResult =
-                    mPendingDownloads.remove(account, file.getRemotePath());
+            Pair<DownloadFileOperation, String> removeResult = mPendingDownloads.remove(account, file.getRemotePath());
             DownloadFileOperation download = removeResult.first;
             if (download != null) {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Canceling returned download of " + file.getRemotePath());*/
                 download.cancel();
             } else {
                 if (mCurrentDownload != null && mCurrentAccount != null &&
                         mCurrentDownload.getRemotePath().startsWith(file.getRemotePath()) &&
                         account.name.equals(mCurrentAccount.name)) {
-                    /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                     "Canceling current sync as descendant: " + mCurrentDownload.getRemotePath());*/
                     mCurrentDownload.cancel();
                 }
             }
         }
 
         /**
-         * Cancels a pending or current upload for an account
+         * Cancels all the downloads for an account
          *
-         * @param account Owncloud accountName where the remote file will be stored.
+         * @param account   ownCloud account.
          */
         public void cancel(Account account) {
             Log_OC.d(TAG, "Account= " + account.name);
@@ -325,7 +291,7 @@ public class FileDownloader extends Service
         /**
          * Returns True when the file described by 'file' in the ownCloud account 'account'
          * is downloading or waiting to download.
-         * <p/>
+         *
          * If 'file' is a directory, returns 'true' if any of its descendant files is downloading or
          * waiting to download.
          *
@@ -349,7 +315,6 @@ public class FileDownloader extends Service
                 OnDatatransferProgressListener listener, Account account, OCFile file
         ) {
             if (account == null || file == null || listener == null) return;
-            //String targetKey = buildKey(account, file.getRemotePath());
             mBoundListeners.put(file.getFileId(), listener);
         }
 
@@ -357,15 +322,14 @@ public class FileDownloader extends Service
         /**
          * Removes a listener interested in the progress of the download for a concrete file.
          *
-         * @param listener Object to notify about progress of transfer.
-         * @param account  ownCloud account holding the file of interest.
-         * @param file     {@link OCFile} of interest for listener.
+         * @param listener      Object to notify about progress of transfer.
+         * @param account       ownCloud account holding the file of interest.
+         * @param file          {@link OCFile} of interest for listener.
          */
         public void removeDatatransferProgressListener(
                 OnDatatransferProgressListener listener, Account account, OCFile file
         ) {
             if (account == null || file == null || listener == null) return;
-            //String targetKey = buildKey(account, file.getRemotePath());
             Long fileId = file.getFileId();
             if (mBoundListeners.get(fileId) == listener) {
                 mBoundListeners.remove(fileId);
@@ -375,8 +339,6 @@ public class FileDownloader extends Service
         @Override
         public void onTransferProgress(long progressRate, long totalTransferredSoFar,
                                        long totalToTransfer, String fileName) {
-            //String key = buildKey(mCurrentDownload.getAccount(),
-            // mCurrentDownload.getFile().getRemotePath());
             OnDatatransferProgressListener boundListener =
                     mBoundListeners.get(mCurrentDownload.getFile().getFileId());
             if (boundListener != null) {
@@ -385,23 +347,12 @@ public class FileDownloader extends Service
             }
         }
 
-        /**
-         * Review downloads and cancel it if its account doesn't exist
-         */
-        public void checkAccountOfCurrentDownload() {
-            if (mCurrentDownload != null &&
-                    !AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) {
-                mCurrentDownload.cancel();
-            }
-            // The rest of downloads are cancelled when they try to start
-        }
-
     }
 
 
     /**
      * Download worker. Performs the pending downloads in the order they were requested.
-     * <p/>
+
      * Created with the Looper of a new thread, started in {@link FileUploader#onCreate()}.
      */
     private static class ServiceHandler extends Handler {
@@ -440,14 +391,13 @@ public class FileDownloader extends Service
      */
     private void downloadFile(String downloadKey) {
 
-        /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                "Getting download of " + downloadKey);*/
         mCurrentDownload = mPendingDownloads.get(downloadKey);
 
         if (mCurrentDownload != null) {
             // Detect if the account exists
             if (AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) {
                 Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().name + " exists");
+
                 notifyDownloadStart(mCurrentDownload);
 
                 RemoteOperationResult downloadResult = null;
@@ -470,26 +420,16 @@ public class FileDownloader extends Service
 
 
                     /// perform the download
-                    /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Executing download of " + mCurrentDownload.getRemotePath());*/
                     downloadResult = mCurrentDownload.execute(mDownloadClient);
                     if (downloadResult.isSuccess()) {
                         saveDownloadedFile();
                     }
 
-                } catch (AccountsException e) {
-                    Log_OC.e(TAG, "Error while trying to get authorization for "
-                            + mCurrentAccount.name, e);
-                    downloadResult = new RemoteOperationResult(e);
-                } catch (IOException e) {
-                    Log_OC.e(TAG, "Error while trying to get authorization for "
-                            + mCurrentAccount.name, e);
+                } catch (Exception e) {
+                    Log_OC.e(TAG, "Error downloading", e);
                     downloadResult = new RemoteOperationResult(e);
 
                 } finally {
-                /*Log_OC.v(   "NOW " + TAG + ", thread " + Thread.currentThread().getName(),
-                        "Removing payload " + mCurrentDownload.getRemotePath());*/
-
                     Pair<DownloadFileOperation, String> removeResult =
                             mPendingDownloads.removePayload(mCurrentAccount,
                                     mCurrentDownload.getRemotePath());
@@ -497,9 +437,9 @@ public class FileDownloader extends Service
                     /// notify result
                     notifyDownloadResult(mCurrentDownload, downloadResult);
 
-                    sendBroadcastDownloadFinished(mCurrentDownload, downloadResult,
-                            removeResult.second);
+                    sendBroadcastDownloadFinished(mCurrentDownload, downloadResult, removeResult.second);
                 }
+
             } else {
                 // Cancel the transfer
                 Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().toString() +
@@ -513,6 +453,8 @@ public class FileDownloader extends Service
 
     /**
      * Updates the OC File after a successful download.
+     *
+     * TODO move to DownloadFileOperation
      */
     private void saveDownloadedFile() {
         OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId());
@@ -522,26 +464,17 @@ public class FileDownloader extends Service
         file.setNeedsUpdateThumbnail(true);
         file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());
         file.setModificationTimestampAtLastSyncForData(mCurrentDownload.getModificationTimestamp());
-        // file.setEtag(mCurrentDownload.getEtag());    // TODO Etag, where available
+        file.setEtag(mCurrentDownload.getEtag());
         file.setMimetype(mCurrentDownload.getMimeType());
         file.setStoragePath(mCurrentDownload.getSavePath());
         file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
         file.setRemoteId(mCurrentDownload.getFile().getRemoteId());
         mStorageManager.saveFile(file);
         mStorageManager.triggerMediaScan(file.getStoragePath());
+        mStorageManager.saveConflict(file, null);
     }
 
     /**
-     * Update the OC File after a unsuccessful download
-     */
-    private void updateUnsuccessfulDownloadedFile() {
-        OCFile file = mStorageManager.getFileById(mCurrentDownload.getFile().getFileId());
-        file.setDownloading(false);
-        mStorageManager.saveFile(file);
-    }
-
-
-    /**
      * Creates a status notification to show the download progress
      *
      * @param download Download operation starting.
@@ -683,6 +616,7 @@ public class FileDownloader extends Service
             DownloadFileOperation download,
             RemoteOperationResult downloadResult,
             String unlinkedFromRemotePath) {
+
         Intent end = new Intent(getDownloadFinishMessage());
         end.putExtra(EXTRA_DOWNLOAD_RESULT, downloadResult.isSuccess());
         end.putExtra(ACCOUNT_NAME, download.getAccount().name);
index 669ff13..9bc2742 100644 (file)
 package com.owncloud.android.files.services;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.AbstractList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Vector;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
-import android.accounts.AccountsException;
 import android.accounts.OnAccountsUpdateListener;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
@@ -46,6 +42,7 @@ import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
 import android.support.v4.app.NotificationCompat;
+import android.util.Pair;
 import android.webkit.MimeTypeMap;
 
 import com.owncloud.android.R;
@@ -86,6 +83,7 @@ public class FileUploader extends Service
     public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
     public static final String EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH";
     public static final String EXTRA_OLD_FILE_PATH = "OLD_FILE_PATH";
+    public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO";
     public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
 
     public static final String KEY_FILE = "FILE";
@@ -100,9 +98,12 @@ public class FileUploader extends Service
     public static final String KEY_INSTANT_UPLOAD = "INSTANT_UPLOAD";
     public static final String KEY_LOCAL_BEHAVIOUR = "BEHAVIOUR";
 
+    public static final String KEY_CANCEL_ALL = "CANCEL_ALL";
+
     public static final int LOCAL_BEHAVIOUR_COPY = 0;
     public static final int LOCAL_BEHAVIOUR_MOVE = 1;
     public static final int LOCAL_BEHAVIOUR_FORGET = 2;
+    public static final int LOCAL_BEHAVIOUR_REMOVE = 3;
 
     public static final int UPLOAD_SINGLE_FILE = 0;
     public static final int UPLOAD_MULTIPLE_FILES = 1;
@@ -113,11 +114,10 @@ public class FileUploader extends Service
     private ServiceHandler mServiceHandler;
     private IBinder mBinder;
     private OwnCloudClient mUploadClient = null;
-    private Account mLastAccount = null;
+    private Account mCurrentAccount = null;
     private FileDataStorageManager mStorageManager;
 
-    private ConcurrentMap<String, UploadFileOperation> mPendingUploads =
-            new ConcurrentHashMap<String, UploadFileOperation>();
+    private IndexedForest<UploadFileOperation> mPendingUploads = new IndexedForest<UploadFileOperation>();
     private UploadFileOperation mCurrentUpload = null;
 
     private NotificationManager mNotificationManager;
@@ -133,26 +133,14 @@ public class FileUploader extends Service
     }
 
     /**
-     * Builds a key for mPendingUploads from the account and file to upload
-     *
-     * @param account   Account where the file to upload is stored
-     * @param file      File to upload
-     */
-    private String buildRemoteName(Account account, OCFile file) {
-        return account.name + file.getRemotePath();
-    }
-
-    private String buildRemoteName(Account account, String remotePath) {
-        return account.name + remotePath;
-    }
-
-    /**
      * Checks if an ownCloud server version should support chunked uploads.
      *
      * @param version OwnCloud version instance corresponding to an ownCloud
      *            server.
      * @return 'True' if the ownCloud server with version supports chunked
      *         uploads.
+     *
+     * TODO - move to OCClient
      */
     private static boolean chunkedUploadIsSupported(OwnCloudVersion version) {
         return (version != null && version.compareTo(OwnCloudVersion.owncloud_v4_5) >= 0);
@@ -209,6 +197,21 @@ public class FileUploader extends Service
     public int onStartCommand(Intent intent, int flags, int startId) {
         Log_OC.d(TAG, "Starting command with id " + startId);
 
+        if (intent.hasExtra(KEY_CANCEL_ALL) && intent.hasExtra(KEY_ACCOUNT)){
+            Account account = intent.getParcelableExtra(KEY_ACCOUNT);
+
+            Log_OC.d(TAG, "Account= " + account.name);
+
+            if (mCurrentUpload != null) {
+                Log_OC.d(TAG, "Current Upload Account= " + mCurrentUpload.getAccount().name);
+                if (mCurrentUpload.getAccount().name.equals(account.name)) {
+                    mCurrentUpload.cancel();
+                }
+            }
+            // Cancel pending uploads
+            cancelUploadsForAccount(account);
+        }
+
         if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE)
                 || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) {
             Log_OC.e(TAG, "Not enough information provided in intent");
@@ -282,7 +285,7 @@ public class FileUploader extends Service
             files = new OCFile[localPaths.length];
             for (int i = 0; i < localPaths.length; i++) {
                 files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i],
-                        ((mimeTypes != null) ? mimeTypes[i] : null), storageManager);
+                        ((mimeTypes != null) ? mimeTypes[i] : null));
                 if (files[i] == null) {
                     // TODO @andomaex add failure Notification
                     return Service.START_NOT_STICKY;
@@ -298,18 +301,23 @@ public class FileUploader extends Service
         UploadFileOperation newUpload = null;
         try {
             for (int i = 0; i < files.length; i++) {
-                uploadKey = buildRemoteName(account, files[i].getRemotePath());
-                newUpload = new UploadFileOperation(account, files[i], chunked, isInstant,
+                newUpload = new UploadFileOperation(
+                        account,
+                        files[i],
+                        chunked,
+                        isInstant,
                         forceOverwrite, localAction,
-                        getApplicationContext());
+                        getApplicationContext()
+                );
                 if (isInstant) {
                     newUpload.setRemoteFolderToBeCreated();
                 }
-                // Grants that the file only upload once time
-                mPendingUploads.putIfAbsent(uploadKey, newUpload);
-
                 newUpload.addDatatransferProgressListener(this);
-                newUpload.addDatatransferProgressListener((FileUploaderBinder)mBinder);
+                newUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
+                Pair<String, String> putResult = mPendingUploads.putIfAbsent(
+                        account, files[i].getRemotePath(), newUpload
+                );
+                uploadKey = putResult.first;
                 requestedUploads.add(uploadKey);
             }
 
@@ -333,7 +341,6 @@ public class FileUploader extends Service
             msg.obj = requestedUploads;
             mServiceHandler.sendMessage(msg);
         }
-        Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size());
         return Service.START_NOT_STICKY;
     }
 
@@ -386,23 +393,27 @@ public class FileUploader extends Service
         /**
          * Cancels a pending or current upload of a remote file.
          *
-         * @param account Owncloud account where the remote file will be stored.
-         * @param file A file in the queue of pending uploads
+         * @param account   ownCloud account where the remote file will be stored.
+         * @param file      A file in the queue of pending uploads
          */
         public void cancel(Account account, OCFile file) {
-            UploadFileOperation upload;
-            synchronized (mPendingUploads) {
-                upload = mPendingUploads.remove(buildRemoteName(account, file));
-            }
+            Pair<UploadFileOperation, String> removeResult = mPendingUploads.remove(account, file.getRemotePath());
+            UploadFileOperation upload = removeResult.first;
             if (upload != null) {
                 upload.cancel();
+            } else {
+                if (mCurrentUpload != null && mCurrentAccount != null &&
+                        mCurrentUpload.getRemotePath().startsWith(file.getRemotePath()) &&
+                        account.name.equals(mCurrentAccount.name)) {
+                    mCurrentUpload.cancel();
+                }
             }
         }
 
         /**
-         * Cancels a pending or current upload for an account
+         * Cancels all the uploads for an account
          *
-         * @param account Owncloud accountName where the remote file will be stored.
+         * @param account   ownCloud account.
          */
         public void cancel(Account account) {
             Log_OC.d(TAG, "Account= " + account.name);
@@ -414,13 +425,14 @@ public class FileUploader extends Service
                 }
             }
             // Cancel pending uploads
-            cancelUploadForAccount(account.name);
+            cancelUploadsForAccount(account);
         }
 
         public void clearListeners() {
             mBoundListeners.clear();
         }
 
+
         /**
          * Returns True when the file described by 'file' is being uploaded to
          * the ownCloud account 'account' or waiting for it
@@ -432,22 +444,8 @@ public class FileUploader extends Service
          * @param file      A file that could be in the queue of pending uploads
          */
         public boolean isUploading(Account account, OCFile file) {
-            if (account == null || file == null)
-                return false;
-            String targetKey = buildRemoteName(account, file);
-            synchronized (mPendingUploads) {
-                if (file.isFolder()) {
-                    // this can be slow if there are many uploads :(
-                    Iterator<String> it = mPendingUploads.keySet().iterator();
-                    boolean found = false;
-                    while (it.hasNext() && !found) {
-                        found = it.next().startsWith(targetKey);
-                    }
-                    return found;
-                } else {
-                    return (mPendingUploads.containsKey(targetKey));
-                }
-            }
+            if (account == null || file == null) return false;
+            return (mPendingUploads.contains(account, file.getRemotePath()));
         }
 
 
@@ -496,15 +494,19 @@ public class FileUploader extends Service
         }
 
         /**
-         * Review uploads and cancel it if its account doesn't exist
+         * Builds a key for the map of listeners.
+         *
+         * TODO remove and replace key with file.getFileId() after changing current policy (upload file, then
+         * add to local database) to better policy (add to local database, then upload)
+         *
+         * @param account       ownCloud account where the file to upload belongs.
+         * @param file          File to upload
+         * @return              Key
          */
-        public void checkAccountOfCurrentUpload() {
-            if (mCurrentUpload != null &&
-                    !AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) {
-                mCurrentUpload.cancel();
-            }
-            // The rest of uploads are cancelled when they try to start
+        private String buildRemoteName(Account account, OCFile file) {
+            return account.name + file.getRemotePath();
         }
+
     }
 
     /**
@@ -544,17 +546,13 @@ public class FileUploader extends Service
     /**
      * Core upload method: sends the file(s) to upload
      *
-     * @param uploadKey Key to access the upload to perform, contained in
-     *            mPendingUploads
+     * @param uploadKey Key to access the upload to perform, contained in mPendingUploads
      */
     public void uploadFile(String uploadKey) {
 
-        synchronized (mPendingUploads) {
-            mCurrentUpload = mPendingUploads.get(uploadKey);
-        }
+        mCurrentUpload = mPendingUploads.get(uploadKey);
 
         if (mCurrentUpload != null) {
-
             // Detect if the account exists
             if (AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) {
                 Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().name + " exists");
@@ -564,16 +562,20 @@ public class FileUploader extends Service
                 RemoteOperationResult uploadResult = null, grantResult;
 
                 try {
-                    /// prepare client object to send requests to the ownCloud server
-                    if (mUploadClient == null ||
-                            !mLastAccount.equals(mCurrentUpload.getAccount())) {
-                        mLastAccount = mCurrentUpload.getAccount();
-                        mStorageManager =
-                                new FileDataStorageManager(mLastAccount, getContentResolver());
-                        OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this);
-                        mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
-                                getClientFor(ocAccount, this);
-                    }
+                    /// prepare client object to send the request to the ownCloud server
+                    if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentUpload.getAccount())) {
+                        mCurrentAccount = mCurrentUpload.getAccount();
+                        mStorageManager = new FileDataStorageManager(
+                                mCurrentAccount,
+                                getContentResolver()
+                        );
+                    }   // else, reuse storage manager from previous operation
+
+                    // always get client from client manager, to get fresh credentials in case of update
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mCurrentAccount, this);
+                    mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, this);
+
 
                     /// check the existence of the parent folder for the file to upload
                     String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent();
@@ -588,43 +590,44 @@ public class FileUploader extends Service
                         uploadResult = mCurrentUpload.execute(mUploadClient);
                         if (uploadResult.isSuccess()) {
                             saveUploadedFile();
+
+                        } else if (uploadResult.getCode() == ResultCode.SYNC_CONFLICT) {
+                            mStorageManager.saveConflict(mCurrentUpload.getFile(),
+                                    mCurrentUpload.getFile().getEtagInConflict());
                         }
                     } else {
                         uploadResult = grantResult;
                     }
 
-                } catch (AccountsException e) {
-                    Log_OC.e(TAG, "Error while trying to get autorization for " +
-                            mLastAccount.name, e);
-                    uploadResult = new RemoteOperationResult(e);
-
-                } catch (IOException e) {
-                    Log_OC.e(TAG, "Error while trying to get autorization for " +
-                            mLastAccount.name, e);
+                } catch (Exception e) {
+                    Log_OC.e(TAG, "Error uploading", e);
                     uploadResult = new RemoteOperationResult(e);
 
                 } finally {
-                    synchronized (mPendingUploads) {
-                        mPendingUploads.remove(uploadKey);
-                        Log_OC.i(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
-                    }
-                    if (uploadResult != null && uploadResult.isException()) {
-                        // enforce the creation of a new client object for next uploads;
-                        // this grant that a new socket will be created in the future if
-                        // the current exception is due to an abrupt lose of network connection
-                        mUploadClient = null;
+                    Pair<UploadFileOperation, String> removeResult;
+                    if (mCurrentUpload.wasRenamed()) {
+                        removeResult = mPendingUploads.removePayload(
+                                mCurrentAccount,
+                                mCurrentUpload.getOldFile().getRemotePath()
+                        );
+                    } else {
+                        removeResult = mPendingUploads.removePayload(
+                                mCurrentAccount,
+                                mCurrentUpload.getRemotePath()
+                        );
                     }
-                }
 
-                /// notify result
-                notifyUploadResult(uploadResult, mCurrentUpload);
-                sendFinalBroadcast(mCurrentUpload, uploadResult);
+                    /// notify result
+                    notifyUploadResult(mCurrentUpload, uploadResult);
+
+                    sendBroadcastUploadFinished(mCurrentUpload, uploadResult, removeResult.second);
+                }
 
             } else {
                 // Cancel the transfer
                 Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().toString() +
                         " doesn't exist");
-                cancelUploadForAccount(mCurrentUpload.getAccount().name);
+                cancelUploadsForAccount(mCurrentUpload.getAccount());
 
             }
         }
@@ -691,7 +694,7 @@ public class FileUploader extends Service
      * synchronized with the server, specially the modification time and Etag
      * (where available)
      *
-     * TODO refactor this ugly thing
+     * TODO move into UploadFileOperation
      */
     private void saveUploadedFile() {
         OCFile file = mCurrentUpload.getFile();
@@ -709,6 +712,8 @@ public class FileUploader extends Service
         if (result.isSuccess()) {
             updateOCFile(file, (RemoteFile) result.getData().get(0));
             file.setLastSyncDateForProperties(syncDate);
+        } else {
+            Log_OC.e(TAG, "Error reading properties of file after successful upload; this is gonna hurt...");
         }
 
         // / maybe this would be better as part of UploadFileOperation... or
@@ -718,6 +723,7 @@ public class FileUploader extends Service
             if (oldFile.fileExists()) {
                 oldFile.setStoragePath(null);
                 mStorageManager.saveFile(oldFile);
+                mStorageManager.saveConflict(oldFile, null);
 
             } // else: it was just an automatic renaming due to a name
             // coincidence; nothing else is needed, the storagePath is right
@@ -725,7 +731,10 @@ public class FileUploader extends Service
         }
         file.setNeedsUpdateThumbnail(true);
         mStorageManager.saveFile(file);
+        mStorageManager.saveConflict(file, null);
+        
         mStorageManager.triggerMediaScan(file.getStoragePath());
+
     }
 
     private void updateOCFile(OCFile file, RemoteFile remoteFile) {
@@ -734,12 +743,11 @@ public class FileUploader extends Service
         file.setMimetype(remoteFile.getMimeType());
         file.setModificationTimestamp(remoteFile.getModifiedTimestamp());
         file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp());
-        // file.setEtag(remoteFile.getEtag());    // TODO Etag, where available
+        file.setEtag(remoteFile.getEtag());
         file.setRemoteId(remoteFile.getRemoteId());
     }
 
-    private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType,
-                                           FileDataStorageManager storageManager) {
+    private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType) {
 
         // MIME type
         if (mimeType == null || mimeType.length() <= 0) {
@@ -830,11 +838,11 @@ public class FileUploader extends Service
     /**
      * Updates the status notification with the result of an upload operation.
      *
-     * @param uploadResult Result of the upload operation.
-     * @param upload Finished upload operation
+     * @param uploadResult  Result of the upload operation.
+     * @param upload        Finished upload operation
      */
-    private void notifyUploadResult(
-            RemoteOperationResult uploadResult, UploadFileOperation upload) {
+    private void notifyUploadResult(UploadFileOperation upload,
+                                    RemoteOperationResult uploadResult) {
         Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode());
         // / cancelled operation or success -> silent removal of progress notification
         mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
@@ -941,10 +949,15 @@ public class FileUploader extends Service
      * Sends a broadcast in order to the interested activities can update their
      * view
      *
-     * @param upload Finished upload operation
-     * @param uploadResult Result of the upload operation
+     * @param upload                    Finished upload operation
+     * @param uploadResult              Result of the upload operation
+     * @param unlinkedFromRemotePath    Path in the uploads tree where the upload was unlinked from
      */
-    private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) {
+    private void sendBroadcastUploadFinished(
+            UploadFileOperation upload,
+            RemoteOperationResult uploadResult,
+            String unlinkedFromRemotePath) {
+
         Intent end = new Intent(getUploadFinishMessage());
         end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
         // path, after
@@ -957,6 +970,10 @@ public class FileUploader extends Service
         end.putExtra(EXTRA_OLD_FILE_PATH, upload.getOriginalStoragePath());
         end.putExtra(ACCOUNT_NAME, upload.getAccount().name);
         end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult.isSuccess());
+        if (unlinkedFromRemotePath != null) {
+            end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
+        }
+
         sendStickyBroadcast(end);
     }
 
@@ -966,6 +983,8 @@ public class FileUploader extends Service
      * @param localPath         Full path to a file in the local file system.
      * @param mimeType          MIME type of the file.
      * @return true if is needed to add the pdf file extension to the file
+     *
+     * TODO - move to OCFile or Utils class
      */
     private boolean isPdfFileFromContentProviderWithoutExtension(String localPath,
                                                                  String mimeType) {
@@ -976,20 +995,11 @@ public class FileUploader extends Service
 
     /**
      * Remove uploads of an account
-     * @param accountName       Name of an OC account
+     *
+     * @param account       Downloads account to remove
      */
-    private void cancelUploadForAccount(String accountName){
-        // this can be slow if there are many uploads :(
-        Iterator<String> it = mPendingUploads.keySet().iterator();
-        Log_OC.d(TAG, "Number of pending updloads= "  + mPendingUploads.size());
-        while (it.hasNext()) {
-            String key = it.next();
-            Log_OC.d(TAG, "mPendingUploads CANCELLED " + key);
-            if (key.startsWith(accountName)) {
-                synchronized (mPendingUploads) {
-                    mPendingUploads.remove(key);
-                }
-            }
-        }
+    private void cancelUploadsForAccount(Account account){
+        // Cancel pending uploads
+        mPendingUploads.remove(account);
     }
 }
index e53c635..d6fbfcc 100644 (file)
 package com.owncloud.android.media;
 
 import android.accounts.Account;
+import android.app.Activity;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.WifiLock;
 import android.os.IBinder;
 import android.os.PowerManager;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.NotificationCompat;
 import android.widget.Toast;
 
 import java.io.IOException;
 
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.accounts.AccountUtils;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
@@ -123,7 +129,6 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
 
     /** Notification to keep in the notification bar while a song is playing */
     private NotificationManager mNotificationManager;
-    private Notification mNotification = null;
 
     /** File being played */
     private OCFile mFile;
@@ -142,8 +147,9 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
 
     /** Control panel shown to the user to control the playback, to register through binding */
     private MediaControlView mMediaController;
-    
 
+    /** Notification builder to create notifications, new reuse way since Android 6 */
+    private NotificationCompat.Builder mNotificationBuilder;
     
     /**
      * Helper method to get an error message suitable to show to users for errors occurred in media playback,
@@ -210,6 +216,25 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
         return context.getString(messageId);
     }
 
+    public static AlertDialog.Builder streamWithExternalApp(final String uri, final Activity activity){
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setMessage(activity.getString(R.string.stream_expose_password))
+                .setPositiveButton(activity.getString(R.string.common_yes),
+                                   new DialogInterface.OnClickListener() {
+                                        public void onClick(DialogInterface dialog, int id) {
+                                            Intent i = new Intent(Intent.ACTION_VIEW);
+                                            i.setData(Uri.parse(uri));
+                                            activity.startActivity(i);
+                                        }
+                                    })
+                .setNegativeButton(activity.getString(R.string.common_no), new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int id) {
+                        // User cancelled the dialog
+                    }
+                });
+        return builder;
+    }
+
 
     
     /**
@@ -226,6 +251,8 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
                 createWifiLock(WifiManager.WIFI_MODE_FULL, MEDIA_WIFI_LOCK_TAG);
 
         mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+        mNotificationBuilder = new NotificationCompat.Builder(this);
+        mNotificationBuilder.setColor(this.getResources().getColor(R.color.primary));
         mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
         mBinder = new MediaServiceBinder(this);
     }
@@ -286,7 +313,6 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
             mState = State.PLAYING;
             setUpAsForeground(String.format(getString(R.string.media_state_playing), mFile.getFileName()));
             configAndStartMediaPlayer();
-            
         }
     }
 
@@ -430,12 +456,7 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
         releaseResources(false); // release everything except MediaPlayer
 
         try {
-            if (mFile == null) { 
-                Toast.makeText(this, R.string.media_err_nothing_to_play, Toast.LENGTH_LONG).show();
-                processStopRequest(true);
-                return;
-                
-            } else if (mAccount == null) {
+            if (mAccount == null) {
                 Toast.makeText(this, R.string.media_err_not_in_owncloud, Toast.LENGTH_LONG).show();
                 processStopRequest(true);
                 return;
@@ -444,12 +465,12 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
             createMediaPlayerIfNeeded();
             mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
             String url = mFile.getStoragePath();
-            /* Streaming is not possible right now
+
             if (url == null || url.length() <= 0) {
                 url = AccountUtils.constructFullURLForAccount(this, mAccount) + mFile.getRemotePath();
             }
             mIsStreaming = url.startsWith("http:") || url.startsWith("https:");
-            */
+
             mIsStreaming = false;
             
             mPlayer.setDataSource(url);
@@ -486,6 +507,8 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
             Log_OC.e(TAG, "IllegalArgumentException " + mAccount.name + mFile.getRemotePath(), e);
             Toast.makeText(this, String.format(getString(R.string.media_err_unexpected), mFile.getFileName()), Toast.LENGTH_LONG).show();
             processStopRequest(true);
+        } catch (AccountUtils.AccountNotFoundException e) {
+            e.printStackTrace();
         }
     }
 
@@ -532,22 +555,25 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
     /** 
      * Updates the status notification
      */
-    @SuppressWarnings("deprecation")
     private void updateNotification(String content) {
+        String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name));
+
         // TODO check if updating the Intent is really necessary
         Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class);
         showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, mFile);
         showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount);
         showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 
-                                                                (int)System.currentTimeMillis(), 
-                                                                showDetailsIntent, 
-                                                                PendingIntent.FLAG_UPDATE_CURRENT);
-        mNotification.when = System.currentTimeMillis();
-        //mNotification.contentView.setTextViewText(R.id.status_text, content);
-        String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name));
-        mNotification.setLatestEventInfo(getApplicationContext(), ticker, content, mNotification.contentIntent);
-        mNotificationManager.notify(R.string.media_notif_ticker, mNotification);
+
+        mNotificationBuilder.setContentIntent(PendingIntent.getActivity(getApplicationContext(),
+                (int) System.currentTimeMillis(),
+                showDetailsIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT));
+        mNotificationBuilder.setWhen(System.currentTimeMillis());
+        mNotificationBuilder.setTicker(ticker);
+        mNotificationBuilder.setContentTitle(ticker);
+        mNotificationBuilder.setContentText(content);
+
+        mNotificationManager.notify(R.string.media_notif_ticker, mNotificationBuilder.build());
     }
 
     
@@ -558,35 +584,29 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
      * 
      * A notification must be created to keep the user aware of the existance of the service.
      */
-    @SuppressWarnings("deprecation")
     private void setUpAsForeground(String content) {
+        String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name));
+
         /// creates status notification
         // TODO put a progress bar to follow the playback progress
-        mNotification = new Notification();
-        mNotification.icon = android.R.drawable.ic_media_play;
+        mNotificationBuilder.setSmallIcon(R.drawable.ic_play_arrow);
         //mNotification.tickerText = text;
-        mNotification.when = System.currentTimeMillis();
-        mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
-        //mNotification.contentView.setTextViewText(R.id.status_text, "ownCloud Music Player");     // NULL POINTER
-        //mNotification.contentView.setTextViewText(R.id.status_text, getString(R.string.downloader_download_in_progress_content));
-
+        mNotificationBuilder.setWhen(System.currentTimeMillis());
+        mNotificationBuilder.setOngoing(true);
         
         /// includes a pending intent in the notification showing the details view of the file
         Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class);
         showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, mFile);
         showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, mAccount);
         showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-        mNotification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 
-                                                                (int)System.currentTimeMillis(), 
-                                                                showDetailsIntent, 
-                                                                PendingIntent.FLAG_UPDATE_CURRENT);
-        
-        
-        //mNotificationManager.notify(R.string.downloader_download_in_progress_ticker, mNotification);
-        String ticker = String.format(getString(R.string.media_notif_ticker), getString(R.string.app_name));
-        mNotification.setLatestEventInfo(getApplicationContext(), ticker, content, mNotification.contentIntent);
-        startForeground(R.string.media_notif_ticker, mNotification);
-        
+        mNotificationBuilder.setContentIntent(PendingIntent.getActivity(getApplicationContext(),
+                (int) System.currentTimeMillis(),
+                showDetailsIntent,
+                PendingIntent.FLAG_UPDATE_CURRENT));
+        mNotificationBuilder.setContentTitle(ticker);
+        mNotificationBuilder.setContentText(content);
+
+        startForeground(R.string.media_notif_ticker, mNotificationBuilder.build());
     }
 
     /**
@@ -639,6 +659,7 @@ public class MediaService extends Service implements OnCompletionListener, OnPre
         mState = State.STOPPED;
         releaseResources(true);
         giveUpAudioFocus();
+        stopForeground(true);
         super.onDestroy();
     }
     
index c71b35f..5dd043f 100644 (file)
@@ -55,7 +55,8 @@ public class NotificationBuilderWithProgressBar extends NotificationCompat.Build
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
             return new NotificationBuilderWithProgressBar(context); 
         } else {
-            return new NotificationCompat.Builder(context);
+            return new NotificationCompat.Builder(context).
+                    setColor(context.getResources().getColor(R.color.primary));
         }
     }
     
index b020b92..0b3343c 100644 (file)
@@ -121,4 +121,8 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper
             Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database");
         }
     }
+
+    public String getRemotePath() {
+        return mRemotePath;
+    }
 }
diff --git a/src/com/owncloud/android/operations/CreateShareOperation.java b/src/com/owncloud/android/operations/CreateShareOperation.java
deleted file mode 100644 (file)
index a7270eb..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
- *   ownCloud Android client application
- *
- *   @author masensio
- *   Copyright (C) 2015 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.operations;
-
-/**
- * Creates a new share from a given file
- */
-
-import android.content.Context;
-import android.content.Intent;
-
-import com.owncloud.android.R;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.resources.shares.OCShare;
-import com.owncloud.android.lib.common.operations.RemoteOperation;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
-import com.owncloud.android.lib.resources.shares.ShareType;
-import com.owncloud.android.lib.resources.shares.CreateRemoteShareOperation;
-import com.owncloud.android.lib.resources.files.FileUtils;
-import com.owncloud.android.operations.common.SyncOperation;
-
-public class CreateShareOperation extends SyncOperation {
-
-    private static final String TAG = CreateShareOperation.class.getSimpleName();
-
-    protected FileDataStorageManager mStorageManager;
-
-    private Context mContext;
-    private String mPath;
-    private ShareType mShareType;
-    private String mShareWith;
-    private boolean mPublicUpload;
-    private String mPassword;
-    private int mPermissions;
-    private Intent mSendIntent;
-
-    /**
-     * Constructor
-     * @param context       The context that the share is coming from.
-     * @param path          Full path of the file/folder being shared. Mandatory argument
-     * @param shareType     0 = user, 1 = group, 3 = Public link. Mandatory argument
-     * @param shareWith     User/group ID with who the file should be shared.
-     *                      This is mandatory for shareType of 0 or 1
-     * @param publicUpload  If false (default) public cannot upload to a public shared folder. 
-     *                      If true public can upload to a shared folder.
-     *                      Only available for public link shares
-     * @param password      Password to protect a public link share.
-     *                      Only available for public link shares
-     * @param permissions   1 - Read only - Default for public shares
-     *                      2 - Update
-     *                      4 - Create
-     *                      8 - Delete
-     *                      16- Re-share
-     *                      31- All above - Default for private shares
-     *                      For user or group shares.
-     *                      To obtain combinations, add the desired values together.  
-     *                      For instance, for Re-Share, delete, read, update, add 16+8+2+1 = 27.
-     */
-    public CreateShareOperation(Context context, String path, ShareType shareType, String shareWith,
-                                boolean publicUpload, String password, int permissions,
-                                Intent sendIntent) {
-
-        mContext = context;
-        mPath = path;
-        mShareType = shareType;
-        mShareWith = shareWith;
-        mPublicUpload = publicUpload;
-        mPassword = password;
-        mPermissions = permissions;
-        mSendIntent = sendIntent;
-    }
-
-    @Override
-    protected RemoteOperationResult run(OwnCloudClient client) {
-        RemoteOperation operation = null;
-        
-        // Check if the share link already exists
-        operation = new GetRemoteSharesForFileOperation(mPath, false, false);
-        RemoteOperationResult result =
-                ((GetRemoteSharesForFileOperation)operation).execute(client);
-
-        if (!result.isSuccess() || result.getData().size() <= 0) {
-            operation = new CreateRemoteShareOperation(mPath, mShareType, mShareWith, mPublicUpload,
-                    mPassword, mPermissions);
-            result = ((CreateRemoteShareOperation)operation).execute(client);
-        }
-        
-        if (result.isSuccess()) {
-            if (result.getData().size() > 0) {
-                OCShare share = (OCShare) result.getData().get(0);
-                updateData(share);
-            } 
-        }
-        
-        return result;
-    }
-    
-    public String getPath() {
-        return mPath;
-    }
-
-    public ShareType getShareType() {
-        return mShareType;
-    }
-
-    public String getShareWith() {
-        return mShareWith;
-    }
-
-    public boolean getPublicUpload() {
-        return mPublicUpload;
-    }
-
-    public String getPassword() {
-        return mPassword;
-    }
-
-    public int getPermissions() {
-        return mPermissions;
-    }
-
-    public Intent getSendIntent() {
-        return mSendIntent;
-    }
-    
-    private void updateData(OCShare share) {
-        // Update DB with the response
-        share.setPath(mPath);
-        if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) {
-            share.setIsFolder(true);
-        } else {
-            share.setIsFolder(false);
-        }
-        share.setPermissions(mPermissions);
-        
-        getStorageManager().saveShare(share);
-        
-        // Update OCFile with data from share: ShareByLink  and publicLink
-        OCFile file = getStorageManager().getFileByPath(mPath);
-        if (file!=null) {
-            mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink());
-            if (getClient().getCredentials().getUsername() == null) {
-                //in saml is null
-                mSendIntent.putExtra(Intent.EXTRA_SUBJECT,
-                        String.format(mContext.getString(R.string.saml_subject_token),
-                                file.getFileName()));
-            } else {
-                mSendIntent.putExtra(Intent.EXTRA_SUBJECT,
-                        String.format(mContext.getString(R.string.subject_token),
-                                getClient().getCredentials().getUsername(), file.getFileName()));
-            }
-            file.setPublicLink(share.getShareLink());
-            file.setShareByLink(true);
-            getStorageManager().saveFile(file);
-            Log_OC.d(TAG, "Public Link = " + file.getPublicLink());
-
-        }
-    }
-
-}
diff --git a/src/com/owncloud/android/operations/CreateShareViaLinkOperation.java b/src/com/owncloud/android/operations/CreateShareViaLinkOperation.java
new file mode 100644 (file)
index 0000000..373c57d
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+/**
+ * Creates a new public share for a given file
+ */
+
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.files.FileUtils;
+import com.owncloud.android.lib.resources.shares.CreateRemoteShareOperation;
+import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.operations.common.SyncOperation;
+
+public class CreateShareViaLinkOperation extends SyncOperation {
+
+    protected FileDataStorageManager mStorageManager;
+
+    private String mPath;
+    private String mPassword;
+    private Intent mSendIntent;
+    private String mFileName;
+
+    /**
+     * Constructor
+     * @param path          Full path of the file/folder being shared. Mandatory argument
+     * @param password      Password to protect a public link share.
+     *                      Only available for public link shares
+     *  @param sendIntent   Optional Intent with the information of an app where the link to the new share (if public)
+     *                      should be posted later.
+     */
+    public CreateShareViaLinkOperation(
+            String path,
+            String password,
+            Intent sendIntent
+    ) {
+
+        mPath = path;
+        mPassword = password;
+        mSendIntent = sendIntent;
+        mFileName = null;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        // Check if the share link already exists
+        RemoteOperation operation = new GetRemoteSharesForFileOperation(mPath, false, false);
+        RemoteOperationResult result = operation.execute(client);
+        // TODO - fix this check; if the user already shared the file with users or group, a share via link will not be created
+
+        if (!result.isSuccess() || result.getData().size() <= 0) {
+            operation = new CreateRemoteShareOperation(
+                    mPath,
+                    ShareType.PUBLIC_LINK,
+                    "",
+                    false,
+                    mPassword,
+                    OCShare.DEFAULT_PERMISSION
+            );
+            result = operation.execute(client);
+        }
+        
+        if (result.isSuccess()) {
+            if (result.getData().size() > 0) {
+                OCShare share = (OCShare) result.getData().get(0);
+                updateData(share);
+            } 
+        }
+        
+        return result;
+    }
+    
+    public String getPath() {
+        return mPath;
+    }
+
+    public String getPassword() {
+        return mPassword;
+    }
+
+    public Intent getSendIntent() {
+        return mSendIntent;
+    }
+
+    public Intent getSendIntentWithSubject(Context context) {
+        if (context != null && mSendIntent != null && mSendIntent.getStringExtra(Intent.EXTRA_SUBJECT) != null) {
+            if (getClient() == null || getClient().getCredentials() == null ||
+                    getClient().getCredentials().getUsername() == null) {
+                mSendIntent.putExtra(
+                        Intent.EXTRA_SUBJECT,
+                        context.getString(R.string.subject_shared_with_you, mFileName)
+                );
+            } else {
+                mSendIntent.putExtra(
+                        Intent.EXTRA_SUBJECT,
+                        context.getString(
+                                R.string.subject_user_shared_with_you,
+                                getClient().getCredentials().getUsername(),
+                                mFileName
+                        )
+                );
+            }
+        }
+        return mSendIntent;
+    }
+
+    private void updateData(OCShare share) {
+        // Update DB with the response
+        share.setPath(mPath);
+        if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) {
+            share.setIsFolder(true);
+        } else {
+            share.setIsFolder(false);
+        }
+
+        getStorageManager().saveShare(share);
+        
+        // Update OCFile with data from share: ShareByLink  and publicLink
+        OCFile file = getStorageManager().getFileByPath(mPath);
+        if (file!=null) {
+            mSendIntent.putExtra(Intent.EXTRA_TEXT, share.getShareLink());
+            file.setPublicLink(share.getShareLink());
+            file.setShareViaLink(true);
+            getStorageManager().saveFile(file);
+        }
+    }
+
+}
diff --git a/src/com/owncloud/android/operations/CreateShareWithShareeOperation.java b/src/com/owncloud/android/operations/CreateShareWithShareeOperation.java
new file mode 100644 (file)
index 0000000..b19d6c2
--- /dev/null
@@ -0,0 +1,115 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+/**
+ * Creates a new private share for a given file
+ */
+
+
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.files.FileUtils;
+import com.owncloud.android.lib.resources.shares.CreateRemoteShareOperation;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.operations.common.SyncOperation;
+
+public class CreateShareWithShareeOperation extends SyncOperation {
+
+    protected FileDataStorageManager mStorageManager;
+
+    private String mPath;
+    private String mShareeName;
+    private ShareType mShareType;
+
+    /**
+     * Constructor.
+     *
+     * @param path          Full path of the file/folder being shared.
+     * @param shareeName    User or group name of the target sharee.
+     * @param shareType     Type of share determines type of sharee; {@link ShareType#USER} and {@link ShareType#GROUP}
+     *                      are the only valid values for the moment.
+     */
+    public CreateShareWithShareeOperation(String path, String shareeName, ShareType shareType) {
+        if (!ShareType.USER.equals(shareType) && !ShareType.GROUP.equals(shareType)) {
+            throw new IllegalArgumentException("Illegal share type " + shareType);
+        }
+        mPath = path;
+        mShareeName = shareeName;
+        mShareType = shareType;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        // Check if the share link already exists
+        // TODO or not
+        /*
+        RemoteOperation operation = new GetRemoteSharesForFileOperation(mPath, false, false);
+        RemoteOperationResult result = operation.execute(client);
+        if (!result.isSuccess() || result.getData().size() <= 0) {
+        */
+
+        CreateRemoteShareOperation operation = new CreateRemoteShareOperation(
+                mPath,
+                mShareType,
+                mShareeName,
+                false,
+                "",
+                OCShare.DEFAULT_PERMISSION
+        );
+        operation.setGetShareDetails(true);
+        RemoteOperationResult result = operation.execute(client);
+
+        
+        if (result.isSuccess()) {
+            if (result.getData().size() > 0) {
+                OCShare share = (OCShare) result.getData().get(0);
+                updateData(share);
+            } 
+        }
+        
+        return result;
+    }
+    
+    public String getPath() {
+        return mPath;
+    }
+
+    private void updateData(OCShare share) {
+        // Update DB with the response
+        share.setPath(mPath);
+        share.setIsFolder(mPath.endsWith(FileUtils.PATH_SEPARATOR));
+
+        getStorageManager().saveShare(share);
+        
+        // Update OCFile with data from share: ShareByLink  and publicLink
+        OCFile file = getStorageManager().getFileByPath(mPath);
+        if (file!=null) {
+            file.setShareWithSharee(true);    // TODO - this should be done by the FileContentProvider, as part of getStorageManager().saveShare(share)
+            getStorageManager().saveFile(file);
+        }
+    }
+
+}
index 0cb303c..dff8aef 100644 (file)
@@ -27,7 +27,6 @@ import java.util.Iterator;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -52,6 +51,7 @@ public class DownloadFileOperation extends RemoteOperation {
     private OCFile mFile;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private long mModificationTimestamp = 0;
+    private String mEtag = "";
     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
     
     private DownloadRemoteFileOperation mDownloadOperation;
@@ -127,11 +127,15 @@ public class DownloadFileOperation extends RemoteOperation {
                 mFile.getModificationTimestamp();
     }
 
+    public String getEtag() {
+        return mEtag;
+    }
+
     @Override
     protected RemoteOperationResult run(OwnCloudClient client) {
-        RemoteOperationResult result = null;
-        File newFile = null;
-        boolean moved = true;
+        RemoteOperationResult result;
+        File newFile;
+        boolean moved;
         
         /// download will be performed to a temporal file, then moved to the final location
         File tmpFile = new File(getTmpPath());
@@ -154,6 +158,7 @@ public class DownloadFileOperation extends RemoteOperation {
         
         if (result.isSuccess()) {
             mModificationTimestamp = mDownloadOperation.getModificationTimestamp();
+            mEtag = mDownloadOperation.getEtag();
             newFile = new File(getSavePath());
             newFile.getParentFile().mkdirs();
             moved = tmpFile.renameTo(newFile);
diff --git a/src/com/owncloud/android/operations/GetCapabilitiesOperarion.java b/src/com/owncloud/android/operations/GetCapabilitiesOperarion.java
new file mode 100644 (file)
index 0000000..0a63449
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.operations;
+
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.status.GetRemoteCapabilitiesOperation;
+import com.owncloud.android.lib.resources.status.OCCapability;
+import com.owncloud.android.operations.common.SyncOperation;
+
+/**
+ * Get and save capabilities from the server
+ */
+public class GetCapabilitiesOperarion extends SyncOperation {
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        GetRemoteCapabilitiesOperation getCapabilities = new GetRemoteCapabilitiesOperation();
+        RemoteOperationResult result = getCapabilities.execute(client);
+
+        if (result.isSuccess()){
+            // Read data from the result
+            if( result.getData()!= null && result.getData().size() > 0) {
+                OCCapability capability = (OCCapability) result.getData().get(0);
+
+                // Save the capabilities into database
+                getStorageManager().saveCapabilities(capability);
+            }
+        }
+
+        return result;
+    }
+
+}
index bf136ad..62c3be1 100644 (file)
 
 package com.owncloud.android.operations;
 
-import java.util.ArrayList;
-
-import com.owncloud.android.MainApp;
 import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
+import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.operations.common.SyncOperation;
 
+import java.util.ArrayList;
+
 /**
  * Provide a list shares for a specific file.
  */
diff --git a/src/com/owncloud/android/operations/GetSharesOperation.java b/src/com/owncloud/android/operations/GetSharesOperation.java
deleted file mode 100644 (file)
index 09a8e34..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- *   ownCloud Android client application
- *
- *   @author masensio
- *   @author David A. Velasco
- *   Copyright (C) 2015 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.operations;
-
-import java.util.ArrayList;
-
-import com.owncloud.android.MainApp;
-import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.shares.OCShare;
-import com.owncloud.android.lib.resources.shares.GetRemoteSharesOperation;
-import com.owncloud.android.operations.common.SyncOperation;
-
-/**
- * Access to remote operation to get the share files/folders
- * Save the data in Database
- */
-
-public class GetSharesOperation extends SyncOperation {
-
-    private static final String TAG = GetSharesOperation.class.getSimpleName();
-
-    @Override
-    protected RemoteOperationResult run(OwnCloudClient client) {
-        GetRemoteSharesOperation operation = new GetRemoteSharesOperation();
-        RemoteOperationResult result = operation.execute(client);
-
-        if (result.isSuccess()) {
-
-            // Update DB with the response
-            Log_OC.d(TAG, "Share list size = " + result.getData().size());
-            ArrayList<OCShare> shares = new ArrayList<OCShare>();
-            for(Object obj: result.getData()) {
-                shares.add((OCShare) obj);
-            }
-
-            getStorageManager().saveSharesDB(shares);
-        }
-
-        return result;
-    }
-
-}
index dade4d9..87dde21 100644 (file)
 
 package com.owncloud.android.operations;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
-import org.apache.http.HttpStatus;
 import android.accounts.Account;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
-//import android.support.v4.content.LocalBroadcastManager;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 
@@ -50,7 +41,6 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
-import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
 import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
 import com.owncloud.android.lib.resources.files.RemoteFile;
@@ -120,7 +110,10 @@ public class RefreshFolderOperation extends RemoteOperation {
     /** 'True' means that Etag will be ignored */
     private boolean mIgnoreETag;
 
-    
+    private List<SynchronizeFileOperation> mFilesToSyncContents;
+    // this will be used for every file when 'folder synchronization' replaces 'folder download'
+
+
     /**
      * Creates a new instance of {@link RefreshFolderOperation}.
      * 
@@ -154,6 +147,7 @@ public class RefreshFolderOperation extends RemoteOperation {
         mForgottenLocalFiles = new HashMap<String, String>();
         mRemoteFolderChanged = false;
         mIgnoreETag = ignoreETag;
+        mFilesToSyncContents = new Vector<SynchronizeFileOperation>();
     }
     
     
@@ -191,8 +185,9 @@ public class RefreshFolderOperation extends RemoteOperation {
         mConflictsFound = 0;
         mForgottenLocalFiles.clear();
         
-        if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
+        if (OCFile.ROOT_PATH.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
             updateOCVersion(client);
+
         }
         
         result = checkForChanges(client);
@@ -201,8 +196,14 @@ public class RefreshFolderOperation extends RemoteOperation {
             if (mRemoteFolderChanged) {
                 result = fetchAndSyncRemoteFolder(client);
             } else {
+                fetchFavoritesToSyncFromLocalData();
                 mChildren = mStorageManager.getFolderContent(mLocalFolder, false);
             }
+
+            if (result.isSuccess()) {
+                // request for the synchronization of KEPT-IN-SYNC file contents
+                startContentSynchronizations(mFilesToSyncContents, client);
+            }
         }
         
         if (!mSyncFullAccount) {            
@@ -231,16 +232,29 @@ public class RefreshFolderOperation extends RemoteOperation {
         RemoteOperationResult result = update.execute(client);
         if (result.isSuccess()) {
             mIsShareSupported = update.getOCVersion().isSharedSupported();
+
+            // Update Capabilities for this account
+            if (update.getOCVersion().isVersionWithCapabilitiesAPI()) {
+                updateCapabilities(client);
+            } else {
+                Log_OC.d(TAG, "Capabilities API disabled");
+            }
+        }
+    }
+
+    private void updateCapabilities(OwnCloudClient client){
+        GetCapabilitiesOperarion getCapabilities = new GetCapabilitiesOperarion();
+        RemoteOperationResult  result = getCapabilities.execute(mStorageManager,mContext);
+        if (!result.isSuccess()){
+            Log_OC.d(TAG, "Update Capabilities unsuccessfully");
         }
     }
 
-    
     private RemoteOperationResult checkForChanges(OwnCloudClient client) {
         mRemoteFolderChanged = true;
         RemoteOperationResult result = null;
-        String remotePath = null;
+        String remotePath = mLocalFolder.getRemotePath();
 
-        remotePath = mLocalFolder.getRemotePath();
         Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
         
         // remote request 
@@ -263,7 +277,7 @@ public class RefreshFolderOperation extends RemoteOperation {
 
             result = new RemoteOperationResult(ResultCode.OK);
         
-            Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + 
+            Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " +
                     (mRemoteFolderChanged ? "changed" : "not changed"));
             
         } else {
@@ -336,15 +350,15 @@ public class RefreshFolderOperation extends RemoteOperation {
         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
 
         // parse data from remote folder 
-        OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
+        OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
         remoteFolder.setFileId(mLocalFolder.getFileId());
         
-        Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() 
+        Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath()
                 + " changed - starting update of local data ");
         
         List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
-        List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
+        mFilesToSyncContents.clear();
 
         // get current data about local contents of the folder to synchronize
         List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder, false);
@@ -354,54 +368,56 @@ public class RefreshFolderOperation extends RemoteOperation {
         }
         
         // loop to update every child
-        OCFile remoteFile = null, localFile = null;
+        OCFile remoteFile = null, localFile = null, updatedFile = null;
+        RemoteFile r;
         for (int i=1; i<folderAndFiles.size(); i++) {
             /// new OCFile instance with the data from the server
-            remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
-            remoteFile.setParentId(mLocalFolder.getFileId());
+            r = (RemoteFile) folderAndFiles.get(i);
+            remoteFile = FileStorageUtils.fillOCFile(r);
+
+            /// new OCFile instance to merge fresh data from server with local state
+            updatedFile = FileStorageUtils.fillOCFile(r);
+            updatedFile.setParentId(mLocalFolder.getFileId());
 
             /// retrieve local data for the read file 
             //  localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
             localFile = localFilesMap.remove(remoteFile.getRemotePath());
             
-            /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
-            remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
+            /// add to updatedFile data about LOCAL STATE (not existing in server)
+            updatedFile.setLastSyncDateForProperties(mCurrentSyncTime);
             if (localFile != null) {
-                // some properties of local state are kept unmodified
-                remoteFile.setFileId(localFile.getFileId());
-                remoteFile.setFavorite(localFile.isFavorite());
-                remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
-                remoteFile.setModificationTimestampAtLastSyncForData(
+                updatedFile.setFileId(localFile.getFileId());
+                updatedFile.setFavorite(localFile.isFavorite());
+                updatedFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
+                updatedFile.setModificationTimestampAtLastSyncForData(
                         localFile.getModificationTimestampAtLastSyncForData()
                 );
-                remoteFile.setStoragePath(localFile.getStoragePath());
-                // eTag will not be updated unless contents are synchronized 
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag(localFile.getEtag());    
-                if (remoteFile.isFolder()) {
-                    remoteFile.setFileLength(localFile.getFileLength()); 
+                updatedFile.setStoragePath(localFile.getStoragePath());
+                // eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag(localFile.getEtag());
+                if (updatedFile.isFolder()) {
+                    updatedFile.setFileLength(localFile.getFileLength());
                         // TODO move operations about size of folders to FileContentProvider
                 } else if (mRemoteFolderChanged && remoteFile.isImage() &&
                         remoteFile.getModificationTimestamp() !=
                                 localFile.getModificationTimestamp()) {
-                    remoteFile.setNeedsUpdateThumbnail(true);
+                    updatedFile.setNeedsUpdateThumbnail(true);
                     Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
                 }
-                remoteFile.setPublicLink(localFile.getPublicLink());
-                remoteFile.setShareByLink(localFile.isShareByLink());
+                updatedFile.setPublicLink(localFile.getPublicLink());
+                updatedFile.setShareViaLink(localFile.isSharedViaLink());
+                updatedFile.setShareWithSharee(localFile.isSharedWithSharee());
+                updatedFile.setEtagInConflict(localFile.getEtagInConflict());
             } else {
-                // remote eTag will not be updated unless contents are synchronized 
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag(""); 
+                // remote eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag("");
             }
 
             /// check and fix, if needed, local storage path
-            checkAndFixForeignStoragePath(remoteFile);      // policy - local files are COPIED 
-                                                            // into the ownCloud local folder;
-            searchForLocalFileInDefaultPath(remoteFile);    // legacy   
+            FileStorageUtils.searchForLocalFileInDefaultPath(updatedFile, mAccount);
 
             /// prepare content synchronization for kept-in-sync files
-            if (remoteFile.isFavorite()) {
+            if (updatedFile.isFavorite()) {
                 SynchronizeFileOperation operation = new SynchronizeFileOperation(  localFile,        
                                                                                     remoteFile, 
                                                                                     mAccount, 
@@ -409,18 +425,15 @@ public class RefreshFolderOperation extends RemoteOperation {
                                                                                     mContext
                                                                                     );
                 
-                filesToSyncContents.add(operation);
+                mFilesToSyncContents.add(operation);
             }
-            
-            updatedFiles.add(remoteFile);
+
+            updatedFiles.add(updatedFile);
         }
 
         // save updated contents in local database
         mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
 
-        // request for the synchronization of file contents AFTER saving current remote properties
-        startContentSynchronizations(filesToSyncContents, client);
-
         mChildren = updatedFiles;
     }
 
@@ -458,103 +471,19 @@ public class RefreshFolderOperation extends RemoteOperation {
     }
 
 
-    public boolean isMultiStatus(int status) {
-        return (status == HttpStatus.SC_MULTI_STATUS); 
-    }
-
     /**
-     * Creates and populates a new {@link OCFile} object with the data read from the server.
-     * 
-     * @param remote    remote file read from the server (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
+     * Syncs the Share resources for the files contained in the folder refreshed (children, not deeper descendants).
+     *
+     * @param client    Handler of a session with an OC server.
+     * @return          The result of the remote operation retrieving the Share resources in the folder refreshed by
+     *                  the operation.
      */
-    private OCFile fillOCFile(RemoteFile remote) {
-        OCFile file = new OCFile(remote.getRemotePath());
-        file.setCreationTimestamp(remote.getCreationTimestamp());
-        file.setFileLength(remote.getLength());
-        file.setMimetype(remote.getMimeType());
-        file.setModificationTimestamp(remote.getModifiedTimestamp());
-        file.setEtag(remote.getEtag());
-        file.setPermissions(remote.getPermissions());
-        file.setRemoteId(remote.getRemoteId());
-        return file;
-    }
-    
-
-    /**
-     * Checks the storage path of the OCFile received as parameter. 
-     * If it's out of the local ownCloud folder, tries to copy the file inside it. 
-     * 
-     * If the copy fails, the link to the local file is nullified. The account of forgotten 
-     * files is kept in {@link #mForgottenLocalFiles}
-     *) 
-     * @param file      File to check and fix.
-     */
-    private void checkAndFixForeignStoragePath(OCFile file) {
-        String storagePath = file.getStoragePath();
-        String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
-        if (storagePath != null && !storagePath.equals(expectedPath)) {
-            /// fix storagePaths out of the local ownCloud folder
-            File originalFile = new File(storagePath);
-            if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
-                mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
-                file.setStoragePath(null);
-                    
-            } else {
-                InputStream in = null;
-                OutputStream out = null;
-                try {
-                    File expectedFile = new File(expectedPath);
-                    File expectedParent = expectedFile.getParentFile();
-                    expectedParent.mkdirs();
-                    if (!expectedParent.isDirectory()) {
-                        throw new IOException(
-                                "Unexpected error: parent directory could not be created"
-                        );
-                    }
-                    expectedFile.createNewFile();
-                    if (!expectedFile.isFile()) {
-                        throw new IOException("Unexpected error: target file could not be created");
-                    }                    
-                    in = new FileInputStream(originalFile);
-                    out = new FileOutputStream(expectedFile);
-                    byte[] buf = new byte[1024];
-                    int len;
-                    while ((len = in.read(buf)) > 0){
-                        out.write(buf, 0, len);
-                    }
-                    file.setStoragePath(expectedPath);
-                    
-                } catch (Exception e) {
-                    Log_OC.e(TAG, "Exception while copying foreign file " + expectedPath, e);
-                    mForgottenLocalFiles.put(file.getRemotePath(), storagePath);
-                    file.setStoragePath(null);
-                    
-                } finally {
-                    try {
-                        if (in != null) in.close();
-                    } catch (Exception e) {
-                        Log_OC.d(TAG, "Weird exception while closing input stream for " 
-                                + storagePath + " (ignoring)", e);
-                    }
-                    try {
-                        if (out != null) out.close();
-                    } catch (Exception e) {
-                        Log_OC.d(TAG, "Weird exception while closing output stream for " 
-                                + expectedPath + " (ignoring)", e);
-                    }
-                }
-            }
-        }
-    }
-    
-    
     private RemoteOperationResult refreshSharesForFolder(OwnCloudClient client) {
         RemoteOperationResult result = null;
         
         // remote request 
         GetRemoteSharesForFileOperation operation = 
-                new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), false, true);
+                new GetRemoteSharesForFileOperation(mLocalFolder.getRemotePath(), true, true);
         result = operation.execute(client);
         
         if (result.isSuccess()) {
@@ -571,24 +500,6 @@ public class RefreshFolderOperation extends RemoteOperation {
     
 
     /**
-     * Scans the default location for saving local copies of files searching for
-     * a 'lost' file with the same full name as the {@link OCFile} received as 
-     * parameter.
-     *  
-     * @param file      File to associate a possible 'lost' local file.
-     */
-    private void searchForLocalFileInDefaultPath(OCFile file) {
-        if (file.getStoragePath() == null && !file.isFolder()) {
-            File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
-            if (f.exists()) {
-                file.setStoragePath(f.getAbsolutePath());
-                file.setLastSyncDateForData(f.lastModified());
-            }
-        }
-    }
-
-    
-    /**
      * Sends a message to any application component interested in the progress 
      * of the synchronization.
      * 
@@ -612,8 +523,20 @@ public class RefreshFolderOperation extends RemoteOperation {
     }
 
 
-    public boolean getRemoteFolderChanged() {
-        return mRemoteFolderChanged;
+    private void fetchFavoritesToSyncFromLocalData() {
+        List<OCFile> children = mStorageManager.getFolderContent(mLocalFolder, false);
+        for (OCFile child : children) {
+            if (!child.isFolder() && child.isFavorite()) {
+                SynchronizeFileOperation operation = new SynchronizeFileOperation(
+                        child,
+                        child,  // cheating with the remote file to get an update to server; to refactor
+                        mAccount,
+                        true,
+                        mContext
+                );
+                mFilesToSyncContents.add(operation);
+            }
+        }
     }
 
 }
index f94adb1..bc0caf1 100644 (file)
@@ -22,7 +22,6 @@
 
 package com.owncloud.android.operations;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
@@ -208,15 +207,13 @@ public class SynchronizeFileOperation extends SyncOperation {
 
                 /// check changes in server and local file
                 boolean serverChanged = false;
-                /* time for eTag is coming, but not yet
-                    if (mServerFile.getEtag() != null) {
-                        serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));
-                    } else { */
-                serverChanged = (
-                    mServerFile.getModificationTimestamp() !=
-                            mLocalFile.getModificationTimestampAtLastSyncForData()
-                );
-                //}
+                if (mLocalFile.getEtag() == null || mLocalFile.getEtag().length() == 0) {
+                    // file uploaded (null) or downloaded ("") before upgrade to version 1.8.0; check the old condition
+                    serverChanged = mServerFile.getModificationTimestamp() !=
+                            mLocalFile.getModificationTimestampAtLastSyncForData();
+                } else {
+                    serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));
+                }
                 boolean localChanged = (
                     mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData()
                 );
@@ -225,6 +222,7 @@ public class SynchronizeFileOperation extends SyncOperation {
                 //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) {
                 if (localChanged && serverChanged) {
                     result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
+                    getStorageManager().saveConflict(mLocalFile, mServerFile.getEtag());
 
                 } else if (localChanged) {
                     if (mSyncFileContents && mAllowUploads) {
@@ -254,6 +252,7 @@ public class SynchronizeFileOperation extends SyncOperation {
                         mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData());
                         mServerFile.setStoragePath(mLocalFile.getStoragePath());
                         mServerFile.setParentId(mLocalFile.getParentId());
+                        mServerFile.setEtag(mLocalFile.getEtag());
                         getStorageManager().saveFile(mServerFile);
 
                     }
@@ -264,7 +263,11 @@ public class SynchronizeFileOperation extends SyncOperation {
                     result = new RemoteOperationResult(ResultCode.OK);
                 }
 
-            } 
+                // safe blanket: sync'ing a not in-conflict file will clean wrong conflict markers in ancestors
+                if (result.getCode() != ResultCode.SYNC_CONFLICT) {
+                    getStorageManager().saveConflict(mLocalFile, null);
+                }
+            }
 
         }
 
index d2d6c37..227e2b2 100644 (file)
@@ -60,7 +60,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
  *  Fetches the list and properties of the files contained in the given folder, including their 
  *  properties, and updates the local database with them.
  *  
- *  Does NOT enter in the child folders to synchronize their contents also.
+ *  Does NOT enter in the child folders to synchronize their contents also, BUT requests for a new operation instance
+ *  doing so.
  */
 public class SynchronizeFolderOperation extends SyncOperation {
 
@@ -96,10 +97,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
     private List<OCFile> mFilesForDirectDownload;
         // to avoid extra PROPFINDs when there was no change in the folder
     
-    private List<SyncOperation> mFilesToSyncContentsWithoutUpload;
-        // this will go out when 'folder synchronization' replaces 'folder download'; step by step  
-
-    private List<SyncOperation> mFavouriteFilesToSyncContents;
+    private List<SyncOperation> mFilesToSyncContents;
         // this will be used for every file when 'folder synchronization' replaces 'folder download' 
 
     private final AtomicBoolean mCancellationRequested;
@@ -120,8 +118,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
         mContext = context;
         mRemoteFolderChanged = false;
         mFilesForDirectDownload = new Vector<OCFile>();
-        mFilesToSyncContentsWithoutUpload = new Vector<SyncOperation>();
-        mFavouriteFilesToSyncContents = new Vector<SyncOperation>();
+        mFilesToSyncContents = new Vector<SyncOperation>();
         mCancellationRequested = new AtomicBoolean(false);
     }
 
@@ -281,7 +278,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
         FileDataStorageManager storageManager = getStorageManager();
         
         // parse data from remote folder
-        OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
+        OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
         remoteFolder.setFileId(mLocalFolder.getFileId());
 
@@ -290,8 +287,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
 
         List<OCFile> updatedFiles = new Vector<OCFile>(folderAndFiles.size() - 1);
         mFilesForDirectDownload.clear();
-        mFilesToSyncContentsWithoutUpload.clear();
-        mFavouriteFilesToSyncContents.clear();
+        mFilesToSyncContents.clear();
 
         if (mCancellationRequested.get()) {
             throw new OperationCancelledException();
@@ -305,85 +301,78 @@ public class SynchronizeFolderOperation extends SyncOperation {
         }
 
         // loop to synchronize every child
-        OCFile remoteFile = null, localFile = null;
+        OCFile remoteFile = null, localFile = null, updatedFile = null;
+        RemoteFile r;
         for (int i=1; i<folderAndFiles.size(); i++) {
             /// new OCFile instance with the data from the server
-            remoteFile = fillOCFile((RemoteFile)folderAndFiles.get(i));
-            remoteFile.setParentId(mLocalFolder.getFileId());
+            r = (RemoteFile) folderAndFiles.get(i);
+            remoteFile = FileStorageUtils.fillOCFile(r);
+
+            /// new OCFile instance to merge fresh data from server with local state
+            updatedFile = FileStorageUtils.fillOCFile(r);
+            updatedFile.setParentId(mLocalFolder.getFileId());
 
             /// retrieve local data for the read file
             //  localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
             localFile = localFilesMap.remove(remoteFile.getRemotePath());
 
-            /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in server)
-            remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
+            /// add to updatedFile data about LOCAL STATE (not existing in server)
+            updatedFile.setLastSyncDateForProperties(mCurrentSyncTime);
             if (localFile != null) {
-                // some properties of local state are kept unmodified
-                remoteFile.setFileId(localFile.getFileId());
-                remoteFile.setFavorite(localFile.isFavorite());
-                remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
-                remoteFile.setModificationTimestampAtLastSyncForData(
+                updatedFile.setFileId(localFile.getFileId());
+                updatedFile.setFavorite(localFile.isFavorite());
+                updatedFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
+                updatedFile.setModificationTimestampAtLastSyncForData(
                         localFile.getModificationTimestampAtLastSyncForData()
                 );
-                remoteFile.setStoragePath(localFile.getStoragePath());
-                // eTag will not be updated unless contents are synchronized
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag(localFile.getEtag());
-                if (remoteFile.isFolder()) {
-                    remoteFile.setFileLength(localFile.getFileLength());
+                updatedFile.setStoragePath(localFile.getStoragePath());
+                // eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag(localFile.getEtag());
+                if (updatedFile.isFolder()) {
+                    updatedFile.setFileLength(localFile.getFileLength());
                         // TODO move operations about size of folders to FileContentProvider
                 } else if (mRemoteFolderChanged && remoteFile.isImage() &&
                         remoteFile.getModificationTimestamp() !=
                                 localFile.getModificationTimestamp()) {
-                    remoteFile.setNeedsUpdateThumbnail(true);
+                    updatedFile.setNeedsUpdateThumbnail(true);
                     Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
                 }
-                remoteFile.setPublicLink(localFile.getPublicLink());
-                remoteFile.setShareByLink(localFile.isShareByLink());
+                updatedFile.setPublicLink(localFile.getPublicLink());
+                updatedFile.setShareViaLink(localFile.isSharedViaLink());
+                updatedFile.setShareWithSharee(localFile.isSharedWithSharee());
+                updatedFile.setEtagInConflict(localFile.getEtagInConflict());
             } else {
-                // remote eTag will not be updated unless contents are synchronized
-                //  (Synchronize[File|Folder]Operation with remoteFile as parameter)
-                remoteFile.setEtag("");
+                // remote eTag will not be updated unless file CONTENTS are synchronized
+                updatedFile.setEtag("");
             }
 
             /// check and fix, if needed, local storage path
-            searchForLocalFileInDefaultPath(remoteFile);
+            searchForLocalFileInDefaultPath(updatedFile);
             
             /// classify file to sync/download contents later
             if (remoteFile.isFolder()) {
                 /// to download children files recursively
-                synchronized(mCancellationRequested) {
+                synchronized (mCancellationRequested) {
                     if (mCancellationRequested.get()) {
                         throw new OperationCancelledException();
                     }
                     startSyncFolderOperation(remoteFile.getRemotePath());
                 }
 
-            } else if (remoteFile.isFavorite()) {
-                /// prepare content synchronization for kept-in-sync files
-                SynchronizeFileOperation operation = new SynchronizeFileOperation(
-                        localFile,
-                        remoteFile,
-                        mAccount,
-                        true,
-                        mContext
-                    );
-                mFavouriteFilesToSyncContents.add(operation);
-                
             } else {
-                /// prepare limited synchronization for regular files
+                /// prepare content synchronization for files (any file, not just favorites)
                 SynchronizeFileOperation operation = new SynchronizeFileOperation(
                         localFile,
                         remoteFile,
                         mAccount,
                         true,
-                        false,
                         mContext
                     );
-                mFilesToSyncContentsWithoutUpload.add(operation);
+                mFilesToSyncContents.add(operation);
+                
             }
 
-            updatedFiles.add(remoteFile);
+            updatedFiles.add(updatedFile);
         }
 
         // save updated contents in local database
@@ -406,10 +395,23 @@ public class SynchronizeFolderOperation extends SyncOperation {
                 }
 
             } else {
-                /// prepare limited synchronization for regular files
+                /// synchronization for regular files
                 if (!child.isDown()) {
                     mFilesForDirectDownload.add(child);
+
+                } else {
+                    /// this should result in direct upload of files that were locally modified
+                    SynchronizeFileOperation operation = new SynchronizeFileOperation(
+                            child,
+                            (child.getEtagInConflict() != null ? child : null),
+                            mAccount,
+                            true,
+                            mContext
+                    );
+                    mFilesToSyncContents.add(operation);
+
                 }
+
             }
         }
     }
@@ -417,8 +419,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
 
     private void syncContents(OwnCloudClient client) throws OperationCancelledException {
         startDirectDownloads();
-        startContentSynchronizations(mFilesToSyncContentsWithoutUpload, client);
-        startContentSynchronizations(mFavouriteFilesToSyncContents, client);
+        startContentSynchronizations(mFilesToSyncContents, client);
     }
 
     
@@ -477,26 +478,6 @@ public class SynchronizeFolderOperation extends SyncOperation {
 
     
     /**
-     * Creates and populates a new {@link com.owncloud.android.datamodel.OCFile}
-     * object with the data read from the server.
-     *
-     * @param remote    remote file read from the server (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
-     */
-    private OCFile fillOCFile(RemoteFile remote) {
-        OCFile file = new OCFile(remote.getRemotePath());
-        file.setCreationTimestamp(remote.getCreationTimestamp());
-        file.setFileLength(remote.getLength());
-        file.setMimetype(remote.getMimeType());
-        file.setModificationTimestamp(remote.getModifiedTimestamp());
-        file.setEtag(remote.getEtag());
-        file.setPermissions(remote.getPermissions());
-        file.setRemoteId(remote.getRemoteId());
-        return file;
-    }
-
-
-    /**
      * Scans the default location for saving local copies of files searching for
      * a 'lost' file with the same full name as the {@link com.owncloud.android.datamodel.OCFile}
      * received as parameter.
diff --git a/src/com/owncloud/android/operations/UnshareLinkOperation.java b/src/com/owncloud/android/operations/UnshareLinkOperation.java
deleted file mode 100644 (file)
index 1b66226..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- *   ownCloud Android client application
- *
- *   @author masensio
- *   Copyright (C) 2015 ownCloud Inc.
- *
- *   This program is free software: you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License version 2,
- *   as published by the Free Software Foundation.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-package com.owncloud.android.operations;
-
-import android.content.Context;
-
-import com.owncloud.android.MainApp;
-import com.owncloud.android.datamodel.OCFile;
-
-import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
-import com.owncloud.android.lib.resources.shares.OCShare;
-import com.owncloud.android.lib.resources.shares.RemoveRemoteShareOperation;
-import com.owncloud.android.lib.resources.shares.ShareType;
-
-import com.owncloud.android.operations.common.SyncOperation;
-
-/**
- * Unshare file/folder
- * Save the data in Database
- */
-public class UnshareLinkOperation extends SyncOperation {
-
-    private static final String TAG = UnshareLinkOperation.class.getSimpleName();
-    
-    private String mRemotePath;
-    private Context mContext;
-    
-    
-    public UnshareLinkOperation(String remotePath, Context context) {
-        mRemotePath = remotePath;
-        mContext = context;
-    }
-
-    @Override
-    protected RemoteOperationResult run(OwnCloudClient client) {
-        RemoteOperationResult result  = null;
-        
-        // Get Share for a file
-        OCShare share = getStorageManager().getFirstShareByPathAndType(mRemotePath,
-                ShareType.PUBLIC_LINK);
-        
-        if (share != null) {
-            RemoveRemoteShareOperation operation =
-                    new RemoveRemoteShareOperation((int) share.getIdRemoteShared());
-            result = operation.execute(client);
-
-            if (result.isSuccess() || result.getCode() == ResultCode.SHARE_NOT_FOUND) {
-                Log_OC.d(TAG, "Share id = " + share.getIdRemoteShared() + " deleted");
-
-                OCFile file = getStorageManager().getFileByPath(mRemotePath);
-                file.setShareByLink(false);
-                file.setPublicLink("");
-                getStorageManager().saveFile(file);
-                getStorageManager().removeShare(share);
-                
-                if (result.getCode() == ResultCode.SHARE_NOT_FOUND) {
-                    if (existsFile(client, file.getRemotePath())) {
-                        result = new RemoteOperationResult(ResultCode.OK);
-                    } else {
-                        getStorageManager().removeFile(file, true, true);
-                    }
-                }
-            } 
-                
-        } else {
-            result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND);
-        }
-
-        return result;
-    }
-    
-    private boolean existsFile(OwnCloudClient client, String remotePath){
-        ExistenceCheckRemoteOperation existsOperation =
-                new ExistenceCheckRemoteOperation(remotePath, mContext, false);
-        RemoteOperationResult result = existsOperation.execute(client);
-        return result.isSuccess();
-    }
-
-}
diff --git a/src/com/owncloud/android/operations/UnshareOperation.java b/src/com/owncloud/android/operations/UnshareOperation.java
new file mode 100644 (file)
index 0000000..4167831
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.operations;
+
+import android.content.Context;
+
+import com.owncloud.android.datamodel.OCFile;
+
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.RemoveRemoteShareOperation;
+import com.owncloud.android.lib.resources.shares.ShareType;
+
+import com.owncloud.android.operations.common.SyncOperation;
+
+import java.util.ArrayList;
+
+/**
+ * Unshare file/folder
+ * Save the data in Database
+ */
+public class UnshareOperation extends SyncOperation {
+
+    private static final String TAG = UnshareOperation.class.getSimpleName();
+    
+    private String mRemotePath;
+    private ShareType mShareType;
+    private String mShareWith;
+    private Context mContext;
+    
+    public UnshareOperation(String remotePath, ShareType shareType, String shareWith,
+                                Context context) {
+        mRemotePath = remotePath;
+        mShareType = shareType;
+        mShareWith = shareWith;
+        mContext = context;
+    }
+
+    @Override
+    protected RemoteOperationResult run(OwnCloudClient client) {
+        RemoteOperationResult result  = null;
+        
+        // Get Share for a file
+        OCShare share = getStorageManager().getFirstShareByPathAndType(mRemotePath,
+                mShareType, mShareWith);
+        
+        if (share != null) {
+            OCFile file = getStorageManager().getFileByPath(mRemotePath);
+            RemoveRemoteShareOperation operation =
+                    new RemoveRemoteShareOperation((int) share.getIdRemoteShared());
+            result = operation.execute(client);
+
+            if (result.isSuccess()) {
+                Log_OC.d(TAG, "Share id = " + share.getIdRemoteShared() + " deleted");
+
+                if (mShareType == ShareType.PUBLIC_LINK) {
+                    file.setShareViaLink(false);
+                    file.setPublicLink("");
+                } else if (mShareType == ShareType.USER || mShareType == ShareType.GROUP){
+                    // Check if it is the last share
+                    ArrayList <OCShare> sharesWith = getStorageManager().
+                            getSharesWithForAFile(mRemotePath,
+                            getStorageManager().getAccount().name);
+                    if (sharesWith.size() == 1) {
+                        file.setShareWithSharee(false);
+                    }
+                }
+
+                getStorageManager().saveFile(file);
+                getStorageManager().removeShare(share);
+                
+            } else if (!existsFile(client, file.getRemotePath())) {
+                // unshare failed because file was deleted before
+                getStorageManager().removeFile(file, true, true);
+            }
+
+        } else {
+            result = new RemoteOperationResult(ResultCode.SHARE_NOT_FOUND);
+        }
+
+        return result;
+    }
+    
+    private boolean existsFile(OwnCloudClient client, String remotePath){
+        ExistenceCheckRemoteOperation existsOperation =
+                new ExistenceCheckRemoteOperation(remotePath, mContext, false);
+        RemoteOperationResult result = existsOperation.execute(client);
+        return result.isSuccess();
+    }
+
+}
index 12cf1ac..a347192 100644 (file)
@@ -31,7 +31,7 @@ import java.util.Iterator;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
-import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.httpclient.HttpStatus;
 import org.apache.commons.httpclient.methods.RequestEntity;
 
 import android.accounts.Account;
@@ -39,6 +39,7 @@ import android.content.Context;
 import android.net.Uri;
 
 import com.owncloud.android.MainApp;
+import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -75,7 +76,6 @@ public class UploadFileOperation extends RemoteOperation {
     private boolean mWasRenamed = false;
     private String mOriginalFileName = null;
     private String mOriginalStoragePath = null;
-    PutMethod mPutMethod = null;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
     private Context mContext;
@@ -312,66 +312,71 @@ public class UploadFileOperation extends RemoteOperation {
                     (new File(mFile.getStoragePath())).length() >
                             ChunkedUploadRemoteFileOperation.CHUNK_SIZE ) {
                 mUploadOperation = new ChunkedUploadRemoteFileOperation(mFile.getStoragePath(),
-                        mFile.getRemotePath(), mFile.getMimetype());
+                        mFile.getRemotePath(), mFile.getMimetype(), mFile.getEtagInConflict());
             } else {
                 mUploadOperation = new UploadRemoteFileOperation(mFile.getStoragePath(),
-                        mFile.getRemotePath(), mFile.getMimetype());
+                        mFile.getRemotePath(), mFile.getMimetype(), mFile.getEtagInConflict());
             }
             Iterator <OnDatatransferProgressListener> listener = mDataTransferListeners.iterator();
             while (listener.hasNext()) {
                 mUploadOperation.addDatatransferProgressListener(listener.next());
             }
-            if (!mCancellationRequested.get()) {
-                result = mUploadOperation.execute(client);
-
-                /// move local temporal file or original file to its corresponding
-                // location in the ownCloud local folder
-                if (result.isSuccess()) {
-                    if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
-                        mFile.setStoragePath(null);
-
-                    } else {
-                        mFile.setStoragePath(expectedPath);
-                        File fileToMove = null;
-                        if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
-                            // ; see where temporalFile was
-                            // set
-                            fileToMove = temporalFile;
-                        } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
-                            fileToMove = originalFile;
-                        }
-                        if (!expectedFile.equals(fileToMove)) {
-                            File expectedFolder = expectedFile.getParentFile();
-                            expectedFolder.mkdirs();
-                            if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) {
-                                mFile.setStoragePath(null); // forget the local file
-                                // by now, treat this as a success; the file was
-                                // uploaded; the user won't like that the local file
-                                // is not linked, but this should be a very rare
-                                // fail;
-                                // the best option could be show a warning message
-                                // (but not a fail)
-                                // result = new
-                                // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
-                                // return result;
-                            }
+            if (mCancellationRequested.get()) {
+                throw new OperationCancelledException();
+            }
+
+            result = mUploadOperation.execute(client);
+
+            /// move local temporal file or original file to its corresponding
+            // location in the ownCloud local folder
+            if (result.isSuccess()) {
+                if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_FORGET) {
+                    mFile.setStoragePath(null);
+
+                } else {
+                    mFile.setStoragePath(expectedPath);
+                    File fileToMove = null;
+                    if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
+                        // ; see where temporalFile was
+                        // set
+                        fileToMove = temporalFile;
+                    } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
+                        fileToMove = originalFile;
+                    }
+                    if (!expectedFile.equals(fileToMove)) {
+                        File expectedFolder = expectedFile.getParentFile();
+                        expectedFolder.mkdirs();
+                        if (!expectedFolder.isDirectory() || !fileToMove.renameTo(expectedFile)) {
+                            mFile.setStoragePath(null); // forget the local file
+                            // by now, treat this as a success; the file was
+                            // uploaded; the user won't like that the local file
+                            // is not linked, but this should be a very rare
+                            // fail;
+                            // the best option could be show a warning message
+                            // (but not a fail)
+                            // result = new
+                            // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
+                            // return result;
                         }
                     }
+                    FileDataStorageManager.triggerMediaScan(originalFile.getAbsolutePath());
+                    FileDataStorageManager.triggerMediaScan(expectedFile.getAbsolutePath());
                 }
+
+            } else if (result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED ) {
+                result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
             }
 
         } catch (Exception e) {
-            // TODO something cleaner with cancellations
-            if (mCancellationRequested.get()) {
-                result = new RemoteOperationResult(new OperationCancelledException());
-            } else {
-                result = new RemoteOperationResult(e);
-            }
+            result = new RemoteOperationResult(e);
 
         } finally {
             if (temporalFile != null && !originalFile.equals(temporalFile)) {
                 temporalFile.delete();
             }
+            if (result == null){
+                return new RemoteOperationResult(false, 404, null);
+            }
             if (result.isSuccess()) {
                 Log_OC.i(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath + ": " +
                         result.getLogMessage());
@@ -406,7 +411,7 @@ public class UploadFileOperation extends RemoteOperation {
         newFile.setModificationTimestamp(mFile.getModificationTimestamp());
         newFile.setModificationTimestampAtLastSyncForData(
                 mFile.getModificationTimestampAtLastSyncForData());
-        // newFile.setEtag(mFile.getEtag())
+        newFile.setEtag(mFile.getEtag());
         newFile.setFavorite(mFile.isFavorite());
         newFile.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties());
         newFile.setLastSyncDateForData(mFile.getLastSyncDateForData());
index 5fb5c8c..3d917d2 100644 (file)
 
 package com.owncloud.android.operations.common;
 
-import com.owncloud.android.MainApp;
+import android.content.Context;
+import android.os.Handler;
+
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
 import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 
-import android.content.Context;
-import android.os.Handler;
-
 
 /**
  * Operation which execution involves both interactions with an ownCloud server and
index 70cd897..e652bad 100644 (file)
 
 package com.owncloud.android.providers;
 
-import java.io.File;
-import java.security.Provider;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import com.owncloud.android.MainApp;
-import com.owncloud.android.R;
-import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.db.ProviderMeta;
-import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
-import com.owncloud.android.lib.common.accounts.AccountUtils;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.shares.ShareType;
-import com.owncloud.android.utils.FileStorageUtils;
-
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.content.ContentProvider;
@@ -55,6 +40,19 @@ import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.text.TextUtils;
 
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.db.ProviderMeta;
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+import com.owncloud.android.lib.common.accounts.AccountUtils;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.utils.FileStorageUtils;
+
+import java.io.File;
+import java.util.ArrayList;
+
 /**
  * The ContentProvider for the ownCloud App.
  */
@@ -62,95 +60,14 @@ public class FileContentProvider extends ContentProvider {
 
     private DataBaseHelper mDbHelper;
 
-    // Projection for filelist table
-    private static HashMap<String, String> mFileProjectionMap;
-    static {
-        mFileProjectionMap = new HashMap<String, String>();
-        mFileProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_PARENT,
-                ProviderTableMeta.FILE_PARENT);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_PATH,
-                ProviderTableMeta.FILE_PATH);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_NAME,
-                ProviderTableMeta.FILE_NAME);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_CREATION,
-                ProviderTableMeta.FILE_CREATION);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_MODIFIED,
-                ProviderTableMeta.FILE_MODIFIED);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA,
-                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_CONTENT_LENGTH,
-                ProviderTableMeta.FILE_CONTENT_LENGTH);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_CONTENT_TYPE,
-                ProviderTableMeta.FILE_CONTENT_TYPE);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_STORAGE_PATH,
-                ProviderTableMeta.FILE_STORAGE_PATH);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,
-                ProviderTableMeta.FILE_LAST_SYNC_DATE);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,
-                ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,
-                ProviderTableMeta.FILE_KEEP_IN_SYNC);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,
-                ProviderTableMeta.FILE_ACCOUNT_OWNER);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_ETAG,
-                ProviderTableMeta.FILE_ETAG);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_SHARE_BY_LINK,
-                ProviderTableMeta.FILE_SHARE_BY_LINK);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_PUBLIC_LINK,
-                ProviderTableMeta.FILE_PUBLIC_LINK);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_PERMISSIONS,
-                ProviderTableMeta.FILE_PERMISSIONS);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_REMOTE_ID,
-                ProviderTableMeta.FILE_REMOTE_ID);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
-                ProviderTableMeta.FILE_UPDATE_THUMBNAIL);
-        mFileProjectionMap.put(ProviderTableMeta.FILE_IS_DOWNLOADING,
-                ProviderTableMeta.FILE_IS_DOWNLOADING);
-    }
-
     private static final int SINGLE_FILE = 1;
     private static final int DIRECTORY = 2;
     private static final int ROOT_DIRECTORY = 3;
     private static final int SHARES = 4;
+    private static final int CAPABILITIES = 5;
 
     private static final String TAG = FileContentProvider.class.getSimpleName();
 
-    // Projection for ocshares table
-    private static HashMap<String, String> mOCSharesProjectionMap;
-    static {
-        mOCSharesProjectionMap = new HashMap<String, String>();
-        mOCSharesProjectionMap.put(ProviderTableMeta._ID, ProviderTableMeta._ID);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_FILE_SOURCE,
-                ProviderTableMeta.OCSHARES_FILE_SOURCE);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE,
-                ProviderTableMeta.OCSHARES_ITEM_SOURCE);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_TYPE,
-                ProviderTableMeta.OCSHARES_SHARE_TYPE);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_WITH,
-                ProviderTableMeta.OCSHARES_SHARE_WITH);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_PATH,
-                ProviderTableMeta.OCSHARES_PATH);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_PERMISSIONS,
-                ProviderTableMeta.OCSHARES_PERMISSIONS);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARED_DATE,
-                ProviderTableMeta.OCSHARES_SHARED_DATE);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE,
-                ProviderTableMeta.OCSHARES_EXPIRATION_DATE);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_TOKEN,
-                ProviderTableMeta.OCSHARES_TOKEN);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME,
-                ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY,
-                ProviderTableMeta.OCSHARES_IS_DIRECTORY);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_USER_ID,
-                ProviderTableMeta.OCSHARES_USER_ID);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED,
-                ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED);
-        mOCSharesProjectionMap.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER,
-                ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
-    }
-
     private UriMatcher mUriMatcher;
 
     @Override
@@ -250,6 +167,9 @@ public class FileContentProvider extends ContentProvider {
         case SHARES:
             count = db.delete(ProviderTableMeta.OCSHARES_TABLE_NAME, where, whereArgs);
             break;
+        case CAPABILITIES:
+            count = db.delete(ProviderTableMeta.CAPABILITIES_TABLE_NAME, where, whereArgs);
+            break;
         default:
             //Log_OC.e(TAG, "Unknown uri " + uri);
             throw new IllegalArgumentException("Unknown uri: " + uri.toString());
@@ -307,9 +227,7 @@ public class FileContentProvider extends ContentProvider {
                 }
                 long rowId = db.insert(ProviderTableMeta.FILE_TABLE_NAME, null, values);
                 if (rowId > 0) {
-                    Uri insertedFileUri =
-                            ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
-                    return insertedFileUri;
+                    return ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
                 } else {
                     throw new SQLException("ERROR " + uri);
                 }
@@ -325,45 +243,29 @@ public class FileContentProvider extends ContentProvider {
             }
 
         case SHARES:
-            String path = values.getAsString(ProviderTableMeta.OCSHARES_PATH);
-            String accountNameShare= values.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER);
-            String[] projectionShare = new String[] {
-                    ProviderTableMeta._ID, ProviderTableMeta.OCSHARES_PATH,
-                    ProviderTableMeta.OCSHARES_ACCOUNT_OWNER
-            };
-            String whereShare = ProviderTableMeta.OCSHARES_PATH + "=? AND " +
-                    ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
-            String[] whereArgsShare = new String[] {path, accountNameShare};
             Uri insertedShareUri = null;
-            Cursor doubleCheckShare =
-                    query(db, uri, projectionShare, whereShare, whereArgsShare, null);
-            // ugly patch; serious refactorization is needed to reduce work in
-            // FileDataStorageManager and bring it to FileContentProvider
-            if (doubleCheckShare == null || !doubleCheckShare.moveToFirst()) {
-                if (doubleCheckShare != null) {
-                    doubleCheckShare.close();
-                }
-                long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
-                if (rowId >0) {
-                    insertedShareUri =
-                            ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
-                } else {
-                    throw new SQLException("ERROR " + uri);
-
-                }
+            long rowId = db.insert(ProviderTableMeta.OCSHARES_TABLE_NAME, null, values);
+            if (rowId >0) {
+                insertedShareUri =
+                        ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_SHARE, rowId);
             } else {
-                // file is already inserted; race condition, let's avoid a duplicated entry
-                insertedShareUri = ContentUris.withAppendedId(
-                        ProviderTableMeta.CONTENT_URI_SHARE,
-                        doubleCheckShare.getLong(
-                                doubleCheckShare.getColumnIndex(ProviderTableMeta._ID)
-                        )
-                );
-                doubleCheckShare.close();
+                throw new SQLException("ERROR " + uri);
+
             }
-            updateFilesTableAccordingToShareInsertion(db, uri, values);
+            updateFilesTableAccordingToShareInsertion(db, values);
             return insertedShareUri;
 
+        case CAPABILITIES:
+            Uri insertedCapUri = null;
+            long id = db.insert(ProviderTableMeta.CAPABILITIES_TABLE_NAME, null, values);
+            if (id >0) {
+                insertedCapUri =
+                        ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_CAPABILITIES, id);
+            } else {
+                throw new SQLException("ERROR " + uri);
+
+            }
+            return insertedCapUri;
 
         default:
             throw new IllegalArgumentException("Unknown uri id: " + uri);
@@ -372,21 +274,23 @@ public class FileContentProvider extends ContentProvider {
     }
 
     private void updateFilesTableAccordingToShareInsertion(
-            SQLiteDatabase db, Uri uri, ContentValues shareValues
+            SQLiteDatabase db, ContentValues newShare
             ) {
         ContentValues fileValues = new ContentValues();
-        fileValues.put(
-                ProviderTableMeta.FILE_SHARE_BY_LINK,
-                ShareType.PUBLIC_LINK.getValue() ==
-                        shareValues.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE) ? 1 : 0
-        );
-        String whereShare = ProviderTableMeta.FILE_PATH + "=? AND " +
+        int newShareType = newShare.getAsInteger(ProviderTableMeta.OCSHARES_SHARE_TYPE);
+        if (newShareType == ShareType.PUBLIC_LINK.getValue()) {
+            fileValues.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, 1);
+        } else if (newShareType == ShareType.USER.getValue() || newShareType == ShareType.GROUP.getValue()) {
+            fileValues.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, 1);
+        }
+
+        String where = ProviderTableMeta.FILE_PATH + "=? AND " +
                 ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?";
-        String[] whereArgsShare = new String[] {
-                shareValues.getAsString(ProviderTableMeta.OCSHARES_PATH),
-                shareValues.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
+        String[] whereArgs = new String[] {
+                newShare.getAsString(ProviderTableMeta.OCSHARES_PATH),
+                newShare.getAsString(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER)
         };
-        db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, whereShare, whereArgsShare);
+        db.update(ProviderTableMeta.FILE_TABLE_NAME, fileValues, where, whereArgs);
     }
 
 
@@ -403,6 +307,8 @@ public class FileContentProvider extends ContentProvider {
         mUriMatcher.addURI(authority, "dir/#", DIRECTORY);
         mUriMatcher.addURI(authority, "shares/", SHARES);
         mUriMatcher.addURI(authority, "shares/#", SHARES);
+        mUriMatcher.addURI(authority, "capabilities/", CAPABILITIES);
+        mUriMatcher.addURI(authority, "capabilities/#", CAPABILITIES);
 
         return true;
     }
@@ -441,7 +347,6 @@ public class FileContentProvider extends ContentProvider {
         SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
 
         sqlQuery.setTables(ProviderTableMeta.FILE_TABLE_NAME);
-        sqlQuery.setProjectionMap(mFileProjectionMap);
 
         switch (mUriMatcher.match(uri)) {
         case ROOT_DIRECTORY:
@@ -459,7 +364,13 @@ public class FileContentProvider extends ContentProvider {
             break;
         case SHARES:
             sqlQuery.setTables(ProviderTableMeta.OCSHARES_TABLE_NAME);
-            sqlQuery.setProjectionMap(mOCSharesProjectionMap);
+            if (uri.getPathSegments().size() > 1) {
+                sqlQuery.appendWhere(ProviderTableMeta._ID + "="
+                        + uri.getPathSegments().get(1));
+            }
+            break;
+        case CAPABILITIES:
+            sqlQuery.setTables(ProviderTableMeta.CAPABILITIES_TABLE_NAME);
             if (uri.getPathSegments().size() > 1) {
                 sqlQuery.appendWhere(ProviderTableMeta._ID + "="
                         + uri.getPathSegments().get(1));
@@ -471,11 +382,16 @@ public class FileContentProvider extends ContentProvider {
 
         String order;
         if (TextUtils.isEmpty(sortOrder)) {
-            if (mUriMatcher.match(uri) == SHARES) {
-                order = ProviderTableMeta.OCSHARES_DEFAULT_SORT_ORDER;
-            } else {
-
-                order = ProviderTableMeta.FILE_DEFAULT_SORT_ORDER;
+            switch (mUriMatcher.match(uri)) {
+                case SHARES:
+                    order = ProviderTableMeta.OCSHARES_DEFAULT_SORT_ORDER;
+                    break;
+                case CAPABILITIES:
+                    order = ProviderTableMeta.CAPABILITIES_DEFAULT_SORT_ORDER;
+                    break;
+                default: // Files
+                    order = ProviderTableMeta.FILE_DEFAULT_SORT_ORDER;
+                    break;
             }
         } else {
             order = sortOrder;
@@ -520,6 +436,10 @@ public class FileContentProvider extends ContentProvider {
                 return db.update(
                         ProviderTableMeta.OCSHARES_TABLE_NAME, values, selection, selectionArgs
                 );
+            case CAPABILITIES:
+                return db.update(
+                        ProviderTableMeta.CAPABILITIES_TABLE_NAME, values, selection, selectionArgs
+                );
             default:
                 return db.update(
                         ProviderTableMeta.FILE_TABLE_NAME, values, selection, selectionArgs
@@ -527,59 +447,6 @@ public class FileContentProvider extends ContentProvider {
         }
     }
 
- /*
-    private int updateFolderSize(SQLiteDatabase db, String folderId) {
-        int count = 0;
-        String [] whereArgs = new String[] { folderId };
-
-        // read current size saved for the folder
-        long folderSize = 0;
-        long folderParentId = -1;
-        Uri selectFolderUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, folderId);
-        String[] folderProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH,  ProviderTableMeta.FILE_PARENT};
-        String folderWhere = ProviderTableMeta._ID + "=?";
-        Cursor folderCursor = query(db, selectFolderUri, folderProjection, folderWhere, whereArgs, null);
-        if (folderCursor != null && folderCursor.moveToFirst()) {
-            folderSize = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));;
-            folderParentId = folderCursor.getLong(folderCursor.getColumnIndex(ProviderTableMeta.FILE_PARENT));;
-        }
-        folderCursor.close();
-
-        // read and sum sizes of children
-        long childrenSize = 0;
-        Uri selectChildrenUri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, folderId);
-        String[] childrenProjection = new String[] { ProviderTableMeta.FILE_CONTENT_LENGTH,  ProviderTableMeta.FILE_PARENT};
-        String childrenWhere = ProviderTableMeta.FILE_PARENT + "=?";
-        Cursor childrenCursor = query(db, selectChildrenUri, childrenProjection, childrenWhere, whereArgs, null);
-        if (childrenCursor != null && childrenCursor.moveToFirst()) {
-            while (!childrenCursor.isAfterLast()) {
-                childrenSize += childrenCursor.getLong(childrenCursor.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH));
-                childrenCursor.moveToNext();
-            }
-        }
-        childrenCursor.close();
-
-        // update if needed
-        if (folderSize != childrenSize) {
-            Log_OC.d("FileContentProvider", "Updating " + folderSize + " to " + childrenSize);
-            ContentValues cv = new ContentValues();
-            cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, childrenSize);
-            count = db.update(ProviderTableMeta.FILE_TABLE_NAME, cv, folderWhere, whereArgs);
-
-            // propagate update until root
-            if (folderParentId > FileDataStorageManager.ROOT_PARENT_ID) {
-                Log_OC.d("FileContentProvider", "Propagating update to " + folderParentId);
-                updateFolderSize(db, String.valueOf(folderParentId));
-            } else {
-                Log_OC.d("FileContentProvider", "NOT propagating to " + folderParentId);
-            }
-        } else {
-            Log_OC.d("FileContentProvider", "NOT updating, sizes are " + folderSize + " and " + childrenSize);
-        }
-        return count;
-    }
-*/
-
     @Override
     public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations)
             throws OperationApplicationException {
@@ -616,28 +483,30 @@ public class FileContentProvider extends ContentProvider {
             // files table
             Log_OC.i("SQL", "Entering in onCreate");
             db.execSQL("CREATE TABLE " + ProviderTableMeta.FILE_TABLE_NAME + "("
-                    + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
-                    + ProviderTableMeta.FILE_NAME + " TEXT, "
-                    + ProviderTableMeta.FILE_PATH + " TEXT, "
-                    + ProviderTableMeta.FILE_PARENT + " INTEGER, "
-                    + ProviderTableMeta.FILE_CREATION + " INTEGER, "
-                    + ProviderTableMeta.FILE_MODIFIED + " INTEGER, "
-                    + ProviderTableMeta.FILE_CONTENT_TYPE + " TEXT, "
-                    + ProviderTableMeta.FILE_CONTENT_LENGTH + " INTEGER, "
-                    + ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "
-                    + ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "
-                    + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
-                    + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
-                    + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
-                    + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, "
-                    + ProviderTableMeta.FILE_ETAG + " TEXT, "
-                    + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER, "
-                    + ProviderTableMeta.FILE_PUBLIC_LINK  + " TEXT, "
-                    + ProviderTableMeta.FILE_PERMISSIONS  + " TEXT null,"
-                    + ProviderTableMeta.FILE_REMOTE_ID  + " TEXT null,"
-                    + ProviderTableMeta.FILE_UPDATE_THUMBNAIL  + " INTEGER," //boolean
-                    + ProviderTableMeta.FILE_IS_DOWNLOADING  + " INTEGER);" //boolean
-                    );
+                            + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
+                            + ProviderTableMeta.FILE_NAME + " TEXT, "
+                            + ProviderTableMeta.FILE_PATH + " TEXT, "
+                            + ProviderTableMeta.FILE_PARENT + " INTEGER, "
+                            + ProviderTableMeta.FILE_CREATION + " INTEGER, "
+                            + ProviderTableMeta.FILE_MODIFIED + " INTEGER, "
+                            + ProviderTableMeta.FILE_CONTENT_TYPE + " TEXT, "
+                            + ProviderTableMeta.FILE_CONTENT_LENGTH + " INTEGER, "
+                            + ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "
+                            + ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "
+                            + ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "
+                            + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "
+                            + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER, "
+                            + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + " INTEGER, "
+                            + ProviderTableMeta.FILE_ETAG + " TEXT, "
+                            + ProviderTableMeta.FILE_SHARED_VIA_LINK + " INTEGER, "
+                            + ProviderTableMeta.FILE_PUBLIC_LINK + " TEXT, "
+                            + ProviderTableMeta.FILE_PERMISSIONS + " TEXT null,"
+                            + ProviderTableMeta.FILE_REMOTE_ID + " TEXT null,"
+                            + ProviderTableMeta.FILE_UPDATE_THUMBNAIL + " INTEGER," //boolean
+                            + ProviderTableMeta.FILE_IS_DOWNLOADING + " INTEGER," //boolean
+                            + ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " TEXT,"
+                            + ProviderTableMeta.FILE_SHARED_WITH_SHAREE + " INTEGER);"
+            );
 
             // Create table ocshares
             db.execSQL("CREATE TABLE " + ProviderTableMeta.OCSHARES_TABLE_NAME + "("
@@ -656,6 +525,10 @@ public class FileContentProvider extends ContentProvider {
                     + ProviderTableMeta.OCSHARES_USER_ID + " INTEGER, "
                     + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + " INTEGER,"
                     + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + " TEXT );" );
+
+            // Create table capabilities
+            createCapabilitiesTable(db);
+
         }
 
         @Override
@@ -735,7 +608,7 @@ public class FileContentProvider extends ContentProvider {
                 db.beginTransaction();
                 try {
                     db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
-                            " ADD COLUMN " + ProviderTableMeta.FILE_SHARE_BY_LINK + " INTEGER " +
+                            " ADD COLUMN " + ProviderTableMeta.FILE_SHARED_VIA_LINK + " INTEGER " +
                             " DEFAULT 0");
 
                     db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
@@ -836,9 +709,88 @@ public class FileContentProvider extends ContentProvider {
              if (!upgraded)
                 Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
                         ", newVersion == " + newVersion);
+
+            if (oldVersion < 11 && newVersion >= 11) {
+                Log_OC.i("SQL", "Entering in the #11 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
+                            " ADD COLUMN " + ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " TEXT " +
+                            " DEFAULT NULL");
+
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (!upgraded)
+                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
+                        ", newVersion == " + newVersion);
+
+            if (oldVersion < 12 && newVersion >= 12) {
+                Log_OC.i("SQL", "Entering in the #12 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    db .execSQL("ALTER TABLE " + ProviderTableMeta.FILE_TABLE_NAME +
+                            " ADD COLUMN " + ProviderTableMeta.FILE_SHARED_WITH_SHAREE + " INTEGER " +
+                            " DEFAULT 0");
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (!upgraded)
+                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
+                        ", newVersion == " + newVersion);
+
+            if (oldVersion < 13 && newVersion >= 13) {
+                Log_OC.i("SQL", "Entering in the #13 ADD in onUpgrade");
+                db.beginTransaction();
+                try {
+                    // Create capabilities table
+                    createCapabilitiesTable(db);
+                    upgraded = true;
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                }
+            }
+            if (!upgraded)
+                Log_OC.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion +
+                        ", newVersion == " + newVersion);
+
         }
     }
 
+    private void createCapabilitiesTable(SQLiteDatabase db){
+        // Create table capabilities
+        db.execSQL("CREATE TABLE " + ProviderTableMeta.CAPABILITIES_TABLE_NAME + "("
+                + ProviderTableMeta._ID + " INTEGER PRIMARY KEY, "
+                + ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + " TEXT, "
+                + ProviderTableMeta.CAPABILITIES_VERSION_MAYOR + " INTEGER, "
+                + ProviderTableMeta.CAPABILITIES_VERSION_MINOR + " INTEGER, "
+                + ProviderTableMeta.CAPABILITIES_VERSION_MICRO + " INTEGER, "
+                + ProviderTableMeta.CAPABILITIES_VERSION_STRING + " TEXT, "
+                + ProviderTableMeta.CAPABILITIES_VERSION_EDITION + " TEXT, "
+                + ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL + " INTEGER, "
+                + ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED + " INTEGER, " // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED + " INTEGER, "  // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED + " INTEGER, "    // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED + " INTEGER, "  // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS + " INTEGER, "
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED + " INTEGER, " // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL + " INTEGER, "    // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD + " INTEGER, "       // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL + " INTEGER, "      // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_RESHARING + " INTEGER, "           // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING + " INTEGER, "     // boolean
+                + ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING + " INTEGER, "     // boolean
+                + ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING + " INTEGER, "   // boolean
+                + ProviderTableMeta.CAPABILITIES_FILES_UNDELETE + " INTEGER, "  // boolean
+                + ProviderTableMeta.CAPABILITIES_FILES_VERSIONING + " INTEGER );" );   // boolean
+    }
 
     /**
      * Version 10 of database does not modify its scheme. It coincides with the upgrade of the ownCloud account names
diff --git a/src/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java b/src/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java
new file mode 100644 (file)
index 0000000..54d78fd
--- /dev/null
@@ -0,0 +1,197 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+package com.owncloud.android.providers;
+
+import android.accounts.Account;
+import android.app.SearchManager;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.support.annotation.Nullable;
+
+import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * Content provider for search suggestions, to search for users and groups existing in an ownCloud server.
+ */
+public class UsersAndGroupsSearchProvider extends ContentProvider {
+
+    private static final String TAG = UsersAndGroupsSearchProvider.class.getSimpleName();
+
+    private static final String[] COLUMNS = {
+        BaseColumns._ID,
+        SearchManager.SUGGEST_COLUMN_TEXT_1,
+        SearchManager.SUGGEST_COLUMN_INTENT_DATA
+    };
+
+    private static final int SEARCH = 1;
+
+    private static final int RESULTS_PER_PAGE = 50;
+    private static final int REQUESTED_PAGE = 1;
+
+    public static final String AUTHORITY = UsersAndGroupsSearchProvider.class.getCanonicalName();
+    public static final String ACTION_SHARE_WITH = AUTHORITY + ".action.SHARE_WITH";
+    public static final String DATA_USER = AUTHORITY + ".data.user";
+    public static final String DATA_GROUP = AUTHORITY + ".data.group";
+
+    private UriMatcher mUriMatcher;
+
+    @Nullable
+    @Override
+    public String getType(Uri uri) {
+        // TODO implement
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+        mUriMatcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH);
+        return true;
+    }
+
+    /**
+     * TODO description
+     *
+     * Reference: http://developer.android.com/guide/topics/search/adding-custom-suggestions.html#CustomContentProvider
+     *
+     * @param uri           Content {@link Uri}, formattted as
+     *                      "content://com.owncloud.android.providers.UsersAndGroupsSearchProvider/" +
+     *                      {@link android.app.SearchManager#SUGGEST_URI_PATH_QUERY} + "/" + 'userQuery'
+     * @param projection    Expected to be NULL.
+     * @param selection     Expected to be NULL.
+     * @param selectionArgs Expected to be NULL.
+     * @param sortOrder     Expected to be NULL.
+     * @return              Cursor with users and groups in the ownCloud server that match 'userQuery'.
+     */
+    @Nullable
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+        Log_OC.d(TAG, "query received in thread " + Thread.currentThread().getName());
+
+        int match = mUriMatcher.match(uri);
+        switch (match) {
+            case SEARCH:
+                return searchForUsersOrGroups(uri);
+
+            default:
+                return null;
+        }
+    }
+
+    private Cursor searchForUsersOrGroups(Uri uri) {
+        MatrixCursor response = null;
+
+
+        String userQuery = uri.getLastPathSegment().toLowerCase();
+
+
+        /// need to trust on the AccountUtils to get the current account since the query in the client side is not
+        /// directly started by our code, but from SearchView implementation
+        Account account = AccountUtils.getCurrentOwnCloudAccount(getContext());
+
+        /// request to the OC server about users and groups matching userQuery
+        GetRemoteShareesOperation searchRequest = new GetRemoteShareesOperation(
+                userQuery, REQUESTED_PAGE, RESULTS_PER_PAGE
+        );
+        RemoteOperationResult result = searchRequest.execute(account, getContext());
+        List<JSONObject> names = new ArrayList<JSONObject>();
+        if (result.isSuccess()) {
+            for (Object o : result.getData()) {
+                // Get JSonObjects from response
+                names.add((JSONObject) o);
+            }
+        }
+
+        /// convert the responses from the OC server to the expected format
+        if (names.size() > 0) {
+            response = new MatrixCursor(COLUMNS);
+            Iterator<JSONObject> namesIt = names.iterator();
+            int count = 0;
+            JSONObject item;
+            String displayName;
+            Uri dataUri;
+            Uri userBaseUri = new Uri.Builder().scheme("content").authority(DATA_USER).build();
+            Uri groupBaseUri = new Uri.Builder().scheme("content").authority(DATA_GROUP).build();
+            try {
+                while (namesIt.hasNext()) {
+                    item = namesIt.next();
+                    String userName = item.getString(GetRemoteShareesOperation.PROPERTY_LABEL);
+                    JSONObject value = item.getJSONObject(GetRemoteShareesOperation.NODE_VALUE);
+                    byte type = (byte) value.getInt(GetRemoteShareesOperation.PROPERTY_SHARE_TYPE);
+                    String shareWith = value.getString(GetRemoteShareesOperation.PROPERTY_SHARE_WITH);
+                    if (GetRemoteShareesOperation.GROUP_TYPE.equals(type)) {
+                        displayName = getContext().getString(R.string.share_group_clarification, userName);
+                        dataUri = Uri.withAppendedPath(groupBaseUri, shareWith);
+                    } else {
+                        displayName = userName;
+                        dataUri = Uri.withAppendedPath(userBaseUri, shareWith);
+                    }
+                    response.newRow()
+                            .add(count++)             // BaseColumns._ID
+                            .add(displayName)         // SearchManager.SUGGEST_COLUMN_TEXT_1
+                            .add(dataUri);
+                }
+            } catch (JSONException e) {
+                Log_OC.e(TAG, "Exception while parsing data of users/groups", e);
+            }
+        }
+
+        return response;
+    }
+
+    @Nullable
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        // TODO implementation
+        return null;
+    }
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // TODO implementation
+        return 0;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+        // TODO implementation
+        return 0;
+    }
+
+}
index 099bd08..eff8e03 100644 (file)
@@ -54,7 +54,8 @@ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.lib.resources.users.GetRemoteUserNameOperation;
 import com.owncloud.android.operations.CopyFileOperation;
 import com.owncloud.android.operations.CreateFolderOperation;
-import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.CreateShareViaLinkOperation;
+import com.owncloud.android.operations.CreateShareWithShareeOperation;
 import com.owncloud.android.operations.GetServerInfoOperation;
 import com.owncloud.android.operations.MoveFileOperation;
 import com.owncloud.android.operations.OAuth2GetAccessToken;
@@ -62,7 +63,7 @@ import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
-import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.operations.UnshareOperation;
 import com.owncloud.android.operations.common.SyncOperation;
 
 import java.io.IOException;
@@ -88,10 +89,13 @@ public class OperationsService extends Service {
     public static final String EXTRA_NEW_PARENT_PATH = "NEW_PARENT_PATH";
     public static final String EXTRA_FILE = "FILE";
     public static final String EXTRA_PASSWORD_SHARE = "PASSWORD_SHARE";
+    public static final String EXTRA_SHARE_TYPE = "SHARE_TYPE";
+    public static final String EXTRA_SHARE_WITH = "SHARE_WITH";
 
     public static final String EXTRA_COOKIE = "COOKIE";
 
-    public static final String ACTION_CREATE_SHARE = "CREATE_SHARE";
+    public static final String ACTION_CREATE_SHARE_VIA_LINK = "CREATE_SHARE_VIA_LINK";
+    public static final String ACTION_CREATE_SHARE_WITH_SHAREE = "CREATE_SHARE_WITH_SHAREE";
     public static final String ACTION_UNSHARE = "UNSHARE";
     public static final String ACTION_GET_SERVER_INFO = "GET_SERVER_INFO";
     public static final String ACTION_OAUTH2_GET_ACCESS_TOKEN = "OAUTH2_GET_ACCESS_TOKEN";
@@ -100,7 +104,7 @@ public class OperationsService extends Service {
     public static final String ACTION_REMOVE = "REMOVE";
     public static final String ACTION_CREATE_FOLDER = "CREATE_FOLDER";
     public static final String ACTION_SYNC_FILE = "SYNC_FILE";
-    public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER";//for the moment, just to download
+    public static final String ACTION_SYNC_FOLDER = "SYNC_FOLDER";
     public static final String ACTION_MOVE_FILE = "MOVE_FILE";
     public static final String ACTION_COPY_FILE = "COPY_FILE";
 
@@ -110,7 +114,6 @@ public class OperationsService extends Service {
             ".OPERATION_FINISHED";
 
 
-
     private ConcurrentMap<Integer, Pair<RemoteOperation, RemoteOperationResult>>
             mUndispatchedFinishedOperations =
             new ConcurrentHashMap<Integer, Pair<RemoteOperation, RemoteOperationResult>>();
@@ -234,7 +237,6 @@ public class OperationsService extends Service {
      */
     @Override
     public IBinder onBind(Intent intent) {
-        //Log_OC.wtf(TAG, "onBind" );
         return mOperationsBinder;
     }
 
@@ -549,22 +551,42 @@ public class OperationsService extends Service {
                 );
                 
                 String action = operationIntent.getAction();
-                if (action.equals(ACTION_CREATE_SHARE)) {  // Create Share
+                if (action.equals(ACTION_CREATE_SHARE_VIA_LINK)) {  // Create public share via link
                     String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
                     String password = operationIntent.getStringExtra(EXTRA_PASSWORD_SHARE);
                     Intent sendIntent = operationIntent.getParcelableExtra(EXTRA_SEND_INTENT);
                     if (remotePath.length() > 0) {
-                        operation = new CreateShareOperation(OperationsService.this, remotePath,
-                                ShareType.PUBLIC_LINK,
-                                "", false, password, 1, sendIntent);
+                        operation = new CreateShareViaLinkOperation(
+                                remotePath,
+                                password,
+                                sendIntent
+                        );
                     }
 
+                } else if (action.equals(ACTION_CREATE_SHARE_WITH_SHAREE)) {  // Create private share with user or group
+                        String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                        String shareeName = operationIntent.getStringExtra(EXTRA_SHARE_WITH);
+                        ShareType shareType = (ShareType) operationIntent.getSerializableExtra(EXTRA_SHARE_TYPE);
+                        if (remotePath.length() > 0) {
+                            operation = new CreateShareWithShareeOperation(
+                                    remotePath,
+                                    shareeName,
+                                    shareType
+                            );
+                        }
+
                 } else if (action.equals(ACTION_UNSHARE)) {  // Unshare file
                     String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
+                    ShareType shareType = (ShareType) operationIntent.
+                            getSerializableExtra(EXTRA_SHARE_TYPE);
+                    String shareWith = operationIntent.getStringExtra(EXTRA_SHARE_WITH);
                     if (remotePath.length() > 0) {
-                        operation = new UnshareLinkOperation(
-                                remotePath, 
-                                OperationsService.this);
+                        operation = new UnshareOperation(
+                                remotePath,
+                                shareType,
+                                shareWith,
+                                OperationsService.this
+                        );
                     }
                     
                 } else if (action.equals(ACTION_GET_SERVER_INFO)) { 
@@ -615,7 +637,7 @@ public class OperationsService extends Service {
                     );
                     
                 } else if (action.equals(ACTION_SYNC_FOLDER)) {
-                    // Sync file
+                    // Sync folder (all its descendant files are sync'ed)
                     String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
                     operation = new SynchronizeFolderOperation(
                             this,                       // TODO remove this dependency from construction time
@@ -623,7 +645,7 @@ public class OperationsService extends Service {
                             account, 
                             System.currentTimeMillis()  // TODO remove this dependency from construction time
                     );
-                    
+
                 } else if (action.equals(ACTION_MOVE_FILE)) {
                     // Move file/folder
                     String remotePath = operationIntent.getStringExtra(EXTRA_REMOTE_PATH);
@@ -726,7 +748,6 @@ public class OperationsService extends Service {
             }
         }
         if (count == 0) {
-            //mOperationResults.put(operation.hashCode(), result);
             Pair<RemoteOperation, RemoteOperationResult> undispatched =
                     new Pair<RemoteOperation, RemoteOperationResult>(operation, result);
             mUndispatchedFinishedOperations.put(((Runnable) operation).hashCode(), undispatched);
index 43ddae3..7dfe520 100644 (file)
@@ -30,7 +30,6 @@ import java.util.Map;
 
 import org.apache.jackrabbit.webdav.DavException;
 
-import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -59,7 +58,7 @@ import android.support.v4.app.NotificationCompat;
  * Implementation of {@link AbstractThreadedSyncAdapter} responsible for synchronizing 
  * ownCloud files.
  * 
- * Performs a full synchronization of the account recieved in {@link #onPerformSync(Account, Bundle,
+ * Performs a full synchronization of the account received in {@link #onPerformSync(Account, Bundle,
  * String, ContentProviderClient, SyncResult)}.
  */
 public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
@@ -77,9 +76,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             ".EVENT_FULL_SYNC_END";
     public static final String EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED =
             FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_CONTENTS_SYNCED";
-    //public static final String EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED =
-    // FileSyncAdapter.class.getName() + ".EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED";
-    
+
     public static final String EXTRA_ACCOUNT_NAME = FileSyncAdapter.class.getName() +
             ".EXTRA_ACCOUNT_NAME";
     public static final String EXTRA_FOLDER_PATH = FileSyncAdapter.class.getName() +
@@ -268,16 +265,6 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
         if (mFailedResultsCounter > MAX_FAILED_RESULTS || isFinisher(mLastFailedResult))
             return;
         
-        /*
-        OCFile folder, 
-        long currentSyncTime, 
-        boolean updateFolderProperties,
-        boolean syncFullAccount,
-        DataStorageManager dataStorageManager, 
-        Account account, 
-        Context context ) {
-        }
-        */
         // folder synchronization
         RefreshFolderOperation synchFolderOp = new RefreshFolderOperation( folder,
                                                                                    mCurrentSyncTime,
@@ -308,7 +295,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
                 // synchronize children folders 
                 List<OCFile> children = synchFolderOp.getChildren();
                 // beware of the 'hidden' recursion here!
-                fetchChildren(folder, children, synchFolderOp.getRemoteFolderChanged());
+                syncChildren(children);
             }
             
         } else {
@@ -351,25 +338,19 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
 
     /**
      * Triggers the synchronization of any folder contained in the list of received files.
+     *
+     * No consideration of etag here because it MUST walk down anyway, in case that kept-in-sync files
+     * have local changes.
      * 
      * @param files         Files to recursively synchronize.
      */
-    private void fetchChildren(OCFile parent, List<OCFile> files, boolean parentEtagChanged) {
+    private void syncChildren(List<OCFile> files) {
         int i;
-        OCFile newFile = null;
-        //String etag = null;
-        //boolean syncDown = false;
+        OCFile newFile;
         for (i=0; i < files.size() && !mCancellation; i++) {
             newFile = files.get(i);
             if (newFile.isFolder()) {
-                /*
-                etag = newFile.getEtag();
-                syncDown = (parentEtagChanged || etag == null || etag.length() == 0);
-                if(syncDown) { */
-                    synchronizeFolder(newFile);
-                    //sendLocalBroadcast(EVENT_FULL_SYNC_FOLDER_SIZE_SYNCED, parent.getRemotePath(),
-                    // null);
-                //}
+                synchronizeFolder(newFile);
             }
         }
        
@@ -526,6 +507,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
     private NotificationCompat.Builder createNotificationBuilder() {
         NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(getContext());
         notificationBuilder.setSmallIcon(R.drawable.notification_icon).setAutoCancel(true);
+        notificationBuilder.setColor(getContext().getResources().getColor(R.color.primary));
         return notificationBuilder;
     }
     
diff --git a/src/com/owncloud/android/ui/activity/ErrorReportActivity.java b/src/com/owncloud/android/ui/activity/ErrorReportActivity.java
new file mode 100644 (file)
index 0000000..d9b5ba0
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.activity;
+
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.AppCompatActivity;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.ui.dialog.LoadingDialog;
+import com.owncloud.android.utils.FileStorageUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+
+
+public class ErrorReportActivity extends AppCompatActivity {
+
+    private static final String TAG = ErrorReportActivity.class.getSimpleName();
+
+    private String mLogText;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.error_send);
+        setTitle(getString(R.string.error_log_title));
+        Button cancelErrorLogButton = (Button) findViewById(R.id.cancelErrorLogButton);
+        Button sendErrorLogButton = (Button) findViewById(R.id.sendErrorLogButton);
+        TextView logTV = (TextView) findViewById(R.id.logTV);
+
+        Intent intent = getIntent();
+        String action = intent.getAction();
+        String type = intent.getType();
+
+        if (Intent.ACTION_SEND.equals(action) && type != null) {
+                mLogText = intent.getStringExtra(Intent.EXTRA_TEXT);
+        } else {
+            // Handle other intents, such as being started from the home screen
+            mLogText = "Error, nothing received!";
+        }
+
+        logTV.setText(mLogText);
+
+        cancelErrorLogButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                finishAffinity();
+
+            }
+        });
+
+        sendErrorLogButton.setOnClickListener(new OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                sendMail();
+            }
+        });
+    }
+
+    /**
+     * Start activity for sending email with logs attached
+     */
+    private void sendMail() {
+        Intent sendIntent = new Intent();
+        sendIntent.setAction(Intent.ACTION_SEND);
+        sendIntent.putExtra(Intent.EXTRA_TEXT, mLogText);
+        sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        sendIntent.setType("text/plain");
+        startActivity(sendIntent);
+    }
+}
\ No newline at end of file
index 8dda1f8..275f5d6 100644 (file)
@@ -43,7 +43,6 @@ import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.ListView;
@@ -68,10 +67,12 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.CreateShareViaLinkOperation;
+import com.owncloud.android.operations.CreateShareWithShareeOperation;
+import com.owncloud.android.operations.GetSharesForFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
-import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.operations.UnshareOperation;
 import com.owncloud.android.services.OperationsService;
 import com.owncloud.android.services.OperationsService.OperationsServiceBinder;
 import com.owncloud.android.ui.NavigationDrawerItem;
@@ -100,12 +101,13 @@ public class FileActivity extends AppCompatActivity
     public static final String TAG = FileActivity.class.getSimpleName();
 
     private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
+
     private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID";
     private static final String DIALOG_SHARE_PASSWORD = "DIALOG_SHARE_PASSWORD";
     private static final String KEY_TRY_SHARE_AGAIN = "TRY_SHARE_AGAIN";
     private static final String KEY_ACTION_BAR_TITLE = "ACTION_BAR_TITLE";
 
-    protected static final long DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS = 200;
+    protected static final long DELAY_TO_REQUEST_OPERATIONS_LATER = 200;
 
 
     /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located.*/
@@ -182,7 +184,9 @@ public class FileActivity extends AppCompatActivity
                     savedInstanceState.getLong(KEY_WAITING_FOR_OP_ID, Long.MAX_VALUE)
                     );
             mTryShareAgain = savedInstanceState.getBoolean(KEY_TRY_SHARE_AGAIN);
-            getSupportActionBar().setTitle(savedInstanceState.getString(KEY_ACTION_BAR_TITLE));
+            if (getSupportActionBar() != null) {
+                getSupportActionBar().setTitle(savedInstanceState.getString(KEY_ACTION_BAR_TITLE));
+            }
         } else {
             account = getIntent().getParcelableExtra(FileActivity.EXTRA_ACCOUNT);
             mFile = getIntent().getParcelableExtra(FileActivity.EXTRA_FILE);
@@ -363,12 +367,7 @@ public class FileActivity extends AppCompatActivity
 //        }
 
         // Display username in drawer
-        Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
-        if (account != null) {
-            TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username);
-            int lastAtPos = account.name.lastIndexOf("@");
-            username.setText(account.name.substring(0, lastAtPos));
-        }
+        setUsernameInDrawer(navigationDrawerLayout, AccountUtils.getCurrentOwnCloudAccount(getApplicationContext()));
 
         // load slide menu items
         mDrawerTitles = getResources().getStringArray(R.array.drawer_items);
@@ -434,6 +433,21 @@ public class FileActivity extends AppCompatActivity
     }
 
     /**
+     * sets the given account name in the drawer in case the drawer is available. The account name
+     * is shortened beginning from the @-sign in the username.
+     *
+     * @param navigationDrawerLayout the drawer layout to be used
+     * @param account                the account to be set in the drawer
+     */
+    protected void setUsernameInDrawer(RelativeLayout navigationDrawerLayout, Account account) {
+        if (navigationDrawerLayout != null && getAccount() != null) {
+            TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username);
+            int lastAtPos = account.name.lastIndexOf("@");
+            username.setText(account.name.substring(0, lastAtPos));
+        }
+    }
+
+    /**
      * Updates title bar and home buttons (state and icon).
      *
      * Assumes that navigation drawer is NOT visible.
@@ -550,7 +564,7 @@ public class FileActivity extends AppCompatActivity
         outState.putBoolean(FileActivity.EXTRA_FROM_NOTIFICATION, mFromNotification);
         outState.putLong(KEY_WAITING_FOR_OP_ID, mFileOperationsHelper.getOpIdWaitingFor());
         outState.putBoolean(KEY_TRY_SHARE_AGAIN, mTryShareAgain);
-        if(getSupportActionBar().getTitle() != null) {
+        if(getSupportActionBar() != null && getSupportActionBar().getTitle() != null) {
             // Null check in case the actionbar is used in ActionBar.NAVIGATION_MODE_LIST
             // since it doesn't have a title then
             outState.putString(KEY_ACTION_BAR_TITLE, getSupportActionBar().getTitle().toString());
@@ -708,6 +722,8 @@ public class FileActivity extends AppCompatActivity
 
         mFileOperationsHelper.setOpIdWaitingFor(Long.MAX_VALUE);
 
+        dismissLoadingDialog();
+
         if (!result.isSuccess() && (
                 result.getCode() == ResultCode.UNAUTHORIZED ||
                 result.isIdPRedirection() ||
@@ -725,18 +741,37 @@ public class FileActivity extends AppCompatActivity
             }
             mTryShareAgain = false;
 
-        } else if (operation instanceof CreateShareOperation) {
-            onCreateShareOperationFinish((CreateShareOperation) operation, result);
+        } else if (operation == null ||
+                operation instanceof CreateShareWithShareeOperation ||
+                operation instanceof UnshareOperation ||
+                operation instanceof SynchronizeFolderOperation
+                ) {
+            if (result.isSuccess()) {
+                updateFileFromDB();
+
+            } else if (result.getCode() != ResultCode.CANCELLED) {
+                Toast t = Toast.makeText(this,
+                        ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
+                        Toast.LENGTH_LONG);
+                t.show();
+            }
 
-        } else if (operation instanceof UnshareLinkOperation) {
-            onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result);
+        } else if (operation instanceof CreateShareViaLinkOperation) {
+            onCreateShareViaLinkOperationFinish((CreateShareViaLinkOperation) operation, result);
 
-        } else if (operation instanceof SynchronizeFolderOperation) {
-            onSynchronizeFolderOperationFinish((SynchronizeFolderOperation)operation, result);
+        } else if (operation instanceof SynchronizeFileOperation) {
+            onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result);
 
-        }else if (operation instanceof SynchronizeFileOperation) {
-            onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
+        } else if (operation instanceof GetSharesForFileOperation) {
+            if (result.isSuccess()) {
+                updateFileFromDB();
 
+            } else if (result.getCode() != ResultCode.SHARE_NOT_FOUND) {
+                Toast t = Toast.makeText(this,
+                        ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
+                        Toast.LENGTH_LONG);
+                t.show();
+            }
         }
     }
 
@@ -752,14 +787,13 @@ public class FileActivity extends AppCompatActivity
 
 
 
-    private void onCreateShareOperationFinish(CreateShareOperation operation,
-                                              RemoteOperationResult result) {
-        dismissLoadingDialog();
+    private void onCreateShareViaLinkOperationFinish(CreateShareViaLinkOperation operation,
+                                                     RemoteOperationResult result) {
         if (result.isSuccess()) {
             mTryShareAgain = false;
             updateFileFromDB();
 
-            Intent sendIntent = operation.getSendIntent();
+            Intent sendIntent = operation.getSendIntentWithSubject(this);
             startActivity(sendIntent);
         } else {
             // Detect Failure (403) --> needs Password
@@ -785,34 +819,8 @@ public class FileActivity extends AppCompatActivity
         }
     }
 
-
-    private void onUnshareLinkOperationFinish(UnshareLinkOperation operation,
-                                              RemoteOperationResult result) {
-        dismissLoadingDialog();
-
-        if (result.isSuccess()){
-            updateFileFromDB();
-
-        } else {
-            Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result,
-                            operation, getResources()), Toast.LENGTH_LONG);
-            t.show();
-        }
-    }
-
-    private void onSynchronizeFolderOperationFinish(
-            SynchronizeFolderOperation operation, RemoteOperationResult result
-    ) {
-        if (!result.isSuccess() && result.getCode() != ResultCode.CANCELLED){
-            Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result,
-                            operation, getResources()), Toast.LENGTH_LONG);
-            t.show();
-        }
-    }
-
     private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation,
                                                   RemoteOperationResult result) {
-        dismissLoadingDialog();
         OCFile syncedFile = operation.getLocalFile();
         if (!result.isSuccess()) {
             if (result.getCode() == ResultCode.SYNC_CONFLICT) {
@@ -844,9 +852,9 @@ public class FileActivity extends AppCompatActivity
     /**
      * Show loading dialog
      */
-    public void showLoadingDialog() {
+    public void showLoadingDialog(String message) {
         // Construct dialog
-        LoadingDialog loading = new LoadingDialog(getResources().getString(R.string.wait_a_moment));
+        LoadingDialog loading = new LoadingDialog(message);
         FragmentManager fm = getSupportFragmentManager();
         FragmentTransaction ft = fm.beginTransaction();
         loading.show(ft, DIALOG_WAIT_TAG);
@@ -860,6 +868,7 @@ public class FileActivity extends AppCompatActivity
     public void dismissLoadingDialog() {
         Fragment frag = getSupportFragmentManager().findFragmentByTag(DIALOG_WAIT_TAG);
         if (frag != null) {
+            Log_OC.d(TAG, "dismiss loading dialog");
             LoadingDialog loading = (LoadingDialog) frag;
             loading.dismiss();
         }
index f75938e..39649ef 100644 (file)
@@ -26,6 +26,7 @@ import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.AuthenticatorException;
 import android.annotation.TargetApi;
+import android.os.Parcelable;
 import android.support.v7.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -79,13 +80,14 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.CopyFileOperation;
 import com.owncloud.android.operations.CreateFolderOperation;
-import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.CreateShareViaLinkOperation;
+import com.owncloud.android.operations.CreateShareWithShareeOperation;
 import com.owncloud.android.operations.MoveFileOperation;
 import com.owncloud.android.operations.RefreshFolderOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
-import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.operations.UnshareOperation;
 import com.owncloud.android.services.observer.FileObserverService;
 import com.owncloud.android.syncadapter.FileSyncAdapter;
 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
@@ -107,6 +109,8 @@ import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.UriUtils;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
 
 /**
  * Displays, what files the user has available in his ownCloud.
@@ -116,8 +120,6 @@ public class FileDisplayActivity extends HookActivity
         implements FileFragment.ContainerActivity,
         OnSslUntrustedCertListener, OnEnforceableRefreshListener {
 
-
-
     private SyncBroadcastReceiver mSyncBroadcastReceiver;
     private UploadFinishReceiver mUploadFinishReceiver;
     private DownloadFinishReceiver mDownloadFinishReceiver;
@@ -149,13 +151,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");
@@ -227,6 +230,13 @@ public class FileDisplayActivity extends HookActivity
     }
 
     @Override
+    protected void onStop() {
+        Log_OC.v(TAG, "onStop() start");
+        super.onStop();
+        Log_OC.v(TAG, "onStop() end");
+    }
+
+    @Override
     protected void onDestroy() {
         Log_OC.v(TAG, "onDestroy() start");
         super.onDestroy();
@@ -265,12 +275,7 @@ public class FileDisplayActivity extends HookActivity
             setFile(file);
 
             if (mAccountWasSet) {
-                RelativeLayout navigationDrawerLayout = (RelativeLayout) findViewById(R.id.left_drawer);
-                if (navigationDrawerLayout != null && getAccount() != null) {
-                    TextView username = (TextView) navigationDrawerLayout.findViewById(R.id.drawer_username);
-                    int lastAtPos = getAccount().name.lastIndexOf("@");
-                    username.setText(getAccount().name.substring(0, lastAtPos));
-                }
+                setUsernameInDrawer((RelativeLayout) findViewById(R.id.left_drawer), getAccount());
             }
 
             if (!stateWasRecovered) {
@@ -318,6 +323,8 @@ public class FileDisplayActivity extends HookActivity
                     startTextPreview(file);
             }
 
+            switchLayout(getFile());
+
         } else {
             Log_OC.wtf(TAG, "initFragments() called with invalid NULLs!");
             if (getAccount() == null) {
@@ -329,6 +336,14 @@ public class FileDisplayActivity extends HookActivity
         }
     }
 
+    private void switchLayout(OCFile file){
+        if (DisplayUtils.isGridView(file, getStorageManager())){
+            switchToGridView();
+        } else {
+            switchToListView();
+        }
+    }
+
     private Fragment chooseInitialSecondFragment(OCFile file) {
         Fragment secondFragment = null;
         if (file != null && !file.isFolder()) {
@@ -480,10 +495,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 +506,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 +521,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 +567,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) {
@@ -631,7 +684,7 @@ public class FileDisplayActivity extends HookActivity
                             requestMoveOperation(fData, fResultCode);
                         }
                     },
-                    DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS
+                    DELAY_TO_REQUEST_OPERATIONS_LATER
             );
 
         } else if (requestCode == ACTION_COPY_FILES && resultCode == RESULT_OK) {
@@ -645,7 +698,7 @@ public class FileDisplayActivity extends HookActivity
                             requestCopyOperation(fData, fResultCode);
                         }
                     },
-                    DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS
+                    DELAY_TO_REQUEST_OPERATIONS_LATER
             );
 
         } else {
@@ -759,8 +812,12 @@ public class FileDisplayActivity extends HookActivity
      */
     private void requestMoveOperation(Intent data, int resultCode) {
         OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
-        OCFile targetFile = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
-        getFileOperationsHelper().moveFile(folderToMoveAt, targetFile);
+
+        ArrayList<OCFile> files = data.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
+
+        for (Parcelable file : files) {
+            getFileOperationsHelper().moveFile(folderToMoveAt, (OCFile) file);
+        }
     }
 
     /**
@@ -771,13 +828,36 @@ public class FileDisplayActivity extends HookActivity
      */
     private void requestCopyOperation(Intent data, int resultCode) {
         OCFile folderToMoveAt = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
-        OCFile targetFile = data.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
-        getFileOperationsHelper().copyFile(folderToMoveAt, targetFile);
+
+        ArrayList<OCFile> files = data.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
+
+        for (Parcelable file : files) {
+            getFileOperationsHelper().copyFile(folderToMoveAt, (OCFile) file);
+        }
     }
 
     @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 +873,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 +965,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 {
 
@@ -976,6 +1076,7 @@ public class FileDisplayActivity extends HookActivity
                             }
 
                         }
+
                     }
                     removeStickyBroadcast(intent);
                     Log_OC.d(TAG, "Setting progress visibility to " + mSyncInProgress);
@@ -1041,7 +1142,11 @@ public class FileDisplayActivity extends HookActivity
                         (uploadedRemotePath.startsWith(currentDir.getRemotePath()));
 
                 if (sameAccount && isDescendant) {
-                    refreshListOfFilesFragment();
+                    String linkedToRemotePath =
+                            intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
+                    if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
+                        refreshListOfFilesFragment();
+                    }
                 }
 
                 boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT,
@@ -1094,6 +1199,16 @@ public class FileDisplayActivity extends HookActivity
 
         }
 
+        // TODO refactor this receiver, and maybe DownloadFinishReceiver; this method is duplicated :S
+        private boolean isAscendant(String linkedToRemotePath) {
+            OCFile currentDir = getCurrentDir();
+            return (
+                    currentDir != null &&
+                            currentDir.getRemotePath().startsWith(linkedToRemotePath)
+            );
+        }
+
+
     }
 
 
@@ -1105,11 +1220,10 @@ public class FileDisplayActivity extends HookActivity
      */
     private class DownloadFinishReceiver extends BroadcastReceiver {
 
-        //int refreshCounter = 0;
         @Override
         public void onReceive(Context context, Intent intent) {
             try {
-                boolean sameAccount = isSameAccount(context, intent);
+                boolean sameAccount = isSameAccount(intent);
                 String downloadedRemotePath =
                         intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
                 boolean isDescendant = isDescendant(downloadedRemotePath);
@@ -1118,7 +1232,6 @@ public class FileDisplayActivity extends HookActivity
                     String linkedToRemotePath =
                             intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
-                        //Log_OC.v(TAG, "refresh #" + ++refreshCounter);
                         refreshListOfFilesFragment();
                     }
                     refreshSecondFragment(
@@ -1160,7 +1273,7 @@ public class FileDisplayActivity extends HookActivity
             );
         }
 
-        private boolean isSameAccount(Context context, Intent intent) {
+        private boolean isSameAccount(Intent intent) {
             String accountName = intent.getStringExtra(FileDownloader.ACCOUNT_NAME);
             return (accountName != null && getAccount() != null &&
                     accountName.equals(getAccount().name));
@@ -1191,6 +1304,11 @@ public class FileDisplayActivity extends HookActivity
         cleanSecondFragment();
         // Sync Folder
         startSyncFolderOperation(directory, false);
+
+        MenuItem menuItem = mOptionsMenu.findItem(R.id.action_switch_view);
+
+        changeGridIcon();
+        switchLayout(directory);
     }
 
     /**
@@ -1323,11 +1441,14 @@ public class FileDisplayActivity extends HookActivity
         } else if (operation instanceof CreateFolderOperation) {
             onCreateFolderOperationFinish((CreateFolderOperation) operation, result);
 
-        } else if (operation instanceof CreateShareOperation) {
-            onCreateShareOperationFinish((CreateShareOperation) operation, result);
+        } else if (operation instanceof CreateShareViaLinkOperation ||
+                    operation instanceof CreateShareWithShareeOperation ) {
 
-        } else if (operation instanceof UnshareLinkOperation) {
-            onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result);
+            refreshShowDetails();
+            refreshListOfFilesFragment();
+
+        } else if (operation instanceof UnshareOperation) {
+            onUnshareLinkOperationFinish((UnshareOperation) operation, result);
 
         } else if (operation instanceof MoveFileOperation) {
             onMoveFileOperationFinish((MoveFileOperation) operation, result);
@@ -1337,15 +1458,8 @@ public class FileDisplayActivity extends HookActivity
         }
 
     }
-    private void onCreateShareOperationFinish(CreateShareOperation operation,
-                                              RemoteOperationResult result) {
-        if (result.isSuccess()) {
-            refreshShowDetails();
-            refreshListOfFilesFragment();
-        }
-    }
 
-    private void onUnshareLinkOperationFinish(UnshareLinkOperation operation,
+    private void onUnshareLinkOperationFinish(UnshareOperation operation,
                                               RemoteOperationResult result) {
         if (result.isSuccess()) {
             refreshShowDetails();
@@ -1386,8 +1500,6 @@ public class FileDisplayActivity extends HookActivity
      */
     private void onRemoveFileOperationFinish(RemoveFileOperation operation,
                                              RemoteOperationResult result) {
-        dismissLoadingDialog();
-
         Toast msg = Toast.makeText(this,
                 ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
                 Toast.LENGTH_LONG);
@@ -1426,10 +1538,8 @@ public class FileDisplayActivity extends HookActivity
     private void onMoveFileOperationFinish(MoveFileOperation operation,
                                            RemoteOperationResult result) {
         if (result.isSuccess()) {
-            dismissLoadingDialog();
             refreshListOfFilesFragment();
         } else {
-            dismissLoadingDialog();
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this,
                         ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
@@ -1451,10 +1561,8 @@ public class FileDisplayActivity extends HookActivity
      */
     private void onCopyFileOperationFinish(CopyFileOperation operation, RemoteOperationResult result) {
         if (result.isSuccess()) {
-            dismissLoadingDialog();
             refreshListOfFilesFragment();
         } else {
-            dismissLoadingDialog();
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this,
                         ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
@@ -1476,7 +1584,6 @@ public class FileDisplayActivity extends HookActivity
      */
     private void onRenameFileOperationFinish(RenameFileOperation operation,
                                              RemoteOperationResult result) {
-        dismissLoadingDialog();
         OCFile renamedFile = operation.getFile();
         if (result.isSuccess()) {
             FileFragment details = getSecondFragment();
@@ -1545,10 +1652,8 @@ public class FileDisplayActivity extends HookActivity
     private void onCreateFolderOperationFinish(CreateFolderOperation operation,
                                                RemoteOperationResult result) {
         if (result.isSuccess()) {
-            dismissLoadingDialog();
             refreshListOfFilesFragment();
         } else {
-            dismissLoadingDialog();
             try {
                 Toast msg = Toast.makeText(FileDisplayActivity.this,
                         ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()),
@@ -1611,26 +1716,60 @@ public class FileDisplayActivity extends HookActivity
         return null;
     }
 
-    public void startSyncFolderOperation(OCFile folder, boolean ignoreETag) {
-        long currentSyncTime = System.currentTimeMillis();
-
-        mSyncInProgress = true;
-
-        // perform folder synchronization
-        RemoteOperation synchFolderOp = new RefreshFolderOperation( folder,
-                currentSyncTime,
-                false,
-                getFileOperationsHelper().isSharedSupported(),
-                ignoreETag,
-                getStorageManager(),
-                getAccount(),
-                getApplicationContext()
+    /**
+     * Starts an operation to refresh the requested folder.
+     *
+     * The operation is run in a new background thread created on the fly.
+     *
+     * The refresh updates is a "light sync": properties of regular files in folder are updated (including
+     * associated shares), but not their contents. Only the contents of files marked to be kept-in-sync are
+     * synchronized too.
+     *
+     * @param folder        Folder to refresh.
+     * @param ignoreETag    If 'true', the data from the server will be fetched and sync'ed even if the eTag
+     *                      didn't change.
+     */
+    public void startSyncFolderOperation(final OCFile folder, final boolean ignoreETag) {
+
+        // the execution is slightly delayed to allow the activity get the window focus if it's being started
+        // or if the method is called from a dialog that is being dismissed
+        getHandler().postDelayed(
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        if (hasWindowFocus()) {
+                            long currentSyncTime = System.currentTimeMillis();
+                            mSyncInProgress = true;
+
+                            // perform folder synchronization
+                            RemoteOperation synchFolderOp = new RefreshFolderOperation(folder,
+                                    currentSyncTime,
+                                    false,
+                                    getFileOperationsHelper().isSharedSupported(),
+                                    ignoreETag,
+                                    getStorageManager(),
+                                    getAccount(),
+                                    getApplicationContext()
+                            );
+                            synchFolderOp.execute(
+                                    getAccount(),
+                                    MainApp.getAppContext(),
+                                    FileDisplayActivity.this,
+                                    null,
+                                    null
+                            );
+
+                            mProgressBar.setIndeterminate(true);
+
+                            setBackgroundText();
+
+                        }   // else: NOTHING ; lets' not refresh when the user rotates the device but there is
+                        // another window floating over
+                    }
+                },
+                DELAY_TO_REQUEST_OPERATIONS_LATER
         );
-        synchFolderOp.execute(getAccount(), MainApp.getAppContext(), this, null, null);
-
-        mProgressBar.setIndeterminate(true);
 
-        setBackgroundText();
     }
 
     /**
@@ -1786,6 +1925,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();
index 5828a14..dc05de9 100644 (file)
@@ -38,7 +38,6 @@ import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.Window;
 import android.widget.Button;
 import android.widget.ProgressBar;
 import android.widget.Toast;
@@ -62,6 +61,8 @@ import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.ui.fragment.OCFileListFragment;
 import com.owncloud.android.utils.ErrorMessageAdapter;
 
+import java.util.ArrayList;
+
 public class FolderPickerActivity extends FileActivity implements FileFragment.ContainerActivity, 
     OnClickListener, OnEnforceableRefreshListener {
 
@@ -69,6 +70,8 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
                                                             + ".EXTRA_FOLDER";
     public static final String EXTRA_FILE = UploadFilesActivity.class.getCanonicalName()
                                                             + ".EXTRA_FILE";
+    public static final String EXTRA_FILES = UploadFilesActivity.class.getCanonicalName()
+            + ".EXTRA_FILES";
     //TODO: Think something better
 
     private SyncBroadcastReceiver mSyncBroadcastReceiver;
@@ -155,6 +158,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 +267,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;
     }
@@ -346,9 +349,9 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
         actionBar.setDisplayHomeAsUpEnabled(!atRoot);
         actionBar.setHomeButtonEnabled(!atRoot);
         actionBar.setTitle(
-            atRoot 
-                ? getString(R.string.default_display_name_for_root_folder) 
-                : currentDir.getFileName()
+                atRoot
+                        ? getString(R.string.default_display_name_for_root_folder)
+                        : currentDir.getFileName()
         );
     }
 
@@ -369,12 +372,16 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
         } else if (v == mChooseBtn) {
             Intent i = getIntent();
             Parcelable targetFile = i.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
+            ArrayList<Parcelable> targetFiles = i.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
 
             Intent data = new Intent();
             data.putExtra(EXTRA_FOLDER, getCurrentFolder());
             if (targetFile != null) {
                 data.putExtra(EXTRA_FILE, targetFile);
             }
+            if (targetFiles != null){
+                data.putParcelableArrayListExtra(EXTRA_FILES, targetFiles);
+            }
             setResult(RESULT_OK, data);
             finish();
         }
@@ -386,7 +393,7 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
         super.onRemoteOperationFinish(operation, result);
         
         if (operation instanceof CreateFolderOperation) {
-            onCreateFolderOperationFinish((CreateFolderOperation)operation, result);
+            onCreateFolderOperationFinish((CreateFolderOperation) operation, result);
             
         }
     }
@@ -404,10 +411,8 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
             ) {
         
         if (result.isSuccess()) {
-            dismissLoadingDialog();
             refreshListOfFilesFragment();
         } else {
-            dismissLoadingDialog();
             try {
                 Toast msg = Toast.makeText(FolderPickerActivity.this, 
                         ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
@@ -536,9 +541,9 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
     
 
     /**
-     * Shows the information of the {@link OCFile} received as a 
+     * Shows the information of the {@link OCFile} received as a
      * parameter in the second fragment.
-     * 
+     *
      * @param file          {@link OCFile} whose details will be shown
      */
     @Override
diff --git a/src/com/owncloud/android/ui/activity/LocalDirectorySelectorActivity.java b/src/com/owncloud/android/ui/activity/LocalDirectorySelectorActivity.java
new file mode 100644 (file)
index 0000000..83b44c5
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author Bartosz Przybylski
+ *   Copyright (C) 2015 ownCloud Inc.
+ *   Copyright (C) 2015 Bartosz Przybylski
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+import com.owncloud.android.R;
+
+/**
+ * Created by Bartosz Przybylski on 07.11.2015.
+ */
+public class LocalDirectorySelectorActivity extends UploadFilesActivity {
+
+       @Override
+       public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+               mUploadBtn.setText(R.string.folder_picker_choose_button_text);
+       }
+
+       @Override
+       public void onClick(View v) {
+               if (v.getId() == R.id.upload_files_btn_cancel) {
+                       setResult(RESULT_CANCELED);
+                       finish();
+
+               } else if (v.getId() == R.id.upload_files_btn_upload) {
+                       Intent resultIntent = new Intent();
+                       resultIntent.putExtra(EXTRA_CHOSEN_FILES, getInitialDirectory().getAbsolutePath());
+                       setResult(RESULT_OK, resultIntent);
+                       finish();
+               }
+       }
+}
index 1697439..d06306b 100644 (file)
@@ -24,6 +24,7 @@ package com.owncloud.android.ui.activity;
 
 import java.util.Arrays;
 
+import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
@@ -45,18 +46,18 @@ public class PassCodeActivity extends AppCompatActivity {
 
     private static final String TAG = PassCodeActivity.class.getSimpleName();
 
-    public final static String ACTION_ENABLE = PassCodeActivity.class.getCanonicalName() +
-            ".ENABLE";
-    public final static String ACTION_DISABLE = PassCodeActivity.class.getCanonicalName() +
-            ".DISABLE";
-    public final static String ACTION_REQUEST = PassCodeActivity.class.getCanonicalName()  +
-            ".REQUEST";
+    public final static String ACTION_REQUEST_WITH_RESULT = "ACTION_REQUEST_WITH_RESULT";
+    public final static String ACTION_CHECK_WITH_RESULT = "ACTION_CHECK_WITH_RESULT";
+    public final static String ACTION_CHECK = "ACTION_CHECK";
+
+    public final static String KEY_PASSCODE  = "KEY_PASSCODE";
+    public final static String KEY_CHECK_RESULT = "KEY_CHECK_RESULT";
 
     private Button mBCancel;
     private TextView mPassCodeHdr;
     private TextView mPassCodeHdrExplanation;
     private EditText[] mPassCodeEditTexts = new EditText[4];
-    
+
     private String [] mPassCodeDigits = {"","","",""};
     private static String KEY_PASSCODE_DIGITS = "PASSCODE_DIGITS";
     private boolean mConfirmingPassCode = false;
@@ -88,13 +89,13 @@ public class PassCodeActivity extends AppCompatActivity {
         mPassCodeEditTexts[2] = (EditText) findViewById(R.id.txt2);
         mPassCodeEditTexts[3] = (EditText) findViewById(R.id.txt3);
 
-        if (ACTION_REQUEST.equals(getIntent().getAction())) {
+        if (ACTION_CHECK.equals(getIntent().getAction())) {
             /// this is a pass code request; the user has to input the right value
             mPassCodeHdr.setText(R.string.pass_code_enter_pass_code);
             mPassCodeHdrExplanation.setVisibility(View.INVISIBLE);
             setCancelButtonEnabled(false);      // no option to cancel
 
-        } else if (ACTION_ENABLE.equals(getIntent().getAction())) {
+        } else if (ACTION_REQUEST_WITH_RESULT.equals(getIntent().getAction())) {
             if (savedInstanceState != null) {
                 mConfirmingPassCode = savedInstanceState.getBoolean(PassCodeActivity.KEY_CONFIRMING_PASSCODE);
                 mPassCodeDigits = savedInstanceState.getStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS);
@@ -112,7 +113,7 @@ public class PassCodeActivity extends AppCompatActivity {
                 setCancelButtonEnabled(true);
             }
 
-        } else if (ACTION_DISABLE.equals(getIntent().getAction())) {
+        } else if (ACTION_CHECK_WITH_RESULT.equals(getIntent().getAction())) {
             /// pass code preference has just been disabled in Preferences;
             // will confirm user knows pass code, then remove it
             mPassCodeHdr.setText(R.string.pass_code_remove_your_pass_code);
@@ -284,7 +285,7 @@ public class PassCodeActivity extends AppCompatActivity {
      * the previously typed pass code, if any.
      */
     private void processFullPassCode() {
-        if (ACTION_REQUEST.equals(getIntent().getAction())) {
+        if (ACTION_CHECK.equals(getIntent().getAction())) {
             if (checkPassCode()) {
                 /// pass code accepted in request, user is allowed to access the app
                 finish();
@@ -294,24 +295,20 @@ public class PassCodeActivity extends AppCompatActivity {
                         View.INVISIBLE);
             }
 
-        } else if (ACTION_DISABLE.equals(getIntent().getAction())) {
+        } else if (ACTION_CHECK_WITH_RESULT.equals(getIntent().getAction())) {
             if (checkPassCode()) {
-                /// pass code accepted when disabling, pass code is removed
-                SharedPreferences.Editor appPrefs = PreferenceManager
-                        .getDefaultSharedPreferences(getApplicationContext()).edit();
-                appPrefs.putBoolean("set_pincode", false);  // TODO remove; this should be
-                // unnecessary, was done before entering in the activity
-                appPrefs.commit();
-
-                Toast.makeText(PassCodeActivity.this, R.string.pass_code_removed, Toast.LENGTH_LONG).show();
-                finish();
 
+                Intent resultIntent = new Intent();
+                resultIntent.putExtra(KEY_CHECK_RESULT, true);
+                setResult(RESULT_OK, resultIntent);
+
+                finish();
             } else {
                 showErrorAndRestart(R.string.pass_code_wrong, R.string.pass_code_enter_pass_code,
                         View.INVISIBLE);
             }
 
-        } else if (ACTION_ENABLE.equals(getIntent().getAction())) {
+        } else if (ACTION_REQUEST_WITH_RESULT.equals(getIntent().getAction())) {
             /// enabling pass code
             if (!mConfirmingPassCode) {
                 requestPassCodeConfirmation();
@@ -403,7 +400,7 @@ public class PassCodeActivity extends AppCompatActivity {
 
     /**
      * Overrides click on the BACK arrow to correctly cancel ACTION_ENABLE or ACTION_DISABLE, while
-     * preventing than ACTION_REQUEST may be worked around.
+     * preventing than ACTION_CHECK may be worked around.
      *
      * @param keyCode       Key code of the key that triggered the down event.
      * @param event         Event triggered.
@@ -412,8 +409,8 @@ public class PassCodeActivity extends AppCompatActivity {
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event){
         if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount()== 0){
-            if (ACTION_ENABLE.equals(getIntent().getAction()) ||
-                    ACTION_DISABLE.equals(getIntent().getAction())) {
+            if (ACTION_REQUEST_WITH_RESULT.equals(getIntent().getAction()) ||
+                    ACTION_CHECK_WITH_RESULT.equals(getIntent().getAction())) {
                 revertActionAndExit();
             }
             return true;
@@ -427,16 +424,12 @@ public class PassCodeActivity extends AppCompatActivity {
     protected void savePassCodeAndExit() {
         SharedPreferences.Editor appPrefs = PreferenceManager
                 .getDefaultSharedPreferences(getApplicationContext()).edit();
-        
-        appPrefs.putString("PrefPinCode1", mPassCodeDigits[0]);
-        appPrefs.putString("PrefPinCode2", mPassCodeDigits[1]);
-        appPrefs.putString("PrefPinCode3", mPassCodeDigits[2]);
-        appPrefs.putString("PrefPinCode4", mPassCodeDigits[3]);
-        appPrefs.putBoolean("set_pincode", true);    /// TODO remove; unnecessary,
-                                                     // Preferences did it before entering here
-        appPrefs.commit();
-
-        Toast.makeText(this, R.string.pass_code_stored, Toast.LENGTH_LONG).show();
+
+        Intent resultIntent = new Intent();
+        resultIntent.putExtra(KEY_PASSCODE,
+                mPassCodeDigits[0] + mPassCodeDigits[1] + mPassCodeDigits[2] + mPassCodeDigits[3]);
+
+        setResult(RESULT_OK, resultIntent);
         finish();
     }
 
@@ -467,7 +460,6 @@ public class PassCodeActivity extends AppCompatActivity {
         outState.putStringArray(PassCodeActivity.KEY_PASSCODE_DIGITS, mPassCodeDigits);
     }
 
-
     private class PassCodeDigitTextWatcher implements TextWatcher {
 
         private int mIndex = -1;
@@ -534,5 +526,4 @@ public class PassCodeActivity extends AppCompatActivity {
 
     }
 
-
 }
index e1c5c10..863a0e4 100644 (file)
@@ -34,7 +34,9 @@ import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.preference.CheckBoxPreference;
@@ -62,6 +64,7 @@ import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
 import android.widget.ListView;
+import android.widget.Toast;
 
 import com.owncloud.android.BuildConfig;
 import com.owncloud.android.MainApp;
@@ -70,15 +73,25 @@ import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.authentication.AuthenticatorActivity;
 import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
 import com.owncloud.android.db.DbHandler;
 import com.owncloud.android.files.FileOperationsHelper;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.services.OperationsService;
+import com.owncloud.android.ui.PreferenceWithLongSummary;
 import com.owncloud.android.ui.RadioButtonPreference;
 import com.owncloud.android.utils.DisplayUtils;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.concurrent.ExecutionException;
+import java.io.File;
+
 
 /**
  * An Activity that allows the user to change the application's settings.
@@ -93,6 +106,10 @@ public class Preferences extends PreferenceActivity
 
     private static final int ACTION_SELECT_UPLOAD_PATH = 1;
     private static final int ACTION_SELECT_UPLOAD_VIDEO_PATH = 2;
+    private static final int ACTION_REQUEST_PASSCODE = 5;
+    private static final int ACTION_CONFIRM_PASSCODE = 6;
+    private static final int ACTION_SELECT_STORAGE_PATH = 3;
+    private static final int ACTION_PERFORM_MIGRATION = 4;
 
     private DbHandler mDbHandler;
     private CheckBoxPreference pCode;
@@ -116,6 +133,9 @@ public class Preferences extends PreferenceActivity
     protected FileDownloader.FileDownloaderBinder mDownloaderBinder = null;
     protected FileUploader.FileUploaderBinder mUploaderBinder = null;
     private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
+    private PreferenceWithLongSummary mPrefStoragePath;
+    private String mStoragePath;
+
 
     @SuppressWarnings("deprecation")
     @Override
@@ -219,28 +239,53 @@ public class Preferences extends PreferenceActivity
         registerForContextMenu(getListView());
 
         pCode = (CheckBoxPreference) findPreference("set_pincode");
-        if (pCode != null){
+        if (pCode != null) {
             pCode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
                 @Override
                 public boolean onPreferenceChange(Preference preference, Object newValue) {
                     Intent i = new Intent(getApplicationContext(), PassCodeActivity.class);
-                    Boolean enable = (Boolean) newValue;
+                    Boolean incoming = (Boolean) newValue;
+
                     i.setAction(
-                            enable.booleanValue() ? PassCodeActivity.ACTION_ENABLE :
-                                    PassCodeActivity.ACTION_DISABLE
+                            incoming.booleanValue() ? PassCodeActivity.ACTION_REQUEST_WITH_RESULT :
+                                    PassCodeActivity.ACTION_CHECK_WITH_RESULT
                     );
-                    startActivity(i);
-                    
-                    return true;
+
+                    startActivityForResult(i, incoming.booleanValue() ? ACTION_REQUEST_PASSCODE :
+                            ACTION_CONFIRM_PASSCODE);
+
+                    // Don't update just yet, we will decide on it in onActivityResult
+                    return false;
                 }
-            });            
+            });
             
         }
 
+        final Preference pCacheSize = findPreference("pref_cache_size");
+        if (pCacheSize != null){
+            final SharedPreferences appPrefs =
+                    PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+            Long cacheSize = ThumbnailsCacheManager.getMaxSize();
+            pCacheSize.setSummary(cacheSize + " Mb");
+            pCacheSize.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+                @Override
+                public boolean onPreferenceChange(Preference preference, Object newValue) {
+                    Long size = Long.decode((String) newValue);
+                    if (ThumbnailsCacheManager.setMaxSize(size)){
+                        appPrefs.edit().putString("pref_cache_size", size.toString());
+                        pCacheSize.setSummary(size + " MB");
+                        return true;
+                    } else {
+                        return false;
+                    }
+                }
+            });
+        }
+
         PreferenceCategory preferenceCategory = (PreferenceCategory) findPreference("more");
         
         boolean helpEnabled = getResources().getBoolean(R.bool.help_enabled);
-        Preference pHelp =  findPreference("help");
+        Preference pHelp = findPreference("help");
         if (pHelp != null ){
             if (helpEnabled) {
                 pHelp.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -262,7 +307,7 @@ public class Preferences extends PreferenceActivity
         }
 
         if (BuildConfig.DEBUG) {
-            Preference pLog =  findPreference("log");
+            Preference pLog = findPreference("log");
             if (pLog != null ){
                 pLog.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                     @Override
@@ -305,7 +350,7 @@ public class Preferences extends PreferenceActivity
                         intent.putExtra(Intent.EXTRA_TEXT, recommendText);
                         startActivity(intent);
 
-                        return(true);
+                        return true;
 
                     }
                 });
@@ -322,9 +367,10 @@ public class Preferences extends PreferenceActivity
                 pFeedback.setOnPreferenceClickListener(new OnPreferenceClickListener() {
                     @Override
                     public boolean onPreferenceClick(Preference preference) {
-                        String feedbackMail   =(String) getText(R.string.mail_feedback);
-                        String feedback   =(String) getText(R.string.prefs_feedback) + " - android v" + appVersion;
-                        Intent intent = new Intent(Intent.ACTION_SENDTO); 
+                        String feedbackMail = (String) getText(R.string.mail_feedback);
+                        String feedback     = String.format("%s - android v%s", getText(R.string.prefs_feedback),  appVersion);
+                        Intent intent       = new Intent(Intent.ACTION_SENDTO);
+
                         intent.setType("text/plain");
                         intent.putExtra(Intent.EXTRA_SUBJECT, feedback);
                         
@@ -363,7 +409,29 @@ public class Preferences extends PreferenceActivity
             }
         }
 
-        mPrefInstantUploadPath =  findPreference("instant_upload_path");
+        mPrefStoragePath =  (PreferenceWithLongSummary)findPreference("storage_path");
+        if (mPrefStoragePath != null) {
+
+            mPrefStoragePath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    Intent intent = new Intent(Preferences.this, LocalDirectorySelectorActivity.class);
+                    intent.putExtra(UploadFilesActivity.KEY_DIRECTORY_PATH, mStoragePath);
+                    startActivityForResult(intent, ACTION_SELECT_STORAGE_PATH);
+                    return true;
+                }
+            });
+
+            mPrefStoragePath.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+                    @Override
+                    public boolean onPreferenceChange(Preference preference, Object newValue) {
+                        MainApp.setStoragePath((String) newValue);
+                        return true;
+                    }
+                });
+        }
+
+        mPrefInstantUploadPath = (PreferenceWithLongSummary)findPreference("instant_upload_path");
         if (mPrefInstantUploadPath != null){
 
             mPrefInstantUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -383,7 +451,7 @@ public class Preferences extends PreferenceActivity
         mPrefInstantUploadCategory =
                 (PreferenceCategory) findPreference("instant_uploading_category");
         
-        mPrefInstantUploadPathWiFi =  findPreference("instant_upload_on_wifi");
+        mPrefInstantUploadPathWiFi = findPreference("instant_upload_on_wifi");
         mPrefInstantUpload = findPreference("instant_uploading");
         
         toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked());
@@ -429,13 +497,21 @@ public class Preferences extends PreferenceActivity
         });
             
         /* About App */
-       pAboutApp = (Preference) findPreference("about_app");
+       pAboutApp = findPreference("about_app");
        if (pAboutApp != null) { 
-               pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name)));
-               pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion));
+               pAboutApp.setTitle(String.format(getString(R.string.about_android),
+                                                getString(R.string.app_name)));
+           try {
+               Integer currentVersion = getPackageManager().getPackageInfo
+                  (getPackageName(), 0).versionCode;
+               pAboutApp.setSummary(String.format(getString(R.string.about_version),
+                                    currentVersion));
+           } catch (NameNotFoundException e) {
+           }
        }
 
        loadInstantUploadPath();
+       loadStoragePath();
        loadInstantUploadVideoPath();
 
         /* ComponentsGetter */
@@ -450,6 +526,65 @@ public class Preferences extends PreferenceActivity
                     Context.BIND_AUTO_CREATE);
         }
 
+        /* Link to Beta apks */
+        Preference pBetaLink =  findPreference("beta_link");
+        if (pBetaLink != null ){
+            pBetaLink.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    Integer latestVersion = -1;
+                    Integer currentVersion = -1;
+                    try {
+                        currentVersion = getPackageManager().getPackageInfo
+                                                 (getPackageName(), 0).versionCode;
+                        LoadingVersionNumberTask loadTask = new LoadingVersionNumberTask();
+                        loadTask.execute();
+                        latestVersion = loadTask.get();
+                    } catch (InterruptedException | ExecutionException e) {
+                        e.printStackTrace();
+                    } catch (NameNotFoundException e) {
+                        e.printStackTrace();
+                    }
+                    if (latestVersion == -1 || currentVersion == -1) {
+                        Toast.makeText(getApplicationContext(), "No information available!",
+                                       Toast.LENGTH_SHORT).show();
+                    }
+                    if (latestVersion > currentVersion) {
+                        String betaLinkWeb = (String) getText(R.string.beta_link) +
+                                                              latestVersion + ".apk";
+                        if (betaLinkWeb != null && betaLinkWeb.length() > 0) {
+                            Uri uriUrl = Uri.parse(betaLinkWeb);
+                            Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
+                            startActivity(intent);
+                            return true;
+                        }
+                    } else {
+                        Toast.makeText(getApplicationContext(), "No new version available!",
+                                       Toast.LENGTH_SHORT).show();
+                        return true;
+                    }
+                    return true;
+                }
+            });
+        }
+
+        /* Link to Beta apks */
+        Preference pChangelogLink =  findPreference("changelog_link");
+        if (pChangelogLink != null) {
+            pChangelogLink.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+                @Override
+                public boolean onPreferenceClick(Preference preference) {
+                    String betaLinkWeb = getString(R.string.changelog);
+                    if (betaLinkWeb != null && betaLinkWeb.length() > 0) {
+                        Uri uriUrl = Uri.parse(betaLinkWeb);
+                        Intent intent = new Intent(Intent.ACTION_VIEW, uriUrl);
+                        startActivity(intent);
+                        return true;
+                    }
+                    return true;
+                }
+            });
+        }
     }
     
     private void toggleInstantPictureOptions(Boolean value){
@@ -457,8 +592,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 +602,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);
         }
     }
 
@@ -554,8 +689,7 @@ public class Preferences extends PreferenceActivity
 
         if (requestCode == ACTION_SELECT_UPLOAD_PATH && resultCode == RESULT_OK){
 
-            OCFile folderToUpload =
-                    (OCFile) data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
+            OCFile folderToUpload =  data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
 
             mUploadPath = folderToUpload.getRemotePath();
 
@@ -566,10 +700,9 @@ public class Preferences extends PreferenceActivity
 
             saveInstantUploadPathOnPreferences();
 
-        } else if (requestCode == ACTION_SELECT_UPLOAD_VIDEO_PATH && resultCode == RESULT_OK){
+        } else if (requestCode == ACTION_SELECT_UPLOAD_VIDEO_PATH && resultCode == RESULT_OK) {
 
-            OCFile folderToUploadVideo =
-                    (OCFile) data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
+            OCFile folderToUploadVideo = data.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER);
 
             mUploadVideoPath = folderToUploadVideo.getRemotePath();
 
@@ -579,6 +712,44 @@ public class Preferences extends PreferenceActivity
             mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath);
 
             saveInstantUploadVideoPathOnPreferences();
+        } else if (requestCode == ACTION_SELECT_STORAGE_PATH && resultCode == RESULT_OK) {
+            File currentStorageDir = new File(mStoragePath);
+            File upcomingStorageDir = new File(data.getStringExtra(UploadFilesActivity.EXTRA_CHOSEN_FILES));
+
+            if (currentStorageDir != upcomingStorageDir) {
+                Intent migrationIntent = new Intent(this, StorageMigrationActivity.class);
+                migrationIntent.putExtra(StorageMigrationActivity.KEY_MIGRATION_SOURCE_DIR,
+                        currentStorageDir.getAbsolutePath());
+                migrationIntent.putExtra(StorageMigrationActivity.KEY_MIGRATION_TARGET_DIR,
+                        upcomingStorageDir.getAbsolutePath());
+                startActivityForResult(migrationIntent, ACTION_PERFORM_MIGRATION);
+            }
+        } else if (requestCode == ACTION_PERFORM_MIGRATION && resultCode == RESULT_OK) {
+            String resultStorageDir = data.getStringExtra(StorageMigrationActivity.KEY_MIGRATION_TARGET_DIR);
+            saveStoragePath(resultStorageDir);
+        } else if (requestCode == ACTION_REQUEST_PASSCODE && resultCode == RESULT_OK) {
+            String passcode = data.getStringExtra(PassCodeActivity.KEY_PASSCODE);
+            if (passcode != null && passcode.length() == 4) {
+                SharedPreferences.Editor appPrefs = PreferenceManager
+                        .getDefaultSharedPreferences(getApplicationContext()).edit();
+
+                for (int i = 1; i <= 4; ++i) {
+                    appPrefs.putString("PrefPinCode" + i, passcode.substring(i-1, i));
+                }
+                appPrefs.putBoolean("set_pincode", true);
+                appPrefs.commit();
+                Toast.makeText(this, R.string.pass_code_stored, Toast.LENGTH_LONG).show();
+            }
+        } else if (requestCode == ACTION_CONFIRM_PASSCODE && resultCode == RESULT_OK) {
+            if (data.getBooleanExtra(PassCodeActivity.KEY_CHECK_RESULT, false)) {
+
+                SharedPreferences.Editor appPrefs = PreferenceManager
+                        .getDefaultSharedPreferences(getApplicationContext()).edit();
+                appPrefs.putBoolean("set_pincode", false);
+                appPrefs.commit();
+
+                Toast.makeText(this, R.string.pass_code_removed, Toast.LENGTH_LONG).show();
+            }
         }
     }
 
@@ -603,6 +774,7 @@ public class Preferences extends PreferenceActivity
     public void setContentView(View view) {
         getDelegate().setContentView(view);
     }
+
     @Override
     public void setContentView(View view, ViewGroup.LayoutParams params) {
         getDelegate().setContentView(view, params);
@@ -788,6 +960,31 @@ public class Preferences extends PreferenceActivity
     }
 
     /**
+     * Save storage path
+     */
+    private void saveStoragePath(String newStoragePath) {
+        SharedPreferences appPrefs =
+                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+        mStoragePath = newStoragePath;
+        MainApp.setStoragePath(mStoragePath);
+        SharedPreferences.Editor editor = appPrefs.edit();
+        editor.putString("storage_path", mStoragePath);
+        editor.commit();
+        mPrefStoragePath.setSummary(mStoragePath);
+    }
+
+    /**
+     * Load storage path set on preferences
+     */
+    private void loadStoragePath() {
+        SharedPreferences appPrefs =
+                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+        mStoragePath = appPrefs.getString("storage_path", Environment.getExternalStorageDirectory()
+                                                         .getAbsolutePath());
+        mPrefStoragePath.setSummary(mStoragePath);
+    }
+
+    /**
      * Save the "Instant Upload Path" on preferences
      */
     private void saveInstantUploadPathOnPreferences() {
@@ -802,10 +999,7 @@ public class Preferences extends PreferenceActivity
      * Load upload video path set on preferences
      */
     private void loadInstantUploadVideoPath() {
-        SharedPreferences appPrefs =
-                PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
-        mUploadVideoPath = appPrefs.getString("instant_video_upload_path", getString(R.string.instant_upload_path));
-        mPrefInstantVideoUploadPath.setSummary(mUploadVideoPath);
+        mPrefInstantVideoUploadPath.setSummary(MainApp.getStoragePath());
     }
 
     /**
@@ -819,7 +1013,7 @@ public class Preferences extends PreferenceActivity
         editor.commit();
     }
 
-    // Methods for ComponetsGetter
+    // Methods for ComponentsGetter
     @Override
     public FileDownloader.FileDownloaderBinder getFileDownloaderBinder() {
         return mDownloaderBinder;
@@ -858,14 +1052,10 @@ public class Preferences extends PreferenceActivity
 
             if (component.equals(new ComponentName(Preferences.this, FileDownloader.class))) {
                 mDownloaderBinder = (FileDownloader.FileDownloaderBinder) service;
-
             } else if (component.equals(new ComponentName(Preferences.this, FileUploader.class))) {
                 Log_OC.d(TAG, "Upload service connected");
                 mUploaderBinder = (FileUploader.FileUploaderBinder) service;
-            } else {
-                return;
             }
-
         }
 
         @Override
@@ -879,4 +1069,29 @@ public class Preferences extends PreferenceActivity
             }
         }
     };
+
+    /**
+     *
+     * Class for loading the version number
+     *
+     */
+    private class LoadingVersionNumberTask extends AsyncTask<Void, Void, Integer> {
+        protected Integer doInBackground(Void... args) {
+            try {
+                URL url = new URL("https://github.com/owncloud/android/raw/beta/apks/latest");
+                BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
+
+                Integer latestVersion = Integer.parseInt(in.readLine());
+                in.close();
+
+                return latestVersion;
+
+            } catch (MalformedURLException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            return -1;
+        }
+    }
 }
diff --git a/src/com/owncloud/android/ui/activity/ShareActivity.java b/src/com/owncloud/android/ui/activity/ShareActivity.java
new file mode 100644 (file)
index 0000000..180b2a0
--- /dev/null
@@ -0,0 +1,197 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.activity;
+
+import android.app.SearchManager;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+
+import com.owncloud.android.R;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.providers.UsersAndGroupsSearchProvider;
+
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.ui.fragment.SearchShareesFragment;
+import com.owncloud.android.ui.fragment.ShareFileFragment;
+import com.owncloud.android.utils.GetShareWithUsersAsyncTask;
+
+
+/**
+ * Activity for sharing files
+ */
+
+public class ShareActivity extends FileActivity
+        implements ShareFileFragment.OnShareFragmentInteractionListener,
+        SearchShareesFragment.OnSearchFragmentInteractionListener {
+
+    private static final String TAG = ShareActivity.class.getSimpleName();
+
+    private static final String TAG_SHARE_FRAGMENT = "SHARE_FRAGMENT";
+    private static final String TAG_SEARCH_FRAGMENT = "SEARCH_USER_AND_GROUPS_FRAGMENT";
+
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.share_activity);
+
+        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+
+        if (savedInstanceState == null) {
+            // Add Share fragment on first creation
+            Fragment fragment = ShareFileFragment.newInstance(getFile(), getAccount());
+            ft.replace(R.id.share_fragment_container, fragment, TAG_SHARE_FRAGMENT);
+            ft.commit();
+        }
+
+    }
+
+    protected void onAccountSet(boolean stateWasRecovered) {
+        super.onAccountSet(stateWasRecovered);
+
+        // Load data into the list
+        Log_OC.d(TAG, "Refreshing lists on account set");
+        refreshUsersInLists();
+
+        // Request for a refresh of the data through the server (starts an Async Task)
+        refreshUsersOrGroupsListFromServer();
+    }
+
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        // Verify the action and get the query
+        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
+            String query = intent.getStringExtra(SearchManager.QUERY);
+            Log_OC.w(TAG, "Ignored Intent requesting to query for " + query);
+
+        } else if (UsersAndGroupsSearchProvider.ACTION_SHARE_WITH.equals(intent.getAction())) {
+            Uri data = intent.getData();
+            doShareWith(
+                    data.getLastPathSegment(),
+                    UsersAndGroupsSearchProvider.DATA_GROUP.equals(data.getAuthority())
+            );
+
+        } else {
+            Log_OC.wtf(TAG, "Unexpected intent " + intent.toString());
+        }
+    }
+
+    private void doShareWith(String shareeName, boolean isGroup) {
+        getFileOperationsHelper().shareFileWithSharee(
+                getFile(),
+                shareeName,
+                (isGroup ? ShareType.GROUP : ShareType.USER)
+        );
+    }
+
+    @Override
+    public void showSearchUsersAndGroups() {
+        // replace ShareFragment with SearchFragment on demand
+        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+        Fragment searchFragment = SearchShareesFragment.newInstance(getFile(), getAccount());
+        ft.replace(R.id.share_fragment_container, searchFragment, TAG_SEARCH_FRAGMENT);
+        ft.addToBackStack(null);    // BACK button will recover the ShareFragment
+        ft.commit();
+    }
+
+    @Override
+    // Call to Unshare operation
+    public void unshareWith(OCShare share) {
+        OCFile file = getFile();
+        getFileOperationsHelper().unshareFileWithUserOrGroup(file, share.getShareType(), share.getShareWith());
+    }
+
+    /**
+     * Get users and groups from the server to fill in the "share with" list
+     */
+    @Override
+    public void refreshUsersOrGroupsListFromServer() {
+        // Show loading
+        showLoadingDialog(getString(R.string.common_loading));
+        // Get Users and Groups
+        GetShareWithUsersAsyncTask getTask = new GetShareWithUsersAsyncTask(this);
+        Object[] params = {getFile(), getAccount(), getStorageManager()};
+        getTask.execute(params);
+    }
+
+    /**
+     * Updates the view associated to the activity after the finish of some operation over files
+     * in the current account.
+     *
+     * @param operation Removal operation performed.
+     * @param result    Result of the removal.
+     */
+    @Override
+    public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
+        super.onRemoteOperationFinish(operation, result);
+
+        if (result.isSuccess()) {
+            Log_OC.d(TAG, "Refreshing lists on successful sync");
+            refreshUsersInLists();
+        }
+
+    }
+
+    private void refreshUsersInLists() {
+        ShareFileFragment shareFileFragment = getShareFileFragment();
+        if (shareFileFragment != null) {          // only if added to the view hierarchy!!
+            if (shareFileFragment.isAdded()) {
+                shareFileFragment.refreshUsersOrGroupsListFromDB();
+            }
+        }
+
+        SearchShareesFragment searchShareesFragment = getSearchFragment();
+        if (searchShareesFragment != null) {
+            if (searchShareesFragment.isAdded()) {  // only if added to the view hierarchy!!
+                searchShareesFragment.refreshUsersOrGroupsListFromDB();
+            }
+        }
+    }
+
+    /**
+     * Shortcut to get access to the {@link ShareFileFragment} instance, if any
+     *
+     * @return  A {@link ShareFileFragment} instance, or null
+     */
+    private ShareFileFragment getShareFileFragment() {
+        return (ShareFileFragment) getSupportFragmentManager().findFragmentByTag(TAG_SHARE_FRAGMENT);
+    }
+
+    /**
+     * Shortcut to get access to the {@link SearchShareesFragment} instance, if any
+     *
+     * @return  A {@link SearchShareesFragment} instance, or null
+     */
+    private SearchShareesFragment getSearchFragment() {
+        return (SearchShareesFragment) getSupportFragmentManager().findFragmentByTag(TAG_SEARCH_FRAGMENT);
+    }
+
+}
diff --git a/src/com/owncloud/android/ui/activity/StorageMigrationActivity.java b/src/com/owncloud/android/ui/activity/StorageMigrationActivity.java
new file mode 100644 (file)
index 0000000..c0b4522
--- /dev/null
@@ -0,0 +1,281 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author Bartosz Przybylski
+ *   Copyright (C) 2015 ownCloud Inc.
+ *   Copyright (C) 2015 Bartosz Przybylski
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package com.owncloud.android.ui.activity;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.utils.FileStorageUtils;
+
+import java.io.File;
+
+/**
+ * Created by Bartosz Przybylski on 07.11.2015.
+ */
+public class StorageMigrationActivity extends AppCompatActivity {
+       private static final String TAG = StorageMigrationActivity.class.getName();
+       public static final String KEY_MIGRATION_TARGET_DIR = "MIGRATION_TARGET";
+       public static final String KEY_MIGRATION_SOURCE_DIR = "MIGRATION_SOURCE";
+
+       private ProgressBar mProgressBar;
+       private Button mFinishButton;
+       private TextView mFeedbackText;
+
+       @Override
+       public void onCreate(Bundle savedInstanceState) {
+               super.onCreate(savedInstanceState);
+
+               setContentView(R.layout.migration_layout);
+               mProgressBar = (ProgressBar)findViewById(R.id.migrationProgress);
+               mFinishButton = (Button)findViewById(R.id.finishButton);
+               mFeedbackText = (TextView)findViewById(R.id.migrationText);
+
+               mProgressBar.setProgress(0);
+               mFinishButton.setVisibility(View.INVISIBLE);
+               mFeedbackText.setText(R.string.file_migration_preparing);
+
+               mFinishButton.setOnClickListener(new View.OnClickListener() {
+                       @Override
+                       public void onClick(View view) {
+                               setResult(RESULT_CANCELED);
+                               finish();
+                       }
+               });
+
+               String source = getIntent().getStringExtra(KEY_MIGRATION_SOURCE_DIR);
+               String destination = getIntent().getStringExtra(KEY_MIGRATION_TARGET_DIR);
+
+               if (source == null || destination == null) {
+                       Log_OC.e(TAG, "source or destination is null");
+                       finish();
+               }
+
+               new FileMigrationTask().execute(source, destination);
+       }
+
+       private class FileMigrationTask extends AsyncTask<String, Integer, Integer> {
+
+               private String mStorageTarget;
+               private String mStorageSource;
+               private int mProgress;
+
+               private static final int mProgressCopyUpperBound = 98;
+
+               private class MigrationException extends Exception {
+                       private int mResId;
+                       /*
+                        * @param resId resource identifier to use for displaying error
+                        */
+                       MigrationException(int resId) {
+                               super();
+                               this.mResId = resId;
+                       }
+
+                       int getResId() { return mResId; }
+               }
+
+               @Override
+               protected Integer doInBackground(String... args) {
+
+                       mStorageSource = args[0];
+                       mStorageTarget = args[1];
+                       mProgress = 0;
+
+                       publishProgress(mProgress++, R.string.file_migration_preparing);
+
+                       Context context = StorageMigrationActivity.this;
+                       String ocAuthority = context.getString(R.string.authority);
+
+                       Account[] ocAccounts = AccountManager.get(context).getAccountsByType(MainApp.getAccountType());
+                       boolean[] oldAutoSync = new boolean[ocAccounts.length];
+
+                       Log_OC.stopLogging();
+
+                       try {
+                               publishProgress(mProgress++, R.string.file_migration_checking_destination);
+
+                               checkDestinationAvailability();
+
+                               publishProgress(mProgress++, R.string.file_migration_saving_accounts_configuration);
+                               saveAccountsSyncStatus(ocAuthority, ocAccounts, oldAutoSync);
+
+                               publishProgress(mProgress++, R.string.file_migration_waiting_for_unfinished_sync);
+                               stopAccountsSyncing(ocAuthority, ocAccounts);
+                               waitForUnfinishedSynchronizations(ocAuthority, ocAccounts);
+
+                               publishProgress(mProgress++, R.string.file_migration_migrating);
+                               copyFiles();
+
+                               publishProgress(mProgress++, R.string.file_migration_updating_index);
+                               updateIndex(context);
+
+                               publishProgress(mProgress++, R.string.file_migration_cleaning);
+                               cleanup();
+
+                       } catch (MigrationException e) {
+                               rollback();
+                               Log_OC.startLogging(mStorageSource);
+                               return e.getResId();
+                       } finally {
+                               publishProgress(mProgress++, R.string.file_migration_restoring_accounts_configuration);
+                               restoreAccountsSyncStatus(ocAuthority, ocAccounts, oldAutoSync);
+                       }
+
+                       Log_OC.startLogging(mStorageTarget);
+                       publishProgress(mProgress++, R.string.file_migration_ok_finished);
+
+                       return 0;
+               }
+
+               @Override
+               protected void onProgressUpdate(Integer... progress) {
+                       mProgressBar.setProgress(progress[0]);
+                       if (progress.length > 1)
+                               mFeedbackText.setText(progress[1]);
+               }
+
+               @Override
+               protected void onPostExecute(Integer code) {
+                       mFinishButton.setVisibility(View.VISIBLE);
+                       if (code != 0) {
+                               mFeedbackText.setText(code);
+                       } else {
+                               mFeedbackText.setText(R.string.file_migration_ok_finished);
+                               mFinishButton.setOnClickListener(new View.OnClickListener() {
+                                       @Override
+                                       public void onClick(View view) {
+                                               Intent resultIntent = new Intent();
+                                               resultIntent.putExtra(KEY_MIGRATION_TARGET_DIR, mStorageTarget);
+                                               setResult(RESULT_OK, resultIntent);
+                                               finish();
+                                       }
+                               });
+                       }
+               }
+
+               void checkDestinationAvailability() throws MigrationException {
+                       File srcFile = new File(mStorageSource);
+                       File dstFile = new File(mStorageTarget);
+
+                       if (!dstFile.canRead() || !srcFile.canRead())
+                               throw new MigrationException(R.string.file_migration_failed_not_readable);
+
+                       if (!dstFile.canWrite() || !srcFile.canWrite())
+                               throw new MigrationException(R.string.file_migration_failed_not_writable);
+
+                       if (new File(dstFile, MainApp.getDataFolder()).exists())
+                               throw new MigrationException(R.string.file_migration_failed_dir_already_exists);
+
+                       if (dstFile.getFreeSpace() < FileStorageUtils.getFolderSize(new File(srcFile, MainApp.getDataFolder())))
+                               throw new MigrationException(R.string.file_migration_failed_not_enough_space);
+               }
+
+               void copyFiles() throws MigrationException {
+                       File srcFile = new File(mStorageSource + File.separator + MainApp.getDataFolder());
+                       File dstFile = new File(mStorageTarget + File.separator + MainApp.getDataFolder());
+
+                       copyDirs(srcFile, dstFile);
+                       mProgress = Math.max(mProgress, mProgressCopyUpperBound);
+                       publishProgress(mProgress);
+               }
+
+               void copyDirs(File src, File dst) throws MigrationException {
+                       if (!dst.mkdirs())
+                               throw new MigrationException(R.string.file_migration_failed_while_coping);
+
+                       for (File f : src.listFiles()) {
+
+                               mProgress = Math.min(mProgress+1, mProgressCopyUpperBound);
+                               publishProgress(mProgress);
+
+                               if (f.isDirectory())
+                                       copyDirs(f, new File(dst, f.getName()));
+                               else if (!FileStorageUtils.copyFile(f, new File(dst, f.getName())))
+                                       throw new MigrationException(R.string.file_migration_failed_while_coping);
+                       }
+
+               }
+
+               void updateIndex(Context context) throws MigrationException {
+                       FileDataStorageManager manager = new FileDataStorageManager(null, context.getContentResolver());
+
+                       try {
+                               manager.migrateStoredFiles(mStorageSource, mStorageTarget);
+                       } catch (Exception e) {
+                               throw new MigrationException(R.string.file_migration_failed_while_updating_index);
+                       }
+               }
+
+               void cleanup() {
+                       File srcFile = new File(mStorageSource + File.separator + MainApp.getDataFolder());
+                       if (!srcFile.delete())
+                               Log_OC.w(TAG, "Migration cleanup step failed");
+               }
+
+               void rollback() {
+                       File dstFile = new File(mStorageTarget + File.separator + MainApp.getDataFolder());
+                       if (dstFile.exists())
+                               if (!dstFile.delete())
+                                       Log_OC.w(TAG, "Rollback step failed");
+               }
+
+               void saveAccountsSyncStatus(String authority, Account accounts[], boolean syncs[]) {
+                       for (int i = 0; i < accounts.length; ++i)
+                               syncs[i] = ContentResolver.getSyncAutomatically(accounts[i], authority);
+               }
+
+               void stopAccountsSyncing(String authority, Account accounts[]) {
+                       for (int i = 0; i < accounts.length; ++i)
+                               ContentResolver.setSyncAutomatically(accounts[i], authority, false);
+               }
+
+               void waitForUnfinishedSynchronizations(String authority, Account accounts[]) {
+                       for (int i = 0; i < accounts.length; ++i)
+                               while (ContentResolver.isSyncActive(accounts[i], authority))
+                                       try {
+                                               Thread.sleep(1000);
+                                       } catch (InterruptedException e) {
+                                               Log_OC.w(TAG, "Thread interrupted while waiting for account to end syncing");
+                                               Thread.currentThread().interrupt();
+                                       }
+               }
+
+               void restoreAccountsSyncStatus(String authority, Account accounts[], boolean oldSync[]) {
+                       for (int i = 0; i < accounts.length; ++i)
+                               ContentResolver.setSyncAutomatically(accounts[i], authority, oldSync[i]);
+               }
+
+       }
+}
index 9a3ce17..d6665e2 100644 (file)
 package com.owncloud.android.ui.activity;
 
 import android.accounts.Account;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Environment;
+import android.preference.PreferenceManager;
 import android.support.v4.app.DialogFragment;
 import android.support.v7.app.ActionBar;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
+import android.widget.RadioButton;
 import android.widget.TextView;
 
 import com.owncloud.android.R;
+import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
 import com.owncloud.android.ui.dialog.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
@@ -57,32 +65,35 @@ public class UploadFilesActivity extends FileActivity implements
     
     private ArrayAdapter<String> mDirectories;
     private File mCurrentDir = null;
-    private LocalFileListFragment mFileListFragment;
-    private Button mCancelBtn;
-    private Button mUploadBtn;
-    private Account mAccountOnCreation;
-    private DialogFragment mCurrentDialog;
+    protected LocalFileListFragment mFileListFragment;
+    protected Button mCancelBtn;
+    protected Button mUploadBtn;
+    protected Account mAccountOnCreation;
+    protected DialogFragment mCurrentDialog;
     
     public static final String EXTRA_CHOSEN_FILES =
             UploadFilesActivity.class.getCanonicalName() + ".EXTRA_CHOSEN_FILES";
 
     public static final int RESULT_OK_AND_MOVE = RESULT_FIRST_USER; 
     
-    private static final String KEY_DIRECTORY_PATH =
+    public static final String KEY_DIRECTORY_PATH =
             UploadFilesActivity.class.getCanonicalName() + ".KEY_DIRECTORY_PATH";
     private static final String TAG = "UploadFilesActivity";
     private static final String WAIT_DIALOG_TAG = "WAIT";
     private static final String QUERY_TO_MOVE_DIALOG_TAG = "QUERY_TO_MOVE";
-    
-    
+    private RadioButton mRadioBtnCopyFiles;
+    private RadioButton mRadioBtnMoveFiles;
+
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         Log_OC.d(TAG, "onCreate() start");
         super.onCreate(savedInstanceState);
 
         if(savedInstanceState != null) {
-            mCurrentDir = new File(savedInstanceState.getString(
-                    UploadFilesActivity.KEY_DIRECTORY_PATH));
+            mCurrentDir = new File(savedInstanceState.getString(KEY_DIRECTORY_PATH));
+        } else if (getIntent() != null && getIntent().hasExtra(KEY_DIRECTORY_PATH)) {
+            mCurrentDir = new File(getIntent().getStringExtra(KEY_DIRECTORY_PATH));
         } else {
             mCurrentDir = Environment.getExternalStorageDirectory();
         }
@@ -112,6 +123,21 @@ public class UploadFilesActivity extends FileActivity implements
         mCancelBtn.setOnClickListener(this);
         mUploadBtn = (Button) findViewById(R.id.upload_files_btn_upload);
         mUploadBtn.setOnClickListener(this);
+
+        SharedPreferences appPreferences = PreferenceManager
+                .getDefaultSharedPreferences(getApplicationContext());
+
+        Integer localBehaviour = appPreferences.getInt("prefs_uploader_behaviour", FileUploader.LOCAL_BEHAVIOUR_COPY);
+
+        mRadioBtnMoveFiles = (RadioButton) findViewById(R.id.upload_radio_move);
+        if (localBehaviour == FileUploader.LOCAL_BEHAVIOUR_MOVE){
+            mRadioBtnMoveFiles.setChecked(true);
+        }
+
+        mRadioBtnCopyFiles = (RadioButton) findViewById(R.id.upload_radio_copy);
+        if (localBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY){
+            mRadioBtnCopyFiles.setChecked(true);
+        }
         
             
         // Action bar setup
@@ -132,6 +158,13 @@ public class UploadFilesActivity extends FileActivity implements
         Log_OC.d(TAG, "onCreate() end");
     }
 
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.uploader_menu, menu);
+        return true;
+    }
+
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
@@ -143,6 +176,34 @@ public class UploadFilesActivity extends FileActivity implements
                 }
                 break;
             }
+            case R.id.action_sort: {
+                SharedPreferences appPreferences = PreferenceManager
+                        .getDefaultSharedPreferences(this);
+
+                // Read sorting order, default to sort by name ascending
+                Integer sortOrder = appPreferences
+                        .getInt("sortOrder", FileStorageUtils.SORT_NAME);
+
+                AlertDialog.Builder builder = new AlertDialog.Builder(this);
+                builder.setTitle(R.string.actionbar_sort_title)
+                        .setSingleChoiceItems(R.array.actionbar_sortby, sortOrder ,
+                                new DialogInterface.OnClickListener() {
+                                    public void onClick(DialogInterface dialog, int which) {
+                                        switch (which){
+                                            case 0:
+                                                mFileListFragment.sortByName(true);
+                                                break;
+                                            case 1:
+                                                mFileListFragment.sortByDate(false);
+                                                break;
+                                        }
+
+                                        dialog.dismiss();
+                                    }
+                                });
+                builder.create().show();
+                break;
+            }
             default:
                 retval = super.onOptionsItemSelected(item);
         }
@@ -342,9 +403,22 @@ public class UploadFilesActivity extends FileActivity implements
                 // return the list of selected files (success)
                 Intent data = new Intent();
                 data.putExtra(EXTRA_CHOSEN_FILES, mFileListFragment.getCheckedFilePaths());
-                setResult(RESULT_OK, data);
+
+                SharedPreferences.Editor appPreferencesEditor = PreferenceManager
+                        .getDefaultSharedPreferences(getApplicationContext()).edit();
+
+
+                if (mRadioBtnMoveFiles.isChecked()){
+                    setResult(RESULT_OK_AND_MOVE, data);
+                    appPreferencesEditor.putInt("prefs_uploader_behaviour",
+                            FileUploader.LOCAL_BEHAVIOUR_MOVE);
+                } else {
+                    setResult(RESULT_OK, data);
+                    appPreferencesEditor.putInt("prefs_uploader_behaviour",
+                            FileUploader.LOCAL_BEHAVIOUR_COPY);
+                }
+                appPreferencesEditor.apply();
                 finish();
-                
             } else {
                 // show a dialog to query the user if wants to move the selected files
                 // to the ownCloud folder instead of copying
index 0549f7d..cd80a94 100644 (file)
@@ -84,6 +84,7 @@ import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.utils.CopyTmpFileAsyncTask;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.ErrorMessageAdapter;
+import com.owncloud.android.utils.FileStorageUtils;
 
 
 /**
@@ -333,7 +334,10 @@ public class Uploader extends FileActivity
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         // click on folder in the list
         Log_OC.d(TAG, "on item click");
-        Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile, false);
+        // TODO Enable when "On Device" is recovered ?
+        Vector<OCFile> tmpfiles = getStorageManager().getFolderContent(mFile , false);
+        tmpfiles = sortFileList(tmpfiles);
+
         if (tmpfiles.size() <= 0) return;
         // filter on dirtype
         Vector<OCFile> files = new Vector<OCFile>();
@@ -398,16 +402,17 @@ public class Uploader extends FileActivity
         setContentView(R.layout.uploader_layout);
         
         ListView mListView = (ListView) findViewById(android.R.id.list);
+        ActionBar actionBar = getSupportActionBar();
 
         String current_dir = mParents.peek();
         if(current_dir.equals("")){
-            getSupportActionBar().setTitle(getString(R.string.default_display_name_for_root_folder));
+            actionBar.setTitle(getString(R.string.uploader_top_message));
         }
         else{
-            getSupportActionBar().setTitle(current_dir);
+            actionBar.setTitle(current_dir);
         }
         boolean notRoot = (mParents.size() > 1);
-        ActionBar actionBar = getSupportActionBar();
+
         actionBar.setDisplayHomeAsUpEnabled(notRoot);
         actionBar.setHomeButtonEnabled(notRoot);
 
@@ -417,20 +422,24 @@ public class Uploader extends FileActivity
 
         mFile = getStorageManager().getFileByPath(full_path);
         if (mFile != null) {
+            // TODO Enable when "On Device" is recovered ?
             Vector<OCFile> files = getStorageManager().getFolderContent(mFile, false);
+            files = sortFileList(files);
+
             List<HashMap<String, Object>> data = new LinkedList<HashMap<String,Object>>();
             for (OCFile f : files) {
-                HashMap<String, Object> h = new HashMap<String, Object>();
                 if (f.isFolder()) {
+                    HashMap<String, Object> h = new HashMap<String, Object>();
                     h.put("dirname", f.getFileName());
+                    h.put("last_mod", DisplayUtils.getRelativeTimestamp(this, f));
                     data.add(h);
                 }
             }
             SimpleAdapter sa = new SimpleAdapter(this,
                                                 data,
                                                 R.layout.uploader_list_item_layout,
-                                                new String[] {"dirname"},
-                                                new int[] {R.id.filename});
+                                                new String[] {"dirname", "last_mod"},
+                                                new int[] {R.id.filename, R.id.last_mod});
             
             mListView.setAdapter(sa);
             Button btnChooseFolder = (Button) findViewById(R.id.uploader_choose_folder);
@@ -443,6 +452,18 @@ public class Uploader extends FileActivity
         }
     }
 
+    private Vector<OCFile> sortFileList(Vector<OCFile> files) {
+        SharedPreferences sharedPreferences = PreferenceManager
+                .getDefaultSharedPreferences(this);
+
+        // Read sorting order, default to sort by name ascending
+        FileStorageUtils.mSortOrder = sharedPreferences.getInt("sortOrder", 0);
+        FileStorageUtils.mSortAscending = sharedPreferences.getBoolean("sortAscending", true);
+
+        files = FileStorageUtils.sortOcFolder(files);
+        return files;
+    }
+
     private String generatePath(Stack<String> dirs) {
         String full_path = "";
 
@@ -606,9 +627,11 @@ public class Uploader extends FileActivity
                                                RemoteOperationResult result) {
         if (result.isSuccess()) {
             dismissLoadingDialog();
+            String remotePath = operation.getRemotePath().substring(0, operation.getRemotePath().length() -1);
+            String newFolder = remotePath.substring(remotePath.lastIndexOf("/") + 1);
+            mParents.push(newFolder);
             populateDirectoryList();
         } else {
-            dismissLoadingDialog();
             try {
                 Toast msg = Toast.makeText(this, 
                         ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()), 
@@ -656,7 +679,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;
index 0f2536f..5a53a86 100644 (file)
@@ -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 {
@@ -193,4 +193,12 @@ public class DiskLruImageCache {
             e.printStackTrace();
         }
     }
+
+    public void setMaxSize(long maxSize){
+        mDiskCache.setMaxSize(maxSize);
+    }
+
+    public long getMaxSize(){
+        return mDiskCache.getMaxSize();
+    }
 }
\ No newline at end of file
diff --git a/src/com/owncloud/android/ui/adapter/DiskLruImageCacheFileProvider.java b/src/com/owncloud/android/ui/adapter/DiskLruImageCacheFileProvider.java
new file mode 100644 (file)
index 0000000..a3c54e8
--- /dev/null
@@ -0,0 +1,140 @@
+/**
+ *   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 <http://www.gnu.org/licenses/>.
+ *
+ *   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.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.provider.OpenableColumns;
+
+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();
+    private FileDataStorageManager mFileDataStorageManager;
+
+    public static final String AUTHORITY = "org.owncloud.beta.imageCache.provider";
+
+    @Override
+    public boolean onCreate() {
+        return true;
+    }
+
+    private OCFile getFile(Uri uri){
+        Account account = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
+        mFileDataStorageManager = new FileDataStorageManager(account,
+                MainApp.getAppContext().getContentResolver());
+
+        OCFile ocFile = mFileDataStorageManager.getFileByPath(uri.getPath());
+        return ocFile;
+    }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        OCFile ocFile = getFile(uri);
+
+        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 String getType(Uri uri) {
+        OCFile ocFile = getFile(uri);
+        return ocFile.getMimetype();
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] arg1, String arg2, String[] arg3, String arg4) {
+        MatrixCursor cursor = null;
+
+        OCFile ocFile = getFile(uri);
+        File file = new File(MainApp.getAppContext().getCacheDir(), ocFile.getFileName());
+        if (file.exists()) {
+            cursor = new MatrixCursor(new String[] {
+                    OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE });
+            cursor.addRow(new Object[] { uri.getLastPathSegment(),
+                    file.length() });
+        }
+
+        return cursor;
+    }
+
+    @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;
+    }
+}
index ef1ec12..c46b296 100644 (file)
@@ -25,12 +25,19 @@ package com.owncloud.android.ui.adapter;
 \r
 \r
 import java.io.File;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
 import java.util.Vector;\r
 \r
 import android.accounts.Account;\r
 import android.content.Context;\r
 import android.content.SharedPreferences;\r
 import android.graphics.Bitmap;\r
+import android.graphics.Color;\r
+import android.graphics.BitmapFactory;\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
 import android.os.Build;\r
 import android.preference.PreferenceManager;\r
 import android.text.format.DateUtils;\r
@@ -63,7 +70,6 @@ import com.owncloud.android.utils.MimetypeIconUtil;
  * instance.\r
  */\r
 public class FileListListAdapter extends BaseAdapter implements ListAdapter {\r
-    private final static String PERMISSION_SHARED_WITH_ME = "S";\r
 \r
     private Context mContext;\r
     private OCFile mFile = null;\r
@@ -79,6 +85,8 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     private enum ViewType {LIST_ITEM, GRID_IMAGE, GRID_ITEM };\r
 \r
     private SharedPreferences mAppPreferences;\r
+\r
+    private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();\r
     \r
     public FileListListAdapter(\r
             boolean justFolders, \r
@@ -154,7 +162,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         ViewType viewType;\r
         if (!mGridMode){\r
             viewType = ViewType.LIST_ITEM;\r
-        } else if (file.isImage()){\r
+        } else if (file.isImage() || file.isVideo()){\r
             viewType = ViewType.GRID_IMAGE;\r
         } else {\r
             viewType = ViewType.GRID_ITEM;\r
@@ -194,36 +202,38 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             switch (viewType){\r
                 case LIST_ITEM:\r
                     TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);\r
+                    TextView fileSizeSeparatorV = (TextView) view.findViewById(R.id.file_separator);\r
                     TextView lastModV = (TextView) view.findViewById(R.id.last_mod);\r
-                    ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+\r
 \r
                     lastModV.setVisibility(View.VISIBLE);\r
-                    lastModV.setText(showRelativeTimestamp(file));\r
+                    lastModV.setText(DisplayUtils.getRelativeTimestamp(mContext, file));\r
 \r
-                    checkBoxV.setVisibility(View.GONE);\r
 \r
+                    fileSizeSeparatorV.setVisibility(View.VISIBLE);\r
                     fileSizeV.setVisibility(View.VISIBLE);\r
                     fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));\r
 \r
-                    if (!file.isFolder()) {\r
-                        AbsListView parentList = (AbsListView)parent;\r
-                        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
-                            if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
-                                checkBoxV.setVisibility(View.GONE);\r
-                            } else {\r
-                                if (parentList.isItemChecked(position)) {\r
-                                    checkBoxV.setImageResource(\r
-                                            android.R.drawable.checkbox_on_background);\r
-                                } else {\r
-                                    checkBoxV.setImageResource(\r
-                                            android.R.drawable.checkbox_off_background);\r
-                                }\r
-                                checkBoxV.setVisibility(View.VISIBLE);\r
-                            }\r
-                        }\r
-\r
-                    } else { //Folder\r
-                        fileSizeV.setVisibility(View.INVISIBLE);\r
+//                    if (!file.isFolder()) {\r
+//                        AbsListView parentList = (AbsListView)parent;\r
+//                        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+//                            if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+//                                checkBoxV.setVisibility(View.GONE);\r
+//                            } else {\r
+//                                if (parentList.isItemChecked(position)) {\r
+//                                    checkBoxV.setImageResource(\r
+//                                            R.drawable.ic_checkbox_marked);\r
+//                                } else {\r
+//                                    checkBoxV.setImageResource(\r
+//                                            R.drawable.ic_checkbox_blank_outline);\r
+//                                }\r
+//                                checkBoxV.setVisibility(View.VISIBLE);\r
+//                            }\r
+//                        }\r
+\r
+                    if (file.isFolder()) {\r
+                        fileSizeSeparatorV.setVisibility(View.GONE);\r
+                        fileSizeV.setVisibility(View.GONE);\r
                     }\r
 \r
                 case GRID_ITEM:\r
@@ -235,13 +245,21 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 case GRID_IMAGE:\r
                     // sharedIcon\r
                     ImageView sharedIconV = (ImageView) view.findViewById(R.id.sharedIcon);\r
-                    if (file.isShareByLink()) {\r
+                    if (file.isSharedViaLink()) {\r
+                        sharedIconV.setImageResource(R.drawable.shared_via_link);\r
+                        sharedIconV.setVisibility(View.VISIBLE);\r
+                        sharedIconV.bringToFront();\r
+                    } else if (file.isSharedWithSharee() || file.isSharedWithMe() ) {\r
+                        sharedIconV.setImageResource(R.drawable.shared_via_users);\r
                         sharedIconV.setVisibility(View.VISIBLE);\r
                         sharedIconV.bringToFront();\r
                     } else {\r
                         sharedIconV.setVisibility(View.GONE);\r
                     }\r
 \r
+                    /*ImageView sharedWithMeIcon = (ImageView) view.findViewById(R.id.sharedWithMeIcon);\r
+                    sharedWithMeIcon.bringToFront();*/\r
+\r
                     // local state\r
                     ImageView localStateView = (ImageView) view.findViewById(R.id.localFileIndicator);\r
                     localStateView.bringToFront();\r
@@ -249,38 +267,69 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                             mTransferServiceGetter.getFileDownloaderBinder();\r
                     FileUploaderBinder uploaderBinder =\r
                             mTransferServiceGetter.getFileUploaderBinder();\r
-                    boolean downloading = (downloaderBinder != null &&\r
-                            downloaderBinder.isDownloading(mAccount, file));\r
                     OperationsServiceBinder opsBinder =\r
                             mTransferServiceGetter.getOperationsServiceBinder();\r
-                    downloading |= (opsBinder != null &&\r
-                            opsBinder.isSynchronizing(mAccount, file.getRemotePath()));\r
-                    if (downloading) {\r
-                        localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+\r
+                    localStateView.setVisibility(View.INVISIBLE);   // default first\r
+\r
+                    if ( //synchronizing\r
+                                opsBinder != null &&\r
+                                opsBinder.isSynchronizing(mAccount, file.getRemotePath())\r
+                            ) {\r
+                        localStateView.setImageResource(R.drawable.synchronizing_file_indicator);\r
                         localStateView.setVisibility(View.VISIBLE);\r
-                    } else if (uploaderBinder != null &&\r
-                            uploaderBinder.isUploading(mAccount, file)) {\r
-                        localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+\r
+                    } else if ( // downloading\r
+                                downloaderBinder != null &&\r
+                                downloaderBinder.isDownloading(mAccount, file)\r
+                            ) {\r
+                        localStateView.setImageResource(\r
+                                file.isFolder() ?\r
+                                        R.drawable.synchronizing_file_indicator :\r
+                                        R.drawable.downloading_file_indicator\r
+                        );\r
+                        localStateView.setVisibility(View.VISIBLE);\r
+\r
+                    } else if ( //uploading\r
+                                uploaderBinder != null &&\r
+                                uploaderBinder.isUploading(mAccount, file)\r
+                            ) {\r
+                        localStateView.setImageResource(\r
+                                file.isFolder() ?\r
+                                        R.drawable.synchronizing_file_indicator :\r
+                                        R.drawable.uploading_file_indicator\r
+                        );\r
                         localStateView.setVisibility(View.VISIBLE);\r
+\r
+                    } else if (file.getEtagInConflict() != null) {   // conflict\r
+                        localStateView.setImageResource(R.drawable.conflict_file_indicator);\r
+                        localStateView.setVisibility(View.VISIBLE);\r
+\r
                     } else if (file.isDown()) {\r
                         localStateView.setImageResource(R.drawable.local_file_indicator);\r
                         localStateView.setVisibility(View.VISIBLE);\r
-                    } else {\r
-                        localStateView.setVisibility(View.INVISIBLE);\r
                     }\r
 \r
-                    // share with me icon\r
-                    ImageView sharedWithMeIconV = (ImageView)\r
-                            view.findViewById(R.id.sharedWithMeIcon);\r
-                    sharedWithMeIconV.bringToFront();\r
-                    if (checkIfFileIsSharedWithMe(file) &&\r
-                            (!file.isFolder() || !mGridMode)) {\r
-                        sharedWithMeIconV.setVisibility(View.VISIBLE);\r
+                    break;\r
+            }\r
+\r
+            ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);\r
+            checkBoxV.setVisibility(View.GONE);\r
+\r
+            AbsListView parentList = (AbsListView)parent;\r
+            if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\r
+                if (parentList.getChoiceMode() == AbsListView.CHOICE_MODE_NONE) {\r
+                    checkBoxV.setVisibility(View.GONE);\r
+                } else if (parentList.getCheckedItemCount() > 0){\r
+                    if (parentList.isItemChecked(position)) {\r
+                        checkBoxV.setImageResource(\r
+                                android.R.drawable.checkbox_on_background);\r
                     } else {\r
-                        sharedWithMeIconV.setVisibility(View.GONE);\r
+                        checkBoxV.setImageResource(\r
+                                android.R.drawable.checkbox_off_background);\r
                     }\r
-\r
-                    break;\r
+                    checkBoxV.setVisibility(View.VISIBLE);\r
+                }\r
             }\r
             \r
             // For all Views\r
@@ -295,13 +344,18 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             \r
             // No Folder\r
             if (!file.isFolder()) {\r
-                if (file.isImage() && file.getRemoteId() != null){\r
+                if ((file.isImage() || file.isVideo()) && file.getRemoteId() != null){\r
                     // Thumbnail in Cache?\r
                     Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(\r
-                            String.valueOf(file.getRemoteId())\r
-                            );\r
+                            "t" + String.valueOf(file.getRemoteId()));\r
                     if (thumbnail != null && !file.needsUpdateThumbnail()){\r
-                        fileIcon.setImageBitmap(thumbnail);\r
+\r
+                        if (file.isVideo()) {\r
+                            Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail);\r
+                            fileIcon.setImageBitmap(withOverlay);\r
+                        } else {\r
+                            fileIcon.setImageBitmap(thumbnail);\r
+                        }\r
                     } else {\r
                         // generate new Thumbnail\r
                         if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {\r
@@ -319,7 +373,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                                     task\r
                                     );\r
                             fileIcon.setImageDrawable(asyncDrawable);\r
-                            task.execute(file);\r
+                            task.execute(file, true);\r
                         }\r
                     }\r
 \r
@@ -338,53 +392,22 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                 // Folder\r
                 fileIcon.setImageResource(\r
                         MimetypeIconUtil.getFolderTypeIconId(\r
-                                checkIfFileIsSharedWithMe(file), file.isShareByLink()));\r
+                                file.isSharedWithMe() || file.isSharedWithSharee(),\r
+                                file.isSharedViaLink()\r
+                        )\r
+                );\r
             }\r
         }\r
 \r
-        return view;\r
-    }\r
-\r
-    /**\r
-     * Local Folder size in human readable format\r
-     * \r
-     * @param path\r
-     *            String\r
-     * @return Size in human readable format\r
-     */\r
-    private String getFolderSizeHuman(String path) {\r
-\r
-        File dir = new File(path);\r
-\r
-        if (dir.exists()) {\r
-            long bytes = FileStorageUtils.getFolderSize(dir);\r
-            return DisplayUtils.bytesToHumanReadable(bytes);\r
+        if (mSelection.get(position) != null) {\r
+            view.setBackgroundColor(Color.rgb(248, 248, 248));\r
+        } else {\r
+            view.setBackgroundColor(Color.WHITE);\r
         }\r
 \r
-        return "0 B";\r
+        return view;\r
     }\r
 \r
-    /**\r
-     * Local Folder size\r
-     * @param dir File\r
-     * @return Size in bytes\r
-     */\r
-    private long getFolderSize(File dir) {\r
-        if (dir.exists()) {\r
-            long result = 0;\r
-            File[] fileList = dir.listFiles();\r
-            for(int i = 0; i < fileList.length; i++) {\r
-                if(fileList[i].isDirectory()) {\r
-                    result += getFolderSize(fileList[i]);\r
-                } else {\r
-                    result += fileList[i].length();\r
-                }\r
-            }\r
-            return result;\r
-        }\r
-        return 0;\r
-    } \r
-\r
     @Override\r
     public int getViewTypeCount() {\r
         return 1;\r
@@ -426,7 +449,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             mFiles = null;\r
         }\r
 \r
-        mFiles = FileStorageUtils.sortFolder(mFiles);\r
+        mFiles = FileStorageUtils.sortOcFolder(mFiles);\r
         notifyDataSetChanged();\r
     }\r
     \r
@@ -449,20 +472,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
     }\r
     \r
     \r
-    /**\r
-     * Check if parent folder does not include 'S' permission and if file/folder\r
-     * is shared with me\r
-     * \r
-     * @param file: OCFile\r
-     * @return boolean: True if it is shared with me and false if it is not\r
-     */\r
-    private boolean checkIfFileIsSharedWithMe(OCFile file) {\r
-        return (mFile.getPermissions() != null \r
-                && !mFile.getPermissions().contains(PERMISSION_SHARED_WITH_ME)\r
-                && file.getPermissions() != null \r
-                && file.getPermissions().contains(PERMISSION_SHARED_WITH_ME));\r
-    }\r
-\r
     public void setSortOrder(Integer order, boolean ascending) {\r
         SharedPreferences.Editor editor = mAppPreferences.edit();\r
         editor.putInt("sortOrder", order);\r
@@ -473,17 +482,53 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         FileStorageUtils.mSortAscending = ascending;\r
         \r
 \r
-        mFiles = FileStorageUtils.sortFolder(mFiles);\r
+        mFiles = FileStorageUtils.sortOcFolder(mFiles);\r
         notifyDataSetChanged();\r
 \r
     }\r
-    \r
-    private CharSequence showRelativeTimestamp(OCFile file){\r
-        return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),\r
-                DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);\r
-    }\r
 \r
     public void setGridMode(boolean gridMode) {\r
         mGridMode = gridMode;\r
     }\r
+\r
+    public boolean isGridMode() {\r
+        return mGridMode;\r
+    }\r
+\r
+    public void setNewSelection(int position, boolean checked) {\r
+        mSelection.put(position, checked);\r
+        notifyDataSetChanged();\r
+    }\r
+\r
+    public void removeSelection(int position) {\r
+        mSelection.remove(position);\r
+        notifyDataSetChanged();\r
+    }\r
+\r
+    public void removeSelection(){\r
+         mSelection.clear();\r
+        notifyDataSetChanged();\r
+    }\r
+\r
+    public ArrayList<Integer> getCheckedItemPositions() {\r
+        ArrayList<Integer> ids = new ArrayList<Integer>();\r
+\r
+        for (Map.Entry<Integer, Boolean> entry : mSelection.entrySet()){\r
+            if (entry.getValue()){\r
+                ids.add(entry.getKey());\r
+            }\r
+        }\r
+        return ids;\r
+    }\r
+\r
+    public ArrayList<OCFile> getCheckedItems() {\r
+        ArrayList<OCFile> files = new ArrayList<OCFile>();\r
+\r
+        for (Map.Entry<Integer, Boolean> entry : mSelection.entrySet()){\r
+            if (entry.getValue()){\r
+                files.add((OCFile) getItem(entry.getKey()));\r
+            }\r
+        }\r
+        return files;\r
+    }\r
 }\r
index 60675f4..79bad6a 100644 (file)
@@ -25,7 +25,9 @@ import java.util.Arrays;
 import java.util.Comparator;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.graphics.Bitmap;
+import android.preference.PreferenceManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -41,6 +43,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.DisplayUtils;
 import com.owncloud.android.utils.MimetypeIconUtil;
+import com.owncloud.android.utils.FileStorageUtils;
 
 /**
  * This Adapter populates a ListView with all files and directories contained
@@ -53,9 +56,18 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
     private Context mContext;
     private File mDirectory;
     private File[] mFiles = null;
+    private SharedPreferences mAppPreferences;
     
     public LocalFileListAdapter(File directory, Context context) {
         mContext = context;
+
+        mAppPreferences = PreferenceManager
+                .getDefaultSharedPreferences(mContext);
+
+        // Read sorting order, default to sort by name ascending
+        FileStorageUtils.mSortOrder = mAppPreferences.getInt("sortOrder", 0);
+        FileStorageUtils.mSortAscending = mAppPreferences.getBoolean("sortAscending", true);
+
         swapDirectory(directory);
     }
 
@@ -121,9 +133,11 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
             fileIcon.setTag(file.hashCode());
 
             TextView fileSizeV = (TextView) view.findViewById(R.id.file_size);
+            TextView fileSizeSeparatorV = (TextView) view.findViewById(R.id.file_separator);
             TextView lastModV = (TextView) view.findViewById(R.id.last_mod);
             ImageView checkBoxV = (ImageView) view.findViewById(R.id.custom_checkbox);
             if (!file.isDirectory()) {
+                fileSizeSeparatorV.setVisibility(View.VISIBLE);
                 fileSizeV.setVisibility(View.VISIBLE);
                 fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.length()));
 
@@ -134,9 +148,9 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                     checkBoxV.setVisibility(View.GONE);
                 } else {
                     if (parentList.isItemChecked(position)) {
-                        checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
+                        checkBoxV.setImageResource(R.drawable.ic_checkbox_marked);
                     } else {
-                        checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
+                        checkBoxV.setImageResource(R.drawable.ic_checkbox_blank_outline);
                     }
                     checkBoxV.setVisibility(View.VISIBLE);
                 }
@@ -175,6 +189,7 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                 }  
 
             } else {
+                fileSizeSeparatorV.setVisibility(View.GONE);
                 fileSizeV.setVisibility(View.GONE);
                 lastModV.setVisibility(View.GONE);
                 checkBoxV.setVisibility(View.GONE);
@@ -185,7 +200,6 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
             view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);
             
             view.findViewById(R.id.sharedIcon).setVisibility(View.GONE);
-            view.findViewById(R.id.sharedWithMeIcon).setVisibility(View.GONE);
         }
 
         return view;
@@ -230,7 +244,23 @@ public class LocalFileListAdapter extends BaseAdapter implements ListAdapter {
                 }
             
             });
+
+            mFiles = FileStorageUtils.sortLocalFolder(mFiles);
         }
         notifyDataSetChanged();
     }
+
+    public void setSortOrder(Integer order, boolean ascending) {
+        SharedPreferences.Editor editor = mAppPreferences.edit();
+        editor.putInt("sortOrder", order);
+        editor.putBoolean("sortAscending", ascending);
+        editor.commit();
+
+        FileStorageUtils.mSortOrder = order;
+        FileStorageUtils.mSortAscending = ascending;
+
+        mFiles = FileStorageUtils.sortLocalFolder(mFiles);
+        notifyDataSetChanged();
+
+    }
 }
diff --git a/src/com/owncloud/android/ui/adapter/ShareUserListAdapter.java b/src/com/owncloud/android/ui/adapter/ShareUserListAdapter.java
new file mode 100644 (file)
index 0000000..413223d
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.ShareType;
+
+import java.util.ArrayList;
+
+/**
+ * Adapter to show a user/group in Share With List
+ */
+public class ShareUserListAdapter extends ArrayAdapter {
+
+    private Context mContext;
+    private ArrayList<OCShare> mShares;
+    private ShareUserAdapterListener mListener;
+
+    public ShareUserListAdapter(Context context, int resource, ArrayList<OCShare>shares,
+                                ShareUserAdapterListener listener) {
+        super(context, resource);
+        mContext= context;
+        mShares = shares;
+        mListener = listener;
+    }
+
+    @Override
+    public int getCount() {
+        return mShares.size();
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return mShares.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return 0;
+    }
+
+    @Override
+    public View getView(final int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflator = (LayoutInflater) mContext
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View view = inflator.inflate(R.layout.share_user_item, parent, false);
+
+        if (mShares != null && mShares.size() > position) {
+            OCShare share = mShares.get(position);
+
+            TextView userName = (TextView) view.findViewById(R.id.userOrGroupName);
+            String name = share.getSharedWithDisplayName();
+            if (share.getShareType() == ShareType.GROUP) {
+                name = getContext().getString(R.string.share_group_clarification, name);
+            }
+            userName.setText(name);
+
+            final ImageView unshareButton = (ImageView) view.findViewById(R.id.unshareButton);
+            unshareButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    mListener.unshareButtonPressed(mShares.get(position));
+                }
+            });
+
+        }
+        return view;
+    }
+
+    public interface ShareUserAdapterListener {
+        void unshareButtonPressed(OCShare share);
+    }
+
+
+
+}
index 1c8c8c2..742d6d8 100644 (file)
@@ -20,6 +20,9 @@
  */
 package com.owncloud.android.ui.adapter;
 
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.text.DateFormat;
 import java.util.Date;
@@ -31,6 +34,7 @@ import javax.security.auth.x500.X500Principal;
 import com.owncloud.android.R;
 import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
 
+import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
 
@@ -42,7 +46,9 @@ public class X509CertificateViewAdapter implements SslUntrustedCertDialog.Certif
     //private final static String TAG = X509CertificateViewAdapter.class.getSimpleName();
     
     private X509Certificate mCertificate = null;
-    
+
+    private static final String TAG = X509CertificateViewAdapter.class.getSimpleName();
+
     public X509CertificateViewAdapter(X509Certificate certificate) {
         mCertificate = certificate;
     }
@@ -63,25 +69,68 @@ public class X509CertificateViewAdapter implements SslUntrustedCertDialog.Certif
         }
     }
 
+    private byte[] getDigest(String algorithm, byte[] message) {
+        MessageDigest md = null;
+
+        try {
+            md = MessageDigest.getInstance(algorithm);
+        } catch (NoSuchAlgorithmException e) {
+            return null;
+        }
+        md.reset();
+        return md.digest(message);
+    }
+
     private void showSignature(View dialogView) {
-        TextView sigView = ((TextView)dialogView.findViewById(R.id.value_signature));
-        TextView algorithmView = ((TextView)dialogView.findViewById(R.id.value_signature_algorithm));
-        sigView.setText(getHex(mCertificate.getSignature()));
-        algorithmView.setText(mCertificate.getSigAlgName());
+        byte[] cert = null;
+
+        TextView certFingerprintView = ((TextView) dialogView.findViewById(R.id.value_certificate_fingerprint));
+        TextView algorithmView = ((TextView) dialogView.findViewById(R.id.value_signature_algorithm));
+
+        try {
+            cert = mCertificate.getEncoded();
+            if (cert == null) {
+
+                certFingerprintView.setText(R.string.certificate_load_problem);
+                algorithmView.setText(R.string.certificate_load_problem);
+
+            } else {
+
+                certFingerprintView.setText(
+                        getDigestHexBytesWithColonsAndNewLines(dialogView, "SHA-256", cert)
+                                + getDigestHexBytesWithColonsAndNewLines(dialogView, "SHA-1", cert)
+                                + getDigestHexBytesWithColonsAndNewLines(dialogView, "MD5", cert));
+                algorithmView.setText(mCertificate.getSigAlgName());
+
+            }
+
+        } catch (CertificateEncodingException e) {
+            Log.e(TAG, "Problem while trying to decode the certificate.");
+        }
+
+
     }
     
-    public String getHex(final byte [] raw) {
-        if (raw == null) {
-           return null;
+    private final String getDigestHexBytesWithColonsAndNewLines(View dialogView, final String digestType, final byte [] cert) {
+        final byte[] rawDigest;
+        final String newLine = System.getProperty("line.separator");
+
+        rawDigest = getDigest(digestType, cert);
+
+        if ( rawDigest == null) {
+            return digestType + ":" + newLine + dialogView.getContext().getString(R.string.digest_algorithm_not_available) + newLine + newLine;
         }
-        final StringBuilder hex = new StringBuilder(2 * raw.length);
-        for (final byte b : raw) {
+
+        final StringBuilder hex = new StringBuilder(3 * rawDigest.length);
+
+        for (final byte b : rawDigest) {
            final int hiVal = (b & 0xF0) >> 4;
            final int loVal = b & 0x0F;
            hex.append((char) ('0' + (hiVal + (hiVal / 10 * 7))));
            hex.append((char) ('0' + (loVal + (loVal / 10 * 7))));
+           hex.append(":");
         }
-        return hex.toString();
+        return digestType + ":" + newLine + hex.toString().replaceFirst("\\:$","") + newLine + newLine;
      }    
 
     private void showValidity(Date notBefore, Date notAfter, View dialogView) {
index 96414a0..e8289d0 100644 (file)
@@ -39,6 +39,7 @@ public class AccountActionsDialogFragment extends DialogFragment implements
      * Listener interface for the file action fragment.
      */
     public interface FileActionsDialogFragmentListener {
+        // TODO Tobi change to int array?
         public boolean onFileActionChosen(int menuId, int filePosition);
     }
 
diff --git a/src/com/owncloud/android/ui/dialog/OwnCloudListPreference.java b/src/com/owncloud/android/ui/dialog/OwnCloudListPreference.java
new file mode 100644 (file)
index 0000000..67ccb3e
--- /dev/null
@@ -0,0 +1,102 @@
+package com.owncloud.android.ui.dialog;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.PreferenceManager;
+import android.support.v7.app.AppCompatDialog;
+import android.util.AttributeSet;
+
+import com.owncloud.android.R;
+import com.owncloud.android.lib.common.utils.Log_OC;
+
+import java.lang.reflect.Method;
+
+public class OwnCloudListPreference extends ListPreference {
+    private static final String TAG = OwnCloudListPreference.class.getSimpleName();
+
+    private Context mContext;
+    private AppCompatDialog mDialog;
+
+    public OwnCloudListPreference(Context context) {
+        super(context);
+        this.mContext = context;
+    }
+
+    public OwnCloudListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        this.mContext = context;
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public OwnCloudListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    public OwnCloudListPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    protected void showDialog(Bundle state) {
+        if (getEntries() == null || getEntryValues() == null) {
+            throw new IllegalStateException(
+                    "ListPreference requires an entries array and an entryValues array.");
+        }
+
+        int preselect = findIndexOfValue(getValue());
+        // TODO for some reason value change is persisted but not directly shown in Android-15 emulator
+        // same thing happens for the Standard ListPreference though
+        android.support.v7.app.AlertDialog.Builder builder =
+                new android.support.v7.app.AlertDialog.Builder(mContext, R.style.ownCloud_AlertDialog)
+                .setTitle(getDialogTitle())
+                .setIcon(getDialogIcon())
+                .setSingleChoiceItems(getEntries(), preselect, this);
+
+        PreferenceManager pm = getPreferenceManager();
+        try {
+            Method method = pm.getClass().getDeclaredMethod(
+                    "registerOnActivityDestroyListener",
+                    PreferenceManager.OnActivityDestroyListener.class);
+            method.setAccessible(true);
+            method.invoke(pm, this);
+        } catch (Exception e) {
+            // no way to handle this but logging it
+            Log_OC.e(TAG, "error invoking registerOnActivityDestroyListener", e);
+        }
+
+        mDialog = builder.create();
+        if (state != null) {
+            mDialog.onRestoreInstanceState(state);
+        }
+        mDialog.show();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (which >= 0 && getEntryValues() != null) {
+            String value = getEntryValues()[which].toString();
+            if (callChangeListener(value)) {
+                setValue(value);
+            }
+            dialog.dismiss();
+        }
+    }
+
+    @Override
+    public AppCompatDialog getDialog() {
+        return mDialog;
+    }
+
+    @Override
+    public void onActivityDestroy() {
+        super.onActivityDestroy();
+        if (mDialog != null && mDialog.isShowing()) {
+            mDialog.dismiss();
+        }
+    }
+}
index 4f34b07..d42cf46 100644 (file)
@@ -25,7 +25,6 @@ package com.owncloud.android.ui.dialog;
  * 
  *  Triggers the removal according to the user response.
  */
-import java.util.Vector;
 
 import android.app.Dialog;
 import android.os.Bundle;
@@ -53,9 +52,9 @@ implements ConfirmationDialogFragmentListener {
         RemoveFileDialogFragment frag = new RemoveFileDialogFragment();
         Bundle args = new Bundle();
         
-        int messageStringId = R.string.confirmation_remove_alert;
+        int messageStringId = R.string.confirmation_remove_file_alert;
         
-        int posBtn = R.string.confirmation_remove_remote;
+        int posBtn = R.string.confirmation_remove_file_remote;
         int negBtn = -1;
         if (file.isFolder()) {
             messageStringId = R.string.confirmation_remove_folder_alert;
@@ -106,33 +105,6 @@ implements ConfirmationDialogFragmentListener {
     public void onCancel(String callerTag) {
         ComponentsGetter cg = (ComponentsGetter)getActivity();
         cg.getFileOperationsHelper().removeFile(mTargetFile, true);
-        
-        FileDataStorageManager storageManager = cg.getStorageManager();
-        
-        boolean containsFavorite = false;
-        if (mTargetFile.isFolder()) {
-            Vector<OCFile> files = storageManager.getFolderContent(mTargetFile, false);
-            for(OCFile file: files) {
-                containsFavorite = file.isFavorite() || containsFavorite;
-
-                if (containsFavorite)
-                    break;
-            }
-        }
-
-        // Remove etag for parent, if file is a favorite
-        // or is a folder and contains favorite
-        if (mTargetFile.isFavorite() || containsFavorite) {
-            OCFile folder = null;
-            if (mTargetFile.isFolder()) {
-                folder = mTargetFile;
-            } else {
-                folder = storageManager.getFileById(mTargetFile.getParentId());
-            }
-            
-           folder.setEtag("");
-           storageManager.saveFile(folder);
-        }
     }
 
     @Override
diff --git a/src/com/owncloud/android/ui/dialog/RemoveFilesDialogFragment.java b/src/com/owncloud/android/ui/dialog/RemoveFilesDialogFragment.java
new file mode 100644 (file)
index 0000000..6d40d8e
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.dialog;
+
+/**
+ *  Dialog requiring confirmation before removing a given OCFile.  
+ * 
+ *  Triggers the removal according to the user response.
+ */
+
+import android.app.Dialog;
+import android.content.res.Resources;
+import android.os.Bundle;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.ui.activity.ComponentsGetter;
+import com.owncloud.android.ui.dialog.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+public class RemoveFilesDialogFragment extends ConfirmationDialogFragment
+implements ConfirmationDialogFragmentListener {
+
+    private ArrayList<OCFile> mTargetFiles;
+
+    private static final String ARG_TARGET_FILES = "TARGET_FILES";
+
+    /**
+     * Public factory method to create new RemoveFileDialogFragment instances.
+     * 
+     * @param files            Files to remove.
+     * @return                Dialog ready to show.
+     */
+    public static RemoveFilesDialogFragment newInstance(ArrayList<OCFile> files) {
+        RemoveFilesDialogFragment frag = new RemoveFilesDialogFragment();
+        Bundle args = new Bundle();
+        
+        int messageStringId = R.string.confirmation_remove_files_alert;
+        
+        int posBtn = R.string.confirmation_remove_file_remote;
+        int negBtn = -1;
+
+        boolean containsFolder = false;
+        boolean containsDown = false;
+        for (OCFile file: files) {
+            if (file.isFolder()) containsFolder = true;
+            if (file.isDown()) containsDown = true;
+        }
+
+        if (containsFolder) {
+            messageStringId = R.string.confirmation_remove_folders_alert;
+            posBtn = R.string.confirmation_remove_remote_and_local;
+            negBtn = R.string.confirmation_remove_local;
+        } else if (containsDown) {
+            posBtn = R.string.confirmation_remove_remote_and_local;
+            negBtn = R.string.confirmation_remove_local;
+        }
+        
+        args.putInt(ARG_CONF_RESOURCE_ID, messageStringId);
+        args.putStringArray(ARG_CONF_ARGUMENTS, new String[]{MainApp.getAppContext().getString(R.string.confirmation_remove_files)});
+        args.putInt(ARG_POSITIVE_BTN_RES, posBtn);
+        args.putInt(ARG_NEUTRAL_BTN_RES, R.string.common_no);
+        args.putInt(ARG_NEGATIVE_BTN_RES, negBtn);
+        args.putParcelableArrayList(ARG_TARGET_FILES, files);
+        frag.setArguments(args);
+        
+        return frag;
+    }
+    
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        Dialog dialog = super.onCreateDialog(savedInstanceState);
+        mTargetFiles = getArguments().getParcelableArrayList(ARG_TARGET_FILES);
+        
+        setOnConfirmationListener(this);
+        
+        return dialog;
+    }    
+
+    /**
+     * Performs the removal of the target file, both locally and in the server.
+     */
+    @Override
+    public void onConfirmation(String callerTag) {
+        ComponentsGetter cg = (ComponentsGetter) getActivity();
+        FileDataStorageManager storageManager = cg.getStorageManager();
+        for (OCFile targetFile : mTargetFiles) {
+            if (storageManager.getFileById(targetFile.getFileId()) != null) {
+                cg.getFileOperationsHelper().removeFile(targetFile, false);
+            }
+        }
+    }
+    
+    /**
+     * Performs the removal of the local copy of the target file
+     */
+    @Override
+    public void onCancel(String callerTag) {
+        ComponentsGetter cg = (ComponentsGetter) getActivity();
+
+        for (OCFile targetFile : mTargetFiles) {
+            cg.getFileOperationsHelper().removeFile(targetFile, true);
+
+            FileDataStorageManager storageManager = cg.getStorageManager();
+
+            boolean containsFavorite = false;
+            if (targetFile.isFolder()) {
+                Vector<OCFile> files = storageManager.getFolderContent(targetFile, false);
+                for (OCFile file : files) {
+                    containsFavorite = file.isFavorite() || containsFavorite;
+
+                    if (containsFavorite)
+                        break;
+                }
+            }
+
+            // Remove etag for parent, if file is a favorite
+            // or is a folder and contains favorite
+            if (targetFile.isFavorite() || containsFavorite) {
+                OCFile folder = null;
+                if (targetFile.isFolder()) {
+                    folder = targetFile;
+                } else {
+                    folder = storageManager.getFileById(targetFile.getParentId());
+                }
+
+                folder.setEtag("");
+                storageManager.saveFile(folder);
+            }
+        }
+    }
+
+    @Override
+    public void onNeutral(String callerTag) {
+        // nothing to do here
+    }
+}
\ No newline at end of file
index 24015d0..589ccfe 100644 (file)
@@ -22,11 +22,15 @@ 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;
 import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.ActionMode;
 import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AbsListView;
@@ -36,12 +40,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 +72,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<Integer> mIndexes;
@@ -96,8 +109,23 @@ public class ExtendedListFragment extends Fragment
         return mCurrentListView;
     }
 
+    public FloatingActionButton getFabUpload() {
+        return fabUpload;
+    }
+
+    public FloatingActionButton getFabUploadFromApp() {
+        return fabUploadFromApp;
+    }
 
-    protected void switchToGridView() {
+    public FloatingActionButton getFabMkdir() {
+        return fabMkdir;
+    }
+
+    public FloatingActionsMenu getFabMain() {
+        return fabMain;
+    }
+
+    public void switchToGridView() {
         if ((mCurrentListView == mListView)) {
 
             mListView.setAdapter(null);
@@ -112,8 +140,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 +155,13 @@ public class ExtendedListFragment extends Fragment
             mCurrentListView = mListView;
         }
     }
+
+    public boolean isGridView(){
+        if (mAdapter instanceof FileListListAdapter) {
+            return ((FileListListAdapter) mAdapter).isGridMode();
+        }
+        return false;
+    }
     
     
     @Override
@@ -134,15 +169,61 @@ public class ExtendedListFragment extends Fragment
                              Bundle savedInstanceState) {
         Log_OC.d(TAG, "onCreateView");
 
+        // TODO Tobi remove
+//         AbsListView.MultiChoiceModeListener listener = new AbsListView.MultiChoiceModeListener() {
+//            @Override
+//            public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+//                // Capture total checked items
+//                final int checkedCount = mListView.getCheckedItemCount();
+//                // Set the CAB title according to total checked items
+//                mode.setTitle(checkedCount + " Selected");
+//                // Calls toggleSelection method from ListViewAdapter Class
+//                 // mAdapter.toggleSelection(position);
+//
+//                if (checked){
+//                    mAdapter.setNewSelection(position,checked);
+//                } else {
+//                    mAdapter.removeSelection(position);
+//                }
+//            }
+//
+//            @Override
+//            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+//                mode.getMenuInflater().inflate(R.menu.context, menu);
+//                return true;
+//            }
+//
+//            @Override
+//            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+//                return false;
+//            }
+//
+//            @Override
+//            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+//                return false;
+//            }
+//
+//            @Override
+//            public void onDestroyActionMode(ActionMode mode) {
+//                // mAdapter.removeSelection();
+//            }
+//        };
+
         View v = inflater.inflate(R.layout.list_fragment, null);
 
         mListView = (ExtendedListView)(v.findViewById(R.id.list_root));
         mListView.setOnItemClickListener(this);
+        mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+        // mListView.setMultiChoiceModeListener(listener);
         mListFooterView = inflater.inflate(R.layout.list_footer, null, false);
 
         mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
         mGridView.setNumColumns(GridView.AUTO_FIT);
         mGridView.setOnItemClickListener(this);
+        mGridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+
+        // mGridView.setMultiChoiceModeListener(listener);
+
         mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);
 
         if (savedInstanceState != null) {
@@ -171,6 +252,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 +406,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) {
index b2e6464..1362a12 100644 (file)
@@ -217,6 +217,24 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
             item.setVisible(false);
             item.setEnabled(false);
         }
+
+        item = menu.findItem(R.id.action_switch_view);
+        if (item != null){
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        item = menu.findItem(R.id.action_sync_account);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        item = menu.findItem(R.id.action_sort);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
     }
 
 
@@ -230,10 +248,15 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
                 return true;
             }
+            case R.id.action_share_with_users: {
+                mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
+                return true;
+            }
             case R.id.action_unshare_file: {
                 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
                 return true;
             }
+
             case R.id.action_open_file_with: {
                 mContainerActivity.getFileOperationsHelper().openFile(getFile());
                 return true;
@@ -248,9 +271,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 dialog.show(getFragmentManager(), FTAG_RENAME_FILE);
                 return true;
             }
-            case R.id.action_cancel_download:
-            case R.id.action_cancel_upload: {
-                ((FileDisplayActivity) mContainerActivity).cancelTransference(getFile());
+            case R.id.action_cancel_sync: {
+                ((FileDisplayActivity)mContainerActivity).cancelTransference(getFile());
                 return true;
             }
             case R.id.action_download_file:
@@ -263,7 +285,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 if (!getFile().isDown()) {  // Download the file                    
                     Log_OC.d(TAG, getFile().getRemotePath() + " : File must be downloaded");
                     ((FileDisplayActivity) mContainerActivity).startDownloadForSending(getFile());
-
                 }
                 else {
                     mContainerActivity.getFileOperationsHelper().sendDownloadedFile(getFile());
@@ -300,7 +321,6 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
         }
     }
 
-
     /**
      * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.
      *
index fd5aeef..cacfa2d 100644 (file)
@@ -141,9 +141,8 @@ public class FileFragment extends Fragment {
          * @param downloading   Flag signaling if the file is now downloading.
          * @param uploading     Flag signaling if the file is now uploading.
          */
-        public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading); 
+        public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading);
 
-        
     }
 
 }
index 8a268b7..c5f74a7 100644 (file)
@@ -37,6 +37,7 @@ import android.widget.ListView;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.ui.adapter.LocalFileListAdapter;
+import com.owncloud.android.utils.FileStorageUtils;
 
 
 /**
@@ -54,7 +55,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 +79,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;
@@ -120,9 +121,9 @@ public class LocalFileListFragment extends ExtendedListFragment {
                 ImageView checkBoxV = (ImageView) v.findViewById(R.id.custom_checkbox);
                 if (checkBoxV != null) {
                     if (((ListView)getListView()).isItemChecked(position)) {
-                        checkBoxV.setImageResource(android.R.drawable.checkbox_on_background);
+                        checkBoxV.setImageResource(R.drawable.ic_checkbox_marked);
                     } else {
-                        checkBoxV.setImageResource(android.R.drawable.checkbox_off_background);
+                        checkBoxV.setImageResource(R.drawable.ic_checkbox_blank_outline);
                     }
                 }
                 // notify the change to the container Activity
@@ -228,7 +229,19 @@ public class LocalFileListFragment extends ExtendedListFragment {
         return result.toArray(new String[result.size()]);
     }
 
-    
+    public void sortByName(boolean descending) {
+        mAdapter.setSortOrder(FileStorageUtils.SORT_NAME, descending);
+    }
+
+    public void sortByDate(boolean descending) {
+        mAdapter.setSortOrder(FileStorageUtils.SORT_DATE, descending);
+    }
+
+    public void sortBySize(boolean descending) {
+        mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending);
+    }
+
+
     /**
      * Interface to implement by any Activity that includes some instance of LocalFileListFragment
      */
index 7b082ea..9a1f9ee 100644 (file)
  */
 package com.owncloud.android.ui.fragment;
 
+import android.accounts.Account;
 import android.app.Activity;
+import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Build;
+import android.net.Uri;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 import android.support.v4.widget.SwipeRefreshLayout;
+import android.view.ActionMode;
+import android.support.v7.app.AlertDialog;
 import android.view.ContextMenu;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.widget.AbsListView;
 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.MainApp;
 import com.owncloud.android.R;
@@ -43,28 +55,37 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.FileMenuFilter;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+import com.owncloud.android.media.MediaService;
 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.RemoveFilesDialogFragment;
 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.ExceptionHandler;
 import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.ui.preview.PreviewTextFragment;
+import com.owncloud.android.utils.FileStorageUtils;
 
 import java.io.File;
+import java.util.ArrayList;
 
 /**
  * A Fragment that lists all files and folders in a given path.
  *
  * TODO refactor to get rid of direct dependency on FileDisplayActivity
  */
-public class OCFileListFragment extends ExtendedListFragment implements FileActionsDialogFragment.FileActionsDialogFragmentListener {
+public class OCFileListFragment extends ExtendedListFragment {
     
     private static final String TAG = OCFileListFragment.class.getSimpleName();
 
@@ -73,8 +94,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;
 
@@ -83,8 +108,8 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
     private boolean mJustFolders;
     
     private OCFile mTargetFile;
-    
-   
+
+    private boolean miniFabClicked = false;
     
     /**
      * {@inheritDoc}
@@ -145,15 +170,211 @@ 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:
+     * <ol>
+     *     <li>persists the click fact</li>
+     *     <li>removes the mini FAB labels</li>
+     * </ol>
+     */
+    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,
-                                           int index, long arg3) {
-                showFileAction(index);
+        getListView().setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
+            private Menu menu;
+
+            @Override
+            public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+                final int checkedCount = getListView().getCheckedItemCount();
+                // TODO Tobi extract to values
+                mode.setTitle(checkedCount + " selected");
+
+                if (checked) {
+                    mAdapter.setNewSelection(position, checked);
+                } else {
+                    mAdapter.removeSelection(position);
+                }
+
+                // TODO maybe change: only recreate menu if count changes
+                menu.clear();
+                if (checkedCount == 1) {
+                    createContextMenu(menu);
+                } else {
+                    // download, move, copy, delete
+                    getActivity().getMenuInflater().inflate(R.menu.multiple_file_actions_menu, menu);
+                }
+
+            }
+
+            @Override
+            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+                this.menu = menu;
                 return true;
             }
+
+            @Override
+            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+                return false;
+            }
+
+            @Override
+            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+                return onFileActionChosen(item.getItemId());
+            }
+
+            @Override
+            public void onDestroyActionMode(ActionMode mode) {
+                mAdapter.removeSelection();
+            }
         });
     }
 
@@ -194,7 +415,8 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
                 }
             }
 
-            FileActionsDialogFragment dialog = FileActionsDialogFragment.newInstance(menu, fileIndex, targetFile.getFileName());
+            FileActionsDialogFragment dialog = FileActionsDialogFragment.newInstance(menu,
+                    fileIndex, targetFile.getFileName());
             dialog.setTargetFragment(this, 0);
             dialog.show(getFragmentManager(), FileActionsDialogFragment.FTAG_FILE_ACTIONS);
         }
@@ -211,11 +433,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.
-     * <p/>
-     * return       Count of folder levels browsed up.
+     * <p>
+     *     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.
+     * </p>
+     * @return Count of folder levels browsed up.
      */
     public int onBrowseUp() {
         OCFile parentDir = null;
@@ -273,41 +495,36 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
                     ((FileDisplayActivity)mContainerActivity).startImagePreview(file);
                 } else if (PreviewTextFragment.canBePreviewed(file)){
                     ((FileDisplayActivity)mContainerActivity).startTextPreview(file);
-                } else if (file.isDown()) {
-                    if (PreviewMediaFragment.canBePreviewed(file)) {
+                } else if (PreviewMediaFragment.canBePreviewed(file)) {
                         // media preview
                         ((FileDisplayActivity) mContainerActivity).startMediaPreview(file, 0, true);
-                    } else {
+                    } else if (file.isDown()) {
                         mContainerActivity.getFileOperationsHelper().openFile(file);
-                    }
-
                 } else {
                     // automatic download, preview on finish
                     ((FileDisplayActivity) mContainerActivity).startDownloadForPreview(file);
                 }
-
             }
-
         } else {
             Log_OC.d(TAG, "Null object in ListAdapter!!");
         }
-
     }
 
     /**
      * {@inheritDoc}
      */
-    @Override
-    public void onCreateContextMenu(
-            ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+    // TODO Tobi needed?
+    public void createContextMenu(Menu menu) {
         Bundle args = getArguments();
         boolean allowContextualActions =
                 (args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
         if (allowContextualActions) {
             MenuInflater inflater = getActivity().getMenuInflater();
             inflater.inflate(R.menu.file_actions_menu, menu);
-            AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
-            OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
+            OCFile targetFile = null;
+            if (mAdapter.getCheckedItems().size() == 1){
+                targetFile = mAdapter.getCheckedItems().get(0);
+            }
 
             if (mContainerActivity.getStorageManager() != null) {
                 FileMenuFilter mf = new FileMenuFilter(
@@ -330,88 +547,135 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
                     item.setEnabled(false);
                 }
             }
+
+//            String.format(mContext.getString(R.string.subject_token),
+//                    getClient().getCredentials().getUsername(), file.getFileName()));
         }
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean onFileActionChosen(int menuId, int filePosition) {
-        mTargetFile = (OCFile) mAdapter.getItem(filePosition);
-        switch (menuId) {
-            case R.id.action_share_file: {
-                mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
-                return true;
-            }
-            case R.id.action_open_file_with: {
-                mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
-                return true;
-            }
-            case R.id.action_unshare_file: {
-                mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile);
-                return true;
-            }
-            case R.id.action_rename_file: {
-                RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
-                dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);
-                return true;
-            }
-            case R.id.action_remove_file: {
-                RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
-                dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
-                return true;
-            }
-            case R.id.action_download_file:
-            case R.id.action_sync_file: {
-                mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
-                return true;
-            }
-            case R.id.action_cancel_download:
-            case R.id.action_cancel_upload: {
-                ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
-                return true;
-            }
-            case R.id.action_see_details: {
-                mContainerActivity.showDetails(mTargetFile);
-                return true;
-            }
-            case R.id.action_send_file: {
-                // Obtain the file
-                if (!mTargetFile.isDown()) {  // Download the file
-                    Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
-                    ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile);
+    public boolean onFileActionChosen(int menuId) {
+        if (mAdapter.getCheckedItems().size() == 1){
+            OCFile mTargetFile = mAdapter.getCheckedItems().get(0);
 
-                } else {
-                    mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
+            switch (menuId) {
+                case R.id.action_share_file: {
+                    mContainerActivity.getFileOperationsHelper().shareFileWithLink(mTargetFile);
+                    return true;
                 }
-                return true;
+                case R.id.action_share_with_users: {
+                    mContainerActivity.getFileOperationsHelper().showShareFile(mTargetFile);
+                    return true;
+                }
+                case R.id.action_open_file_with: {
+                    mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
+                    return true;
+                }
+                case R.id.action_unshare_file: {
+                    mContainerActivity.getFileOperationsHelper().unshareFileWithLink(mTargetFile);
+                    return true;
+                }
+                case R.id.action_rename_file: {
+                    RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
+                    dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);
+                    return true;
+                }
+                case R.id.action_remove_file: {
+                    RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
+                    dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+                    return true;
+                }
+                case R.id.action_download_file:
+                case R.id.action_sync_file: {
+                    mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
+                    return true;
+                }
+                case R.id.action_cancel_sync: {
+                    ((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
+                    return true;
+                }
+                case R.id.action_see_details: {
+                    mContainerActivity.showDetails(mTargetFile);
+                    return true;
+                }
+                case R.id.action_send_file: {
+                    // Obtain the file
+                    if (!mTargetFile.isDown()) {  // Download the file
+                        Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
+                        ((FileDisplayActivity) mContainerActivity).startDownloadForSending(mTargetFile);
+                        return true;
+                    } else {
+                        mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
+                    }
+                }
+                case R.id.action_stream_file: {
+                    Account account = ((FileActivity)mContainerActivity).getAccount();
+                    Context context = MainApp.getAppContext();
+                    String uri = PreviewMediaFragment.generateUrlWithCredentials(account, context, mTargetFile);
+                    MediaService.streamWithExternalApp(uri, getActivity()).show();
+                    return true;
+                }
+                case R.id.action_move: {
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                    ArrayList files = new ArrayList();
+                    files.add(mTargetFile);
+                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, files);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
+                    return true;
+                }
+                case R.id.action_favorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
+                    return true;
+                }
+                case R.id.action_unfavorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
+                    return true;
+                }
+                case R.id.action_copy:
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                    ArrayList files = new ArrayList();
+                    files.add(mTargetFile);
+                    action.putExtra(FolderPickerActivity.EXTRA_FILES, files);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
+                    return true;
+                default:
+                    return false;
             }
-            case R.id.action_move: {
-                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+        } else {
+            ArrayList<OCFile> mTargetFiles = mAdapter.getCheckedItems();
 
-                // Pass mTargetFile that contains info of selected file/folder
-                action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
-                getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
-                return true;
-            }
-            case R.id.action_favorite_file: {
-                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
-                return true;
-            }
-            case R.id.action_unfavorite_file: {
-                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
-                return true;
+            switch (menuId) {
+                case R.id.action_remove_file: {
+                    RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(mTargetFiles);
+                    dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
+                    return true;
+                }
+                case R.id.action_download_file:
+                case R.id.action_sync_file: {
+                    mContainerActivity.getFileOperationsHelper().syncFiles(mTargetFiles);
+                    return true;
+                }
+                case R.id.action_move: {
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
+                    return true;
+                }
+                case R.id.action_favorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, true);
+                    return true;
+                }
+                case R.id.action_unfavorite_file: {
+                    mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, false);
+                    return true;
+                }
+                case R.id.action_copy:
+                    Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+                    action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
+                    getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
+                    return true;
+                default:
+                    return false;
             }
-            case R.id.action_copy:
-                Intent action = new Intent(getActivity(), FolderPickerActivity.class);
-
-                // Pass mTargetFile that contains info of selected file/folder
-                action.putExtra(FolderPickerActivity.EXTRA_FILE, mTargetFile);
-                getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_COPY_FILES);
-                return true;
-            default:
-                return false;
         }
     }
     
@@ -421,7 +685,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
     @Override
     public boolean onContextItemSelected (MenuItem item) {
         AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
-        boolean matched = onFileActionChosen(item.getItemId(), ((AdapterContextMenuInfo) item.getMenuInfo()).position);
+        boolean matched = onFileActionChosen(item.getItemId())  ;
         if(!matched) {
             return super.onContextItemSelected(item);
         } else {
@@ -503,7 +767,7 @@ public class OCFileListFragment extends ExtendedListFragment implements FileActi
                     if (!file.isHidden()) {
                         filesCount++;
 
-                        if (file.isImage()) {
+                        if (file.isImage() || file.isVideo()) {
                             imagesCount++;
                         }
                     }
@@ -516,11 +780,12 @@ 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 {
                 switchToListView();
+//                switchToGridView();
             }
         }
     }
diff --git a/src/com/owncloud/android/ui/fragment/SearchShareesFragment.java b/src/com/owncloud/android/ui/fragment/SearchShareesFragment.java
new file mode 100644 (file)
index 0000000..0059b3f
--- /dev/null
@@ -0,0 +1,247 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.fragment;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.app.SearchManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.ListView;
+import android.widget.SearchView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.ui.activity.ShareActivity;
+import com.owncloud.android.ui.adapter.ShareUserListAdapter;
+
+import java.util.ArrayList;
+
+/**
+ * Fragment for Searching sharees (users and groups)
+ *
+ * A simple {@link Fragment} subclass.
+ *
+ * Activities that contain this fragment must implement the
+ * {@link SearchShareesFragment.OnSearchFragmentInteractionListener} interface
+ * to handle interaction events.
+ *
+ * Use the {@link SearchShareesFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class SearchShareesFragment extends Fragment implements ShareUserListAdapter.ShareUserAdapterListener {
+    private static final String TAG = SearchShareesFragment.class.getSimpleName();
+
+    // the fragment initialization parameters
+    private static final String ARG_FILE = "FILE";
+    private static final String ARG_ACCOUNT = "ACCOUNT";
+
+    // Parameters
+    private OCFile mFile;
+    private Account mAccount;
+
+    // other members
+    private ArrayList<OCShare> mShares;
+    private ShareUserListAdapter mUserGroupsAdapter = null;
+    private OnSearchFragmentInteractionListener mListener;
+
+
+    /**
+     * Public factory method to create new SearchShareesFragment instances.
+     *
+     * @param fileToShare   An {@link OCFile} to be shared
+     * @param account       The ownCloud account containing fileToShare
+     * @return A new instance of fragment SearchShareesFragment.
+     */
+    public static SearchShareesFragment newInstance(OCFile fileToShare, Account account) {
+        SearchShareesFragment fragment = new SearchShareesFragment();
+        Bundle args = new Bundle();
+        args.putParcelable(ARG_FILE, fileToShare);
+        args.putParcelable(ARG_ACCOUNT, account);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public SearchShareesFragment() {
+        // Required empty public constructor
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getArguments() != null) {
+            mFile = getArguments().getParcelable(ARG_FILE);
+            mAccount = getArguments().getParcelable(ARG_ACCOUNT);
+        }
+
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        View view = inflater.inflate(R.layout.search_users_groups_layout, container, false);
+
+        // Get the SearchView and set the searchable configuration
+        SearchView searchView = (SearchView) view.findViewById(R.id.searchView);
+        SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
+        searchView.setSearchableInfo(searchManager.getSearchableInfo(
+                getActivity().getComponentName())   // assumes parent activity is the searchable activity
+        );
+        searchView.setIconifiedByDefault(false);    // do not iconify the widget; expand it by default
+
+        searchView.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); // avoid fullscreen with softkeyboard
+
+        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+            @Override
+            public boolean onQueryTextSubmit(String query) {
+                Log_OC.v(TAG, "onQueryTextSubmit intercepted, query: " + query);
+                return true;    // return true to prevent the query is processed to be queried;
+                // a user / group will be picked only if selected in the list of suggestions
+            }
+
+            @Override
+            public boolean onQueryTextChange(String newText) {
+                return false;   // let it for the parent listener in the hierarchy / default behaviour
+            }
+        });
+
+        return view;
+    }
+
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // Load data into the list
+        refreshUsersOrGroupsListFromDB();
+    }
+
+
+    /**
+     * Get users and groups from the DB to fill in the "share with" list
+     *
+     * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
+     * instance ready to use. If not ready, does nothing.
+     */
+    public void refreshUsersOrGroupsListFromDB (){
+        // Get Users and Groups
+        if (((FileActivity) mListener).getStorageManager() != null) {
+            mShares = ((FileActivity) mListener).getStorageManager().getSharesWithForAFile(
+                    mFile.getRemotePath(),
+                    mAccount.name
+            );
+
+            // Update list of users/groups
+            updateListOfUserGroups();
+        }
+    }
+
+    private void updateListOfUserGroups() {
+        // Update list of users/groups
+        // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
+        mUserGroupsAdapter = new ShareUserListAdapter(
+                getActivity().getApplicationContext(),
+                R.layout.share_user_item, mShares, this
+        );
+
+        // Show data
+        ListView usersList = (ListView) getView().findViewById(R.id.searchUsersListView);
+
+        if (mShares.size() > 0) {
+            usersList.setVisibility(View.VISIBLE);
+            usersList.setAdapter(mUserGroupsAdapter);
+
+        } else {
+            usersList.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        try {
+            mListener = (OnSearchFragmentInteractionListener) activity;
+        } catch (ClassCastException e) {
+            throw new ClassCastException(activity.toString()
+                    + " must implement OnFragmentInteractionListener");
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        // focus the search view and request the software keyboard be shown
+        View searchView = getView().findViewById(R.id.searchView);
+        if (searchView.requestFocus()) {
+            InputMethodManager imm = (InputMethodManager)
+                    getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+            if (imm != null) {
+                imm.showSoftInput(searchView.findFocus(), InputMethodManager.SHOW_IMPLICIT);
+            }
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+        mListener = null;
+    }
+
+    @Override
+    public void unshareButtonPressed(OCShare share) {
+        // Unshare
+        mListener.unshareWith(share);
+        Log_OC.d(TAG, "Unshare - " + share.getSharedWithDisplayName());
+    }
+
+    /**
+     * This interface must be implemented by activities that contain this
+     * fragment to allow an interaction in this fragment to be communicated
+     * to the activity and potentially other fragments contained in that
+     * activity.
+     * <p/>
+     * See the Android Training lesson <a href=
+     * "http://developer.android.com/training/basics/fragments/communicating.html"
+     * >Communicating with Other Fragments</a> for more information.
+     */
+    public interface OnSearchFragmentInteractionListener {
+        void unshareWith(OCShare share);
+    }
+
+}
diff --git a/src/com/owncloud/android/ui/fragment/ShareFileFragment.java b/src/com/owncloud/android/ui/fragment/ShareFileFragment.java
new file mode 100644 (file)
index 0000000..a029653
--- /dev/null
@@ -0,0 +1,259 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   @author David A. Velasco
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.ui.fragment;
+
+import android.accounts.Account;
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+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.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.ui.activity.FileActivity;
+import com.owncloud.android.ui.activity.ShareActivity;
+import com.owncloud.android.ui.adapter.ShareUserListAdapter;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.MimetypeIconUtil;
+
+import java.util.ArrayList;
+
+/**
+ * Fragment for Sharing a file with sharees (users or groups)
+ *
+ * A simple {@link Fragment} subclass.
+ *
+ * Activities that contain this fragment must implement the
+ * {@link ShareFileFragment.OnShareFragmentInteractionListener} interface
+ * to handle interaction events.
+ *
+ * Use the {@link ShareFileFragment#newInstance} factory method to
+ * create an instance of this fragment.
+ */
+public class ShareFileFragment extends Fragment
+        implements ShareUserListAdapter.ShareUserAdapterListener{
+
+    private static final String TAG = ShareFileFragment.class.getSimpleName();
+
+    // the fragment initialization parameters
+    private static final String ARG_FILE = "FILE";
+    private static final String ARG_ACCOUNT = "ACCOUNT";
+
+    // Parameters
+    private OCFile mFile;
+    private Account mAccount;
+
+    // other members
+    private ArrayList<OCShare> mShares;
+    private ShareUserListAdapter mUserGroupsAdapter = null;
+    private OnShareFragmentInteractionListener mListener;
+
+    /**
+     * Public factory method to create new ShareFileFragment instances.
+     *
+     * @param fileToShare An {@link OCFile} to show in the fragment
+     * @param account     An ownCloud account
+     * @return A new instance of fragment ShareFileFragment.
+     */
+    public static ShareFileFragment newInstance(OCFile fileToShare, Account account) {
+        ShareFileFragment fragment = new ShareFileFragment();
+        Bundle args = new Bundle();
+        args.putParcelable(ARG_FILE, fileToShare);
+        args.putParcelable(ARG_ACCOUNT, account);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    public ShareFileFragment() {
+        // Required empty public constructor
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (getArguments() != null) {
+            mFile = getArguments().getParcelable(ARG_FILE);
+            mAccount = getArguments().getParcelable(ARG_ACCOUNT);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        View view = inflater.inflate(R.layout.share_file_layout, container, false);
+
+        // Setup layout
+        // Image
+        ImageView icon = (ImageView) view.findViewById(R.id.shareFileIcon);
+        icon.setImageResource(MimetypeIconUtil.getFileTypeIconId(mFile.getMimetype(),
+                mFile.getFileName()));
+        if (mFile.isImage()) {
+            String remoteId = String.valueOf(mFile.getRemoteId());
+            Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(remoteId);
+            if (thumbnail != null) {
+                icon.setImageBitmap(thumbnail);
+            }
+        }
+        // Name
+        TextView filename = (TextView) view.findViewById(R.id.shareFileName);
+        filename.setText(mFile.getFileName());
+        // Size
+        TextView size = (TextView) view.findViewById(R.id.shareFileSize);
+        if (mFile.isFolder()) {
+            size.setVisibility(View.GONE);
+        } else {
+            size.setText(DisplayUtils.bytesToHumanReadable(mFile.getFileLength()));
+        }
+
+        //  Add User Button
+        Button addUserGroupButton = (Button)
+                view.findViewById(R.id.addUserButton);
+        addUserGroupButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                 boolean shareWithUsersEnable = AccountUtils.hasSearchUsersSupport(mAccount);
+                if (shareWithUsersEnable) {
+                    // Show Search Fragment
+                    mListener.showSearchUsersAndGroups();
+                } else {
+                    String message = getString(R.string.share_sharee_unavailable);
+                    Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
+                }
+            }
+        });
+
+        return view;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        // Load data into the list
+        refreshUsersOrGroupsListFromDB();
+    }
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        try {
+            mListener = (OnShareFragmentInteractionListener) activity;
+        } catch (ClassCastException e) {
+            throw new ClassCastException(activity.toString()
+                    + " must implement OnShareFragmentInteractionListener");
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        super.onDetach();
+        mListener = null;
+    }
+
+    /**
+     * Get users and groups from the DB to fill in the "share with" list
+     *
+     * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager}
+     * instance ready to use. If not ready, does nothing.
+     */
+    public void refreshUsersOrGroupsListFromDB (){
+        if (((FileActivity) mListener).getStorageManager() != null) {
+            // Get Users and Groups
+            mShares = ((FileActivity) mListener).getStorageManager().getSharesWithForAFile(
+                    mFile.getRemotePath(),
+                    mAccount.name
+            );
+
+            // Update list of users/groups
+            updateListOfUserGroups();
+        }
+    }
+
+    private void updateListOfUserGroups() {
+        // Update list of users/groups
+        // TODO Refactoring: create a new {@link ShareUserListAdapter} instance with every call should not be needed
+        mUserGroupsAdapter = new ShareUserListAdapter(
+                getActivity(),
+                R.layout.share_user_item,
+                mShares,
+                this
+        );
+
+        // Show data
+        TextView noShares = (TextView) getView().findViewById(R.id.shareNoUsers);
+        ListView usersList = (ListView) getView().findViewById(R.id.shareUsersList);
+
+        if (mShares.size() > 0) {
+            noShares.setVisibility(View.GONE);
+            usersList.setVisibility(View.VISIBLE);
+            usersList.setAdapter(mUserGroupsAdapter);
+
+        } else {
+            noShares.setVisibility(View.VISIBLE);
+            usersList.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void unshareButtonPressed(OCShare share) {
+        // Unshare
+        mListener.unshareWith(share);
+        Log_OC.d(TAG, "Unshare - " + share.getSharedWithDisplayName());
+    }
+
+
+    /**
+     * This interface must be implemented by activities that contain this
+     * fragment to allow an interaction in this fragment to be communicated
+     * to the activity and potentially other fragments contained in that
+     * activity.
+     * <p/>
+     * See the Android Training lesson <a href=
+     * "http://developer.android.com/training/basics/fragments/communicating.html"
+     * >Communicating with Other Fragments</a> for more information.
+     */
+    public interface OnShareFragmentInteractionListener {
+        void showSearchUsersAndGroups();
+        void refreshUsersOrGroupsListFromServer();
+        void unshareWith(OCShare share);
+    }
+
+}
index 69182d6..5bb24e7 100644 (file)
@@ -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();
+        }
+    }
+
 }
index 3dafb9d..f797fe2 100644 (file)
@@ -26,7 +26,6 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.graphics.drawable.ColorDrawable;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -55,14 +54,15 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.CreateShareViaLinkOperation;
+import com.owncloud.android.operations.CreateShareWithShareeOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
-import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.operations.UnshareOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
+import com.owncloud.android.ui.activity.ShareActivity;
 import com.owncloud.android.ui.fragment.FileFragment;
-import com.owncloud.android.utils.DisplayUtils;
 
 
 /**
@@ -230,11 +230,12 @@ public class PreviewImageActivity extends FileActivity implements
     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
         super.onRemoteOperationFinish(operation, result);
         
-        if (operation instanceof CreateShareOperation) {
-            onCreateShareOperationFinish((CreateShareOperation) operation, result);
-            
-        } else if (operation instanceof UnshareLinkOperation) {
-            onUnshareLinkOperationFinish((UnshareLinkOperation) operation, result);
+        if (operation instanceof CreateShareViaLinkOperation ||
+                operation instanceof CreateShareWithShareeOperation) {
+            onCreateShareOperationFinish(result);
+
+        } else if (operation instanceof UnshareOperation) {
+            onUnshareLinkOperationFinish((UnshareOperation) operation, result);
             
         } else if (operation instanceof RemoveFileOperation) {
             finish();
@@ -245,7 +246,7 @@ public class PreviewImageActivity extends FileActivity implements
     }
     
     
-    private void onUnshareLinkOperationFinish(UnshareLinkOperation operation,
+    private void onUnshareLinkOperationFinish(UnshareOperation operation,
                                               RemoteOperationResult result) {
         if (result.isSuccess()) {
             OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath());
@@ -259,8 +260,7 @@ public class PreviewImageActivity extends FileActivity implements
             
     }
     
-    private void onCreateShareOperationFinish(CreateShareOperation operation,
-                                              RemoteOperationResult result) {
+    private void onCreateShareOperationFinish(RemoteOperationResult result) {
         if (result.isSuccess()) {
             OCFile file = getStorageManager().getFileByPath(getFile().getRemotePath());
             if (file != null) {
@@ -400,7 +400,6 @@ public class PreviewImageActivity extends FileActivity implements
         
     }
 
-    
     private void requestForDownload(OCFile file) {
         if (mDownloaderBinder == null) {
             Log_OC.d(TAG, "requestForDownload called without binder to download service");
@@ -430,12 +429,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();
         }
index e61e335..b3aab45 100644 (file)
@@ -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;
@@ -69,11 +71,14 @@ public class PreviewImageFragment extends FileFragment {
 
     private static final String ARG_FILE = "FILE";
     private static final String ARG_IGNORE_FIRST = "IGNORE_FIRST";
+    private static final String ARG_SHOW_RESIZED_IMAGE = "SHOW_RESIZED_IMAGE";
 
     private TouchImageViewCustom mImageView;
     private TextView mMessageView;
     private ProgressBar mProgressWheel;
 
+    private Boolean mShowResizedImage = false;
+
     public Bitmap mBitmap = null;
 
     private static final String TAG = PreviewImageFragment.class.getSimpleName();
@@ -97,11 +102,14 @@ 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);
+        args.putBoolean(ARG_SHOW_RESIZED_IMAGE, showResizedImage);
         frag.setArguments(args);
         return frag;
     }
@@ -134,6 +142,7 @@ public class PreviewImageFragment extends FileFragment {
             // not right now
 
         mIgnoreFirstSavedState = args.getBoolean(ARG_IGNORE_FIRST);
+        mShowResizedImage = args.getBoolean(ARG_SHOW_RESIZED_IMAGE);
         setHasOptionsMenu(true);
     }
 
@@ -179,9 +188,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 +205,44 @@ 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) &&
+                        mContainerActivity.getStorageManager() != null) {
+                        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());
+            }
         }
     }
 
@@ -224,6 +264,9 @@ public class PreviewImageFragment extends FileFragment {
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         super.onCreateOptionsMenu(menu, inflater);
         inflater.inflate(R.menu.file_actions_menu, menu);
+
+//        MenuItem item = menu.findItem(R.id.action_set_as_wallpaper);
+//        item.setVisible(getFile().isDown());
     }
 
     /**
@@ -289,6 +332,10 @@ public class PreviewImageFragment extends FileFragment {
                 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
                 return true;
             }
+            case R.id.action_share_with_users: {
+                mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
+                return true;
+            }
             case R.id.action_unshare_file: {
                 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
                 return true;
@@ -307,9 +354,15 @@ 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_download_file:
             case R.id.action_sync_file: {
                 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
                 return true;
@@ -322,6 +375,10 @@ public class PreviewImageFragment extends FileFragment {
                 mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
                 return true;
             }
+            case R.id.action_set_as_wallpaper:{
+                mContainerActivity.getFileOperationsHelper().setPictureAs(getFile());
+                return true;
+            }
             default:
                 return false;
         }
@@ -332,7 +389,6 @@ public class PreviewImageFragment extends FileFragment {
         mContainerActivity.showDetails(getFile());
     }
 
-
     @Override
     public void onResume() {
         super.onResume();
@@ -509,7 +565,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
             }
index 8197143..5ca2e98 100644 (file)
@@ -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;
 
@@ -79,7 +82,7 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
         mStorageManager = storageManager;
         mImageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice);
         
-        mImageFiles = FileStorageUtils.sortFolder(mImageFiles);
+        mImageFiles = FileStorageUtils.sortOcFolder(mImageFiles);
         
         mObsoleteFragments = new HashSet<Object>();
         mObsoletePositions = new HashSet<Integer>();
@@ -103,17 +106,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;
index 0dbb1a3..ba80ace 100644 (file)
 package com.owncloud.android.ui.preview;
 
 import android.accounts.Account;
+import android.accounts.AuthenticatorException;
+import android.accounts.OperationCanceledException;
 import android.app.Activity;
+import android.content.ActivityNotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.AsyncTask;
 import android.support.v7.app.AlertDialog;
 import android.content.ComponentName;
 import android.content.Context;
@@ -36,8 +41,6 @@ import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.MediaPlayer.OnPreparedListener;
-import android.net.Uri;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.view.LayoutInflater;
@@ -52,9 +55,16 @@ import android.widget.ImageView;
 import android.widget.Toast;
 import android.widget.VideoView;
 
+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.OwnCloudAccount;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.OwnCloudCredentials;
+import com.owncloud.android.lib.common.accounts.AccountUtils;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.media.MediaControlView;
 import com.owncloud.android.media.MediaService;
@@ -64,6 +74,9 @@ import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
 import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
 
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+
 
 /**
  * This fragment shows a preview of a downloaded media file (audio or video).
@@ -87,6 +100,7 @@ public class PreviewMediaFragment extends FileFragment implements
     private ImageView mImagePreview;
     private VideoView mVideoPreview;
     private int mSavedPlaybackPosition;
+    private String mUri;
 
     private MediaServiceBinder mMediaServiceBinder = null;
     private MediaControlView mMediaController = null;
@@ -153,7 +167,7 @@ public class PreviewMediaFragment extends FileFragment implements
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
         super.onCreateView(inflater, container, savedInstanceState);
-        Log_OC.e(TAG, "onCreateView");
+        Log_OC.v(TAG, "onCreateView");
 
 
         mView = inflater.inflate(R.layout.file_preview, container, false);
@@ -174,7 +188,7 @@ public class PreviewMediaFragment extends FileFragment implements
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        Log_OC.e(TAG, "onActivityCreated");
+        Log_OC.v(TAG, "onActivityCreated");
 
         OCFile file = getFile();
         if (savedInstanceState == null) {
@@ -184,10 +198,6 @@ public class PreviewMediaFragment extends FileFragment implements
             if (mAccount == null) {
                 throw new IllegalStateException("Instanced with a NULL ownCloud Account");
             }
-            if (!file.isDown()) {
-                throw new IllegalStateException("There is no local file to preview");
-            }
-
         }
         else {
             file = (OCFile) savedInstanceState.getParcelable(PreviewMediaFragment.EXTRA_FILE);
@@ -198,7 +208,7 @@ public class PreviewMediaFragment extends FileFragment implements
             mAutoplay = savedInstanceState.getBoolean(PreviewMediaFragment.EXTRA_PLAYING);
 
         }
-        if (file != null && file.isDown()) {
+        if (file != null) {
             if (file.isVideo()) {
                 mVideoPreview.setVisibility(View.VISIBLE);
                 mImagePreview.setVisibility(View.GONE);
@@ -244,7 +254,7 @@ public class PreviewMediaFragment extends FileFragment implements
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        Log_OC.e(TAG, "onSaveInstanceState");
+        Log_OC.v(TAG, "onSaveInstanceState");
 
         outState.putParcelable(PreviewMediaFragment.EXTRA_FILE, getFile());
         outState.putParcelable(PreviewMediaFragment.EXTRA_ACCOUNT, mAccount);
@@ -268,10 +278,10 @@ public class PreviewMediaFragment extends FileFragment implements
     @Override
     public void onStart() {
         super.onStart();
-        Log_OC.e(TAG, "onStart");
+        Log_OC.v(TAG, "onStart");
 
         OCFile file = getFile();
-        if (file != null && file.isDown()) {
+        if (file != null) {
             if (file.isAudio()) {
                 bindMediaService();
 
@@ -355,6 +365,10 @@ public class PreviewMediaFragment extends FileFragment implements
                 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
                 return true;
             }
+            case R.id.action_share_with_users: {
+                seeShareFile();
+                return true;
+            }
             case R.id.action_unshare_file: {
                 stopPreview(false);
                 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
@@ -398,7 +412,7 @@ public class PreviewMediaFragment extends FileFragment implements
     /**
      * Update the file of the fragment with file value
      *
-     * @param file
+     * @param file      Replaces the held file with a new one
      */
     public void updateFile(OCFile file) {
         setFile(file);
@@ -415,6 +429,10 @@ public class PreviewMediaFragment extends FileFragment implements
         mContainerActivity.showDetails(getFile());
     }
 
+    private void seeShareFile() {
+        stopPreview(false);
+        mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
+    }
 
     private void prepareVideo() {
         // create helper to get more control on the playback
@@ -431,8 +449,65 @@ public class PreviewMediaFragment extends FileFragment implements
 
         // load the video file in the video player ; 
         // when done, VideoHelper#onPrepared() will be called
-        Uri uri = Uri.parse(getFile().getStoragePath());
-        mVideoPreview.setVideoPath(uri.encode(getFile().getStoragePath()));
+        if (getFile().isDown()) {
+            mUri = getFile().getStoragePath();
+        } else {
+            Context context = MainApp.getAppContext();
+            Account account = mContainerActivity.getStorageManager().getAccount();
+
+            mUri = generateUrlWithCredentials(account, context, getFile());
+        }
+
+        mVideoPreview.setVideoURI(getFile().getStorageUri());
+    }
+
+    public static String generateUrlWithCredentials(Account account, Context context, OCFile file){
+        OwnCloudAccount ocAccount = null;
+        try {
+            ocAccount = new OwnCloudAccount(account, context);
+
+            final ClientGenerationTask task = new ClientGenerationTask();
+            task.execute(ocAccount);
+
+            OwnCloudClient mClient = task.get();
+            String url = AccountUtils.constructFullURLForAccount(context, account) + Uri.encode(file.getRemotePath(), "/");
+            OwnCloudCredentials credentials = mClient.getCredentials();
+
+            return url.replace("//", "//" + credentials.getUsername() + ":" + credentials.getAuthToken() + "@");
+
+        } catch (AccountUtils.AccountNotFoundException e) {
+            e.printStackTrace();
+
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        } catch (ExecutionException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+
+    public static class ClientGenerationTask extends AsyncTask<Object, Void, OwnCloudClient> {
+        @Override
+        protected OwnCloudClient doInBackground(Object... params) {
+            Object account = params[0];
+            if (account instanceof OwnCloudAccount){
+                try {
+                    OwnCloudAccount ocAccount = (OwnCloudAccount) account;
+                    return OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, MainApp.getAppContext());
+                } catch (AccountUtils.AccountNotFoundException e) {
+                    e.printStackTrace();
+                } catch (OperationCanceledException e) {
+                    e.printStackTrace();
+                } catch (AuthenticatorException e) {
+                    e.printStackTrace();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+
+            return null;
+        }
     }
 
 
@@ -447,7 +522,7 @@ public class PreviewMediaFragment extends FileFragment implements
          */
         @Override
         public void onPrepared(MediaPlayer vp) {
-            Log_OC.e(TAG, "onPrepared");
+            Log_OC.v(TAG, "onPrepared");
             mVideoPreview.seekTo(mSavedPlaybackPosition);
             if (mAutoplay) {
                 mVideoPreview.start();
@@ -467,25 +542,9 @@ public class PreviewMediaFragment extends FileFragment implements
          */
         @Override
         public void onCompletion(MediaPlayer mp) {
-            Log_OC.e(TAG, "completed");
+            Log_OC.v(TAG, "completed");
             if (mp != null) {
                 mVideoPreview.seekTo(0);
-                // next lines are necessary to work around undesired video loops
-                if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD) {
-                    mVideoPreview.pause();
-
-                }
-                else {
-                    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.GINGERBREAD_MR1) {
-                        // mVideePreview.pause() is not enough
-
-                        mMediaController.setEnabled(false);
-                        mVideoPreview.stopPlayback();
-                        mAutoplay = false;
-                        mSavedPlaybackPosition = 0;
-                        mVideoPreview.setVideoPath(getFile().getStoragePath());
-                    }
-                }
             } // else : called from onError()
             mMediaController.updatePausePlay();
         }
@@ -500,48 +559,32 @@ public class PreviewMediaFragment extends FileFragment implements
          */
         @Override
         public boolean onError(MediaPlayer mp, int what, int extra) {
-            if (mVideoPreview.getWindowToken() != null) {
-                String message = MediaService.getMessageForMediaError(
-                        getActivity(), what, extra);
-                new AlertDialog.Builder(getActivity())
-                        .setMessage(message)
-                        .setPositiveButton(android.R.string.VideoView_error_button,
-                                new DialogInterface.OnClickListener() {
-                                    public void onClick(DialogInterface dialog, int whichButton) {
-                                        dialog.dismiss();
-                                        VideoHelper.this.onCompletion(null);
-                                    }
-                                })
-                        .setCancelable(false)
-                        .show();
-            }
+            MediaService.streamWithExternalApp(mUri, getActivity()).show();
             return true;
         }
-
     }
 
-
     @Override
     public void onPause() {
-        Log_OC.e(TAG, "onPause");
+        Log_OC.v(TAG, "onPause");
         super.onPause();
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        Log_OC.e(TAG, "onResume");
+        Log_OC.v(TAG, "onResume");
     }
 
     @Override
     public void onDestroy() {
-        Log_OC.e(TAG, "onDestroy");
+        Log_OC.v(TAG, "onDestroy");
         super.onDestroy();
     }
 
     @Override
     public void onStop() {
-        Log_OC.e(TAG, "onStop");
+        Log_OC.v(TAG, "onStop");
 
         mPrepared = false;
         if (mMediaServiceConnection != null) {
@@ -582,12 +625,12 @@ public class PreviewMediaFragment extends FileFragment implements
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        Log_OC.e(TAG, "onConfigurationChanged " + this);
+        Log_OC.v(TAG, "onConfigurationChanged " + this);
     }
 
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        Log_OC.e(TAG, "onActivityResult " + this);
+        Log_OC.v(TAG, "onActivityResult " + this);
         super.onActivityResult(requestCode, resultCode, data);
         if (resultCode == Activity.RESULT_OK) {
             mSavedPlaybackPosition = data.getExtras().getInt(
@@ -661,7 +704,7 @@ public class PreviewMediaFragment extends FileFragment implements
         @Override
         public void onServiceDisconnected(ComponentName component) {
             if (component.equals(new ComponentName(getActivity(), MediaService.class))) {
-                Log_OC.e(TAG, "Media service suddenly disconnected");
+                Log_OC.w(TAG, "Media service suddenly disconnected");
                 if (mMediaController != null) {
                     mMediaController.setMediaPlayer(null);
                 }
@@ -725,7 +768,7 @@ public class PreviewMediaFragment extends FileFragment implements
         if (mPrepared) {
             mSavedPlaybackPosition = mVideoPreview.getCurrentPosition();
         }
-        Log_OC.e(TAG, "getting position: " + mSavedPlaybackPosition);
+        Log_OC.v(TAG, "getting position: " + mSavedPlaybackPosition);
         return mSavedPlaybackPosition;
     }
 
index 6595bf7..a37a1bb 100644 (file)
@@ -290,6 +290,18 @@ public class PreviewTextFragment extends FileFragment {
             item.setVisible(false);
             item.setEnabled(false);
         }
+
+        item = menu.findItem(R.id.action_switch_view);
+        if (item != null){
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
+
+        item = menu.findItem(R.id.action_sort);
+        if (item != null) {
+            item.setVisible(false);
+            item.setEnabled(false);
+        }
     }
 
     /**
@@ -302,6 +314,10 @@ public class PreviewTextFragment extends FileFragment {
                 mContainerActivity.getFileOperationsHelper().shareFileWithLink(getFile());
                 return true;
             }
+            case R.id.action_share_with_users: {
+                mContainerActivity.getFileOperationsHelper().showShareFile(getFile());
+                return true;
+            }
             case R.id.action_unshare_file: {
                 mContainerActivity.getFileOperationsHelper().unshareFileWithLink(getFile());
                 return true;
index 42b7fb2..c1b4125 100644 (file)
@@ -78,7 +78,7 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Log_OC.e(TAG, "ACTIVITY\t\tonCreate");
+        Log_OC.v(TAG, "onCreate");
         
         setContentView(R.layout.video_layout);
     
@@ -110,7 +110,6 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
     @Override
     public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        Log_OC.e(TAG, "ACTIVITY\t\tonSaveInstanceState");
         outState.putInt(PreviewVideoActivity.EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
         outState.putBoolean(PreviewVideoActivity.EXTRA_AUTOPLAY , mVideoPlayer.isPlaying());
     }
@@ -118,7 +117,7 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
     
     @Override
     public void onBackPressed() {
-        Log_OC.e(TAG, "ACTIVTIY\t\tonBackPressed");
+        Log_OC.v(TAG, "onBackPressed");
         Intent i = new Intent();
         i.putExtra(EXTRA_AUTOPLAY, mVideoPlayer.isPlaying());
         i.putExtra(EXTRA_START_POSITION, mVideoPlayer.getCurrentPosition());
@@ -136,7 +135,7 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
      */
     @Override
     public void onPrepared(MediaPlayer mp) {
-        Log_OC.e(TAG, "ACTIVITY\t\tonPrepare");
+        Log_OC.v(TAG, "onPrepare");
         mVideoPlayer.seekTo(mSavedPlaybackPosition);
         if (mAutoplay) { 
             mVideoPlayer.start();
@@ -204,25 +203,20 @@ public class PreviewVideoActivity extends FileActivity implements OnCompletionLi
             file = getStorageManager().getFileById(file.getFileId()); 
             if (file != null) {
                 if (file.isDown()) {
-                    mVideoPlayer.setVideoPath(file.getStoragePath());
-                    
+                    mVideoPlayer.setVideoURI(file.getStorageUri());
+
                 } else {
-                    // not working yet
                     String url;
-                    try {
-                        url = AccountUtils.constructFullURLForAccount(this, getAccount()) + file.getRemotePath();
-                        mVideoPlayer.setVideoURI(Uri.parse(url));
-                    } catch (AccountNotFoundException e) {
-                        onError(null, MediaService.OC_MEDIA_ERROR, R.string.media_err_no_account);
-                    }
+                    url = PreviewMediaFragment.generateUrlWithCredentials(getAccount(), getApplicationContext(), getFile());
+                    mVideoPlayer.setVideoURI(Uri.parse(url));
                 }
-                
+
                 // create and prepare control panel for the user
                 mMediaController = new MediaController(this);
                 mMediaController.setMediaPlayer(mVideoPlayer);
                 mMediaController.setAnchorView(mVideoPlayer);
                 mVideoPlayer.setMediaController(mMediaController);
-                
+
             } else {
                 finish();
             }
index 8a281e9..e3c94f2 100644 (file)
 \r
 package com.owncloud.android.utils;\r
 \r
+import java.io.File;\r
+import java.net.IDN;\r
+import java.text.DateFormat;\r
+import java.util.Arrays;\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.Set;\r
+import java.util.Vector;\r
+\r
 import android.annotation.TargetApi;\r
 import android.app.Activity;\r
 import android.content.Context;\r
+import android.content.SharedPreferences;\r
 import android.graphics.Point;\r
 import android.graphics.PorterDuff;\r
 import android.os.Build;\r
@@ -35,8 +47,10 @@ import android.widget.SeekBar;
 \r
 import com.owncloud.android.MainApp;\r
 import com.owncloud.android.R;\r
+import com.owncloud.android.datamodel.FileDataStorageManager;\r
 import com.owncloud.android.datamodel.OCFile;\r
 \r
+import java.math.BigDecimal;\r
 import java.net.IDN;\r
 import java.text.DateFormat;\r
 import java.util.Calendar;\r
@@ -52,6 +66,7 @@ public class DisplayUtils {
     private static final String OWNCLOUD_APP_NAME = "ownCloud";\r
     \r
     private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };\r
+    private static final int[] sizeScales = { 0, 0, 0, 1, 1, 2, 2, 2, 2 };\r
 \r
     private static Map<String, String> mimeType2HumanReadable;\r
 \r
@@ -72,19 +87,24 @@ public class DisplayUtils {
 \r
     /**\r
      * Converts the file size in bytes to human readable output.\r
-     * \r
+     * <ul>\r
+     *     <li>appends a size suffix, e.g. B, KB, MB etc.</li>\r
+     *     <li>rounds the size based on the suffix to 0,1 or 2 decimals</li>\r
+     * </ul>\r
+     *\r
      * @param bytes Input file size\r
      * @return Like something readable like "12 MB"\r
      */\r
     public static String bytesToHumanReadable(long bytes) {\r
         double result = bytes;\r
-        int attachedsuff = 0;\r
-        while (result > 1024 && attachedsuff < sizeSuffixes.length) {\r
+        int attachedSuff = 0;\r
+        while (result > 1024 && attachedSuff < sizeSuffixes.length) {\r
             result /= 1024.;\r
-            attachedsuff++;\r
+            attachedSuff++;\r
         }\r
-        result = ((int) (result * 100)) / 100.;\r
-        return result + " " + sizeSuffixes[attachedsuff];\r
+\r
+        return new BigDecimal(result).setScale(\r
+                sizeScales[attachedSuff], BigDecimal.ROUND_HALF_UP) + " " + sizeSuffixes[attachedSuff];\r
     }\r
 \r
     /**\r
@@ -178,8 +198,13 @@ public class DisplayUtils {
         return fileExtension;\r
     }\r
 \r
+    public static CharSequence getRelativeTimestamp(Context context, OCFile file) {\r
+        return getRelativeDateTimeString(context, file.getModificationTimestamp(),\r
+                DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);\r
+    }\r
+\r
     @SuppressWarnings("deprecation")\r
-    public static CharSequence getRelativeDateTimeString (\r
+    private static CharSequence getRelativeDateTimeString (\r
             Context c, long time, long minResolution, long transitionResolution, int flags\r
             ){\r
         \r
@@ -193,22 +218,19 @@ public class DisplayUtils {
         else if ((System.currentTimeMillis() - time) < 60 * 1000) {\r
             return c.getString(R.string.file_list_seconds_ago);\r
         } else {\r
-            // Workaround 2.x bug (see https://github.com/owncloud/android/issues/716)\r
-            if (    Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB && \r
-                    (System.currentTimeMillis() - time) > 24 * 60 * 60 * 1000   ) {\r
-                Date date = new Date(time);\r
-                date.setHours(0);\r
-                date.setMinutes(0);\r
-                date.setSeconds(0);\r
-                dateString = DateUtils.getRelativeDateTimeString(\r
-                        c, date.getTime(), minResolution, transitionResolution, flags\r
-                );\r
-            } else {\r
-                dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);\r
+            dateString = DateUtils.getRelativeDateTimeString(c, time, minResolution, transitionResolution, flags);\r
+        }\r
+\r
+        String[] parts = dateString.toString().split(",");\r
+        if (parts.length == 2) {\r
+            if (parts[1].contains(":") && !parts[0].contains(":")) {\r
+                return parts[0];\r
+            } else if (parts[0].contains(":") && !parts[1].contains(":")) {\r
+                return parts[1];\r
             }\r
         }\r
-        \r
-        return dateString.toString().split(",")[0];\r
+        //dateString contains unexpected format. fallback: use relative date time string from android api as is.\r
+        return dateString.toString();\r
     }\r
 \r
     /**\r
@@ -245,6 +267,67 @@ public class DisplayUtils {
     }\r
 \r
     /**\r
+     * Determines if user set folder to grid or list view. If folder is not set itself,\r
+     * it finds a parent that is set (at least root is set).\r
+     * @param file\r
+     * @param storageManager\r
+     * @return\r
+     */\r
+    public static boolean isGridView(OCFile file, FileDataStorageManager storageManager){\r
+        if (file != null) {\r
+            OCFile fileToTest = file;\r
+            OCFile parentDir = null;\r
+            String parentPath = null;\r
+\r
+            SharedPreferences setting = MainApp.getAppContext().getSharedPreferences(\r
+                    "viewMode", Context.MODE_PRIVATE);\r
+\r
+            if (setting.contains(fileToTest.getRemoteId())) {\r
+                return setting.getBoolean(fileToTest.getRemoteId(), false);\r
+            } else {\r
+                do {\r
+                    if (fileToTest.getParentId() != FileDataStorageManager.ROOT_PARENT_ID) {\r
+                        parentPath = new File(fileToTest.getRemotePath()).getParent();\r
+                        parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :\r
+                                parentPath + OCFile.PATH_SEPARATOR;\r
+                        parentDir = storageManager.getFileByPath(parentPath);\r
+                    } else {\r
+                        parentDir = storageManager.getFileByPath(OCFile.ROOT_PATH);\r
+                    }\r
+\r
+                    while (parentDir == null) {\r
+                        parentPath = new File(parentPath).getParent();\r
+                        parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath :\r
+                                parentPath + OCFile.PATH_SEPARATOR;\r
+                        parentDir = storageManager.getFileByPath(parentPath);\r
+                    }\r
+                    fileToTest = parentDir;\r
+                } while (endWhile(parentDir, setting));\r
+                return setting.getBoolean(fileToTest.getRemoteId(), false);\r
+            }\r
+        } else {\r
+            return false;\r
+        }\r
+    }\r
+\r
+    private static boolean endWhile(OCFile parentDir, SharedPreferences setting) {\r
+        if (parentDir.getRemotePath().compareToIgnoreCase(OCFile.ROOT_PATH) == 0) {\r
+            return false;\r
+        } else {\r
+            return !setting.contains(parentDir.getRemoteId());\r
+        }\r
+    }\r
+\r
+    public static void setViewMode(OCFile file, boolean setGrid){\r
+        SharedPreferences setting = MainApp.getAppContext().getSharedPreferences(\r
+                "viewMode", Context.MODE_PRIVATE);\r
+\r
+        SharedPreferences.Editor editor = setting.edit();\r
+        editor.putBoolean(file.getRemoteId(), setGrid);\r
+        editor.commit();\r
+    }\r
+\r
+    /**\r
      * sets the coloring of the given progress bar to color_accent.\r
      *\r
      * @param progressBar the progress bar to be colored\r
index b80cc57..37b2fba 100644 (file)
@@ -29,14 +29,15 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.operations.CopyFileOperation;
 import com.owncloud.android.operations.CreateFolderOperation;
-import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.CreateShareViaLinkOperation;
+import com.owncloud.android.operations.CreateShareWithShareeOperation;
 import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.operations.MoveFileOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
 import com.owncloud.android.operations.RenameFileOperation;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
-import com.owncloud.android.operations.UnshareLinkOperation;
+import com.owncloud.android.operations.UnshareOperation;
 import com.owncloud.android.operations.UploadFileOperation;
 
 import org.apache.commons.httpclient.ConnectTimeoutException;
@@ -60,7 +61,10 @@ public class ErrorMessageAdapter {
         
         String message = null;
 
-        if (operation instanceof UploadFileOperation) {
+        if (!result.isSuccess() && isNetworkError(result.getCode())) {
+            message = getErrorMessage(result, res);
+
+        } else if (operation instanceof UploadFileOperation) {
 
             if (result.isSuccess()) {
                 message = String.format(
@@ -119,9 +123,6 @@ public class ErrorMessageAdapter {
                     // Error --> No permissions
                     message = String.format(res.getString(R.string.forbidden_permissions),
                             res.getString(R.string.forbidden_permissions_delete));
-                } else if (isNetworkError(result.getCode())) {
-                    message = getErrorMessage(result, res);
-
                 } else {
                     message = res.getString(R.string.remove_fail_msg);
                 }
@@ -139,9 +140,6 @@ public class ErrorMessageAdapter {
             } else if (result.getCode().equals(ResultCode.INVALID_CHARACTER_IN_NAME)) {
                 message = res.getString(R.string.filename_forbidden_characters);
 
-            } else if (isNetworkError(result.getCode())) {
-                message = getErrorMessage(result, res);
-
             } else if (result.getCode() == ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER) {
                 message = res.getString(R.string.filename_forbidden_charaters_from_server);
 
@@ -162,16 +160,18 @@ public class ErrorMessageAdapter {
                 message = String.format(res.getString(R.string.forbidden_permissions),
                         res.getString(R.string.forbidden_permissions_create));
 
-            } else if (isNetworkError(result.getCode())) {
-                message = getErrorMessage(result, res);
-
             } else if (result.getCode() == ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER) {
                 message = res.getString(R.string.filename_forbidden_charaters_from_server);
             } else {
                 message = res.getString(R.string.create_dir_fail_msg);
             }
-        } else if (operation instanceof CreateShareOperation) {        
-            if (result.getCode() == ResultCode.SHARE_NOT_FOUND)  {      // Error --> SHARE_NOT_FOUND
+        } else if (operation instanceof CreateShareViaLinkOperation ||
+                    operation instanceof CreateShareWithShareeOperation) {
+
+            if (result.getData() != null && result.getData().size() > 0) {
+                message = (String) result.getData().get(0);     // share API sends its own error messages
+
+            } else if (result.getCode() == ResultCode.SHARE_NOT_FOUND)  {
                 message = res.getString(R.string.share_link_file_no_exist);
 
             } else if (result.getCode() == ResultCode.SHARE_FORBIDDEN) {
@@ -179,17 +179,17 @@ public class ErrorMessageAdapter {
                 message = String.format(res.getString(R.string.forbidden_permissions),
                         res.getString(R.string.share_link_forbidden_permissions));
 
-            } else if (isNetworkError(result.getCode())) {
-                message = getErrorMessage(result, res);
-
             } else {    // Generic error
                 // Show a Message, operation finished without success
                 message = res.getString(R.string.share_link_file_error);
             }
 
-        } else if (operation instanceof UnshareLinkOperation) {
+        } else if (operation instanceof UnshareOperation) {
 
-            if (result.getCode() == ResultCode.SHARE_NOT_FOUND)  {      // Error --> SHARE_NOT_FOUND
+            if (result.getData() != null && result.getData().size() > 0) {
+                message = (String) result.getData().get(0);     // share API sends its own error messages
+
+            } else  if (result.getCode() == ResultCode.SHARE_NOT_FOUND)  {
                 message = res.getString(R.string.unshare_link_file_no_exist);
 
             } else if (result.getCode() == ResultCode.SHARE_FORBIDDEN) {
@@ -197,18 +197,13 @@ public class ErrorMessageAdapter {
                 message = String.format(res.getString(R.string.forbidden_permissions),
                         res.getString(R.string.unshare_link_forbidden_permissions));
 
-            } else if (isNetworkError(result.getCode())) {
-                message = getErrorMessage(result, res);
-
             } else {    // Generic error
                 // Show a Message, operation finished without success
                 message = res.getString(R.string.unshare_link_file_error);
             }
         } else if (operation instanceof MoveFileOperation) {
 
-            if(isNetworkError(result.getCode())){
-                message = getErrorMessage(result, res);
-            } else if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
+            if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
                 message = res.getString(R.string.move_file_not_found);
             } else if (result.getCode() == ResultCode.INVALID_MOVE_INTO_DESCENDANT) {
                 message = res.getString(R.string.move_file_invalid_into_descendent);
@@ -238,14 +233,12 @@ public class ErrorMessageAdapter {
 
                 } else {    // Generic error
                     // Show a Message, operation finished without success
-                    message = String.format(res.getString(R.string.download_folder_failed_content),
+                    message = String.format(res.getString(R.string.sync_folder_failed_content),
                             folderPathName);
                 }
             }
         } else if (operation instanceof CopyFileOperation) {
-            if(isNetworkError(result.getCode())){
-                message = getErrorMessage(result, res);
-            } else if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
+            if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
                 message = res.getString(R.string.copy_file_not_found);
             } else if (result.getCode() == ResultCode.INVALID_COPY_INTO_DESCENDANT) {
                 message = res.getString(R.string.copy_file_invalid_into_descendent);
diff --git a/src/com/owncloud/android/utils/ExceptionHandler.java b/src/com/owncloud/android/utils/ExceptionHandler.java
new file mode 100644 (file)
index 0000000..b06ec70
--- /dev/null
@@ -0,0 +1,102 @@
+package com.owncloud.android.utils;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.ui.activity.ErrorReportActivity;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+// from https://stackoverflow.com/questions/23486627/catching-error-and-user-information#answer-23486834
+public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+    Context context;
+    private final String LINE_SEPARATOR = "\n";
+
+    public ExceptionHandler() {
+        // TODO Auto-generated constructor stub
+        context = MainApp.getAppContext();
+    }
+
+    @Override
+    public void uncaughtException(Thread arg0, Throwable arg1) {
+        // TODO Auto-generated method stub
+
+        StringWriter stackTrace = new StringWriter();
+        arg1.printStackTrace(new PrintWriter(stackTrace));
+        final StringBuilder errorReport = new StringBuilder();
+        errorReport.append("************ CAUSE OF ERROR ************\n\n");
+        errorReport.append(stackTrace.toString());
+
+        errorReport.append("\n************ DEVICE INFORMATION ***********\n");
+        errorReport.append("Brand: ");
+        errorReport.append(Build.BRAND);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("Device: ");
+        errorReport.append(Build.DEVICE);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("Model: ");
+        errorReport.append(Build.MODEL);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("Id: ");
+        errorReport.append(Build.ID);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("Product: ");
+        errorReport.append(Build.PRODUCT);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("\n************ FIRMWARE ************\n");
+        errorReport.append("SDK: ");
+        errorReport.append(Build.VERSION.SDK);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("Release: ");
+        errorReport.append(Build.VERSION.RELEASE);
+        errorReport.append(LINE_SEPARATOR);
+        errorReport.append("Incremental: ");
+        errorReport.append(Build.VERSION.INCREMENTAL);
+        errorReport.append(LINE_SEPARATOR);
+
+
+        //after this you can do whatever you want , like i start an activity and show error log there
+
+        if (isUIThread()) {
+            invokeLogActivity(errorReport);
+        } else {  //handle non UI thread throw uncaught exception
+
+            new Handler(Looper.getMainLooper()).post(new Runnable() {
+                @Override
+                public void run() {
+                    invokeLogActivity(errorReport);
+                }
+            });
+        }
+    }
+    private void invokeLogActivity(StringBuilder errorReport){
+//        Intent sendIntent = new Intent();
+//        sendIntent.setAction(Intent.ACTION_SEND);
+//        sendIntent.putExtra(Intent.EXTRA_TEXT, errorReport.toString());
+//        sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+//        sendIntent.setType("text/plain");
+//        context.startActivity(sendIntent);
+
+        Intent sendIntent = new Intent(context, ErrorReportActivity.class);
+        sendIntent.putExtra(Intent.EXTRA_TEXT, errorReport.toString());
+        sendIntent.setAction(Intent.ACTION_SEND);
+        sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        sendIntent.setType("text/plain");
+        context.startActivity(sendIntent);
+
+
+        System.exit(1);
+//        android.os.Process.killProcess(android.os.Process.myPid());
+
+        }
+
+    private boolean isUIThread(){
+        return Looper.getMainLooper().getThread() == Thread.currentThread();
+    }
+}
\ No newline at end of file
index 3983771..e300a5e 100644 (file)
 package com.owncloud.android.utils;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.List;
 import java.util.Vector;
 
 import third_parties.daveKoeller.AlphanumComparator;
@@ -32,12 +40,12 @@ import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.resources.files.RemoteFile;
 
+import android.accounts.Account;
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
 import android.net.Uri;
-import android.os.Environment;
 import android.os.StatFs;
 import android.webkit.MimeTypeMap;
 
@@ -53,11 +61,10 @@ public class FileStorageUtils {
     public static Boolean mSortAscending = true;
 
     
-    //private static final String LOG_TAG = "FileStorageUtils";
-
     public static final String getSavePath(String accountName) {
-        File sdCard = Environment.getExternalStorageDirectory();
-        return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/" + Uri.encode(accountName, "@");
+//        File sdCard = Environment.getExternalStorageDirectory();
+
+        return MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator + Uri.encode(accountName, "@");
         // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
     }
 
@@ -66,14 +73,13 @@ public class FileStorageUtils {
     }
 
     public static final String getTemporalPath(String accountName) {
-        File sdCard = Environment.getExternalStorageDirectory();
-        return sdCard.getAbsolutePath() + "/" + MainApp.getDataFolder() + "/tmp/" + Uri.encode(accountName, "@");
+        return MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator + "tmp" + File.separator + Uri.encode(accountName, "@");
             // URL encoding is an 'easy fix' to overcome that NTFS and FAT32 don't allow ":" in file names, that can be in the accountName since 0.1.190B
     }
 
     @SuppressLint("NewApi")
     public static final long getUsableSpace(String accountName) {
-        File savePath = Environment.getExternalStorageDirectory();
+        File savePath = new File(MainApp.getStoragePath());
         if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
             return savePath.getUsableSpace();
 
@@ -85,7 +91,7 @@ public class FileStorageUtils {
     }
     
     public static final String getLogPath()  {
-        return Environment.getExternalStorageDirectory() + File.separator + MainApp.getDataFolder() + File.separator + "log";
+        return MainApp.getStoragePath() + File.separator + MainApp.getDataFolder() + File.separator + "log";
     }
 
     public static String getInstantUploadFilePath(Context context, String fileName) {
@@ -120,7 +126,7 @@ public class FileStorageUtils {
      * Creates and populates a new {@link OCFile} object with the data read from the server.
      * 
      * @param remote    remote file read from the server (remote file or folder).
-     * @return          New OCFile instance representing the remote resource described by we.
+     * @return          New OCFile instance representing the remote resource described by remote.
      */
     public static OCFile fillOCFile(RemoteFile remote) {
         OCFile file = new OCFile(remote.getRemotePath());
@@ -155,13 +161,13 @@ public class FileStorageUtils {
     /**
      * Sorts all filenames, regarding last user decision 
      */
-    public static Vector<OCFile> sortFolder(Vector<OCFile> files){
+    public static Vector<OCFile> sortOcFolder(Vector<OCFile> files){
         switch (mSortOrder){
         case 0:
-            files = FileStorageUtils.sortByName(files);
+            files = FileStorageUtils.sortOCFilesByName(files);
             break;
         case 1:
-            files = FileStorageUtils.sortByDate(files);
+            files = FileStorageUtils.sortOCFilesByDate(files);
             break;
         case 2: 
            // mFiles = FileStorageUtils.sortBySize(mSortAscending);
@@ -170,12 +176,31 @@ public class FileStorageUtils {
        
         return files;
     }
+
+    /**
+     * Sorts all filenames, regarding last user decision
+     */
+    public static File[] sortLocalFolder(File[] files){
+        switch (mSortOrder){
+            case 0:
+                files = FileStorageUtils.sortLocalFilesByName(files);
+                break;
+            case 1:
+                files = FileStorageUtils.sortLocalFilesByDate(files);
+                break;
+            case 2:
+                // mFiles = FileStorageUtils.sortBySize(mSortAscending);
+                break;
+        }
+
+        return files;
+    }
     
     /**
      * Sorts list by Date
      * @param files
      */
-    public static Vector<OCFile> sortByDate(Vector<OCFile> files){
+    public static Vector<OCFile> sortOCFilesByDate(Vector<OCFile> files){
         final Integer val;
         if (mSortAscending){
             val = 1;
@@ -205,6 +230,43 @@ public class FileStorageUtils {
         return files;
     }
 
+    /**
+     * Sorts list by Date
+     * @param filesArray
+     */
+    public static File[] sortLocalFilesByDate(File[] filesArray){
+        final Integer val;
+        if (mSortAscending){
+            val = 1;
+        } else {
+            val = -1;
+        }
+
+        List<File> files = new ArrayList<File>(Arrays.asList(filesArray));
+
+        Collections.sort(files, new Comparator<File>() {
+            public int compare(File o1, File o2) {
+                if (o1.isDirectory() && o2.isDirectory()) {
+                    Long obj1 = o1.lastModified();
+                    return val * obj1.compareTo(o2.lastModified());
+                }
+                else if (o1.isDirectory()) {
+                    return -1;
+                } else if (o2.isDirectory()) {
+                    return 1;
+                } else if (o1.lastModified() == 0 || o2.lastModified() == 0){
+                    return 0;
+                } else {
+                    Long obj1 = o1.lastModified();
+                    return val * obj1.compareTo(o2.lastModified());
+                }
+            }
+        });
+
+        File[] returnArray = new File[1];
+        return files.toArray(returnArray);
+    }
+
 //    /**
 //     * Sorts list by Size
 //     * @param sortAscending true: ascending, false: descending
@@ -243,7 +305,7 @@ public class FileStorageUtils {
      * Sorts list by Name
      * @param files     files to sort
      */
-    public static Vector<OCFile> sortByName(Vector<OCFile> files){
+    public static Vector<OCFile> sortOCFilesByName(Vector<OCFile> files){
         final Integer val;
         if (mSortAscending){
             val = 1;
@@ -266,6 +328,38 @@ public class FileStorageUtils {
         
         return files;
     }
+
+    /**
+     * Sorts list by Name
+     * @param filesArray    files to sort
+     */
+    public static File[] sortLocalFilesByName(File[] filesArray){
+        final Integer val;
+        if (mSortAscending){
+            val = 1;
+        } else {
+            val = -1;
+        }
+
+        List<File> files = new ArrayList<File>(Arrays.asList(filesArray));
+
+        Collections.sort(files, new Comparator<File>() {
+            public int compare(File o1, File o2) {
+                if (o1.isDirectory() && o2.isDirectory()) {
+                    return val * o1.getPath().toLowerCase().compareTo(o2.getPath().toLowerCase());
+                } else if (o1.isDirectory()) {
+                    return -1;
+                } else if (o2.isDirectory()) {
+                    return 1;
+                }
+                return val * new AlphanumComparator().compare(o1.getPath().toLowerCase(),
+                                                              o2.getPath().toLowerCase());
+            }
+        });
+
+        File[] returnArray = new File[1];
+        return files.toArray(returnArray);
+    }
     
     /**
      * Local Folder size
@@ -275,13 +369,11 @@ public class FileStorageUtils {
     public static long getFolderSize(File dir) {
         if (dir.exists()) {
             long result = 0;
-            File[] fileList = dir.listFiles();
-            for(int i = 0; i < fileList.length; i++) {
-                if(fileList[i].isDirectory()) {
-                    result += getFolderSize(fileList[i]);
-                } else {
-                    result += fileList[i].length();
-                }
+            for (File f : dir.listFiles()) {
+                if (f.isDirectory())
+                    result += getFolderSize(f);
+                else
+                    result += f.length();
             }
             return result;
         }
@@ -302,5 +394,65 @@ public class FileStorageUtils {
         String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
         return (result != null) ? result : "";
     }
-  
+
+    /**
+     * Scans the default location for saving local copies of files searching for
+     * a 'lost' file with the same full name as the {@link OCFile} received as
+     * parameter.
+     *
+     * This method helps to keep linked local copies of the files when the app is uninstalled, and then
+     * reinstalled in the device. OR after the cache of the app was deleted in system settings.
+     *
+     * The method is assuming that all the local changes in the file where synchronized in the past. This is dangerous,
+     * but assuming the contrary could lead to massive unnecessary synchronizations of downloaded file after deleting
+     * the app cache.
+     *
+     * This should be changed in the near future to avoid any chance of data loss, but we need to add some options
+     * to limit hard automatic synchronizations to wifi, unless the user wants otherwise.
+     *
+     * @param file      File to associate a possible 'lost' local file.
+     * @param account   Account holding file.
+     */
+    public static void searchForLocalFileInDefaultPath(OCFile file, Account account) {
+        if (file.getStoragePath() == null && !file.isFolder()) {
+            File f = new File(FileStorageUtils.getDefaultSavePathFor(account.name, file));
+            if (f.exists()) {
+                file.setStoragePath(f.getAbsolutePath());
+                file.setLastSyncDateForData(f.lastModified());
+            }
+        }
+    }
+
+    public static boolean copyFile(File src, File target) {
+        boolean ret = true;
+
+        InputStream in = null;
+        OutputStream out = null;
+
+        try {
+            in = new FileInputStream(src);
+            out = new FileOutputStream(target);
+            byte[] buf = new byte[1024];
+            int len;
+            while ((len = in.read(buf)) > 0) {
+                out.write(buf, 0, len);
+            }
+        } catch (IOException ex) {
+            ret = false;
+        } finally {
+            if (in != null) try {
+                in.close();
+            } catch (IOException e) {
+                e.printStackTrace(System.err);
+            }
+            if (out != null) try {
+                out.close();
+            } catch (IOException e) {
+                e.printStackTrace(System.err);
+            }
+        }
+
+        return ret;
+    }
+
 }
diff --git a/src/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java b/src/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java
new file mode 100644 (file)
index 0000000..a5f696e
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ *   ownCloud Android client application
+ *
+ *   @author masensio
+ *   Copyright (C) 2015 ownCloud Inc.
+ *
+ *   This program is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License version 2,
+ *   as published by the Free Software Foundation.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package com.owncloud.android.utils;
+
+import android.accounts.Account;
+import android.os.AsyncTask;
+import android.util.Pair;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.common.OwnCloudAccount;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.operations.GetSharesForFileOperation;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Async Task to get the users and groups which a file is shared with
+ */
+public class GetShareWithUsersAsyncTask extends AsyncTask<Object, Void, Pair<RemoteOperation, RemoteOperationResult>> {
+
+    private final String TAG = GetShareWithUsersAsyncTask.class.getSimpleName();
+    private final WeakReference<OnRemoteOperationListener> mListener;
+
+    public GetShareWithUsersAsyncTask(OnRemoteOperationListener listener) {
+        mListener = new WeakReference<OnRemoteOperationListener>(listener);
+    }
+
+    @Override
+    protected Pair<RemoteOperation, RemoteOperationResult> doInBackground(Object... params) {
+
+        GetSharesForFileOperation operation = null;
+        RemoteOperationResult result = null;
+
+        if (params != null && params.length == 3) {
+            OCFile file = (OCFile) params[0];
+            Account account = (Account) params[1];
+            FileDataStorageManager fileDataStorageManager = (FileDataStorageManager) params[2];
+
+            try {
+                // Get shares request
+                operation = new GetSharesForFileOperation(file.getRemotePath(), false, false);
+                OwnCloudAccount ocAccount = new OwnCloudAccount(account,
+                        MainApp.getAppContext());
+                OwnCloudClient client = OwnCloudClientManagerFactory.getDefaultSingleton().
+                        getClientFor(ocAccount, MainApp.getAppContext());
+                result = operation.execute(client, fileDataStorageManager);
+
+            } catch (Exception e) {
+                result = new RemoteOperationResult(e);
+                Log_OC.e(TAG, "Exception while getting shares", e);
+            }
+        } else {
+            result = new RemoteOperationResult(RemoteOperationResult.ResultCode.UNKNOWN_ERROR);
+        }
+
+        return new Pair(operation, result);
+    }
+
+    @Override
+    protected void onPostExecute(Pair<RemoteOperation, RemoteOperationResult> result) {
+
+        if (result!= null)
+        {
+            OnRemoteOperationListener listener = mListener.get();
+            if (listener!= null)
+            {
+                listener.onRemoteOperationFinish(result.first, result.second);
+            }
+        }
+    }
+
+}
\ No newline at end of file
index bd8c5d9..5fc4c8c 100644 (file)
@@ -69,15 +69,15 @@ public class MimetypeIconUtil {
     /**
      * Returns the resource identifier of an image to use as icon associated to a type of folder.
      *
-     * @param isSharedWithUser flag if the folder is shared with the user
-     * @param isShareByLink flag if the folder is shared by link
+     * @param isSharedViaUsers flag if the folder is shared via the users system
+     * @param isSharedViaLink flag if the folder is publicly shared via link
      * @return Identifier of an image resource.
      */
-    public static int getFolderTypeIconId(boolean isSharedWithUser, boolean isShareByLink) {
-        if (isSharedWithUser) {
-            return R.drawable.shared_with_me_folder;
-        } else if (isShareByLink) {
+    public static int getFolderTypeIconId(boolean isSharedViaUsers, boolean isSharedViaLink) {
+        if (isSharedViaLink) {
             return R.drawable.folder_public;
+        } else if (isSharedViaUsers) {
+            return R.drawable.shared_with_me_folder;
         }
 
         return R.drawable.ic_menu_archive;
index 47cf143..0324493 100644 (file)
@@ -24,6 +24,7 @@
 \r
 package third_parties.daveKoeller;\r
 import java.text.Collator;\r
+import java.io.File;\r
 import java.util.Comparator;\r
 \r
 import com.owncloud.android.datamodel.OCFile;\r
@@ -77,9 +78,20 @@ public class AlphanumComparator implements Comparator<OCFile>
     }\r
 \r
     public int compare(OCFile o1, OCFile o2){\r
-        String s1 = (String)o1.getRemotePath().toLowerCase();\r
-        String s2 = (String)o2.getRemotePath().toLowerCase();\r
+        String s1 = o1.getRemotePath().toLowerCase();\r
+        String s2 = o2.getRemotePath().toLowerCase();\r
 \r
+        return compare(s1, s2);\r
+    }\r
+\r
+    public int compare(File f1, File f2){\r
+        String s1 = f1.getPath().toLowerCase();\r
+        String s2 = f2.getPath().toLowerCase();\r
+\r
+        return compare(s1, s2);\r
+    }\r
+\r
+    public int compare(String s1, String s2) {\r
         int thisMarker = 0;\r
         int thatMarker = 0;\r
         int s1Length = s1.length();\r
index de2b2d5..9661234 100644 (file)
@@ -22,13 +22,13 @@ Dolphin. The first time you log in to a new ownCloud account you'll see a screen
 with a download link to the ownCloud app in the `Google Play store
 <https://play.google.com/store/apps/details?id=com.owncloud.android>`_.
 
-.. figure:: images/android-first-screen.jpg
+.. figure:: images/android-1.png
+   :scale: 75% 
+   :alt: Android app new account welcome screen.
 
-You will also find these links on your Personal page in the Web interface,
+You will also find these links on your Personal page in the ownCloud Web interface.
 
-You can also get it from the `Amazon App store 
-<http://www.amazon.com/ownCloud-Inc/dp/B00944PQMK/>`_, and get source code and 
-more information from the `ownCloud download page 
+Find source code and more information from the `ownCloud download page 
 <http://owncloud.org/install/#mobile>`_.
 
 Connecting to Your ownCloud Server
@@ -39,77 +39,100 @@ screen. Enter your server URL, login name, password, and click the Connect
 button. (Click the eyeball to the right of your password to expose your 
 password.)
 
-.. figure:: images/android-new-account.png
+.. figure:: images/android-2.png
+   :scale: 75% 
+   :alt: New account creation screen.
 
 For best security your ownCloud server should be SSL-enabled, so that you can 
 connect via ``https``. The ownCloud app will test your connection as soon as 
 you enter it and tell you if you entered it correctly. If your server has a 
-self-signed SSL certificate you'll get a scary warning how it is not to be 
+self-signed SSL certificate you'll get a warning that it is not to be 
 trusted. Click the OK button to accept the certificate and complete your account 
 setup.
 
-.. figure:: images/android-ssl-cert.png
+.. figure:: images/android-3.png 
+   :alt: SSL certificate warning.
 
 Managing Files
 --------------
 
-Now you should see the Files page of your ownCloud account. Click the overflow 
-button at the top right (that's the one with three vertical dots, and that is 
-really what it is called) to open a user menu. ``Refresh account`` refreshes the 
-page view. ``Settings`` take you to your settings menu. ``Sort`` gives you the 
-option to sort your files by date, or alphabetically.
+Now you should see the Files page of your ownCloud account. 
 
-.. figure:: images/android-files-page.png
+.. figure:: images/android-4.png
+   :scale: 75% 
+   :alt: Your ownCloud Files page.
 
-The little file folder icon to the left of the overflow button opens a dialog to 
-create a new folder. The arrow button opens a file upload dialog, and you can 
-either upload content from other Android apps such as Google Drive, the Gallery, 
-your music player, or from your Android filesystem. When you add a new file 
-you will see a confirmation on the top left when it has uploaded successfully, 
-and it is immediately synchronized with the server.
-
-.. figure:: images/android-upload.png
-
-All files (that you have permission to access) on your ownCloud server are 
-displayed in your Android app, but are not downloaded until you download them. 
-Downloaded files are marked with a green arrow.
-
-.. figure:: images/android-file-list.png
-
-Download and preview a file with a short press on the filename.  When the file 
-is in preview mode, a short press on the overflow button opens a menu with 
-options for sharing, opening with an app, removing, sending, and displaying file 
-details. 
+The ownCloud menu at the top left shows the name of the logged-in user, has a 
+shortcut to your files, and contains the Settings button.
 
-.. figure:: images/android-file.png
+.. figure:: images/android-5.png
+   :alt: Top-left menu.
 
+Click the overflow button at the top right (that's the one with three vertical 
+dots, and that is really what it is called) to open a user menu. ``Refresh 
+account`` syncs your files, and ``Sort`` gives you the option to sort your files 
+by date, or alphabetically.
 
-A long press on the filename does not download it, but opens a dialog with 
-options for sharing, downloading, renaming, moving, removing, sending, and 
-viewing file details. 
+.. figure:: images/android-6.png
+   :alt: Top-right menu.
 
+The little file folder icon to the left of the overflow button opens a dialog to 
+create a new folder. The arrow button opens a file upload dialog, and you can 
+either upload content from other Android apps such as Google Drive, the Gallery, 
+your music player, or from your Android filesystem.
 
-.. figure:: images/android-file-options.png
+.. figure:: images/android-7.png
+   :scale: 75%
+   :alt: File upload dialogue.
 
+All files (that you have permission to access) on your ownCloud server are 
+displayed in your Android app, but are not downloaded until you click on them to 
+download them. Downloaded files are marked with a green arrow.
+
+.. figure:: images/android-8.png
+   :scale: 75%
+   :alt: Downloaded files are marked with green arrows.
+
+Download and preview a file with a short press on the filename.  Then a short 
+press on the overflow button opens a menu with 
+options for managing your file.
+
+.. figure:: images/android-9.png
+   :scale: 75%
+   :alt: File management options. Betsy Ross says "Don't believe everything you 
+   read on the Internet."
+   
+When you are on your mail Files page, a long press on any folder displays a 
+list of options: Share Link, Download, Rename, Move, Copy, and Remove.
+
+.. figure:: images/android-11.png
+   :scale: 75%
+   :alt: Folder and file management options.
+   
+When you enter a folder, a long press on any file or folder has these 
+additional options: Open With, Refresh File, Send, Favorite, and Details. The 
+Download option appears on files that have not been downloaded to your Android 
+device.  
 
 Settings
 --------
 
-The Settings screen offers a number of useful options. In the Accounts 
-section you can configure multiple ownCloud accounts.
+Use the Settings screen to control your ownCloud app functions.
+
+.. figure:: images/android-10.png
+   :scale: 75%
+   :alt: Setting screen.
+
+In the Accounts section you can set up and manage multiple accounts.
 
 The Security section sets up strong two-factor authentication by allowing you 
 to add a PIN (personal identification number) to access your account.  
 
-The Instant Uploads section creates a directory, :file:`/InstantUpload`, and 
-any photos or videos created with your Android device's camera are instantly 
+The Instant Uploads section creates a directory, :file:`/InstantUpload`, and any 
+photos or videos created with your Android device's camera are instantly 
 uploaded to this directory. You also have the option to choose any other 
-existing directory. Another nice option is Upload Pictures/Video via WiFi Only, 
-to conserve your Internet data usage.
-
-.. figure:: images/android-settings.png
+existing directory, or to create a new one. Another nice option is Upload 
+Pictures/Video via WiFi Only, to conserve your mobile data usage.
 
 The bottom section of the Settings screen has links to help and the 
 app's version number.
-
-.. figure:: images/android-help.png
diff --git a/user_manual/images/android-1.png b/user_manual/images/android-1.png
new file mode 100644 (file)
index 0000000..ed45645
Binary files /dev/null and b/user_manual/images/android-1.png differ
diff --git a/user_manual/images/android-10.png b/user_manual/images/android-10.png
new file mode 100644 (file)
index 0000000..187a753
Binary files /dev/null and b/user_manual/images/android-10.png differ
diff --git a/user_manual/images/android-11.png b/user_manual/images/android-11.png
new file mode 100644 (file)
index 0000000..c84166e
Binary files /dev/null and b/user_manual/images/android-11.png differ
diff --git a/user_manual/images/android-2.png b/user_manual/images/android-2.png
new file mode 100644 (file)
index 0000000..ddee8e4
Binary files /dev/null and b/user_manual/images/android-2.png differ
diff --git a/user_manual/images/android-3.png b/user_manual/images/android-3.png
new file mode 100644 (file)
index 0000000..14afed9
Binary files /dev/null and b/user_manual/images/android-3.png differ
diff --git a/user_manual/images/android-4.png b/user_manual/images/android-4.png
new file mode 100644 (file)
index 0000000..ee9cf66
Binary files /dev/null and b/user_manual/images/android-4.png differ
diff --git a/user_manual/images/android-5.png b/user_manual/images/android-5.png
new file mode 100644 (file)
index 0000000..d089cc1
Binary files /dev/null and b/user_manual/images/android-5.png differ
diff --git a/user_manual/images/android-6.png b/user_manual/images/android-6.png
new file mode 100644 (file)
index 0000000..20f6fbb
Binary files /dev/null and b/user_manual/images/android-6.png differ
diff --git a/user_manual/images/android-7.png b/user_manual/images/android-7.png
new file mode 100644 (file)
index 0000000..aaa33bf
Binary files /dev/null and b/user_manual/images/android-7.png differ
diff --git a/user_manual/images/android-8.png b/user_manual/images/android-8.png
new file mode 100644 (file)
index 0000000..b1ecc62
Binary files /dev/null and b/user_manual/images/android-8.png differ
diff --git a/user_manual/images/android-9.png b/user_manual/images/android-9.png
new file mode 100644 (file)
index 0000000..631f6b1
Binary files /dev/null and b/user_manual/images/android-9.png differ
diff --git a/user_manual/images/android-downloads.png b/user_manual/images/android-downloads.png
deleted file mode 100644 (file)
index e0bb545..0000000
Binary files a/user_manual/images/android-downloads.png and /dev/null differ
diff --git a/user_manual/images/android-file-list.png b/user_manual/images/android-file-list.png
deleted file mode 100644 (file)
index e479b9f..0000000
Binary files a/user_manual/images/android-file-list.png and /dev/null differ
diff --git a/user_manual/images/android-file-options.png b/user_manual/images/android-file-options.png
deleted file mode 100644 (file)
index 12867a3..0000000
Binary files a/user_manual/images/android-file-options.png and /dev/null differ
diff --git a/user_manual/images/android-file.png b/user_manual/images/android-file.png
deleted file mode 100644 (file)
index 89ffd28..0000000
Binary files a/user_manual/images/android-file.png and /dev/null differ
diff --git a/user_manual/images/android-files-page.png b/user_manual/images/android-files-page.png
deleted file mode 100644 (file)
index 1c7fc4d..0000000
Binary files a/user_manual/images/android-files-page.png and /dev/null differ
diff --git a/user_manual/images/android-first-screen.jpg b/user_manual/images/android-first-screen.jpg
deleted file mode 100644 (file)
index f4c5132..0000000
Binary files a/user_manual/images/android-first-screen.jpg and /dev/null differ
diff --git a/user_manual/images/android-help.png b/user_manual/images/android-help.png
deleted file mode 100644 (file)
index 56a7464..0000000
Binary files a/user_manual/images/android-help.png and /dev/null differ
diff --git a/user_manual/images/android-new-account.png b/user_manual/images/android-new-account.png
deleted file mode 100644 (file)
index ffbe12e..0000000
Binary files a/user_manual/images/android-new-account.png and /dev/null differ
diff --git a/user_manual/images/android-settings.png b/user_manual/images/android-settings.png
deleted file mode 100644 (file)
index 7a16084..0000000
Binary files a/user_manual/images/android-settings.png and /dev/null differ
diff --git a/user_manual/images/android-ssl-cert.png b/user_manual/images/android-ssl-cert.png
deleted file mode 100644 (file)
index 9286fe6..0000000
Binary files a/user_manual/images/android-ssl-cert.png and /dev/null differ
diff --git a/user_manual/images/android-upload.png b/user_manual/images/android-upload.png
deleted file mode 100644 (file)
index 6ee1b95..0000000
Binary files a/user_manual/images/android-upload.png and /dev/null differ