From: David A. Velasco Date: Wed, 5 Nov 2014 08:09:48 +0000 (+0100) Subject: Merge pull request #706 from owncloud/christmas_app X-Git-Tag: oc-android-1.7.0_signed~118 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/80cfc55fda1f71124e2a658b46229cbb7c1feb77?hp=e53c6001dde8258a6f07505dd48a34d809f68dad Merge pull request #706 from owncloud/christmas_app Winter holidays fix --- diff --git a/res/layout/list_item.xml b/res/layout/list_item.xml index a4113de7..c6c7b92f 100644 --- a/res/layout/list_item.xml +++ b/res/layout/list_item.xml @@ -32,16 +32,16 @@ diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 326f51a9..76f388b9 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -11,6 +11,12 @@ Настройки Подробно Отправить + Упорядочить + Упорядочить по + + А-Я + Новые - Старые + Основные @@ -241,6 +247,7 @@ Предпросмотр Это изображение не может быть отображено %1$s не возможно скопировать в локальною папку %2$s + Путь для загрузки К сожалению, на вашем сервере отключен совместный доступ. Пожалуйста, свяжитесь с вашим администратором. Невозможно добавить в общий доступ. Пожалуйста, проверьте, существует ли файл Ошибка предоставления общего доступа к этому файлу или каталогу @@ -265,6 +272,7 @@ Этот файл больше недоступен на сервере Учётные записи Добавить учетную запись + Защищённое соединение перенаправлено по незащищённому маршруту Журналы История Отправлений Журналы Андроид-приложения ownCloud @@ -279,5 +287,6 @@ Файл уже существует в папке назначения Произошла ошибка при попытке перемещения этого файла или папки переместить этот файл + Мгновенные загрузки Безопасность diff --git a/res/values/dims.xml b/res/values/dims.xml new file mode 100644 index 00000000..d433cba3 --- /dev/null +++ b/res/values/dims.xml @@ -0,0 +1,21 @@ + + + + 32dp + diff --git a/res/values/strings.xml b/res/values/strings.xml index af5a684d..2655e29f 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -39,7 +39,9 @@ Recommend to a friend Feedback Imprint - + Remember share location + Remember last share upload location + "Try %1$s on your smartphone!" "I want to invite you to use %1$s on your smartphone!\nDownload here: %2$s" @@ -279,6 +281,7 @@ An error occurred while waiting for the server, the operation couldn\'t have been done An error occurred while waiting for the server, the operation couldn\'t have been done The operation couldn\'t be completed, server is unavailable + You do not have permission %s @@ -313,5 +316,4 @@ Instant Uploads Security - diff --git a/src/com/owncloud/android/MainApp.java b/src/com/owncloud/android/MainApp.java index e04239df..c2a4c68b 100644 --- a/src/com/owncloud/android/MainApp.java +++ b/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(); diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index 5b1bef1b..41a51063 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/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())) { diff --git a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index e75404ef..1d2cda8c 100644 --- a/src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/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 { + @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 { private final WeakReference 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); 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"); + } + } } } diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index cdf12823..d61e6784 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/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 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()); diff --git a/src/com/owncloud/android/ui/activity/Uploader.java b/src/com/owncloud/android/ui/activity/Uploader.java index 62ad44a4..66359f3d 100644 --- a/src/com/owncloud/android/ui/activity/Uploader.java +++ b/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(); - 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 files = mStorageManager.getFolderContent(mFile); @@ -317,6 +337,14 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro } } + private String generatePath(Stack 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(); @@ -408,6 +436,13 @@ public class Uploader extends ListActivity implements OnItemClickListener, andro intent.putExtra(FileUploader.KEY_REMOTE_FILE, remote.toArray(new String[remote.size()])); intent.putExtra(FileUploader.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; + } + } diff --git a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java b/src/com/owncloud/android/ui/adapter/FileListListAdapter.java index 9a2a0d3a..e002efb7 100644 --- a/src/com/owncloud/android/ui/adapter/FileListListAdapter.java +++ b/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;