Browse Source

Merge remote-tracking branch 'upstream/develop' into retry_uploads

Luke Owncloud 10 years ago
parent
commit
0d12225ec6

+ 1 - 1
owncloud-android-library

@@ -1 +1 @@
-Subproject commit 5bd0d7387712ce3f53869294761ac4d8537841cd
+Subproject commit 4f315c7e06f6eef48df246be0ee9252fdfccdf00

+ 4 - 4
res/layout/list_item.xml

@@ -32,16 +32,16 @@
 
         <ImageView
             android:id="@+id/imageView2"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
+            android:layout_width="@dimen/file_icon_size"
+            android:layout_height="@dimen/file_icon_size"
             android:layout_gravity="center_vertical"
             android:layout_marginLeft="22dp"
             android:src="@drawable/local_file_indicator" />
 
         <ImageView
             android:id="@+id/imageView1"
-            android:layout_width="32dp"
-            android:layout_height="32dp"
+            android:layout_width="@dimen/file_icon_size"
+            android:layout_height="@dimen/file_icon_size"
             android:layout_gravity="center_vertical"
             android:layout_marginLeft="9dp"
             android:src="@drawable/ic_menu_archive" />

+ 11 - 0
res/menu/file_select_all.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item
+        android:id="@+id/actionbar_select_all"
+        android:icon="@android:drawable/checkbox_off_background"
+        android:orderInCategory="1"
+        android:showAsAction="always"
+        android:title="actionbar_select_all"/>
+    
+
+</menu>

+ 7 - 0
res/values-ja-rJP/strings.xml

@@ -13,6 +13,10 @@
   <string name="actionbar_send_file">送信</string>
   <string name="actionbar_sort">ソート</string>
   <string name="actionbar_sort_title">ソート: </string>
+  <string-array name="actionbar_sortby">
+    <item>A-Z</item>
+    <item>最新 - 最古</item>
+  </string-array>
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
   <string name="prefs_category_general">一般</string>
@@ -243,6 +247,7 @@
   <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="prefs_instant_upload_path_title">アップロードパス</string>
   <string name="share_link_no_support_share_api">申し訳ございません。共有がサーバー上で有効になっていません。 管理者に
 		ご連絡ください。</string>
   <string name="share_link_file_no_exist">共有できません。ファイルがあるか確認してください。</string>
@@ -268,6 +273,7 @@
   <string name="downloader_download_file_not_found">ファイルはサーバー上で利用できません</string>
   <string name="prefs_category_accounts">アカウント</string>
   <string name="prefs_add_account">アカウントを追加</string>
+  <string name="auth_redirect_non_secure_connection_title">暗号化接続は非暗号化接続にリダイレクトされました。</string>
   <string name="actionbar_logger">ログ</string>
   <string name="log_send_history_button">ログを送信</string>
   <string name="log_mail_subject">ownCloud Android アプリログ</string>
@@ -282,5 +288,6 @@
   <string name="move_file_invalid_overwrite">そのファイルは、宛先フォルダに既に存在しています。</string>
   <string name="move_file_error">このファイルまたはフォルダーを移動する際にエラーが発生しました</string>
   <string name="forbidden_permissions_move">このファイルを移動</string>
+  <string name="prefs_category_instant_uploading">自動アップロード</string>
   <string name="prefs_category_security">セキュリティ</string>
 </resources>

+ 8 - 0
res/values-ro/strings.xml

@@ -11,6 +11,8 @@
   <string name="actionbar_settings">Setări</string>
   <string name="actionbar_see_details">Detalii</string>
   <string name="actionbar_send_file">Expediază</string>
+  <string name="actionbar_sort">Sortare</string>
+  <string name="actionbar_sort_title">Sortare după</string>
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
   <string name="prefs_category_general">General</string>
@@ -259,7 +261,13 @@
   <string name="uploader_upload_forbidden_permissions">pentru a încărca în acest folder</string>
   <string name="downloader_download_file_not_found">Fișierul nu mai este disponibil pe server</string>
   <string name="prefs_category_accounts">Conturi</string>
+  <string name="prefs_add_account">Adaugă cont</string>
+  <string name="log_progress_dialog_text">Se încarcă datele...</string>
+  <string name="saml_authentication_required_text">Autentificare necesară</string>
   <string name="saml_authentication_wrong_pass">Parolă greșită</string>
+  <string name="actionbar_move">Mutare</string>
+  <string name="file_list_empty_moving">Nu este nimic aici. Poți adăuga un director!</string>
   <string name="move_choose_button_text">Alege</string>
+  <string name="forbidden_permissions_move">pentru a muta acest fișier</string>
   <string name="prefs_category_security">Securitate</string>
 </resources>

+ 9 - 0
res/values-ru/strings.xml

@@ -11,6 +11,12 @@
   <string name="actionbar_settings">Настройки</string>
   <string name="actionbar_see_details">Подробно</string>
   <string name="actionbar_send_file">Отправить</string>
+  <string name="actionbar_sort">Упорядочить</string>
+  <string name="actionbar_sort_title">Упорядочить по</string>
+  <string-array name="actionbar_sortby">
+    <item>А-Я</item>
+    <item>Новые - Старые</item>
+  </string-array>
   <!--TODO re-enable when server-side folder size calculation is available   
     	<item>Biggest - Smallest</item>-->
   <string name="prefs_category_general">Основные</string>
@@ -241,6 +247,7 @@
   <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="prefs_instant_upload_path_title">Путь для загрузки</string>
   <string name="share_link_no_support_share_api">К сожалению, на вашем сервере отключен совместный доступ. Пожалуйста, свяжитесь с вашим администратором.</string>
   <string name="share_link_file_no_exist">Невозможно добавить в общий доступ. Пожалуйста, проверьте, существует ли файл</string>
   <string name="share_link_file_error">Ошибка предоставления общего доступа к этому файлу или каталогу</string>
@@ -265,6 +272,7 @@
   <string name="downloader_download_file_not_found">Этот файл больше недоступен на сервере</string>
   <string name="prefs_category_accounts">Учётные записи</string>
   <string name="prefs_add_account">Добавить учетную запись</string>
+  <string name="auth_redirect_non_secure_connection_title">Защищённое соединение перенаправлено по незащищённому маршруту</string>
   <string name="actionbar_logger">Журналы</string>
   <string name="log_send_history_button">История Отправлений</string>
   <string name="log_mail_subject">Журналы Андроид-приложения ownCloud</string>
@@ -279,5 +287,6 @@
   <string name="move_file_invalid_overwrite">Файл уже существует в папке назначения</string>
   <string name="move_file_error">Произошла ошибка при попытке перемещения этого файла или папки</string>
   <string name="forbidden_permissions_move">переместить этот файл</string>
+  <string name="prefs_category_instant_uploading">Мгновенные загрузки</string>
   <string name="prefs_category_security">Безопасность</string>
 </resources>

+ 21 - 0
res/values/dims.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ownCloud Android client application
+
+  Copyright (C) 2014 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/>.
+-->
+<resources>
+	<dimen name="file_icon_size">32dp</dimen>
+</resources>

+ 4 - 2
res/values/strings.xml

@@ -39,7 +39,9 @@
     <string name="prefs_recommend">Recommend to a friend</string>
     <string name="prefs_feedback">Feedback</string>
     <string name="prefs_imprint">Imprint</string>
-    
+    <string name="prefs_remember_last_share_location">Remember share location</string>
+    <string name="prefs_remember_last_upload_location_summary">Remember last share upload location</string>
+
 	<string name="recommend_subject">"Try %1$s on your smartphone!"</string>
 	<string name="recommend_text">"I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s"</string>
 
@@ -279,6 +281,7 @@
 	<string name="network_error_socket_timeout_exception">An error occurred while waiting for the server, the operation couldn\'t have been done</string>
 	<string name="network_error_connect_timeout_exception">An error occurred while waiting for the server, the operation couldn\'t have been done</string>
 	<string name="network_host_not_available">The operation couldn\'t be completed, server is unavailable</string>
+
 	<string name="empty"></string>
 	
 	<string name="forbidden_permissions">You do not have permission %s</string>
@@ -313,5 +316,4 @@
 
 	<string name="prefs_category_instant_uploading">Instant Uploads</string>
 	<string name="prefs_category_security">Security</string>
-
 </resources>

+ 1 - 1
src/com/owncloud/android/MainApp.java

@@ -55,7 +55,7 @@ public class MainApp extends Application {
         } else {
             OwnCloudClientManagerFactory.setDefaultPolicy(Policy.ALWAYS_NEW_CLIENT);
         }
-        
+
         // initialise thumbnails cache on background thread
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
         

+ 1 - 0
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -300,6 +300,7 @@ public class FileDataStorageManager {
             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());
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {

+ 64 - 8
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -20,19 +20,30 @@ package com.owncloud.android.datamodel;
 import java.io.File;
 import java.lang.ref.WeakReference;
 
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.media.ThumbnailUtils;
+import android.net.Uri;
 import android.os.AsyncTask;
-import android.util.TypedValue;
 import android.widget.ImageView;
 
 import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+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.accounts.AccountUtils.Constants;
 import com.owncloud.android.lib.common.utils.Log_OC;
+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;
@@ -47,7 +58,8 @@ public class ThumbnailsCacheManager {
     
     private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
     
-    private static final String CACHE_FOLDER = "thumbnailCache"; 
+    private static final String CACHE_FOLDER = "thumbnailCache";
+    private static final String MINOR_SERVER_VERSION_FOR_THUMBS = "7.8.0";
     
     private static final Object mThumbnailsDiskCacheLock = new Object();
     private static DiskLruImageCache mThumbnailCache = null;
@@ -56,7 +68,9 @@ public class ThumbnailsCacheManager {
     private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
     private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
     private static final int mCompressQuality = 70;
-    
+    private static OwnCloudClient mClient = null;
+    private static String mServerVersion = null;
+
     public static Bitmap mDefaultImg = 
             BitmapFactory.decodeResource(
                     MainApp.getAppContext().getResources(), 
@@ -65,10 +79,12 @@ public class ThumbnailsCacheManager {
 
     
     public static class InitDiskCacheTask extends AsyncTask<File, Void, Void> {
+
         @Override
         protected Void doInBackground(File... params) {
             synchronized (mThumbnailsDiskCacheLock) {
                 mThumbnailCacheStarting = true;
+
                 if (mThumbnailCache == null) {
                     try {
                         // Check if media is mounted or storage is built-in, if so, 
@@ -153,15 +169,17 @@ public class ThumbnailsCacheManager {
 
     public static class ThumbnailGenerationTask extends AsyncTask<OCFile, Void, Bitmap> {
         private final WeakReference<ImageView> mImageViewReference;
+        private static Account mAccount;
         private OCFile mFile;
         private FileDataStorageManager mStorageManager;
         
-        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager) {
+        public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account) {
          // Use a WeakReference to ensure the ImageView can be garbage collected
             mImageViewReference = new WeakReference<ImageView>(imageView);
             if (storageManager == null)
                 throw new IllegalArgumentException("storageManager must not be NULL");
             mStorageManager = storageManager;
+            mAccount = account;
         }
 
         // Decode image in background.
@@ -170,6 +188,15 @@ public class ThumbnailsCacheManager {
             Bitmap thumbnail = null;
             
             try {
+                if (mAccount != null) {
+                    AccountManager accountMgr = AccountManager.get(MainApp.getAppContext());
+                    
+                    mServerVersion = accountMgr.getUserData(mAccount, Constants.KEY_OC_VERSION);
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
+                    mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, MainApp.getAppContext());
+                }
+                
                 mFile = params[0];
                 final String imageKey = String.valueOf(mFile.getRemoteId());
     
@@ -180,9 +207,8 @@ public class ThumbnailsCacheManager {
                 if (thumbnail == null || mFile.needsUpdateThumbnail()) { 
                     // Converts dp to pixel
                     Resources r = MainApp.getAppContext().getResources();
-                    int px = (int) Math.round(TypedValue.applyDimension(
-                            TypedValue.COMPLEX_UNIT_DIP, 150, r.getDisplayMetrics()
-                    ));
+                    
+                    int px = (int) Math.round(r.getDimension(R.dimen.file_icon_size));
                     
                     if (mFile.isDown()){
                         Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(
@@ -198,6 +224,36 @@ public class ThumbnailsCacheManager {
                             mStorageManager.saveFile(mFile);
                         }
     
+                    } else {
+                        // Download thumbnail from server
+                        if (mClient != null && mServerVersion != null) {
+                            OwnCloudVersion serverOCVersion = new OwnCloudVersion(mServerVersion);
+                            if (serverOCVersion.compareTo(new OwnCloudVersion(MINOR_SERVER_VERSION_FOR_THUMBS)) >= 0) {
+                                try {
+                                    int status = -1;
+
+                                    String uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + 
+                                            px + "/" + px + Uri.encode(mFile.getRemotePath(), "/");
+                                    Log_OC.d("Thumbnail", "URI: " + uri);
+                                    GetMethod get = new GetMethod(uri);
+                                    status = mClient.executeMethod(get);
+                                    if (status == HttpStatus.SC_OK) {
+                                        byte[] bytes = get.getResponseBody();
+                                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
+                                        thumbnail = ThumbnailUtils.extractThumbnail(bitmap, px, px);
+
+                                        // Add thumbnail to cache
+                                        if (thumbnail != null) {
+                                            addBitmapToCache(imageKey, thumbnail);
+                                        }
+                                    }
+                                } catch (Exception e) {
+                                    e.printStackTrace();
+                                }
+                            } else {
+                                Log_OC.d(TAG, "Server too old");
+                            }
+                        }
                     }
                 }
                 

+ 6 - 1
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -33,6 +33,7 @@ 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.datamodel.FileDataStorageManager;
@@ -325,7 +326,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
     private void synchronizeData(ArrayList<Object> folderAndFiles, OwnCloudClient client) {
         // get 'fresh data' from the database
         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
-        
+
         // parse data from remote folder 
         OCFile remoteFolder = fillOCFile((RemoteFile)folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
@@ -372,6 +373,10 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                 if (remoteFile.isFolder()) {
                     remoteFile.setFileLength(localFile.getFileLength()); 
                         // TODO move operations about size of folders to FileContentProvider
+                } else if (mRemoteFolderChanged && remoteFile.isImage() &&
+                        remoteFile.getModificationTimestamp() != localFile.getModificationTimestamp()) {
+                    remoteFile.setNeedsUpdateThumbnail(true);
+                    Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
                 }
                 remoteFile.setPublicLink(localFile.getPublicLink());
                 remoteFile.setShareByLink(localFile.isShareByLink());

+ 40 - 4
src/com/owncloud/android/ui/activity/UploadFilesActivity.java

@@ -34,6 +34,9 @@ import android.widget.TextView;
 
 import com.actionbarsherlock.app.ActionBar;
 import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
+import com.actionbarsherlock.internal.view.menu.ActionMenuItemView;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuInflater;
 import com.actionbarsherlock.view.MenuItem;
 import com.owncloud.android.R;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -73,6 +76,8 @@ public class UploadFilesActivity extends FileActivity implements
     private static final String WAIT_DIALOG_TAG = "WAIT";
     private static final String QUERY_TO_MOVE_DIALOG_TAG = "QUERY_TO_MOVE";
     
+    private boolean selectAllToggled = false;
+    private Menu menu;
     
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -119,6 +124,7 @@ public class UploadFilesActivity extends FileActivity implements
         actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
         actionBar.setListNavigationCallbacks(mDirectories, this);
         
+        
         // wait dialog
         if (mCurrentDialog != null) {
             mCurrentDialog.dismiss();
@@ -127,8 +133,15 @@ public class UploadFilesActivity extends FileActivity implements
             
         Log_OC.d(TAG, "onCreate() end");
     }
-
-
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Inflate the menu items for use in the action bar
+        MenuInflater inflater = getSherlock().getMenuInflater();
+        inflater.inflate(R.menu.file_select_all, menu);     
+        this.menu = menu;
+        return true;
+    }
+ 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         boolean retval = true;
@@ -139,12 +152,33 @@ public class UploadFilesActivity extends FileActivity implements
                 }
                 break;
             }
+            case R.id.actionbar_select_all:{
+                if(selectAllToggled){
+                    toggleOffSelectAll();
+                }else{
+                    toggleOnSelectAll(item);
+                }
+                break;
+            }
             default:
                 retval = super.onOptionsItemSelected(item);
         }
         return retval;
     }
-
+    public void toggleOffSelectAll(MenuItem item){
+        selectAllToggled = false;
+        item.setIcon(android.R.drawable.checkbox_off_background);
+        mFileListFragment.deselectAll();
+    }
+    public void toggleOffSelectAll(){
+        MenuItem item = menu.findItem(R.id.actionbar_select_all);
+        toggleOffSelectAll(item);
+    }
+    public void toggleOnSelectAll(MenuItem item){
+        selectAllToggled = true;
+        item.setIcon(android.R.drawable.checkbox_on_background);        
+        mFileListFragment.selectAll();
+    }
     
     @Override
     public boolean onNavigationItemSelected(int itemPosition, long itemId) {
@@ -175,6 +209,7 @@ public class UploadFilesActivity extends FileActivity implements
             ActionBar actionBar = getSupportActionBar(); 
             actionBar.setDisplayHomeAsUpEnabled(false);
         } 
+        toggleOffSelectAll();
     }
 
     
@@ -242,10 +277,11 @@ public class UploadFilesActivity extends FileActivity implements
      * {@inheritDoc}
      */
     @Override
-    public void onDirectoryClick(File directory) {
+    public void onDirectoryClick(File directory) { 
         pushDirname(directory);
         ActionBar actionBar = getSupportActionBar();
         actionBar.setDisplayHomeAsUpEnabled(true);
+        toggleOffSelectAll();
     }
     
     

+ 91 - 9
src/com/owncloud/android/ui/activity/Uploader.java

@@ -39,22 +39,22 @@ import android.accounts.AccountManager;
 import android.app.AlertDialog;
 import android.app.AlertDialog.Builder;
 import android.app.Dialog;
-import android.app.ListActivity;
 import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcelable;
+import android.preference.PreferenceManager;
 import android.provider.MediaStore.Audio;
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Video;
 import android.view.View;
-import android.view.Window;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.Button;
@@ -62,6 +62,10 @@ import android.widget.EditText;
 import android.widget.SimpleAdapter;
 import android.widget.Toast;
 
+import com.actionbarsherlock.app.ActionBar;
+import com.actionbarsherlock.app.SherlockListActivity;
+import com.actionbarsherlock.view.MenuItem;
+import com.owncloud.android.utils.DisplayUtils;
 
 /**
  * This can be used to upload things to an ownCloud instance.
@@ -69,7 +73,7 @@ import android.widget.Toast;
  * @author Bartek Przybylski
  * 
  */
-public class Uploader extends ListActivity implements OnItemClickListener, android.view.View.OnClickListener {
+public class Uploader extends SherlockListActivity implements OnItemClickListener, android.view.View.OnClickListener {
     private static final String TAG = "ownCloudUploader";
 
     private Account mAccount;
@@ -91,9 +95,11 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
         mParents = new Stack<String>();
-        mParents.add("");
+
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setIcon(DisplayUtils.getSeasonalIconId());
+
         if (prepareStreamsToUpload()) {
             mAccountManager = (AccountManager) getSystemService(Context.ACCOUNT_SERVICE);
             Account[] accounts = mAccountManager.getAccountsByType(MainApp.getAccountType());
@@ -106,8 +112,11 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
             } else {
                 mAccount = accounts[0];
                 mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+                initTargetFolder();
                 populateDirectoryList();
+                
             }
+            
         } else {
             showDialog(DIALOG_NO_STREAM);
         }
@@ -169,6 +178,7 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
                 public void onClick(DialogInterface dialog, int which) {
                     mAccount = mAccountManager.getAccountsByType(MainApp.getAccountType())[which];
                     mStorageManager = new FileDataStorageManager(mAccount, getContentResolver());
+                    initTargetFolder();
                     populateDirectoryList();
                 }
             });
@@ -288,12 +298,22 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
     private void populateDirectoryList() {
         setContentView(R.layout.uploader_layout);
 
-        String full_path = "";
-        for (String a : mParents)
-            full_path += a + "/";
+        String current_dir = mParents.peek();
+        if(current_dir.equals("")){
+            getSupportActionBar().setTitle(getString(R.string.default_display_name_for_root_folder));
+        }
+        else{
+            getSupportActionBar().setTitle(current_dir);
+        }
+        boolean notRoot = (mParents.size() > 1);
+        ActionBar actionBar = getSupportActionBar();
+        actionBar.setDisplayHomeAsUpEnabled(notRoot);
+        actionBar.setHomeButtonEnabled(notRoot);
+
+        String full_path = generatePath(mParents);
         
         Log_OC.d(TAG, "Populating view with content of : " + full_path);
-        
+
         mFile = mStorageManager.getFileByPath(full_path);
         if (mFile != null) {
             Vector<OCFile> files = mStorageManager.getFolderContent(mFile);
@@ -317,6 +337,14 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
         }
     }
 
+    private String generatePath(Stack<String> dirs) {
+        String full_path = "";
+
+        for (String a : dirs)
+            full_path += a + "/";
+        return full_path;
+    }
+
     private boolean prepareStreamsToUpload() {
         if (getIntent().getAction().equals(Intent.ACTION_SEND)) {
             mStreamsToUpload = new ArrayList<Parcelable>();
@@ -408,6 +436,13 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
             intent.putExtra(FileUploadService.KEY_REMOTE_FILE, remote.toArray(new String[remote.size()]));
             intent.putExtra(FileUploadService.KEY_ACCOUNT, mAccount);
             startService(intent);
+
+            //Save the path to shared preferences
+            SharedPreferences.Editor appPrefs = PreferenceManager
+                    .getDefaultSharedPreferences(getApplicationContext()).edit();
+            appPrefs.putString("last_upload_path", mUploadPath);
+            appPrefs.apply();
+
             finish();
             }
             
@@ -416,5 +451,52 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro
             Toast.makeText(this, message, Toast.LENGTH_LONG).show();            
         }
     }
+    
+    /**
+     *  Loads the target folder initialize shown to the user.
+     * 
+     *  The target account has to be chosen before this method is called. 
+     */
+    private void initTargetFolder() {
+        if (mStorageManager == null) {
+            throw new IllegalStateException("Do not call this method before initializing mStorageManager");
+        }
+        
+        SharedPreferences appPreferences = PreferenceManager
+                .getDefaultSharedPreferences(getApplicationContext());
+
+        String last_path = appPreferences.getString("last_upload_path", "");
+        // "/" equals root-directory
+        if(last_path.equals("/")) {
+            mParents.add("");
+        }
+        else{
+            String[] dir_names = last_path.split("/");
+            for (String dir : dir_names)
+                mParents.add(dir);
+        }
+        //Make sure that path still exists, if it doesn't pop the stack and try the previous path
+            while(!mStorageManager.fileExists(generatePath(mParents)) && mParents.size() > 1){
+                mParents.pop();
+            }
+    }
+
+    
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        boolean retval = true;
+        switch (item.getItemId()) {
+        case android.R.id.home: {
+            if((mParents.size() > 1)) {                
+                onBackPressed(); 
+            }
+            break;
+        }
+        default:
+            retval = super.onOptionsItemSelected(item);
+        }
+        return retval;
+    }
 
+    
 }

+ 4 - 2
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -82,10 +82,11 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             Context context, 
             ComponentsGetter transferServiceGetter
             ) {
-        
+
         mJustFolders = justFolders;
         mContext = context;
         mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
+
         mTransferServiceGetter = transferServiceGetter;
         
         mAppPreferences = PreferenceManager
@@ -98,6 +99,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
         
         // initialise thumbnails cache on background thread
         new ThumbnailsCacheManager.InitDiskCacheTask().execute();
+
     }
     
     @Override
@@ -217,7 +219,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
                         if (ThumbnailsCacheManager.cancelPotentialWork(file, fileIcon)) {
                             final ThumbnailsCacheManager.ThumbnailGenerationTask task = 
                                     new ThumbnailsCacheManager.ThumbnailGenerationTask(
-                                            fileIcon, mStorageManager
+                                            fileIcon, mStorageManager, mAccount
                                     );
                             if (thumbnail == null) {
                                 thumbnail = ThumbnailsCacheManager.mDefaultImg;

+ 30 - 7
src/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -18,6 +18,7 @@
 package com.owncloud.android.ui.fragment;
 
 import java.io.File;
+import java.util.ArrayList;
 
 import android.app.Activity;
 import android.os.Bundle;
@@ -97,13 +98,33 @@ public class LocalFileListFragment extends ExtendedListFragment {
         Log_OC.i(TAG, "onActivityCreated() stop");
     }
     
+    public void selectAll(){
+        int numberOfFiles = mAdapter.getCount();
+        for(int i = 0; i < numberOfFiles; i++){
+            File file = (File) mAdapter.getItem(i);
+            if (file != null) {                
+                if (!file.isDirectory()) {  
+                    /// Click on a file
+                    getListView().setItemChecked(i, true);                       
+                    // notify the change to the container Activity
+                    mContainerActivity.onFileClick(file);
+                }
+            }
+        }
+    }
+    
+    public void deselectAll(){        
+        mAdapter = new LocalFileListAdapter(mContainerActivity.getInitialDirectory(), getActivity());
+        setListAdapter(mAdapter);
+    }
     
     /**
      * Checks the file clicked over. Browses inside if it is a directory. Notifies the container activity in any case.
      */
     @Override
     public void onItemClick(AdapterView<?> l, View v, int position, long id) {
-        File file = (File) mAdapter.getItem(position); 
+        File file = (File) mAdapter.getItem(position);
+        
         if (file != null) {
             /// Click on a directory
             if (file.isDirectory()) {
@@ -209,16 +230,18 @@ public class LocalFileListFragment extends ExtendedListFragment {
      * @return      File paths to the files checked by the user.
      */
     public String[] getCheckedFilePaths() {
-        String [] result = null;
+        ArrayList<String> result = new ArrayList<String>();
         SparseBooleanArray positions = mList.getCheckedItemPositions();
         if (positions.size() > 0) {
-            Log_OC.d(TAG, "Returning " + positions.size() + " selected files");
-            result = new String[positions.size()];
-            for (int i=0; i<positions.size(); i++) {
-                result[i] = ((File) mList.getItemAtPosition(positions.keyAt(i))).getAbsolutePath();
+            for (int i = 0; i < positions.size(); i++) {
+                if (positions.get(positions.keyAt(i)) == true) {
+                    result.add(((File) mList.getItemAtPosition(positions.keyAt(i))).getAbsolutePath());
+                }
             }
+
+            Log_OC.d(TAG, "Returning " + result.size() + " selected files");
         }
-        return result;
+        return result.toArray(new String[result.size()]);
     }
 
     

+ 5 - 1
src/com/owncloud/android/utils/DisplayUtils.java

@@ -29,6 +29,7 @@ import java.util.Set;
 import android.annotation.TargetApi;
 import android.os.Build;
 
+import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 
 /**
@@ -39,6 +40,8 @@ import com.owncloud.android.R;
  */
 public class DisplayUtils {
     
+    private static final String OWNCLOUD_APP_NAME = "ownCloud";
+
     //private static String TAG = DisplayUtils.class.getSimpleName(); 
     
     private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
@@ -233,7 +236,8 @@ public class DisplayUtils {
     
     
     public static int getSeasonalIconId() {
-        if (Calendar.getInstance().get(Calendar.DAY_OF_YEAR) >= 354) {
+        if (Calendar.getInstance().get(Calendar.DAY_OF_YEAR) >= 354 &&
+                MainApp.getAppContext().getString(R.string.app_name).equals(OWNCLOUD_APP_NAME)) {
             return R.drawable.winter_holidays_icon;
         } else {
             return R.drawable.icon;

+ 2 - 2
tests/.classpath

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" path="src"/>
-	<classpathentry kind="src" path="gen"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/owncloud-android"/>
 	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
 	<classpathentry kind="output" path="bin/classes"/>
 </classpath>