Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortobiasKaminsky <tobias@kaminsky.me>2018-07-06 11:16:50 +0300
committertobiasKaminsky <tobias@kaminsky.me>2018-12-03 17:44:09 +0300
commitb80bba82c189540cf8d155d3ba4d2e20e29a9e09 (patch)
tree00b3a90b1c486e73ede7343de59a1b632c3b2763
parentdf3bb7936547be8f74e1cc63bca10db471b045ab (diff)
Glide 4glide
Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
-rw-r--r--build.gradle5
-rw-r--r--src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java3
-rw-r--r--src/gplay/java/com/owncloud/android/utils/PushUtils.java4
-rw-r--r--src/main/AndroidManifest.xml6
-rw-r--r--src/main/java/com/owncloud/android/MainApp.java5
-rw-r--r--src/main/java/com/owncloud/android/authentication/AccountUtils.java32
-rw-r--r--src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java12
-rw-r--r--src/main/java/com/owncloud/android/datamodel/OCFile.java19
-rw-r--r--src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java1169
-rw-r--r--src/main/java/com/owncloud/android/db/ProviderMeta.java11
-rw-r--r--src/main/java/com/owncloud/android/files/services/FileDownloader.java1
-rw-r--r--src/main/java/com/owncloud/android/files/services/FileUploader.java10
-rw-r--r--src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java4
-rw-r--r--src/main/java/com/owncloud/android/operations/RemoveFileOperation.java10
-rw-r--r--src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java7
-rw-r--r--src/main/java/com/owncloud/android/operations/UploadFileOperation.java8
-rw-r--r--src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java141
-rw-r--r--src/main/java/com/owncloud/android/providers/FileContentProvider.java22
-rw-r--r--src/main/java/com/owncloud/android/ui/CustomPopup.java3
-rw-r--r--src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java99
-rw-r--r--src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java2
-rw-r--r--src/main/java/com/owncloud/android/ui/activity/ManageSpaceActivity.java4
-rwxr-xr-xsrc/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java2
-rw-r--r--src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java38
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/AccountListAdapter.java11
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java52
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java55
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java36
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java107
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java25
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java79
-rwxr-xr-xsrc/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java107
-rw-r--r--src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java52
-rw-r--r--src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java127
-rw-r--r--src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java91
-rw-r--r--src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java28
-rw-r--r--src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java38
-rwxr-xr-xsrc/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java88
-rw-r--r--src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java134
-rw-r--r--src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java2
-rw-r--r--src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java10
-rw-r--r--src/main/java/com/owncloud/android/utils/DisplayUtils.java445
-rw-r--r--src/main/java/com/owncloud/android/utils/FileStorageUtils.java2
-rw-r--r--src/main/java/com/owncloud/android/utils/GlideUtils.java25
-rw-r--r--src/main/java/com/owncloud/android/utils/MimeTypeUtil.java8
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/AvatarFetcher.java64
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/AvatarLoader.java45
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/AvatarModelLoaderFactory.java44
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/FileFetcher.java84
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideAvatar.java (renamed from src/main/java/com/owncloud/android/utils/glide/CustomGlideStreamLoader.java)32
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideContainer.java31
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideContainerModelLoaderFactory.java44
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideContainerStreamLoader.java49
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideKey.java75
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideOCFileType.java26
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideOcFile.java54
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideStringStreamFetcher.java94
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/GlideStringStreamLoader.java47
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/HttpStreamFetcher.java94
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/HttpStreamGlideContainerFetcher.java89
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/NextcloudGlideModule.java58
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/OCFileModelLoader.java55
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/OCFileModelLoaderFactory.java44
-rw-r--r--src/main/java/com/owncloud/android/utils/glide/StringModelLoaderFactory.java44
-rw-r--r--src/main/java/com/owncloud/android/utils/svg/SvgDecoder.java24
-rw-r--r--src/main/java/com/owncloud/android/utils/svg/SvgDrawableTranscoder.java13
-rw-r--r--src/main/java/com/owncloud/android/utils/svg/SvgSoftwareLayerSetter.java37
-rw-r--r--src/main/res/layout/grid_image.xml8
-rw-r--r--src/main/res/layout/grid_item.xml11
-rw-r--r--src/main/res/layout/list_item.xml415
-rw-r--r--src/main/res/values/strings.xml3
-rw-r--r--src/main/res/xml/exposed_filepaths.xml7
-rw-r--r--src/main/res/xml/filepaths.xml26
73 files changed, 2275 insertions, 2481 deletions
diff --git a/build.gradle b/build.gradle
index 136799b4b3..9c789bf59f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -239,9 +239,8 @@ dependencies {
implementation 'org.parceler:parceler-api:1.1.11'
annotationProcessor 'org.parceler:parceler:1.1.11'
- implementation ('com.github.bumptech.glide:glide:3.7.0') {
- exclude group: "com.android.support"
- }
+ implementation 'com.github.bumptech.glide:glide:4.8.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
implementation 'com.caverock:androidsvg:1.3'
implementation "com.android.support:support-annotations:${supportLibraryVersion}"
implementation 'com.google.code.gson:gson:2.8.5'
diff --git a/src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java b/src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java
index 8cccfd9f0b..123e1b13cd 100644
--- a/src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java
+++ b/src/androidTest/java/com/owncloud/android/datamodel/OCFileUnitTest.java
@@ -91,7 +91,6 @@ public class OCFileUnitTest {
mFile.setPublicLink(PUBLIC_LINK);
mFile.setPermissions(PERMISSIONS);
mFile.setRemoteId(REMOTE_ID);
- mFile.setNeedsUpdateThumbnail(true);
mFile.setDownloading(true);
mFile.setEtagInConflict(ETAG_IN_CONFLICT);
@@ -121,12 +120,12 @@ public class OCFileUnitTest {
assertThat(fileReadFromParcel.getLastSyncDateForData(), is(LAST_SYNC_DATE_FOR_DATA));
assertThat(fileReadFromParcel.isAvailableOffline(), is(true));
assertThat(fileReadFromParcel.getEtag(), is(ETAG));
+ assertThat(fileReadFromParcel.getEtagOnServer(), is(ETAG));
assertThat(fileReadFromParcel.isSharedViaLink(), is(true));
assertThat(fileReadFromParcel.isSharedWithSharee(), is(true));
assertThat(fileReadFromParcel.getPublicLink(), is(PUBLIC_LINK));
assertThat(fileReadFromParcel.getPermissions(), is(PERMISSIONS));
assertThat(fileReadFromParcel.getRemoteId(), is(REMOTE_ID));
- assertThat(fileReadFromParcel.needsUpdateThumbnail(), is(true));
assertThat(fileReadFromParcel.isDownloading(), is(true));
assertThat(fileReadFromParcel.getEtagInConflict(), is(ETAG_IN_CONFLICT));
diff --git a/src/gplay/java/com/owncloud/android/utils/PushUtils.java b/src/gplay/java/com/owncloud/android/utils/PushUtils.java
index 648159e71c..71bf2c303e 100644
--- a/src/gplay/java/com/owncloud/android/utils/PushUtils.java
+++ b/src/gplay/java/com/owncloud/android/utils/PushUtils.java
@@ -397,7 +397,7 @@ public final class PushUtils {
if (oldPrivateKeyFile.exists()) {
try {
FileStorageUtils.moveFile(oldPrivateKeyFile, privateKeyFile);
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Failed to move old private key to new location");
}
}
@@ -405,7 +405,7 @@ public final class PushUtils {
if (oldPublicKeyFile.exists()) {
try {
FileStorageUtils.moveFile(oldPublicKeyFile, publicKeyFile);
- } catch (IOException e) {
+ } catch (Exception e) {
Log.e(TAG, "Failed to move old public key to new location");
}
}
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index ee9212f523..984a9052cc 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -203,12 +203,6 @@
android:resource="@xml/exposed_filepaths" />
</provider>
- <provider
- android:name=".providers.DiskLruImageCacheFileProvider"
- android:authorities="@string/image_cache_provider_authority"
- android:exported="true">
- </provider>
-
<activity
android:name=".authentication.AuthenticatorActivity"
android:exported="true"
diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java
index 0e5d9bac83..347c3c000e 100644
--- a/src/main/java/com/owncloud/android/MainApp.java
+++ b/src/main/java/com/owncloud/android/MainApp.java
@@ -53,7 +53,6 @@ import com.owncloud.android.datamodel.MediaFolderType;
import com.owncloud.android.datamodel.MediaProvider;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.datastorage.DataStorageProvider;
import com.owncloud.android.datastorage.StoragePoint;
import com.owncloud.android.db.PreferenceManager;
@@ -143,10 +142,6 @@ public class MainApp extends MultiDexApplication {
.setDefaultPolicy(Policy.SINGLE_SESSION_PER_ACCOUNT_IF_SERVER_SUPPORTS_SERVER_MONITORING);
}
- // initialise thumbnails cache on background thread
- new ThumbnailsCacheManager.InitDiskCacheTask().execute();
-
-
if (BuildConfig.DEBUG || getApplicationContext().getResources().getBoolean(R.bool.logger_enabled) ||
appPrefs.getBoolean(Preferences.PREFERENCE_EXPERT_MODE, false)) {
// use app writable dir, no permissions needed
diff --git a/src/main/java/com/owncloud/android/authentication/AccountUtils.java b/src/main/java/com/owncloud/android/authentication/AccountUtils.java
index 77f39880ba..d24f33f211 100644
--- a/src/main/java/com/owncloud/android/authentication/AccountUtils.java
+++ b/src/main/java/com/owncloud/android/authentication/AccountUtils.java
@@ -29,6 +29,9 @@ import android.support.annotation.Nullable;
import com.owncloud.android.MainApp;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
+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.resources.status.OwnCloudVersion;
import com.owncloud.android.ui.activity.ManageAccountsActivity;
@@ -196,4 +199,33 @@ public final class AccountUtils {
public static boolean hasSearchSupport(Account account) {
return getServerVersion(account).isSearchSupported();
}
+
+ public static @Nullable
+ OwnCloudClient getClientForCurrentAccount(Context context) {
+ try {
+ Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(context);
+
+ if (currentAccount == null) {
+ return null;
+ }
+
+ OwnCloudAccount ocAccount = new OwnCloudAccount(currentAccount, context);
+ return OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context);
+ } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
+ throw new IllegalStateException("Account not found", e);
+ } catch (Exception e) {
+ throw new IllegalStateException("Client could not be instantiated", e);
+ }
+ }
+
+ public static OwnCloudClient getClientForAccount(Account account, Context context) {
+ try {
+ OwnCloudAccount ocAccount = new OwnCloudAccount(account, context);
+ return OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, context);
+ } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
+ throw new IllegalStateException("Account not found");
+ } catch (Exception e) {
+ throw new IllegalStateException("Client could not be instantiated");
+ }
+ }
}
diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
index c30115c0f4..445c3d6cf8 100644
--- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
+++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java
@@ -210,12 +210,12 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isAvailableOffline() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
+ cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer());
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());
@@ -450,6 +450,7 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isAvailableOffline() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
+ cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, folder.getEtagOnServer());
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());
@@ -479,12 +480,12 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isAvailableOffline() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
+ cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer());
cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
- cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict());
cv.put(ProviderTableMeta.FILE_FAVORITE, file.isFavorite());
@@ -968,12 +969,12 @@ public class FileDataStorageManager {
file.setLastSyncDateForData(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
file.setAvailableOffline(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1);
file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
+ file.setEtagOnServer(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_ON_SERVER)));
file.setShareViaLink(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_SHARED_VIA_LINK)) == 1);
file.setShareWithSharee(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_SHARED_WITH_SHAREE)) == 1);
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)));
- file.setNeedsUpdateThumbnail(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1);
file.setDownloading(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1);
file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT)));
file.setFavorite(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_FAVORITE)) == 1);
@@ -1394,6 +1395,7 @@ public class FileDataStorageManager {
);
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isAvailableOffline() ? 1 : 0);
cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
+ cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer());
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());
@@ -1401,10 +1403,6 @@ public class FileDataStorageManager {
cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
cv.put(ProviderTableMeta.FILE_FAVORITE, file.isFavorite());
cv.put(
- ProviderTableMeta.FILE_UPDATE_THUMBNAIL,
- file.needsUpdateThumbnail() ? 1 : 0
- );
- cv.put(
ProviderTableMeta.FILE_IS_DOWNLOADING,
file.isDownloading() ? 1 : 0
);
diff --git a/src/main/java/com/owncloud/android/datamodel/OCFile.java b/src/main/java/com/owncloud/android/datamodel/OCFile.java
index 8b558bebe6..8b4070a2fa 100644
--- a/src/main/java/com/owncloud/android/datamodel/OCFile.java
+++ b/src/main/java/com/owncloud/android/datamodel/OCFile.java
@@ -81,6 +81,7 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
private boolean mAvailableOffline;
private String mEtag;
+ private String mEtagOnServer;
private boolean mShareByLink;
private String mPublicLink;
@@ -154,6 +155,7 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
mLastSyncDateForProperties = source.readLong();
mLastSyncDateForData = source.readLong();
mEtag = source.readString();
+ mEtagOnServer = source.readString();
mShareByLink = source.readInt() == 1;
mPublicLink = source.readString();
mPermissions = source.readString();
@@ -184,6 +186,7 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
dest.writeLong(mLastSyncDateForProperties);
dest.writeLong(mLastSyncDateForData);
dest.writeString(mEtag);
+ dest.writeString(mEtagOnServer);
dest.writeInt(mShareByLink ? 1 : 0);
dest.writeString(mPublicLink);
dest.writeString(mPermissions);
@@ -513,6 +516,7 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
mAvailableOffline = false;
mNeedsUpdating = false;
mEtag = null;
+ mEtagOnServer = null;
mShareByLink = false;
mPublicLink = null;
mPermissions = null;
@@ -600,14 +604,6 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
return mNeedsUpdating;
}
- public boolean needsUpdateThumbnail() {
- return mNeedsUpdateThumbnail;
- }
-
- public void setNeedsUpdateThumbnail(boolean needsUpdateThumbnail) {
- this.mNeedsUpdateThumbnail = needsUpdateThumbnail;
- }
-
public long getLastSyncDateForProperties() {
return mLastSyncDateForProperties;
}
@@ -685,6 +681,9 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
this.mEtag = (etag != null ? etag : "");
}
+ public void setEtagOnServer(String eTag) {
+ this.mEtagOnServer = eTag != null ? eTag : "";
+ }
public boolean isSharedViaLink() {
return mShareByLink;
@@ -797,4 +796,8 @@ public class OCFile implements Parcelable, Comparable<OCFile>, ServerFileInterfa
public void setMountType(WebdavEntry.MountType mountType) {
mMountType = mountType;
}
+
+ public String getEtagOnServer() {
+ return mEtagOnServer;
+ }
}
diff --git a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
deleted file mode 100644
index c40375f463..0000000000
--- a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java
+++ /dev/null
@@ -1,1169 +0,0 @@
-/*
- * ownCloud Android client application
- *
- * @author Tobias Kaminsky
- * @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.datamodel;
-
-import android.accounts.Account;
-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.Paint;
-import android.graphics.Point;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.media.MediaMetadataRetriever;
-import android.media.ThumbnailUtils;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.provider.MediaStore;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.view.Display;
-import android.view.MenuItem;
-import android.view.WindowManager;
-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.operations.RemoteOperation;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.files.ServerFileInterface;
-import com.owncloud.android.lib.resources.files.TrashbinFile;
-import com.owncloud.android.ui.TextDrawable;
-import com.owncloud.android.ui.adapter.DiskLruImageCache;
-import com.owncloud.android.ui.fragment.FileFragment;
-import com.owncloud.android.ui.preview.PreviewImageFragment;
-import com.owncloud.android.utils.BitmapUtils;
-import com.owncloud.android.utils.ConnectivityUtils;
-import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener;
-import com.owncloud.android.utils.FileStorageUtils;
-import com.owncloud.android.utils.MimeTypeUtil;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.GetMethod;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.lang.ref.WeakReference;
-import java.net.URLEncoder;
-import java.util.List;
-
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-
-/**
- * Manager for concurrent access to thumbnails cache.
- */
-public final class ThumbnailsCacheManager {
-
- public static final String PREFIX_RESIZED_IMAGE = "r";
- public static final String PREFIX_THUMBNAIL = "t";
-
- private static final String TAG = ThumbnailsCacheManager.class.getSimpleName();
- private static final String PNG_MIMETYPE = "image/png";
- private static final String CACHE_FOLDER = "thumbnailCache";
- public static final String AVATAR = "avatar";
- private static final String ETAG = "ETag";
-
- private static final Object mThumbnailsDiskCacheLock = new Object();
- private static DiskLruImageCache mThumbnailCache;
- private static boolean mThumbnailCacheStarting = true;
-
- private static final int DISK_CACHE_SIZE = 1024 * 1024 * 200; // 200MB
- private static final CompressFormat mCompressFormat = CompressFormat.JPEG;
- private static final int mCompressQuality = 70;
- private static OwnCloudClient mClient;
-
- public static final Bitmap mDefaultImg = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
- R.drawable.file_image);
-
- public static final Bitmap mDefaultVideo = BitmapFactory.decodeResource(MainApp.getAppContext().getResources(),
- R.drawable.file_movie);
-
- private 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,
- // try and use external cache dir; otherwise use internal cache dir
- File cacheDir = MainApp.getAppContext().getExternalCacheDir();
-
- if (cacheDir != null) {
- String cachePath = cacheDir.getPath() + File.separator + CACHE_FOLDER;
- Log_OC.d(TAG, "create dir: " + cachePath);
- File diskCacheDir = new File(cachePath);
- mThumbnailCache = new DiskLruImageCache(diskCacheDir, DISK_CACHE_SIZE, mCompressFormat,
- mCompressQuality);
- } else {
- throw new FileNotFoundException("Thumbnail cache could not be opened");
- }
- } catch (Exception e) {
- Log_OC.d(TAG, e.getMessage());
- mThumbnailCache = null;
- }
- }
- mThumbnailCacheStarting = false; // Finished initialization
- mThumbnailsDiskCacheLock.notifyAll(); // Wake any waiting threads
- }
- return null;
- }
- }
-
- /**
- * Converts size of file icon from dp to pixel
- * @return int
- */
- private static int getThumbnailDimension(){
- // Converts dp to pixel
- Resources r = MainApp.getAppContext().getResources();
- return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
- }
-
- /**
- * Converts dimension of screen as point
- *
- * @return Point
- */
- private static Point getScreenDimension() {
- WindowManager wm = (WindowManager) MainApp.getAppContext().getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Point point = new Point();
- display.getSize(point);
- return point;
- }
-
- /**
- * Add thumbnail to cache
- * @param imageKey: thumb key
- * @param bitmap: image for extracting thumbnail
- * @param path: image path
- * @param pxW: thumbnail width in pixel
- * @param pxH: thumbnail height in pixel
- * @return Bitmap
- */
- private static Bitmap addThumbnailToCache(String imageKey, Bitmap bitmap, String path, int pxW, int pxH){
-
- Bitmap thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
-
- // Rotate image, obeying exif tag
- thumbnail = BitmapUtils.rotateImage(thumbnail,path);
-
- // Add thumbnail to cache
- addBitmapToCache(imageKey, thumbnail);
-
- return thumbnail;
- }
-
- public static void addBitmapToCache(String key, Bitmap bitmap) {
- synchronized (mThumbnailsDiskCacheLock) {
- if (mThumbnailCache != null) {
- mThumbnailCache.put(key, bitmap);
- }
- }
- }
-
- public static Bitmap getBitmapFromDiskCache(String key) {
- synchronized (mThumbnailsDiskCacheLock) {
- // Wait while disk cache is started from background thread
- while (mThumbnailCacheStarting) {
- try {
- mThumbnailsDiskCacheLock.wait();
- } catch (InterruptedException e) {
- Log_OC.e(TAG, "Wait in mThumbnailsDiskCacheLock was interrupted", e);
- }
- }
- if (mThumbnailCache != null) {
- return mThumbnailCache.getBitmap(key);
- }
- }
- return null;
- }
-
- public static class ResizedImageGenerationTask extends AsyncTask<Object, Void, Bitmap> {
- private FileFragment fileFragment;
- private FileDataStorageManager storageManager;
- private Account account;
- private WeakReference<ImageView> imageViewReference;
- private OCFile file;
-
-
- public ResizedImageGenerationTask(FileFragment fileFragment, ImageView imageView,
- FileDataStorageManager storageManager, Account account)
- throws IllegalArgumentException {
- this.fileFragment = fileFragment;
- imageViewReference = new WeakReference<>(imageView);
- this.storageManager = storageManager;
- this.account = account;
- }
-
- @Override
- protected Bitmap doInBackground(Object... params) {
- Bitmap thumbnail = null;
-
- file = (OCFile) params[0];
-
- try {
- if (account != null) {
- OwnCloudAccount ocAccount = new OwnCloudAccount(account, MainApp.getAppContext());
- mClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount,
- MainApp.getAppContext());
- }
-
- thumbnail = doResizedImageInBackground();
-
- if (MimeTypeUtil.isVideo(file) && thumbnail != null) {
- thumbnail = addVideoOverlay(thumbnail);
- }
-
- } catch (OutOfMemoryError oome) {
- Log_OC.e(TAG, "Out of memory");
- } catch (Throwable t) {
- // the app should never break due to a problem with thumbnails
- Log_OC.e(TAG, "Generation of thumbnail for " + file + " failed", t);
- }
-
- return thumbnail;
- }
-
- private Bitmap doResizedImageInBackground() {
- Bitmap thumbnail;
-
- String imageKey = PREFIX_RESIZED_IMAGE + String.valueOf(file.getRemoteId());
-
- // Check disk cache in background thread
- thumbnail = getBitmapFromDiskCache(imageKey);
-
- // Not found in disk cache
- if (thumbnail == null || file.needsUpdateThumbnail()) {
- Point p = getScreenDimension();
- int pxW = p.x;
- int pxH = p.y;
-
- if (file.isDown()) {
- Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getStoragePath(), pxW, pxH);
-
- if (bitmap != null) {
- // Handle PNG
- if (file.getMimeType().equalsIgnoreCase(PNG_MIMETYPE)) {
- bitmap = handlePNG(bitmap, pxW, pxH);
- }
-
- thumbnail = addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), pxW, pxH);
-
- file.setNeedsUpdateThumbnail(false);
- storageManager.saveFile(file);
- }
-
- } else {
- // Download thumbnail from server
- if (mClient != null) {
- GetMethod getMethod = null;
- try {
- String uri = mClient.getBaseUri() + "/index.php/core/preview.png?file="
- + URLEncoder.encode(file.getRemotePath())
- + "&x=" + pxW + "&y=" + pxH + "&a=1&mode=cover&forceIcon=0";
- getMethod = new GetMethod(uri);
-
- int status = mClient.executeMethod(getMethod);
- if (status == HttpStatus.SC_OK) {
- InputStream inputStream = getMethod.getResponseBodyAsStream();
- thumbnail = BitmapFactory.decodeStream(inputStream);
- } else {
- mClient.exhaustResponse(getMethod.getResponseBodyAsStream());
- }
-
- // Handle PNG
- if (thumbnail != null && file.getMimeType().equalsIgnoreCase(PNG_MIMETYPE)) {
- thumbnail = handlePNG(thumbnail, thumbnail.getWidth(), thumbnail.getHeight());
- }
-
- // Add thumbnail to cache
- if (thumbnail != null) {
- Log_OC.d(TAG, "add thumbnail to cache: " + file.getFileName());
- addBitmapToCache(imageKey, thumbnail);
- }
-
- } catch (Exception e) {
- Log_OC.d(TAG, e.getMessage(), e);
- } finally {
- if (getMethod != null) {
- getMethod.releaseConnection();
- }
- }
- }
- }
- }
-
- return thumbnail;
-
- }
-
- protected void onPostExecute(Bitmap bitmap) {
- if (imageViewReference != null) {
- final ImageView imageView = imageViewReference.get();
-
- if (bitmap != null) {
- final ResizedImageGenerationTask bitmapWorkerTask = getResizedImageGenerationWorkerTask(imageView);
-
- if (this == bitmapWorkerTask) {
- String tagId = String.valueOf(file.getFileId());
-
- if (String.valueOf(imageView.getTag()).equals(tagId)) {
- imageView.setImageBitmap(bitmap);
- }
- }
- } else {
- new Thread(() -> {
- if (ConnectivityUtils.isInternetWalled(MainApp.getAppContext())) {
- if (fileFragment instanceof PreviewImageFragment) {
- ((PreviewImageFragment) fileFragment).setNoConnectionErrorMessage();
- }
- } else {
- if (fileFragment instanceof PreviewImageFragment) {
- ((PreviewImageFragment) fileFragment).setErrorPreviewMessage();
- }
- }
- }).start();
-
- }
- }
- }
- }
-
- public static class ThumbnailGenerationTaskObject {
- private Object file;
- private String imageKey;
-
- public ThumbnailGenerationTaskObject(Object file, String imageKey) {
- this.file = file;
- this.imageKey = imageKey;
- }
-
- private Object getFile() {
- return file;
- }
-
- private String getImageKey() {
- return imageKey;
- }
- }
-
- public static class ThumbnailGenerationTask extends AsyncTask<ThumbnailGenerationTaskObject, Void, Bitmap> {
- private final WeakReference<ImageView> mImageViewReference;
- private static Account mAccount;
- private List<ThumbnailGenerationTask> mAsyncTasks;
- private Object mFile;
- private String mImageKey;
- private FileDataStorageManager mStorageManager;
- private GetMethod getMethod;
-
- public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager, Account account)
- throws IllegalArgumentException {
- this(imageView, storageManager, account, null);
- }
-
- public ThumbnailGenerationTask(ImageView imageView, FileDataStorageManager storageManager,
- Account account, List<ThumbnailGenerationTask> asyncTasks)
- throws IllegalArgumentException {
- // 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;
- mAsyncTasks = asyncTasks;
- }
-
- public GetMethod getGetMethod() {
- return getMethod;
- }
-
- public ThumbnailGenerationTask(FileDataStorageManager storageManager, Account account){
- if (storageManager == null) {
- throw new IllegalArgumentException("storageManager must not be NULL");
- }
- mStorageManager = storageManager;
- mAccount = account;
- mImageViewReference = null;
- }
-
- public ThumbnailGenerationTask(ImageView imageView) {
- // Use a WeakReference to ensure the ImageView can be garbage collected
- mImageViewReference = new WeakReference<ImageView>(imageView);
- }
-
- @SuppressFBWarnings("Dm")
- @Override
- protected Bitmap doInBackground(ThumbnailGenerationTaskObject... params) {
- Bitmap thumbnail = null;
-
- try {
- if (mAccount != null) {
- OwnCloudAccount ocAccount = new OwnCloudAccount(
- mAccount,
- MainApp.getAppContext()
- );
- mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
- getClientFor(ocAccount, MainApp.getAppContext());
- }
-
- ThumbnailGenerationTaskObject object = params[0];
- mFile = object.getFile();
- mImageKey = object.getImageKey();
-
- if (mFile instanceof ServerFileInterface) {
- thumbnail = doThumbnailFromOCFileInBackground();
-
- if (MimeTypeUtil.isVideo((ServerFileInterface) mFile) && thumbnail != null) {
- thumbnail = addVideoOverlay(thumbnail);
- }
- } else if (mFile instanceof File) {
- thumbnail = doFileInBackground();
-
- String url = ((File) mFile).getAbsolutePath();
- String mMimeType = FileStorageUtils.getMimeTypeFromName(url);
-
- if (MimeTypeUtil.isVideo(mMimeType) && thumbnail != null) {
- thumbnail = addVideoOverlay(thumbnail);
- }
- //} else { do nothing
- }
-
- } catch(OutOfMemoryError oome) {
- Log_OC.e(TAG, "Out of memory");
- } catch (Throwable t) {
- // the app should never break due to a problem with thumbnails
- Log_OC.e(TAG, "Generation of thumbnail for " + mFile + " failed", t);
- }
-
- return thumbnail;
- }
-
- protected void onPostExecute(Bitmap bitmap) {
- if (bitmap != null && mImageViewReference != null) {
- final ImageView imageView = mImageViewReference.get();
- final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
- if (this == bitmapWorkerTask) {
- String tagId = "";
- if (mFile instanceof OCFile) {
- tagId = String.valueOf(((OCFile)mFile).getFileId());
- } else if (mFile instanceof File) {
- tagId = String.valueOf(mFile.hashCode());
- } else if (mFile instanceof TrashbinFile) {
- tagId = String.valueOf(((TrashbinFile) mFile).getRemoteId());
- }
- if (String.valueOf(imageView.getTag()).equals(tagId)) {
- imageView.setImageBitmap(bitmap);
- }
- }
- }
-
- if (mAsyncTasks != null) {
- mAsyncTasks.remove(this);
- }
- }
-
- private Bitmap doThumbnailFromOCFileInBackground() {
- Bitmap thumbnail;
- ServerFileInterface file = (ServerFileInterface) mFile;
- String imageKey = PREFIX_THUMBNAIL + String.valueOf(file.getRemoteId());
-
- // Check disk cache in background thread
- thumbnail = getBitmapFromDiskCache(imageKey);
-
- // Not found in disk cache
- if (thumbnail == null || (file instanceof OCFile && ((OCFile) file).needsUpdateThumbnail())) {
- int pxW;
- int pxH;
- pxW = pxH = getThumbnailDimension();
-
- if (file instanceof OCFile) {
- OCFile ocFile = (OCFile) file;
- if (ocFile.isDown()) {
- Bitmap bitmap;
- if (MimeTypeUtil.isVideo(ocFile)) {
- bitmap = ThumbnailUtils.createVideoThumbnail(ocFile.getStoragePath(),
- MediaStore.Images.Thumbnails.MINI_KIND);
- } else {
- bitmap = BitmapUtils.decodeSampledBitmapFromFile(ocFile.getStoragePath(), pxW, pxH);
- }
-
- if (bitmap != null) {
- // Handle PNG
- if (ocFile.getMimeType().equalsIgnoreCase(PNG_MIMETYPE)) {
- bitmap = handlePNG(bitmap, pxW, pxH);
- }
-
- thumbnail = addThumbnailToCache(imageKey, bitmap, ocFile.getStoragePath(), pxW, pxH);
-
- ocFile.setNeedsUpdateThumbnail(false);
- mStorageManager.saveFile(ocFile);
- }
- }
- }
-
- if (thumbnail == null) {
- // check if resized version is available
- String resizedImageKey = PREFIX_RESIZED_IMAGE + String.valueOf(file.getRemoteId());
- Bitmap resizedImage = getBitmapFromDiskCache(resizedImageKey);
-
- if (resizedImage != null) {
- thumbnail = ThumbnailUtils.extractThumbnail(resizedImage, pxW, pxH);
- } else {
- // Download thumbnail from server
- if (mClient != null) {
- getMethod = null;
- try {
- // thumbnail
- String uri;
- if (file instanceof OCFile) {
- uri = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" +
- pxW + "/" + pxH + Uri.encode(file.getRemotePath(), "/");
- } else {
- uri = mClient.getBaseUri() + "/index.php/apps/files_trashbin/preview?fileId=" +
- file.getLocalId() + "&x=" + pxW + "&y=" + pxH;
- }
-
- Log_OC.d(TAG, "generate thumbnail: " + file.getFileName() + " URI: " + uri);
- getMethod = new GetMethod(uri);
- getMethod.setRequestHeader("Cookie",
- "nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
-
- getMethod.setRequestHeader(RemoteOperation.OCS_API_HEADER,
- RemoteOperation.OCS_API_HEADER_VALUE);
-
- int status = mClient.executeMethod(getMethod);
- if (status == HttpStatus.SC_OK) {
- InputStream inputStream = getMethod.getResponseBodyAsStream();
- Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
- thumbnail = ThumbnailUtils.extractThumbnail(bitmap, pxW, pxH);
- } else {
- mClient.exhaustResponse(getMethod.getResponseBodyAsStream());
- }
-
- // Handle PNG
- if (file.getMimeType().equalsIgnoreCase(PNG_MIMETYPE)) {
- thumbnail = handlePNG(thumbnail, pxW, pxH);
- }
- } catch (Exception e) {
- Log_OC.d(TAG, e.getMessage(), e);
- } finally {
- if (getMethod != null) {
- getMethod.releaseConnection();
- }
- }
- }
- }
-
- // Add thumbnail to cache
- if (thumbnail != null) {
- Log_OC.d(TAG, "add thumbnail to cache: " + file.getFileName());
- addBitmapToCache(imageKey, thumbnail);
- }
- }
- }
-
- return thumbnail;
- }
-
- /**
- * Converts size of file icon from dp to pixel
- *
- * @return int
- */
- private int getThumbnailDimension() {
- // Converts dp to pixel
- Resources r = MainApp.getAppContext().getResources();
- Double d = Math.pow(2, Math.floor(Math.log(r.getDimension(R.dimen.file_icon_size_grid)) / Math.log(2)));
- return d.intValue();
- }
-
- private Bitmap doFileInBackground() {
- File file = (File)mFile;
-
- final String imageKey;
- if (mImageKey != null) {
- imageKey = mImageKey;
- } else {
- imageKey = String.valueOf(file.hashCode());
- }
-
- // local file should always generate a thumbnail
- mImageKey = PREFIX_THUMBNAIL + mImageKey;
-
- // Check disk cache in background thread
- Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
-
- // Not found in disk cache
- if (thumbnail == null) {
- int pxW;
- int pxH;
- pxW = pxH = getThumbnailDimension();
-
- Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), pxW, pxH);
-
- if (bitmap != null) {
- thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), pxW, pxH);
- }
- }
- return thumbnail;
- }
-
- }
-
- public static class MediaThumbnailGenerationTask extends AsyncTask<Object, Void, Bitmap> {
-
- private static final int IMAGE_KEY_PARAMS_LENGTH = 2;
-
- private enum Type {IMAGE, VIDEO}
- private final WeakReference<ImageView> mImageViewReference;
- private File mFile;
- private String mImageKey = null;
- private Context mContext;
-
- public MediaThumbnailGenerationTask(ImageView imageView, Context context) {
- // Use a WeakReference to ensure the ImageView can be garbage collected
- mImageViewReference = new WeakReference<>(imageView);
- mContext = context;
- }
-
- @Override
- protected Bitmap doInBackground(Object... params) {
- Bitmap thumbnail = null;
-
- try {
- if (params[0] instanceof File) {
- mFile = (File) params[0];
- if (params.length == IMAGE_KEY_PARAMS_LENGTH) {
- mImageKey = (String) params[1];
- }
-
- if (MimeTypeUtil.isImage(mFile)) {
- thumbnail = doFileInBackground(mFile, Type.IMAGE);
- } else if (MimeTypeUtil.isVideo(mFile)) {
- thumbnail = doFileInBackground(mFile, Type.VIDEO);
- }
- }
- } // the app should never break due to a problem with thumbnails
- catch (OutOfMemoryError t) {
- Log_OC.e(TAG, "Generation of thumbnail for " + mFile.getAbsolutePath() + " failed", t);
- Log_OC.e(TAG, "Out of memory");
- } catch (Throwable t) {
- // the app should never break due to a problem with thumbnails
- Log_OC.e(TAG, "Generation of thumbnail for " + mFile.getAbsolutePath() + " failed", t);
- }
-
- return thumbnail;
- }
-
- protected void onPostExecute(Bitmap bitmap) {
- String tagId = "";
- final ImageView imageView = mImageViewReference.get();
- if (imageView != null) {
- if (mFile != null) {
- tagId = String.valueOf(mFile.hashCode());
- }
-
- if (bitmap != null) {
- if (tagId.equals(String.valueOf(imageView.getTag()))) {
- imageView.setImageBitmap(bitmap);
- }
- } else {
- if (mFile != null) {
- if (mFile.isDirectory()) {
- imageView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(mContext));
- } else {
- if (MimeTypeUtil.isVideo(mFile)) {
- imageView.setImageBitmap(ThumbnailsCacheManager.mDefaultVideo);
- } else {
- imageView.setImageDrawable(MimeTypeUtil.getFileTypeIcon(null, mFile.getName(),
- mContext));
- }
- }
- }
- }
- }
- }
-
- private Bitmap doFileInBackground(File file, Type type) {
- final String imageKey;
-
- if (mImageKey != null) {
- imageKey = mImageKey;
- } else {
- imageKey = String.valueOf(file.hashCode());
- }
-
- // Check disk cache in background thread
- Bitmap thumbnail = getBitmapFromDiskCache(imageKey);
-
- // Not found in disk cache
- if (thumbnail == null) {
-
- if (Type.IMAGE.equals(type)) {
- int px = getThumbnailDimension();
-
- Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getAbsolutePath(), px, px);
-
- if (bitmap != null) {
- thumbnail = addThumbnailToCache(imageKey, bitmap, file.getPath(), px, px);
- }
- } else if (Type.VIDEO.equals(type)) {
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- try {
- retriever.setDataSource(file.getAbsolutePath());
- thumbnail = retriever.getFrameAtTime(-1);
- } catch (Exception ex) {
- // can't create a bitmap
- Log_OC.w(TAG, "Failed to create bitmap from video " + file.getAbsolutePath());
- } finally {
- try {
- retriever.release();
- } catch (RuntimeException ex) {
- // Ignore failure at this point.
- Log_OC.w(TAG, "Failed release MediaMetadataRetriever for " + file.getAbsolutePath());
- }
- }
-
- if (thumbnail != null) {
- // Scale down bitmap if too large.
- int px = getThumbnailDimension();
- int width = thumbnail.getWidth();
- int height = thumbnail.getHeight();
- int max = Math.max(width, height);
- if (max > px) {
- thumbnail = BitmapUtils.scaleBitmap(thumbnail, px, width, height, max);
- thumbnail = addThumbnailToCache(imageKey, thumbnail, file.getPath(), px, px);
- }
- }
- }
- }
-
- return thumbnail;
- }
- }
-
- public static class AvatarGenerationTask extends AsyncTask<String, Void, Drawable> {
- private final WeakReference<AvatarGenerationListener> mAvatarGenerationListener;
- private final Object mCallContext;
- private final Resources mResources;
- private final float mAvatarRadius;
- private Account mAccount;
- private String mUserId;
- private String mServerName;
- private Context mContext;
-
-
- public AvatarGenerationTask(AvatarGenerationListener avatarGenerationListener, Object callContext,
- Account account, Resources resources, float avatarRadius, String userId,
- String serverName, Context context) {
- mAvatarGenerationListener = new WeakReference<>(avatarGenerationListener);
- mCallContext = callContext;
- mAccount = account;
- mResources = resources;
- mAvatarRadius = avatarRadius;
- mUserId = userId;
- mServerName = serverName;
- mContext = context;
- }
-
- @SuppressFBWarnings("Dm")
- @Override
- protected Drawable doInBackground(String... params) {
- Drawable thumbnail = null;
-
- try {
- if (mAccount != null) {
- OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, mContext);
- mClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, mContext);
- }
-
- thumbnail = doAvatarInBackground();
-
- } catch (OutOfMemoryError oome) {
- Log_OC.e(TAG, "Out of memory");
- } catch (Throwable t) {
- // the app should never break due to a problem with avatars
- Log_OC.e(TAG, "Generation of avatar for " + mUserId + " failed", t);
- }
-
- return thumbnail;
- }
-
- protected void onPostExecute(Drawable drawable) {
- if (drawable != null) {
- AvatarGenerationListener listener = mAvatarGenerationListener.get();
- AvatarGenerationTask avatarWorkerTask = getAvatarWorkerTask(mCallContext);
-
- if (this == avatarWorkerTask && listener.shouldCallGeneratedCallback(mUserId, mCallContext)) {
- listener.avatarGenerated(drawable, mCallContext);
- }
- }
- }
-
- /**
- * Converts size of file icon from dp to pixel
- *
- * @return int
- */
- private int getAvatarDimension() {
- // Converts dp to pixel
- Resources r = MainApp.getAppContext().getResources();
- return Math.round(r.getDimension(R.dimen.file_avatar_size));
- }
-
- private @Nullable
- Drawable doAvatarInBackground() {
- Bitmap avatar = null;
-
- String accountName = mUserId + "@" + mServerName;
-
- ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(mContext.getContentResolver());
-
- String eTag = arbitraryDataProvider.getValue(accountName, ThumbnailsCacheManager.AVATAR);
- String avatarKey = "a_" + mUserId + "_" + mServerName + "_" + eTag;
-
- int px = getAvatarDimension();
-
- // Download avatar from server
- if (mClient != null) {
- GetMethod get = null;
- try {
- String uri = mClient.getBaseUri() + "/index.php/avatar/" + Uri.encode(mUserId) + "/" + px;
- Log_OC.d("Avatar", "URI: " + uri);
- get = new GetMethod(uri);
-
- // only use eTag if available and corresponding avatar is still there
- // (might be deleted from cache)
- if (!eTag.isEmpty() && getBitmapFromDiskCache(avatarKey) != null) {
- get.setRequestHeader("If-None-Match", eTag);
- }
-
- int status = mClient.executeMethod(get);
-
- // we are using eTag to download a new avatar only if it changed
- switch (status) {
- case HttpStatus.SC_OK:
- case HttpStatus.SC_CREATED:
- // new avatar
- InputStream inputStream = get.getResponseBodyAsStream();
-
- String newETag = null;
- if (get.getResponseHeader(ETAG) != null) {
- newETag = get.getResponseHeader(ETAG).getValue().replace("\"", "");
- arbitraryDataProvider.storeOrUpdateKeyValue(accountName, AVATAR, newETag);
- }
-
- Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
- avatar = ThumbnailUtils.extractThumbnail(bitmap, px, px);
-
- // Add avatar to cache
- if (avatar != null && !TextUtils.isEmpty(newETag)) {
- avatar = handlePNG(avatar, px, px);
- String newImageKey = "a_" + mUserId + "_" + mServerName + "_" + newETag;
- addBitmapToCache(newImageKey, avatar);
- } else {
- return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
- }
- break;
-
- case HttpStatus.SC_NOT_MODIFIED:
- // old avatar
- avatar = getBitmapFromDiskCache(avatarKey);
- mClient.exhaustResponse(get.getResponseBodyAsStream());
- break;
-
- default:
- // everything else
- mClient.exhaustResponse(get.getResponseBodyAsStream());
- break;
-
- }
- } catch (Exception e) {
- try {
- return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
- } catch (Exception e1) {
- Log_OC.e(TAG, "Error generating fallback avatar");
- }
- } finally {
- if (get != null) {
- get.releaseConnection();
- }
- }
-
- try {
- return TextDrawable.createAvatar(mAccount.name, mAvatarRadius);
- } catch (Exception e) {
- Log_OC.e(TAG, "Error generating fallback avatar");
- }
- }
-
- return BitmapUtils.bitmapToCircularBitmapDrawable(mResources, avatar);
- }
- }
-
- public static boolean cancelPotentialThumbnailWork(Object file, ImageView imageView) {
- final ThumbnailGenerationTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
-
- if (bitmapWorkerTask != null) {
- final Object bitmapData = bitmapWorkerTask.mFile;
- // If bitmapData is not yet set or it differs from the new data
- if (bitmapData == null || !bitmapData.equals(file)) {
- // Cancel previous task
- bitmapWorkerTask.cancel(true);
- Log_OC.v(TAG, "Cancelled generation of thumbnail for a reused imageView");
- } else {
- // The same work is already in progress
- return false;
- }
- }
- // No task associated with the ImageView, or an existing task was cancelled
- return true;
- }
-
- public static boolean cancelPotentialAvatarWork(Object file, Object callContext) {
- if (callContext instanceof ImageView) {
- return cancelPotentialAvatarWork(file, (ImageView) callContext);
- } else if (callContext instanceof MenuItem) {
- return cancelPotentialAvatarWork(file, (MenuItem)callContext);
- }
-
- return false;
- }
-
- public static boolean cancelPotentialAvatarWork(Object file, ImageView imageView) {
- final AvatarGenerationTask avatarWorkerTask = getAvatarWorkerTask(imageView);
-
- if (avatarWorkerTask != null) {
- final Object usernameData = avatarWorkerTask.mUserId;
- // If usernameData is not yet set or it differs from the new data
- if (usernameData == null || !usernameData.equals(file)) {
- // Cancel previous task
- avatarWorkerTask.cancel(true);
- Log_OC.v(TAG, "Cancelled generation of avatar for a reused imageView");
- } else {
- // The same work is already in progress
- return false;
- }
- }
- // No task associated with the ImageView, or an existing task was cancelled
- return true;
- }
-
- public static boolean cancelPotentialAvatarWork(Object file, MenuItem menuItem) {
- final AvatarGenerationTask avatarWorkerTask = getAvatarWorkerTask(menuItem);
-
- if (avatarWorkerTask != null) {
- final Object usernameData = avatarWorkerTask.mUserId;
- // If usernameData is not yet set or it differs from the new data
- if (usernameData == null || !usernameData.equals(file)) {
- // Cancel previous task
- avatarWorkerTask.cancel(true);
- Log_OC.v(TAG, "Cancelled generation of avatar for a reused imageView");
- } else {
- // The same work is already in progress
- return false;
- }
- }
- // No task associated with the ImageView, or an existing task was cancelled
- return true;
- }
-
- public static ThumbnailGenerationTask getBitmapWorkerTask(ImageView imageView) {
- if (imageView != null) {
- final Drawable drawable = imageView.getDrawable();
- if (drawable instanceof AsyncThumbnailDrawable) {
- final AsyncThumbnailDrawable asyncDrawable = (AsyncThumbnailDrawable) drawable;
- return asyncDrawable.getBitmapWorkerTask();
- }
- }
- return null;
- }
-
- private static ResizedImageGenerationTask getResizedImageGenerationWorkerTask(ImageView imageView) {
- if (imageView != null) {
- final Drawable drawable = imageView.getDrawable();
- if (drawable instanceof AsyncResizedImageDrawable) {
- final AsyncResizedImageDrawable asyncDrawable = (AsyncResizedImageDrawable) drawable;
- return asyncDrawable.getBitmapWorkerTask();
- }
- }
- 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;
-
-
- 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 AvatarGenerationTask getAvatarWorkerTask(Object callContext) {
- if (callContext instanceof ImageView) {
- return getAvatarWorkerTask(((ImageView)callContext).getDrawable());
- } else if (callContext instanceof MenuItem) {
- return getAvatarWorkerTask(((MenuItem)callContext).getIcon());
- }
-
- return null;
- }
-
- private static AvatarGenerationTask getAvatarWorkerTask(Drawable drawable) {
- if (drawable instanceof AsyncAvatarDrawable) {
- final AsyncAvatarDrawable asyncDrawable = (AsyncAvatarDrawable) drawable;
- return asyncDrawable.getAvatarWorkerTask();
- }
- return null;
- }
-
-
- public static class AsyncThumbnailDrawable extends BitmapDrawable {
- private final WeakReference<ThumbnailGenerationTask> bitmapWorkerTaskReference;
-
- public AsyncThumbnailDrawable(
- Resources res, Bitmap bitmap, ThumbnailGenerationTask bitmapWorkerTask
- ) {
-
- super(res, bitmap);
- bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
- }
-
- public ThumbnailGenerationTask getBitmapWorkerTask() {
- return bitmapWorkerTaskReference.get();
- }
- }
-
- public static class AsyncResizedImageDrawable extends BitmapDrawable {
- private final WeakReference<ResizedImageGenerationTask> bitmapWorkerTaskReference;
-
- public AsyncResizedImageDrawable(Resources res, Bitmap bitmap, ResizedImageGenerationTask bitmapWorkerTask) {
- super(res, bitmap);
- bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
- }
-
- private ResizedImageGenerationTask getBitmapWorkerTask() {
- return bitmapWorkerTaskReference.get();
- }
- }
-
- public static class AsyncMediaThumbnailDrawable extends BitmapDrawable {
- private final WeakReference<MediaThumbnailGenerationTask> bitmapWorkerTaskReference;
-
- public AsyncMediaThumbnailDrawable(Resources res, Bitmap bitmap,
- MediaThumbnailGenerationTask bitmapWorkerTask) {
-
- super(res, bitmap);
- bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask);
- }
- }
-
- public static class AsyncAvatarDrawable extends BitmapDrawable {
- private final WeakReference<AvatarGenerationTask> avatarWorkerTaskReference;
-
- public AsyncAvatarDrawable(Resources res, Drawable bitmap, AvatarGenerationTask avatarWorkerTask) {
- super(res, BitmapUtils.drawableToBitmap(bitmap));
- avatarWorkerTaskReference = new WeakReference<>(avatarWorkerTask);
- }
-
- public AvatarGenerationTask getAvatarWorkerTask() {
- return avatarWorkerTaskReference.get();
- }
- }
-
- private static Bitmap handlePNG(Bitmap bitmap, int pxW, int pxH) {
- Bitmap resultBitmap = Bitmap.createBitmap(pxW, pxH, Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(resultBitmap);
-
- c.drawColor(MainApp.getAppContext().getResources().getColor(R.color.background_color));
- c.drawBitmap(bitmap, 0, 0, null);
-
- return resultBitmap;
- }
-
- public static void generateResizedImage(OCFile file) {
- Point p = getScreenDimension();
- int pxW = p.x;
- int pxH = p.y;
- String imageKey = PREFIX_RESIZED_IMAGE + String.valueOf(file.getRemoteId());
-
- Bitmap bitmap = BitmapUtils.decodeSampledBitmapFromFile(file.getStoragePath(), pxW, pxH);
-
- if (bitmap != null) {
- // Handle PNG
- if (file.getMimeType().equalsIgnoreCase(PNG_MIMETYPE)) {
- bitmap = handlePNG(bitmap, pxW, pxH);
- }
-
- addThumbnailToCache(imageKey, bitmap, file.getStoragePath(), pxW, pxH);
- }
- }
-} \ No newline at end of file
diff --git a/src/main/java/com/owncloud/android/db/ProviderMeta.java b/src/main/java/com/owncloud/android/db/ProviderMeta.java
index 7dae332ae3..bb96f8516b 100644
--- a/src/main/java/com/owncloud/android/db/ProviderMeta.java
+++ b/src/main/java/com/owncloud/android/db/ProviderMeta.java
@@ -32,7 +32,7 @@ import com.owncloud.android.MainApp;
public class ProviderMeta {
public static final String DB_NAME = "filelist";
- public static final int DB_VERSION = 34;
+ public static final int DB_VERSION = 35;
private ProviderMeta() {
}
@@ -92,6 +92,7 @@ public class ProviderMeta {
public static final String FILE_LAST_SYNC_DATE_FOR_DATA = "last_sync_date_for_data";
public static final String FILE_KEEP_IN_SYNC = "keep_in_sync";
public static final String FILE_ETAG = "etag";
+ public static final String FILE_ETAG_ON_SERVER = "etag_on_server";
public static final String FILE_SHARED_VIA_LINK = "share_by_link";
public static final String FILE_SHARED_WITH_SHAREE = "shared_via_users";
public static final String FILE_PUBLIC_LINK = "public_link";
@@ -104,12 +105,12 @@ public class ProviderMeta {
public static final String FILE_IS_ENCRYPTED = "is_encrypted";
public static final String FILE_MOUNT_TYPE = "mount_type";
- public static final String [] FILE_ALL_COLUMNS = {_ID, FILE_PARENT, FILE_NAME
- , FILE_CREATION, FILE_MODIFIED,
+ public static final String[] FILE_ALL_COLUMNS = {_ID, FILE_PARENT, FILE_NAME, FILE_CREATION, FILE_MODIFIED,
FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, FILE_CONTENT_LENGTH, FILE_CONTENT_TYPE, FILE_STORAGE_PATH,
FILE_PATH, FILE_ACCOUNT_OWNER, FILE_LAST_SYNC_DATE, FILE_LAST_SYNC_DATE_FOR_DATA, FILE_KEEP_IN_SYNC,
- FILE_ETAG, FILE_SHARED_VIA_LINK, FILE_SHARED_WITH_SHAREE, FILE_PUBLIC_LINK, FILE_PERMISSIONS,
- FILE_REMOTE_ID, FILE_UPDATE_THUMBNAIL, FILE_IS_DOWNLOADING, FILE_ETAG_IN_CONFLICT, FILE_FAVORITE};
+ FILE_ETAG, FILE_ETAG_ON_SERVER, FILE_SHARED_VIA_LINK, FILE_SHARED_WITH_SHAREE, FILE_PUBLIC_LINK,
+ FILE_PERMISSIONS, FILE_REMOTE_ID, FILE_IS_DOWNLOADING, FILE_ETAG_IN_CONFLICT,
+ FILE_FAVORITE};
public static final String FILE_DEFAULT_SORT_ORDER = FILE_NAME + " collate nocase asc";
diff --git a/src/main/java/com/owncloud/android/files/services/FileDownloader.java b/src/main/java/com/owncloud/android/files/services/FileDownloader.java
index 560d51570e..e811e3d511 100644
--- a/src/main/java/com/owncloud/android/files/services/FileDownloader.java
+++ b/src/main/java/com/owncloud/android/files/services/FileDownloader.java
@@ -492,7 +492,6 @@ public class FileDownloader extends Service
long syncDate = System.currentTimeMillis();
file.setLastSyncDateForProperties(syncDate);
file.setLastSyncDateForData(syncDate);
- file.setNeedsUpdateThumbnail(true);
file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());
file.setModificationTimestampAtLastSyncForData(mCurrentDownload.getModificationTimestamp());
file.setEtag(mCurrentDownload.getEtag());
diff --git a/src/main/java/com/owncloud/android/files/services/FileUploader.java b/src/main/java/com/owncloud/android/files/services/FileUploader.java
index 4a9409eca7..e1d143147e 100644
--- a/src/main/java/com/owncloud/android/files/services/FileUploader.java
+++ b/src/main/java/com/owncloud/android/files/services/FileUploader.java
@@ -53,7 +53,6 @@ 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.datamodel.UploadsStorageManager;
import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus;
import com.owncloud.android.db.OCUpload;
@@ -71,6 +70,7 @@ import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.UploadListActivity;
import com.owncloud.android.ui.notifications.NotificationUtils;
import com.owncloud.android.utils.ConnectivityUtils;
+import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.ErrorMessageAdapter;
import com.owncloud.android.utils.PowerUtils;
import com.owncloud.android.utils.ThemeUtils;
@@ -1120,13 +1120,7 @@ public class FileUploader extends Service
}
// generate new Thumbnail
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(mStorageManager, mCurrentAccount);
-
- File file = new File(mCurrentUpload.getOriginalStoragePath());
- String remoteId = mCurrentUpload.getFile().getRemoteId();
-
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, remoteId));
+ DisplayUtils.generateThumbnail(mCurrentUpload.getFile(), mCurrentUpload.getOriginalStoragePath(), getBaseContext());
}
}
diff --git a/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java
index 6dc0a42d46..faf9a7c715 100644
--- a/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java
+++ b/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java
@@ -477,7 +477,6 @@ public class RefreshFolderOperation extends RemoteOperation {
} else if (remoteFolderChanged && MimeTypeUtil.isImage(remoteFile) &&
remoteFile.getModificationTimestamp() !=
localFile.getModificationTimestamp()) {
- updatedFile.setNeedsUpdateThumbnail(true);
Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
}
@@ -488,6 +487,9 @@ public class RefreshFolderOperation extends RemoteOperation {
// remote eTag will not be updated unless file CONTENTS are synchronized
updatedFile.setEtag("");
}
+
+ // eTag on Server is used for thumbnail validation
+ updatedFile.setEtagOnServer(remoteFile.getEtag());
}
@NonNull
diff --git a/src/main/java/com/owncloud/android/operations/RemoveFileOperation.java b/src/main/java/com/owncloud/android/operations/RemoveFileOperation.java
index 7c955de72b..254911a2a5 100644
--- a/src/main/java/com/owncloud/android/operations/RemoveFileOperation.java
+++ b/src/main/java/com/owncloud/android/operations/RemoveFileOperation.java
@@ -26,19 +26,21 @@ import android.accounts.Account;
import android.content.Context;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
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.common.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.RemoveRemoteFileOperation;
import com.owncloud.android.operations.common.SyncOperation;
+import com.owncloud.android.utils.DisplayUtils;
/**
* Remote operation performing the removal of a remote file or folder in the ownCloud server.
*/
public class RemoveFileOperation extends SyncOperation {
+ private final static String TAG = RemoveFileOperation.class.getSimpleName();
private OCFile fileToRemove;
private String remotePath;
@@ -92,7 +94,11 @@ public class RemoveFileOperation extends SyncOperation {
fileToRemove = getStorageManager().getFileByPath(remotePath);
// store resized image
- ThumbnailsCacheManager.generateResizedImage(fileToRemove);
+ try {
+ DisplayUtils.generateResizedImage(fileToRemove, context);
+ } catch (Exception e) {
+ Log_OC.e(TAG, "Thumbnail generation failed", e);
+ }
boolean localRemovalFailed = false;
if (!onlyLocalCopy) {
diff --git a/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java
index 2ec650b5ca..edd168bb06 100644
--- a/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java
+++ b/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java
@@ -23,7 +23,6 @@ package com.owncloud.android.operations;
import android.accounts.Account;
import android.content.Context;
import android.content.Intent;
-import android.util.Log;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
@@ -39,7 +38,6 @@ import com.owncloud.android.lib.resources.files.RemoteFile;
import com.owncloud.android.operations.common.SyncOperation;
import com.owncloud.android.services.OperationsService;
import com.owncloud.android.utils.FileStorageUtils;
-import com.owncloud.android.utils.MimeTypeUtil;
import java.io.File;
import java.util.HashMap;
@@ -332,11 +330,6 @@ public class SynchronizeFolderOperation extends SyncOperation {
if (updatedFile.isFolder()) {
updatedFile.setFileLength(localFile.getFileLength());
// TODO move operations about size of folders to FileContentProvider
- } else if (mRemoteFolderChanged && MimeTypeUtil.isImage(remoteFile) &&
- remoteFile.getModificationTimestamp() !=
- localFile.getModificationTimestamp()) {
- updatedFile.setNeedsUpdateThumbnail(true);
- Log.d(TAG, "Image " + remoteFile.getFileName() + " updated on the server");
}
updatedFile.setPublicLink(localFile.getPublicLink());
updatedFile.setShareViaLink(localFile.isSharedViaLink());
diff --git a/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/src/main/java/com/owncloud/android/operations/UploadFileOperation.java
index 4f2d5b6d25..dbb95947ee 100644
--- a/src/main/java/com/owncloud/android/operations/UploadFileOperation.java
+++ b/src/main/java/com/owncloud/android/operations/UploadFileOperation.java
@@ -35,7 +35,6 @@ import com.owncloud.android.datamodel.DecryptedFolderMetadata;
import com.owncloud.android.datamodel.EncryptedFolderMetadata;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.db.OCUpload;
import com.owncloud.android.files.services.FileUploader;
@@ -59,6 +58,7 @@ import com.owncloud.android.lib.resources.files.UpdateMetadataOperation;
import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
import com.owncloud.android.operations.common.SyncOperation;
import com.owncloud.android.utils.ConnectivityUtils;
+import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.EncryptionUtils;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.MimeType;
@@ -1332,16 +1332,13 @@ public class UploadFileOperation extends SyncOperation {
// coincidence; nothing else is needed, the storagePath is right
// in the instance returned by mCurrentUpload.getFile()
}
- file.setNeedsUpdateThumbnail(true);
getStorageManager().saveFile(file);
getStorageManager().saveConflict(file, null);
FileDataStorageManager.triggerMediaScan(file.getStoragePath());
// generate new Thumbnail
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(getStorageManager(), mAccount);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
+ DisplayUtils.generateThumbnail(file, mOriginalStoragePath, getContext());
}
private void updateOCFile(OCFile file, RemoteFile remoteFile) {
@@ -1352,6 +1349,7 @@ public class UploadFileOperation extends SyncOperation {
file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp());
file.setEtag(remoteFile.getEtag());
file.setRemoteId(remoteFile.getRemoteId());
+ file.setEtagOnServer(remoteFile.getEtag());
}
public interface OnRenameListener {
diff --git a/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java b/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java
deleted file mode 100644
index 3759086b78..0000000000
--- a/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Nextcloud Android client application
- *
- * @author Tobias Kaminsky
- * Copyright (C) 2017 Tobias Kaminsky
- * Copyright (C) 2017 Nextcloud GmbH.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.owncloud.android.providers;
-
-import android.accounts.Account;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-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 android.support.annotation.NonNull;
-
-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;
-
-public class DiskLruImageCacheFileProvider extends ContentProvider {
- public static final String TAG = DiskLruImageCacheFileProvider.class.getSimpleName();
-
- @Override
- public boolean onCreate() {
- return true;
- }
-
- private OCFile getFile(Uri uri) {
- Account account = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
- FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(account,
- MainApp.getAppContext().getContentResolver());
-
- return fileDataStorageManager.getFileByPath(uri.getPath());
- }
-
- @Override
- public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
- OCFile ocFile = getFile(uri);
-
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + ocFile.getRemoteId()));
-
- // fallback to thumbnail
- if (thumbnail == null) {
- thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + ocFile.getRemoteId()));
- }
-
- // fallback to default image
- if (thumbnail == null) {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
-
- // 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
- try (FileOutputStream fos = new FileOutputStream(f)){
- fos.write(bitmapData);
- } catch (FileNotFoundException e) {
- Log_OC.e(TAG, "File not found: " + e.getMessage());
- }
-
- } catch (Exception e) {
- Log_OC.e(TAG, "Error opening file: " + e.getMessage());
- }
-
- return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
- }
-
- @Override
- public String getType(@NonNull Uri uri) {
- OCFile ocFile = getFile(uri);
- return ocFile.getMimeType();
- }
-
- @Override
- public Cursor query(@NonNull 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(@NonNull Uri uri, ContentValues values) {
- return null;
- }
-
- @Override
- public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- return 0;
- }
-}
diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java
index 2c2770c248..75f514e7bd 100644
--- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java
+++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java
@@ -84,7 +84,7 @@ public class FileContentProvider extends ContentProvider {
private static final String TEXT = " TEXT, ";
private static final String ALTER_TABLE = "ALTER TABLE ";
private static final String ADD_COLUMN = " ADD COLUMN ";
- private static final String REMOVE_COLUMN = " REMOVE COLUMN ";
+ private static final String REMOVE_COLUMN = " DROP COLUMN ";
private static final String UPGRADE_VERSION_MSG = "OUT of the ADD in onUpgrade; oldVersion == %d, newVersion == %d";
private static final int SINGLE_PATH_SEGMENT = 1;
public static final int ARBITRARY_DATA_TABLE_INTRODUCTION_VERSION = 20;
@@ -738,11 +738,11 @@ public class FileContentProvider extends ContentProvider {
+ ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + INTEGER
+ ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA + INTEGER
+ ProviderTableMeta.FILE_ETAG + TEXT
+ + ProviderTableMeta.FILE_ETAG_ON_SERVER + 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_FAVORITE + INTEGER // boolean
+ ProviderTableMeta.FILE_IS_ENCRYPTED + INTEGER // boolean
@@ -1745,6 +1745,24 @@ public class FileContentProvider extends ContentProvider {
if (!upgraded) {
Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
}
+
+ if (oldVersion < 35 && newVersion >= 35) {
+ Log_OC.i(SQL, "Entering in the #35 add eTagOnServer");
+ db.beginTransaction();
+ try {
+ db.execSQL(ALTER_TABLE + ProviderTableMeta.FILE_TABLE_NAME +
+ ADD_COLUMN + ProviderTableMeta.FILE_ETAG_ON_SERVER + " TEXT ");
+
+ upgraded = true;
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ if (!upgraded) {
+ Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion));
+ }
}
@Override
diff --git a/src/main/java/com/owncloud/android/ui/CustomPopup.java b/src/main/java/com/owncloud/android/ui/CustomPopup.java
index 5eea6d4a35..a4c8b55149 100644
--- a/src/main/java/com/owncloud/android/ui/CustomPopup.java
+++ b/src/main/java/com/owncloud/android/ui/CustomPopup.java
@@ -32,6 +32,8 @@ import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.PopupWindow;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
/**
* Represents a custom PopupWindows
*/
@@ -121,6 +123,7 @@ public class CustomPopup {
showLikeQuickAction(0, 0);
}
+ @SuppressFBWarnings("CLI")
public void showLikeQuickAction(int x, int y) {
preShow();
diff --git a/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java
index 08901133a1..6e8427a3a8 100644
--- a/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java
@@ -39,6 +39,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
@@ -56,9 +57,8 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
@@ -94,6 +94,7 @@ import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.DrawerMenuUtil;
import com.owncloud.android.utils.FilesSyncHelper;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideKey;
import com.owncloud.android.utils.svg.MenuSimpleTarget;
import org.greenrobot.eventbus.EventBus;
@@ -630,11 +631,8 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
// activate second/end account avatar
if (mAvatars[1] != null) {
- View accountEndView = findNavigationViewChildById(R.id.drawer_account_end);
- accountEndView.setTag(mAvatars[1].name);
-
- DisplayUtils.setAvatar(mAvatars[1], this, mOtherAccountAvatarRadiusDimension, getResources(),
- accountEndView, this);
+ ImageView accountEndView = (ImageView) findNavigationViewChildById(R.id.drawer_account_end);
+ DisplayUtils.setAvatar(mAvatars[1], this, accountEndView, mOtherAccountAvatarRadiusDimension);
mAccountEndAccountAvatar.setVisibility(View.VISIBLE);
} else {
mAccountEndAccountAvatar.setVisibility(View.GONE);
@@ -642,11 +640,8 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
// activate third/middle account avatar
if (mAvatars[2] != null) {
- View accountMiddleView = findNavigationViewChildById(R.id.drawer_account_middle);
- accountMiddleView.setTag(mAvatars[2].name);
-
- DisplayUtils.setAvatar(mAvatars[2], this, mOtherAccountAvatarRadiusDimension, getResources(),
- accountMiddleView, this);
+ ImageView accountMiddleView = (ImageView) findNavigationViewChildById(R.id.drawer_account_middle);
+ DisplayUtils.setAvatar(mAvatars[2], this, accountMiddleView, mOtherAccountAvatarRadiusDimension);
mAccountMiddleAccountAvatar.setVisibility(View.VISIBLE);
} else {
mAccountMiddleAccountAvatar.setVisibility(View.GONE);
@@ -666,12 +661,11 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
private void repopulateAccountList(List<Account> accounts) {
// remove all accounts from list
mNavigationView.getMenu().removeGroup(R.id.drawer_menu_accounts);
-
+ SimpleTarget<Drawable> menuTarget;
// add all accounts to list
for (Account account: accounts) {
try {
// show all accounts except the currently active one and those pending for removal
-
if (!getAccount().name.equals(account.name)) {
MenuItem accountMenuItem = mNavigationView.getMenu().add(
R.id.drawer_menu_accounts,
@@ -679,8 +673,16 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
MENU_ORDER_ACCOUNT,
account.name)
.setIcon(TextDrawable.createAvatar(account.name, mMenuAccountAvatarRadiusDimension));
- DisplayUtils.setAvatar(account, this, mMenuAccountAvatarRadiusDimension, getResources(),
- accountMenuItem, this);
+
+ menuTarget = new SimpleTarget<Drawable>() {
+ @Override
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
+ accountMenuItem.setIcon(resource);
+ }
+ };
+
+ DisplayUtils.setAvatar(account, this, menuTarget, mMenuAccountAvatarRadiusDimension);
}
} catch (Exception e) {
Log_OC.e(TAG, "Error calculating RGB value for account menu item.", e);
@@ -748,11 +750,9 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
username.setText(AccountUtils.getAccountUsername(account.name));
}
- View currentAccountView = findNavigationViewChildById(R.id.drawer_current_account);
- currentAccountView.setTag(account.name);
+ ImageView currentAccountView = (ImageView) findNavigationViewChildById(R.id.drawer_current_account);
- DisplayUtils.setAvatar(account, this, mCurrentAccountAvatarRadiusDimension, getResources(),
- currentAccountView, this);
+ DisplayUtils.setAvatar(account, this, currentAccountView, mCurrentAccountAvatarRadiusDimension);
// check and show quota info if available
getAndDisplayUserQuota();
@@ -862,31 +862,26 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
mQuotaTextLink.setText(firstQuota.name);
mQuotaTextLink.setClickable(true);
mQuotaTextLink.setVisibility(View.VISIBLE);
- mQuotaTextLink.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent externalWebViewIntent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
- externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, firstQuota.name);
- externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_URL, firstQuota.url);
- externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, true);
- externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_MENU_ITEM_ID, -1);
- startActivity(externalWebViewIntent);
- }
+ mQuotaTextLink.setOnClickListener(v -> {
+ Intent externalWebViewIntent = new Intent(getApplicationContext(), ExternalSiteWebView.class);
+ externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_TITLE, firstQuota.name);
+ externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_URL, firstQuota.url);
+ externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_SHOW_SIDEBAR, true);
+ externalWebViewIntent.putExtra(ExternalSiteWebView.EXTRA_MENU_ITEM_ID, -1);
+ startActivity(externalWebViewIntent);
});
-
- SimpleTarget target = new SimpleTarget<Drawable>() {
+ SimpleTarget<Drawable> target = new SimpleTarget<Drawable>() {
@Override
- public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
Drawable test = resource.getCurrent();
test.setBounds(0, 0, size, size);
mQuotaTextLink.setCompoundDrawablesWithIntrinsicBounds(test, null, null, null);
}
@Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
- super.onLoadFailed(e, errorDrawable);
-
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
Drawable test = errorDrawable.getCurrent();
test.setBounds(0, 0, size, size);
@@ -894,8 +889,8 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
}
};
- DisplayUtils.downloadIcon(this, firstQuota.iconUrl, target, R.drawable.ic_link_grey, size, size);
-
+ DisplayUtils.downloadIcon(this, firstQuota.iconUrl, target, R.drawable.ic_link_grey,
+ R.drawable.ic_link_grey);
} else {
mQuotaTextLink.setVisibility(View.GONE);
}
@@ -1018,28 +1013,28 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
mNavigationView.getMenu().removeGroup(R.id.drawer_menu_external_links);
float density = getResources().getDisplayMetrics().density;
- final int size = Math.round(24 * density);
int greyColor = getResources().getColor(R.color.standard_grey);
+ MenuSimpleTarget<Drawable> target;
for (final ExternalLink link : externalLinksProvider.getExternalLink(ExternalLinkType.LINK)) {
int id = mNavigationView.getMenu().add(R.id.drawer_menu_external_links,
MENU_ITEM_EXTERNAL_LINK + link.id, MENU_ORDER_EXTERNAL_LINKS, link.name)
.setCheckable(true).getItemId();
- MenuSimpleTarget target = new MenuSimpleTarget<Drawable>(id) {
+ target = new MenuSimpleTarget<Drawable>(id) {
@Override
- public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
setExternalLinkIcon(getIdMenuItem(), resource, greyColor);
}
@Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
- super.onLoadFailed(e, errorDrawable);
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
setExternalLinkIcon(getIdMenuItem(), errorDrawable, greyColor);
}
};
- DisplayUtils.downloadIcon(this, link.iconUrl, target, R.drawable.ic_link_grey, size, size);
+ DisplayUtils.downloadIcon(this, link.iconUrl, target, R.drawable.ic_link_grey, R.drawable.ic_link_grey);
}
setDrawerMenuItemChecked(mCheckedMenuItem);
@@ -1083,16 +1078,17 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
// use url
if (URLUtil.isValidUrl(background) || background.isEmpty()) {
// background image
- SimpleTarget target = new SimpleTarget<Drawable>() {
+ SimpleTarget<Drawable> target = new SimpleTarget<Drawable>() {
@Override
- public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
Drawable[] drawables = {new ColorDrawable(primaryColor), resource};
LayerDrawable layerDrawable = new LayerDrawable(drawables);
setNavigationHeaderBackground(layerDrawable, navigationHeader);
}
@Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
Drawable[] drawables = {new ColorDrawable(primaryColor), errorDrawable};
LayerDrawable layerDrawable = new LayerDrawable(drawables);
setNavigationHeaderBackground(layerDrawable, navigationHeader);
@@ -1107,13 +1103,8 @@ public abstract class DrawerActivity extends ToolbarActivity implements DisplayU
backgroundResource = R.drawable.background;
}
- Glide.with(this)
- .load(background)
- .centerCrop()
- .placeholder(backgroundResource)
- .error(backgroundResource)
- .crossFade()
- .into(target);
+ DisplayUtils.downloadImage(background, backgroundResource, backgroundResource, target,
+ GlideKey.url(background), this);
} else {
// plain color
setNavigationHeaderBackground(new ColorDrawable(primaryColor), navigationHeader);
diff --git a/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
index 835a2f2b21..c81fdc25da 100644
--- a/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
@@ -441,7 +441,7 @@ public class FileDisplayActivity extends HookActivity
setFile(file);
if (mAccountWasSet) {
- setAccountInDrawer(getAccount());
+ // setAccountInDrawer(getAccount()); // no need to call this here, as updateAccountList will be used
setupDrawer();
}
diff --git a/src/main/java/com/owncloud/android/ui/activity/ManageSpaceActivity.java b/src/main/java/com/owncloud/android/ui/activity/ManageSpaceActivity.java
index 56247affd1..c1ae3c50c7 100644
--- a/src/main/java/com/owncloud/android/ui/activity/ManageSpaceActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/ManageSpaceActivity.java
@@ -58,7 +58,7 @@ public class ManageSpaceActivity extends AppCompatActivity {
clearDataButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- ClearDataAsynTask clearDataTask = new ClearDataAsynTask();
+ ClearDataAsyncTask clearDataTask = new ClearDataAsyncTask();
clearDataTask.execute();
}
});
@@ -82,7 +82,7 @@ public class ManageSpaceActivity extends AppCompatActivity {
/**
* AsyncTask for Clear Data, saving the passcode
*/
- private class ClearDataAsynTask extends AsyncTask<Void, Void, Boolean>{
+ private class ClearDataAsyncTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... params) {
diff --git a/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java b/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java
index be7eb670c3..8ddd6fd56c 100755
--- a/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/ReceiveExternalFilesActivity.java
@@ -776,7 +776,7 @@ public class ReceiveExternalFilesActivity extends FileActivity
R.layout.uploader_list_item_layout,
new String[]{"dirname"},
new int[]{R.id.filename},
- getStorageManager(), getAccount());
+ getAccount());
mListView.setAdapter(sa);
}
diff --git a/src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java b/src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java
index 2a3abdeb43..602062fc41 100644
--- a/src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java
+++ b/src/main/java/com/owncloud/android/ui/activity/UserInfoActivity.java
@@ -56,9 +56,8 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
import com.google.gson.Gson;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
@@ -68,11 +67,13 @@ import com.owncloud.android.lib.common.UserInfo;
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.status.OwnCloudVersion;
import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation;
import com.owncloud.android.ui.events.TokenPushEvent;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.PushUtils;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideKey;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -221,34 +222,38 @@ public class UserInfoActivity extends FileActivity {
ImageView backgroundImageView = appBar.findViewById(R.id.drawer_header_background);
String background = getStorageManager().getCapability(account.name).getServerBackground();
- int primaryColor = ThemeUtils.primaryColor(getAccount(), false, this);
+ int primaryColor = ThemeUtils.primaryColor(account, false, this);
if (URLUtil.isValidUrl(background)) {
+ Drawable backgroundResource;
+ OwnCloudVersion ownCloudVersion = AccountUtils.getServerVersion(account);
+ if (ownCloudVersion.compareTo(OwnCloudVersion.nextcloud_13) >= 0) {
+ backgroundResource = getResources().getDrawable(R.drawable.background_nc13);
+ } else {
+ backgroundResource = getResources().getDrawable(R.drawable.background);
+ }
+
// background image
- SimpleTarget target = new SimpleTarget<Drawable>() {
+ SimpleTarget<Drawable> target = new SimpleTarget<Drawable>() {
@Override
- public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
Drawable[] drawables = {new ColorDrawable(primaryColor), resource};
LayerDrawable layerDrawable = new LayerDrawable(drawables);
backgroundImageView.setImageDrawable(layerDrawable);
}
@Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
Drawable[] drawables = {new ColorDrawable(primaryColor),
- getResources().getDrawable(R.drawable.background)};
+ backgroundResource};
LayerDrawable layerDrawable = new LayerDrawable(drawables);
backgroundImageView.setImageDrawable(layerDrawable);
}
};
- Glide.with(this)
- .load(background)
- .centerCrop()
- .placeholder(R.drawable.background)
- .error(R.drawable.background)
- .crossFade()
- .into(target);
+ DisplayUtils.downloadImage(background, R.drawable.background, R.drawable.background, target,
+ GlideKey.url(background), this);
} else {
// plain color
backgroundImageView.setImageDrawable(new ColorDrawable(primaryColor));
@@ -259,8 +264,8 @@ public class UserInfoActivity extends FileActivity {
private void populateUserInfoUi(UserInfo userInfo) {
userName.setText(account.name);
- avatar.setTag(account.name);
- DisplayUtils.setAvatar(account, this, mCurrentAccountAvatarRadiusDimension, getResources(), avatar, this);
+
+ DisplayUtils.setAvatar(account, this, avatar, mCurrentAccountAvatarRadiusDimension);
int tint = ThemeUtils.primaryColor(account, true, this);
@@ -485,6 +490,7 @@ public class UserInfoActivity extends FileActivity {
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
View view = inflater.inflate(R.layout.user_info_details_table_item, parent, false);
+
return new ViewHolder(view);
}
diff --git a/src/main/java/com/owncloud/android/ui/adapter/AccountListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/AccountListAdapter.java
index 34b1159ada..35763cafd1 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/AccountListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/AccountListAdapter.java
@@ -3,16 +3,16 @@
*
* @author Andy Scherzinger
* Copyright (C) 2016 ownCloud Inc.
- * <p/>
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
- * <p/>
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- * <p/>
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -155,10 +155,7 @@ public class AccountListAdapter extends ArrayAdapter<AccountListItem> implements
private void setAvatar(AccountViewHolderItem viewHolder, Account account) {
try {
- View viewItem = viewHolder.imageViewItem;
- viewItem.setTag(account.name);
- DisplayUtils.setAvatar(account, this, mAccountAvatarRadiusDimension, mContext.getResources(), viewItem,
- mContext);
+ DisplayUtils.setAvatar(account, mContext, viewHolder.imageViewItem, mAccountAvatarRadiusDimension);
} catch (Exception e) {
Log_OC.e(TAG, "Error calculating RGB value for account list item.", e);
// use user icon as a fallback
diff --git a/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java
index 7bbf165e48..aec89ac31e 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/ActivityListAdapter.java
@@ -22,8 +22,6 @@ package com.owncloud.android.ui.adapter;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
-import android.graphics.drawable.PictureDrawable;
-import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.Spannable;
@@ -44,12 +42,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.bumptech.glide.GenericRequestBuilder;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
-import com.bumptech.glide.load.model.StreamEncoder;
-import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
-import com.caverock.androidsvg.SVG;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -63,12 +55,7 @@ import com.owncloud.android.lib.resources.files.FileUtils;
import com.owncloud.android.ui.interfaces.ActivityListInterface;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimeTypeUtil;
-import com.owncloud.android.utils.glide.CustomGlideStreamLoader;
-import com.owncloud.android.utils.svg.SvgDecoder;
-import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
-import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -175,7 +162,8 @@ public class ActivityListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
if (!TextUtils.isEmpty(activity.getIcon())) {
- downloadIcon(activity.getIcon(), activityViewHolder.activityIcon);
+ DisplayUtils.downloadSVG(activity.getIcon(), R.drawable.ic_activity_light_grey,
+ R.drawable.ic_activity_light_grey, activityViewHolder.activityIcon, context);
}
if (activity.getRichSubjectElement() != null &&
@@ -240,20 +228,11 @@ public class ActivityListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
// No Folder
if (!file.isFolder()) {
if (MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) {
- int placeholder;
-
- if (MimeTypeUtil.isImage(file)) {
- placeholder = R.drawable.file_image;
+ if (TextUtils.isEmpty(file.getEtag())) {
+ DisplayUtils.downloadActivityThumbnail(file, fileIcon, client, context);
} else {
- placeholder = R.drawable.file_movie;
+ DisplayUtils.downloadThumbnail(file, fileIcon, client, context);
}
-
- String uri = client.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + px + "/" + px +
- Uri.encode(file.getRemotePath(), "/");
-
- Glide.with(context).using(new CustomGlideStreamLoader()).load(uri).placeholder(placeholder)
- .error(placeholder).into(fileIcon); // using custom fetcher
-
} else {
if (isDetailView) {
fileIcon.setVisibility(View.GONE);
@@ -274,27 +253,6 @@ public class ActivityListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
- private void downloadIcon(String icon, ImageView itemViewType) {
- GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(context)
- .using(Glide.buildStreamModelLoader(Uri.class, context), InputStream.class)
- .from(Uri.class)
- .as(SVG.class)
- .transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
- .sourceEncoder(new StreamEncoder())
- .cacheDecoder(new FileToStreamDecoder<>(new SvgDecoder()))
- .decoder(new SvgDecoder())
- .placeholder(R.drawable.ic_activity)
- .error(R.drawable.ic_activity)
- .animate(android.R.anim.fade_in)
- .listener(new SvgSoftwareLayerSetter<>());
-
- Uri uri = Uri.parse(icon);
- requestBuilder
- .diskCacheStrategy(DiskCacheStrategy.SOURCE)
- .load(uri)
- .into(itemViewType);
- }
-
private SpannableStringBuilder addClickablePart(RichElement richElement) {
String text = richElement.getRichSubject();
SpannableStringBuilder ssb = new SpannableStringBuilder(text);
diff --git a/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
index 1702e39b94..a55b19fa8f 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java
@@ -23,7 +23,6 @@ package com.owncloud.android.ui.adapter;
import android.content.Context;
import android.content.res.Resources;
import android.database.DataSetObserver;
-import android.graphics.Bitmap;
import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
@@ -37,7 +36,6 @@ import android.widget.ListView;
import android.widget.TextView;
import com.owncloud.android.R;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.interfaces.LocalFileListFragmentInterface;
@@ -45,6 +43,7 @@ import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileSortOrder;
import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideKey;
import java.io.File;
import java.util.ArrayList;
@@ -192,9 +191,14 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View
gridViewHolder.checkbox.setImageResource(R.drawable.ic_checkbox_blank_outline);
}
- gridViewHolder.thumbnail.setTag(file.hashCode());
setThumbnail(file, gridViewHolder.thumbnail);
+ if (MimeTypeUtil.isVideo(file)) {
+ gridViewHolder.playIcon.setVisibility(View.VISIBLE);
+ } else {
+ gridViewHolder.playIcon.setVisibility(View.GONE);
+ }
+
if (file.isDirectory()) {
gridViewHolder.checkbox.setVisibility(View.GONE);
} else {
@@ -236,45 +240,10 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View
if (file.isDirectory()) {
thumbnailView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(mContext));
} else {
- thumbnailView.setImageResource(R.drawable.file);
-
- /* Cancellation needs do be checked and done before changing the drawable in fileIcon, or
- * {@link ThumbnailsCacheManager#cancelPotentialThumbnailWork} will NEVER cancel any task.
- */
- boolean allowedToCreateNewThumbnail = ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailView);
-
-
- // get Thumbnail if file is image
- if (MimeTypeUtil.isImage(file)) {
- // Thumbnail in Cache?
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.hashCode()
- );
- if (thumbnail != null) {
- thumbnailView.setImageBitmap(thumbnail);
- } else {
-
- // generate new Thumbnail
- if (allowedToCreateNewThumbnail) {
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(thumbnailView);
- if (MimeTypeUtil.isVideo(file)) {
- thumbnail = ThumbnailsCacheManager.mDefaultVideo;
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
- final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncThumbnailDrawable(
- mContext.getResources(),
- thumbnail,
- task
- );
- thumbnailView.setImageDrawable(asyncDrawable);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, null));
- Log_OC.v(TAG, "Executing task to generate a new thumbnail");
-
- } // else, already being generated, don't restart it
- }
+ if (MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) {
+ int placeholder = MimeTypeUtil.isImage(file) ? R.drawable.file_image : R.drawable.file_movie;
+ DisplayUtils.localImage(file, placeholder, placeholder, thumbnailView, GlideKey.localFile(file),
+ mContext);
} else {
thumbnailView.setImageDrawable(MimeTypeUtil.getFileTypeIcon(null, file.getName(), mContext));
}
@@ -544,6 +513,7 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View
private final TextView fileName;
private final ImageView checkbox;
private final LinearLayout itemLayout;
+ private final ImageView playIcon;
private LocalFileListGridViewHolder(View itemView) {
super(itemView);
@@ -552,6 +522,7 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View
fileName = itemView.findViewById(R.id.Filename);
checkbox = itemView.findViewById(R.id.custom_checkbox);
itemLayout = itemView.findViewById(R.id.ListItemLayout);
+ playIcon = itemView.findViewById(R.id.play_icon);
itemView.findViewById(R.id.sharedIcon).setVisibility(View.GONE);
itemView.findViewById(R.id.favorite_action).setVisibility(View.GONE);
diff --git a/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java
index dde75dc80b..19214a4eb6 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/NotificationListAdapter.java
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
-import android.graphics.drawable.PictureDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
@@ -41,12 +40,6 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.bumptech.glide.GenericRequestBuilder;
-import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
-import com.bumptech.glide.load.model.StreamEncoder;
-import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
-import com.caverock.androidsvg.SVG;
import com.owncloud.android.R;
import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.operations.RemoteOperation;
@@ -57,9 +50,6 @@ import com.owncloud.android.lib.resources.notifications.models.RichObject;
import com.owncloud.android.ui.activity.NotificationsActivity;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.ThemeUtils;
-import com.owncloud.android.utils.svg.SvgDecoder;
-import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
-import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
@@ -68,7 +58,6 @@ import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@@ -130,7 +119,8 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
// Todo set proper action icon (to be clarified how to pick)
if (!TextUtils.isEmpty(notification.getIcon())) {
- downloadIcon(notification.getIcon(), holder.icon);
+ DisplayUtils.downloadSVG(notification.getIcon(), R.drawable.ic_notification, R.drawable.ic_notification,
+ holder.icon, notificationsActivity);
}
// add action buttons
@@ -237,28 +227,6 @@ public class NotificationListAdapter extends RecyclerView.Adapter<NotificationLi
}
}
- private void downloadIcon(String icon, ImageView itemViewType) {
- GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(notificationsActivity)
- .using(Glide.buildStreamModelLoader(Uri.class, notificationsActivity), InputStream.class)
- .from(Uri.class)
- .as(SVG.class)
- .transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
- .sourceEncoder(new StreamEncoder())
- .cacheDecoder(new FileToStreamDecoder<>(new SvgDecoder()))
- .decoder(new SvgDecoder())
- .placeholder(R.drawable.ic_notification)
- .error(R.drawable.ic_notification)
- .animate(android.R.anim.fade_in)
- .listener(new SvgSoftwareLayerSetter<>());
-
-
- Uri uri = Uri.parse(icon);
- requestBuilder
- .diskCacheStrategy(DiskCacheStrategy.SOURCE)
- .load(uri)
- .into(itemViewType);
- }
-
private void openLink(String link) {
notificationsActivity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(link)));
}
diff --git a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java
index c2048f51de..7a43d66a14 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java
@@ -21,16 +21,16 @@
package com.owncloud.android.ui.adapter;
-
import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Bitmap;
import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
@@ -41,16 +41,18 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.bumptech.glide.request.target.CustomViewTarget;
+import com.bumptech.glide.request.transition.Transition;
import com.owncloud.android.R;
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.datamodel.VirtualFolderType;
import com.owncloud.android.db.PreferenceManager;
import com.owncloud.android.db.ProviderMeta;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileUploader;
+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.common.utils.Log_OC;
@@ -88,6 +90,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
private final FileUploader.FileUploaderBinder uploaderBinder;
private final OperationsService.OperationsServiceBinder operationsServiceBinder;
private Context mContext;
+ private OwnCloudClient client;
private List<OCFile> mFiles = new ArrayList<>();
private List<OCFile> mFilesAll = new ArrayList<>();
private boolean mHideItemOptions;
@@ -107,15 +110,15 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
private static final int VIEWTYPE_ITEM = 1;
private static final int VIEWTYPE_IMAGE = 2;
- private List<ThumbnailsCacheManager.ThumbnailGenerationTask> asyncTasks = new ArrayList<>();
private boolean onlyOnDevice = false;
- public OCFileListAdapter(Context context, ComponentsGetter transferServiceGetter,
+ public OCFileListAdapter(Context context, OwnCloudClient client, ComponentsGetter transferServiceGetter,
OCFileListFragmentInterface ocFileListFragmentInterface, boolean argHideItemOptions,
boolean gridView) {
this.ocFileListFragmentInterface = ocFileListFragmentInterface;
mContext = context;
+ this.client = client;
mAccount = AccountUtils.getCurrentOwnCloudAccount(mContext);
mHideItemOptions = argHideItemOptions;
this.gridView = gridView;
@@ -124,9 +127,6 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
downloaderBinder = transferServiceGetter.getFileDownloaderBinder();
uploaderBinder = transferServiceGetter.getFileUploaderBinder();
operationsServiceBinder = transferServiceGetter.getOperationsServiceBinder();
-
- // initialise thumbnails cache on background thread
- new ThumbnailsCacheManager.InitDiskCacheTask().execute();
}
public boolean isMultiSelect() {
@@ -263,8 +263,13 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
boolean gridImage = MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file);
- gridViewHolder.thumbnail.setTag(file.getFileId());
- setThumbnail(file, gridViewHolder.thumbnail);
+ setThumbnail(file, gridViewHolder);
+
+ if (MimeTypeUtil.isVideo(file)) {
+ gridViewHolder.playIcon.setVisibility(View.VISIBLE);
+ } else {
+ gridViewHolder.playIcon.setVisibility(View.GONE);
+ }
if (isCheckedFile(file)) {
gridViewHolder.itemLayout.setBackgroundColor(mContext.getResources()
@@ -373,52 +378,42 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
}
}
- private void setThumbnail(OCFile file, ImageView thumbnailView) {
+ private void setThumbnail(OCFile file, OCFileListGridImageViewHolder gridImageViewHolder) {
+ ImageView thumbnailView = gridImageViewHolder.thumbnail;
+
if (file.isFolder()) {
thumbnailView.setImageDrawable(MimeTypeUtil.getFolderTypeIcon(file.isSharedWithMe() ||
file.isSharedWithSharee(), file.isSharedViaLink(), file.isEncrypted(), file.getMountType(),
mContext));
} else {
if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
- // Thumbnail in cache?
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.getRemoteId()
- );
-
- if (thumbnail != null && !file.needsUpdateThumbnail()) {
- if (MimeTypeUtil.isVideo(file)) {
- Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail);
- thumbnailView.setImageBitmap(withOverlay);
- } else {
- thumbnailView.setImageBitmap(thumbnail);
+
+ if (client == null) {
+ client = AccountUtils.getClientForCurrentAccount(mContext);
+ }
+
+ CustomViewTarget thumbnailTarget = new CustomViewTarget<ImageView, Drawable>(thumbnailView) {
+ @Override
+ protected void onResourceCleared(@Nullable Drawable placeholder) {
+ thumbnailView.setImageDrawable(placeholder);
}
- } else {
- // generate new thumbnail
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailView)) {
- try {
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(thumbnailView, mStorageManager,
- mAccount, asyncTasks);
-
- if (thumbnail == null) {
- if (MimeTypeUtil.isVideo(file)) {
- thumbnail = ThumbnailsCacheManager.mDefaultVideo;
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
- }
- final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncThumbnailDrawable(mContext.getResources(),
- thumbnail, task);
- thumbnailView.setImageDrawable(asyncDrawable);
- asyncTasks.add(task);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file,
- file.getRemoteId()));
- } catch (IllegalArgumentException e) {
- Log_OC.d(TAG, "ThumbnailGenerationTask : " + e.getMessage());
- }
+
+ @Override
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
+ int placeholder = MimeTypeUtil.isVideo(file) ? R.drawable.file_movie : R.drawable.file_image;
+ thumbnailView.setImageResource(placeholder);
+ gridImageViewHolder.playIcon.setVisibility(View.GONE);
+ }
+
+ @Override
+ public void onResourceReady(@NonNull Drawable resource,
+ @Nullable Transition<? super Drawable> transition) {
+ thumbnailView.setImageDrawable(resource);
}
- }
+
+ };
+
+ DisplayUtils.downloadThumbnail(file, thumbnailTarget, client, mContext);
if ("image/png".equalsIgnoreCase(file.getMimeType())) {
thumbnailView.setBackgroundColor(mContext.getResources().getColor(R.color.background_color));
@@ -789,20 +784,6 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
return ret;
}
- public void cancelAllPendingTasks() {
- for (ThumbnailsCacheManager.ThumbnailGenerationTask task : asyncTasks) {
- if (task != null) {
- task.cancel(true);
- if (task.getGetMethod() != null) {
- Log_OC.d(TAG, "cancel: abort get method directly");
- task.getGetMethod().abort();
- }
- }
- }
-
- asyncTasks.clear();
- }
-
public void setGridView(boolean bool) {
gridView = bool;
}
@@ -838,6 +819,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
private final ImageView localFileIndicator;
private final ImageView shared;
private final ImageView checkbox;
+ private final ImageView playIcon;
private final LinearLayout itemLayout;
private OCFileListGridImageViewHolder(View itemView) {
@@ -849,6 +831,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
localFileIndicator = itemView.findViewById(R.id.localFileIndicator);
shared = itemView.findViewById(R.id.sharedIcon);
checkbox = itemView.findViewById(R.id.custom_checkbox);
+ playIcon = itemView.findViewById(R.id.play_icon);
itemLayout = itemView.findViewById(R.id.ListItemLayout);
}
}
diff --git a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
index e7af2e555a..639963c851 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java
@@ -22,6 +22,7 @@
package com.owncloud.android.ui.adapter;
import android.content.Context;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
@@ -37,8 +38,10 @@ import com.afollestad.sectionedrecyclerview.SectionedViewHolder;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.MediaFolderType;
import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideKey;
import java.io.File;
import java.util.ArrayList;
@@ -179,21 +182,8 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SyncedFold
if (mSyncFolderItems.get(section).getFilePaths() != null) {
File file = new File(mSyncFolderItems.get(section).getFilePaths().get(relativePosition));
- ThumbnailsCacheManager.MediaThumbnailGenerationTask task =
- new ThumbnailsCacheManager.MediaThumbnailGenerationTask(holder.image, mContext);
-
- ThumbnailsCacheManager.AsyncMediaThumbnailDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncMediaThumbnailDrawable(
- mContext.getResources(),
- ThumbnailsCacheManager.mDefaultImg,
- task
- );
- holder.image.setImageDrawable(asyncDrawable);
-
- task.execute(file);
-
- // set proper tag
- holder.image.setTag(file.hashCode());
+ int placeholder = MimeTypeUtil.isImage(file) ? R.drawable.file_image : R.drawable.file_movie;
+ DisplayUtils.localImage(file, placeholder, placeholder, holder.image, GlideKey.localFile(file), mContext);
holder.itemView.setTag(relativePosition % mGridWidth);
@@ -208,8 +198,9 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter<SyncedFold
}
}
+ @NonNull
@Override
- public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ public MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(
viewType == VIEW_TYPE_HEADER ?
R.layout.synced_folders_item_header : R.layout.grid_sync_item, parent, false);
diff --git a/src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java
index edde6e2d3e..41e0589d6a 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/TrashbinListAdapter.java
@@ -23,7 +23,6 @@ package com.owncloud.android.ui.adapter;
import android.accounts.Account;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Bitmap;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@@ -35,15 +34,15 @@ import android.widget.TextView;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
-import com.owncloud.android.datamodel.FileDataStorageManager;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.db.PreferenceManager;
+import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.TrashbinFile;
import com.owncloud.android.ui.interfaces.TrashbinActivityInterface;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileSortOrder;
import com.owncloud.android.utils.MimeTypeUtil;
+import com.owncloud.android.utils.glide.GlideKey;
import java.util.ArrayList;
import java.util.List;
@@ -64,17 +63,15 @@ public class TrashbinListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
private List<TrashbinFile> files;
private Context context;
private Account account;
- private FileDataStorageManager storageManager;
+ private OwnCloudClient client;
- private List<ThumbnailsCacheManager.ThumbnailGenerationTask> asyncTasks = new ArrayList<>();
-
- public TrashbinListAdapter(TrashbinActivityInterface trashbinActivityInterface,
- FileDataStorageManager storageManager, Context context) {
+ public TrashbinListAdapter(TrashbinActivityInterface trashbinActivityInterface, Context context) {
this.files = new ArrayList<>();
this.trashbinActivityInterface = trashbinActivityInterface;
this.account = AccountUtils.getCurrentOwnCloudAccount(context);
- this.storageManager = storageManager;
this.context = context;
+
+ client = AccountUtils.getClientForCurrentAccount(context);
}
public void setTrashbinFiles(List<Object> trashbinFiles, boolean clear) {
@@ -113,7 +110,6 @@ public class TrashbinListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
trashbinFileViewHolder.itemLayout.setOnClickListener(v -> trashbinActivityInterface.onItemClicked(file));
// thumbnail
- trashbinFileViewHolder.thumbnail.setTag(file.getRemoteId());
setThumbnail(file, trashbinFileViewHolder.thumbnail);
// fileName
@@ -208,42 +204,21 @@ public class TrashbinListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
if (file.isFolder()) {
thumbnailView.setImageDrawable(MimeTypeUtil.getDefaultFolderIcon(context));
} else {
- if ((MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file)) && file.getRemoteId() != null) {
- // Thumbnail in cache?
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.getRemoteId()
- );
-
- if (thumbnail != null) {
- if (MimeTypeUtil.isVideo(file)) {
- Bitmap withOverlay = ThumbnailsCacheManager.addVideoOverlay(thumbnail);
- thumbnailView.setImageBitmap(withOverlay);
- } else {
- thumbnailView.setImageBitmap(thumbnail);
- }
- } else {
- // generate new thumbnail
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailView)) {
- try {
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(thumbnailView, storageManager,
- account, asyncTasks);
-
- final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncThumbnailDrawable(context.getResources(),
- thumbnail, task);
- thumbnailView.setImageDrawable(asyncDrawable);
- asyncTasks.add(task);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file,
- file.getRemoteId()));
- } catch (IllegalArgumentException e) {
- Log_OC.d(TAG, "ThumbnailGenerationTask : " + e.getMessage());
- }
- }
- }
+ if (MimeTypeUtil.isImageOrVideo(file)) {
+ try {
+ int placeholder = MimeTypeUtil.isImage(file) ? R.drawable.file_image : R.drawable.file_movie;
+
+ int px = DisplayUtils.getThumbnailDimension();
+
+ String url = DisplayUtils.getThumbnailUri(client, file, px);
+ DisplayUtils.downloadImage(url, placeholder, placeholder, thumbnailView, client,
+ GlideKey.trashbinThumbnail(file), context);
- if ("image/png".equalsIgnoreCase(file.getMimeType())) {
- thumbnailView.setBackgroundColor(context.getResources().getColor(R.color.background_color));
+ if ("image/png".equalsIgnoreCase(file.getMimeType())) {
+ thumbnailView.setBackgroundColor(context.getResources().getColor(R.color.background_color));
+ }
+ } catch (Exception e) {
+ Log_OC.e(TAG, e.getMessage());
}
} else {
thumbnailView.setImageDrawable(MimeTypeUtil.getFileTypeIcon(file.getMimeType(), file.getFileName(),
@@ -266,20 +241,6 @@ public class TrashbinListAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
return files.size() + 1;
}
- public void cancelAllPendingTasks() {
- for (ThumbnailsCacheManager.ThumbnailGenerationTask task : asyncTasks) {
- if (task != null) {
- task.cancel(true);
- if (task.getGetMethod() != null) {
- Log_OC.d(TAG, "cancel: abort get method directly");
- task.getGetMethod().abort();
- }
- }
- }
-
- asyncTasks.clear();
- }
-
public void setSortOrder(FileSortOrder sortOrder) {
PreferenceManager.setSortOrder(context, null, sortOrder);
files = sortOrder.sortTrashbinFiles(files);
diff --git a/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java
index 4c1298ce46..b61bfe6bd2 100755
--- a/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java
@@ -24,7 +24,6 @@ package com.owncloud.android.ui.adapter;
import android.accounts.Account;
import android.content.ActivityNotFoundException;
import android.content.Intent;
-import android.graphics.Bitmap;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.text.format.DateUtils;
@@ -42,17 +41,18 @@ import com.afollestad.sectionedrecyclerview.SectionedViewHolder;
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.datamodel.UploadsStorageManager;
import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus;
import com.owncloud.android.db.OCUpload;
import com.owncloud.android.db.UploadResult;
import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideKey;
import java.io.File;
import java.util.Arrays;
@@ -66,6 +66,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedViewHolder> {
private static final String TAG = UploadListAdapter.class.getSimpleName();
+ private OwnCloudClient client;
private ProgressListener mProgressListener;
@@ -130,6 +131,9 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
fixAndSortItems(mUploadsStorageManager.getFinishedUploadsForCurrentAccount());
}
};
+
+ client = AccountUtils.getClientForCurrentAccount(mParentActivity);
+
loadUploadItemsFromDb();
}
@@ -285,100 +289,31 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
});
}
} else {
- itemViewHolder.itemLayout.setOnClickListener(v ->
- onUploadItemClick(item));
+ itemViewHolder.itemLayout.setOnClickListener(v -> onUploadItemClick(item));
}
- // Set icon or thumbnail
- itemViewHolder.thumbnail.setImageResource(R.drawable.file);
-
- /*
- * Cancellation needs do be checked and done before changing the drawable in fileIcon, or
- * {@link ThumbnailsCacheManager#cancelPotentialWork} will NEVER cancel any task.
- */
- OCFile fakeFileToCheatThumbnailsCacheManagerInterface = new OCFile(item.getRemotePath());
- fakeFileToCheatThumbnailsCacheManagerInterface.setStoragePath(item.getLocalPath());
- fakeFileToCheatThumbnailsCacheManagerInterface.setMimetype(item.getMimeType());
-
- boolean allowedToCreateNewThumbnail = ThumbnailsCacheManager.cancelPotentialThumbnailWork(
- fakeFileToCheatThumbnailsCacheManagerInterface, itemViewHolder.thumbnail
- );
-
- // TODO this code is duplicated; refactor to a common place
- if (MimeTypeUtil.isImage(fakeFileToCheatThumbnailsCacheManagerInterface)
- && fakeFileToCheatThumbnailsCacheManagerInterface.getRemoteId() != null &&
- item.getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED) {
- // Thumbnail in Cache?
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(fakeFileToCheatThumbnailsCacheManagerInterface.getRemoteId())
- );
- if (thumbnail != null && !fakeFileToCheatThumbnailsCacheManagerInterface.needsUpdateThumbnail()) {
- itemViewHolder.thumbnail.setImageBitmap(thumbnail);
- } else {
- // generate new Thumbnail
- if (allowedToCreateNewThumbnail) {
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(
- itemViewHolder.thumbnail, mParentActivity.getStorageManager(), mParentActivity.getAccount()
- );
- if (thumbnail == null) {
- if (MimeTypeUtil.isVideo(fakeFileToCheatThumbnailsCacheManagerInterface)) {
- thumbnail = ThumbnailsCacheManager.mDefaultVideo;
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
- }
- final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncThumbnailDrawable(
- mParentActivity.getResources(),
- thumbnail,
- task
- );
- itemViewHolder.thumbnail.setImageDrawable(asyncDrawable);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(
- fakeFileToCheatThumbnailsCacheManagerInterface, null));
- }
- }
+ if (MimeTypeUtil.isImageOrVideo(new File(item.getLocalPath()))) {
+ if (item.getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED) {
- if ("image/png".equals(item.getMimeType())) {
- itemViewHolder.thumbnail.setBackgroundColor(mParentActivity.getResources()
- .getColor(R.color.background_color));
- }
+ OCFile file = mParentActivity.getStorageManager().getFileByPath(item.getRemotePath());
+ if (file != null) {
+ DisplayUtils.downloadThumbnail(file, itemViewHolder.thumbnail, client, mParentActivity);
+ }
- } else if (MimeTypeUtil.isImage(fakeFileToCheatThumbnailsCacheManagerInterface)) {
- File file = new File(item.getLocalPath());
- // Thumbnail in Cache?
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(file.hashCode()));
- if (thumbnail != null) {
- itemViewHolder.thumbnail.setImageBitmap(thumbnail);
} else {
- // generate new Thumbnail
- if (allowedToCreateNewThumbnail) {
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(itemViewHolder.thumbnail);
+ File file = new File(item.getLocalPath());
- if (MimeTypeUtil.isVideo(file)) {
- thumbnail = ThumbnailsCacheManager.mDefaultVideo;
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
+ int placeholder = MimeTypeUtil.isImage(new File(item.getLocalPath())) ?
+ R.drawable.file_image : R.drawable.file_movie;
+ DisplayUtils.localImage(file, placeholder, placeholder, itemViewHolder.thumbnail,
+ GlideKey.localFile(file), mParentActivity);
- final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncThumbnailDrawable(mParentActivity.getResources(), thumbnail,
- task);
-
- itemViewHolder.thumbnail.setImageDrawable(asyncDrawable);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, null));
- Log_OC.v(TAG, "Executing task to generate a new thumbnail");
+ if ("image/png".equalsIgnoreCase(item.getMimeType())) {
+ itemViewHolder.thumbnail.setBackgroundColor(mParentActivity.getResources()
+ .getColor(R.color.background_color));
}
}
-
- if ("image/png".equalsIgnoreCase(item.getMimeType())) {
- itemViewHolder.thumbnail.setBackgroundColor(mParentActivity.getResources()
- .getColor(R.color.background_color));
- }
} else {
itemViewHolder.thumbnail.setImageDrawable(MimeTypeUtil.getFileTypeIcon(item.getMimeType(), fileName,
account, mParentActivity));
diff --git a/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java
index 61368ab5fb..835ee6ee60 100644
--- a/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java
@@ -1,4 +1,4 @@
-/**
+/*
* ownCloud Android client application
*
* @author Tobias Kaminsky
@@ -22,7 +22,6 @@ package com.owncloud.android.ui.adapter;
import android.accounts.Account;
import android.content.Context;
-import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -31,10 +30,9 @@ import android.widget.SimpleAdapter;
import android.widget.TextView;
import com.owncloud.android.R;
-import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncThumbnailDrawable;
+import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimeTypeUtil;
@@ -43,21 +41,19 @@ import java.util.List;
import java.util.Map;
public class UploaderAdapter extends SimpleAdapter {
-
private Context mContext;
private Account mAccount;
- private FileDataStorageManager mStorageManager;
private LayoutInflater inflater;
+ private OwnCloudClient client;
public UploaderAdapter(Context context,
List<? extends Map<String, ?>> data, int resource, String[] from,
- int[] to, FileDataStorageManager storageManager, Account account) {
+ int[] to, Account account) {
super(context, data, resource, from, to);
mAccount = account;
- mStorageManager = storageManager;
mContext = context;
- inflater = (LayoutInflater) mContext
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ client = AccountUtils.getClientForCurrentAccount(context);
}
@Override
@@ -74,7 +70,6 @@ public class UploaderAdapter extends SimpleAdapter {
filename.setText(file.getFileName());
ImageView fileIcon = vi.findViewById(R.id.thumbnail);
- fileIcon.setTag(file.getFileId());
TextView lastModV = vi.findViewById(R.id.last_mod);
lastModV.setText(DisplayUtils.getRelativeTimestamp(mContext, file.getModificationTimestamp()));
@@ -97,35 +92,8 @@ public class UploaderAdapter extends SimpleAdapter {
file.getMountType(), mContext));
} else {
// get Thumbnail if file is image
- if (MimeTypeUtil.isImage(file) && file.getRemoteId() != null) {
- // Thumbnail in Cache?
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(file.getRemoteId())
- );
- if (thumbnail != null && !file.needsUpdateThumbnail()) {
- fileIcon.setImageBitmap(thumbnail);
- } else {
- // generate new Thumbnail
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
- final ThumbnailsCacheManager.ThumbnailGenerationTask task =
- new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, mStorageManager,
- mAccount);
- if (thumbnail == null) {
- if (MimeTypeUtil.isVideo(file)) {
- thumbnail = ThumbnailsCacheManager.mDefaultVideo;
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
- }
- final AsyncThumbnailDrawable asyncDrawable = new AsyncThumbnailDrawable(
- mContext.getResources(),
- thumbnail,
- task
- );
- fileIcon.setImageDrawable(asyncDrawable);
- task.execute(new ThumbnailsCacheManager.ThumbnailGenerationTaskObject(file, file.getRemoteId()));
- }
- }
+ if (MimeTypeUtil.isImageOrVideo(file)) {
+ DisplayUtils.downloadThumbnail(file, fileIcon, client, mContext);
} else {
fileIcon.setImageDrawable(
MimeTypeUtil.getFileTypeIcon(file.getMimeType(), file.getFileName(), mAccount, mContext)
@@ -135,6 +103,4 @@ public class UploaderAdapter extends SimpleAdapter {
return vi;
}
-
-
}
diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
index e7122cfcd1..34450b3c20 100644
--- a/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
+++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailFragment.java
@@ -25,6 +25,9 @@ package com.owncloud.android.ui.fragment;
import android.accounts.Account;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -42,14 +45,20 @@ import android.widget.PopupMenu;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
+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.files.FileMenuFilter;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
+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.network.OnDatatransferProgressListener;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.FileActivity;
@@ -61,8 +70,12 @@ import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideApp;
+import com.owncloud.android.utils.glide.GlideContainer;
+import com.owncloud.android.utils.glide.GlideKey;
import java.lang.ref.WeakReference;
+import java.net.URLEncoder;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -552,56 +565,86 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
* @param file a {@link OCFile} to be previewed
*/
private void setFilePreview(OCFile file) {
- Bitmap resizedImage;
- if (MimeTypeUtil.isImage(file) && activity != null) {
- String tagId = String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId());
- resizedImage = ThumbnailsCacheManager.getBitmapFromDiskCache(tagId);
+ if (MimeTypeUtil.isImage(file) && activity != null && activity.getPreviewImageView() != null) {
+ try {
+ Account account = AccountUtils.getCurrentOwnCloudAccount(getContext());
+ OwnCloudAccount ocAccount = new OwnCloudAccount(account, MainApp.getAppContext());
+
+ OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+ getClientFor(ocAccount, MainApp.getAppContext());
+
+ int thumbnailW = DisplayUtils.getThumbnailDimension();
+ int thumbnailH = DisplayUtils.getThumbnailDimension();
- if (resizedImage != null && !file.needsUpdateThumbnail()) {
- activity.setPreviewImageBitmap(resizedImage);
activatePreviewImage();
previewLoaded = true;
- } else {
- // show thumbnail while loading resized image
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId()));
- if (thumbnail != null) {
- activity.setPreviewImageBitmap(thumbnail);
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
-
- // generate new resized image
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(getFile(), activity.getPreviewImageView()) &&
- mContainerActivity.getStorageManager() != null) {
- final ThumbnailsCacheManager.ResizedImageGenerationTask task =
- new ThumbnailsCacheManager.ResizedImageGenerationTask(this,
- activity.getPreviewImageView(),
- mContainerActivity.getStorageManager(),
- mContainerActivity.getStorageManager().getAccount());
-
- if (resizedImage == null) {
- resizedImage = thumbnail;
- }
-
- final ThumbnailsCacheManager.AsyncResizedImageDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncResizedImageDrawable(
- MainApp.getAppContext().getResources(),
- resizedImage,
- task
- );
-
- activity.setPreviewImageDrawable(asyncDrawable);
- activatePreviewImage();
- previewLoaded = true;
- task.execute(getFile());
- }
+ // Thumbnail
+ GlideContainer container = new GlideContainer();
+ int placeholder = MimeTypeUtil.isVideo(getFile()) ? R.drawable.file_movie : R.drawable.file_image;
+
+ container.url = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" +
+ thumbnailW + "/" + thumbnailH + Uri.encode(getFile().getRemotePath(), "/");
+ container.client = mClient;
+ container.key = GlideKey.serverThumbnail(getFile());
+
+ // resized image
+ GlideContainer containerResizedImage = new GlideContainer();
+
+ Point p = DisplayUtils.getScreenDimension();
+ int pxW = p.x;
+ int pxH = p.y;
+
+ containerResizedImage.url = mClient.getBaseUri() + "/index.php/core/preview.png?file="
+ + URLEncoder.encode(getFile().getRemotePath())
+ + "&x=" + pxW + "&y=" + pxH + "&a=1&mode=cover&forceIcon=0";
+ containerResizedImage.key = GlideKey.resizedImage(getFile());
+ containerResizedImage.client = mClient;
+
+ GlideApp.with(requireContext())
+ .asBitmap()
+ .load(container)
+ .placeholder(placeholder)
+ .priority(Priority.IMMEDIATE)
+ .onlyRetrieveFromCache(true)
+ .into(new SimpleTarget<Bitmap>() {
+ @Override
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
+ activity.setPreviewImageDrawable(activity.getResources()
+ .getDrawable(placeholder));
+ loadResizedImage(containerResizedImage);
+ }
+
+ @Override
+ public void onResourceReady(@NonNull Bitmap resource,
+ @Nullable Transition<? super Bitmap> transition) {
+ activity.setPreviewImageBitmap(resource);
+ loadResizedImage(containerResizedImage);
+ }
+ }
+ );
+ } catch (Exception e) {
+ Log_OC.e(TAG, e.getMessage());
}
}
}
+ private void loadResizedImage(GlideContainer containerResizedImage) {
+ GlideApp.with(requireContext())
+ .asBitmap()
+ .load(containerResizedImage)
+ .priority(Priority.IMMEDIATE)
+ .into(new SimpleTarget<Bitmap>() {
+ @Override
+ public void onResourceReady(@NonNull Bitmap resource,
+ @Nullable Transition<? super Bitmap> transition) {
+ activity.setPreviewImageBitmap(resource);
+ }
+ }
+ );
+ }
+
/**
* Enables or disables buttons for a file being downloaded
*/
diff --git a/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
index 72a57313ab..a6a2d98b91 100644
--- a/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
+++ b/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java
@@ -25,8 +25,6 @@ package com.owncloud.android.ui.fragment;
import android.accounts.Account;
import android.accounts.AccountManager;
-import android.accounts.AuthenticatorException;
-import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -68,9 +66,7 @@ import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.VirtualFolderType;
import com.owncloud.android.db.PreferenceManager;
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.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC;
@@ -113,7 +109,6 @@ import org.greenrobot.eventbus.ThreadMode;
import org.parceler.Parcels;
import java.io.File;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -175,6 +170,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
private boolean searchFragment;
private SearchEvent searchEvent;
private AsyncTask remoteOperationAsyncTask;
+ private OwnCloudClient client;
private enum MenuItemAddRemove {
DO_NOTHING, REMOVE_SORT, REMOVE_GRID_AND_SORT, ADD_SORT, ADD_GRID_AND_SORT, ADD_GRID_AND_SORT_WITH_SEARCH,
@@ -288,13 +284,6 @@ public class OCFileListFragment extends ExtendedListFragment implements
super.onDetach();
}
- @Override
- public void onPause() {
- super.onPause();
- mAdapter.cancelAllPendingTasks();
- }
-
-
/**
* {@inheritDoc}
*/
@@ -312,7 +301,9 @@ public class OCFileListFragment extends ExtendedListFragment implements
mOnlyFoldersClickable = args != null && args.getBoolean(ARG_ONLY_FOLDERS_CLICKABLE, false);
boolean hideItemOptions = args != null && args.getBoolean(ARG_HIDE_ITEM_OPTIONS, false);
- mAdapter = new OCFileListAdapter(getActivity(), mContainerActivity, this, hideItemOptions,
+ client = AccountUtils.getClientForCurrentAccount(getContext());
+
+ mAdapter = new OCFileListAdapter(getActivity(), client, mContainerActivity, this, hideItemOptions,
isGridViewPreferred(mFile));
setRecyclerViewAdapter(mAdapter);
@@ -1317,36 +1308,21 @@ public class OCFileListFragment extends ExtendedListFragment implements
public void onMessageEvent(FavoriteEvent event) {
Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
- OwnCloudAccount ocAccount = null;
AccountManager mAccountMgr = AccountManager.get(getActivity());
- try {
- ocAccount = new OwnCloudAccount(
- currentAccount,
- MainApp.getAppContext()
- );
-
- OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
- getClientFor(ocAccount, MainApp.getAppContext());
-
- String userId = mAccountMgr.getUserData(currentAccount,
- com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
-
- if (TextUtils.isEmpty(userId)) {
- userId = mClient.getCredentials().getUsername();
- }
+ String userId = mAccountMgr.getUserData(currentAccount,
+ com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
- ToggleFavoriteOperation toggleFavoriteOperation = new ToggleFavoriteOperation(event.shouldFavorite,
- event.remotePath, userId);
- RemoteOperationResult remoteOperationResult = toggleFavoriteOperation.execute(mClient);
+ if (TextUtils.isEmpty(userId)) {
+ userId = client.getCredentials().getUsername();
+ }
- if (remoteOperationResult.isSuccess()) {
- mAdapter.setFavoriteAttributeForItemID(event.remoteId, event.shouldFavorite);
- }
+ ToggleFavoriteOperation toggleFavoriteOperation = new ToggleFavoriteOperation(event.shouldFavorite,
+ event.remotePath, userId);
+ RemoteOperationResult remoteOperationResult = toggleFavoriteOperation.execute(client);
- } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException | AuthenticatorException
- | IOException | OperationCanceledException e) {
- Log_OC.e(TAG, "Error processing event", e);
+ if (remoteOperationResult.isSuccess()) {
+ mAdapter.setFavoriteAttributeForItemID(event.remoteId, event.shouldFavorite);
}
}
@@ -1475,35 +1451,16 @@ public class OCFileListFragment extends ExtendedListFragment implements
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent(EncryptionEvent event) {
- Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
-
- OwnCloudAccount ocAccount = null;
- try {
- ocAccount = new OwnCloudAccount(currentAccount, MainApp.getAppContext());
-
- OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
- getClientFor(ocAccount, MainApp.getAppContext());
-
- ToggleEncryptionOperation toggleEncryptionOperation = new ToggleEncryptionOperation(event.localId,
- event.remotePath, event.shouldBeEncrypted);
- RemoteOperationResult remoteOperationResult = toggleEncryptionOperation.execute(mClient, true);
-
- if (remoteOperationResult.isSuccess()) {
- mAdapter.setEncryptionAttributeForItemID(event.remoteId, event.shouldBeEncrypted);
- } else if (remoteOperationResult.getHttpCode() == HttpStatus.SC_FORBIDDEN) {
- Snackbar.make(getRecyclerView(), R.string.end_to_end_encryption_folder_not_empty, Snackbar.LENGTH_LONG).show();
- } else {
- Snackbar.make(getRecyclerView(), R.string.common_error_unknown, Snackbar.LENGTH_LONG).show();
- }
-
- } catch (com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException e) {
- Log_OC.e(TAG, "Account not found", e);
- } catch (AuthenticatorException e) {
- Log_OC.e(TAG, "Authentication failed", e);
- } catch (IOException e) {
- Log_OC.e(TAG, "IO error", e);
- } catch (OperationCanceledException e) {
- Log_OC.e(TAG, "Operation has been canceled", e);
+ ToggleEncryptionOperation toggleEncryptionOperation = new ToggleEncryptionOperation(event.localId,
+ event.remotePath, event.shouldBeEncrypted);
+ RemoteOperationResult remoteOperationResult = toggleEncryptionOperation.execute(client, true);
+
+ if (remoteOperationResult.isSuccess()) {
+ mAdapter.setEncryptionAttributeForItemID(event.remoteId, event.shouldBeEncrypted);
+ } else if (remoteOperationResult.getHttpCode() == HttpStatus.SC_FORBIDDEN) {
+ Snackbar.make(getRecyclerView(), R.string.end_to_end_encryption_folder_not_empty, Snackbar.LENGTH_LONG).show();
+ } else {
+ Snackbar.make(getRecyclerView(), R.string.common_error_unknown, Snackbar.LENGTH_LONG).show();
}
}
diff --git a/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java b/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java
index 25db421e28..b58bde603a 100644
--- a/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java
+++ b/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java
@@ -25,8 +25,8 @@ package com.owncloud.android.ui.fragment;
import android.accounts.Account;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
-import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.Bundle;
@@ -47,8 +47,9 @@ import android.widget.ScrollView;
import android.widget.TextView;
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.OwnCloudClient;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.shares.OCShare;
import com.owncloud.android.lib.resources.shares.ShareType;
@@ -62,8 +63,8 @@ import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.ThemeUtils;
import java.text.SimpleDateFormat;
-import java.util.List;
import java.util.Date;
+import java.util.List;
/**
* Fragment for Sharing a file with sharees (users or groups) or creating
@@ -189,17 +190,20 @@ public class ShareFileFragment extends Fragment implements ShareUserListAdapter.
// Setup layout
// Image
ImageView icon = view.findViewById(R.id.shareFileIcon);
- icon.setImageDrawable(
- MimeTypeUtil.getFileTypeIcon(mFile.getMimeType(), mFile.getFileName(), mAccount, getContext())
- );
- if (MimeTypeUtil.isImage(mFile)) {
- String remoteId = String.valueOf(mFile.getRemoteId());
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(remoteId);
- if (thumbnail != null) {
- icon.setImageBitmap(thumbnail);
+ Context context = getContext();
+
+ if ((MimeTypeUtil.isImage(mFile) || MimeTypeUtil.isVideo(mFile)) && mFile.getRemoteId() != null) {
+ OwnCloudClient client = AccountUtils.getClientForCurrentAccount(context);
+ DisplayUtils.downloadThumbnail(mFile, icon, client, context);
+
+ if ("image/png".equalsIgnoreCase(mFile.getMimeType())) {
+ icon.setBackgroundColor(container.getResources().getColor(R.color.background_color));
}
+ } else {
+ icon.setImageDrawable(MimeTypeUtil.getFileTypeIcon(mFile.getMimeType(), mFile.getFileName(),
+ mAccount, getContext()));
}
-
+
// Title
TextView title = view.findViewById(R.id.shareWithUsersSectionTitle);
title.setTextColor(accentColor);
diff --git a/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java b/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java
index f50945bd90..3aa8bf496d 100644
--- a/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java
+++ b/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java
@@ -32,7 +32,6 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
@@ -61,15 +60,15 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-import com.bumptech.glide.request.animation.GlideAnimation;
-import com.bumptech.glide.request.target.SimpleTarget;
import com.evernote.android.job.JobRequest;
import com.evernote.android.job.util.support.PersistableBundleCompat;
import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.jobs.ContactsImportJob;
+import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.TextDrawable;
import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
@@ -79,6 +78,7 @@ import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.PermissionUtil;
import com.owncloud.android.utils.ThemeUtils;
+import com.owncloud.android.utils.glide.GlideKey;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -168,6 +168,8 @@ public class ContactListFragment extends FileFragment {
View view = inflater.inflate(R.layout.contactlist_fragment, container, false);
ButterKnife.bind(this, view);
+ OwnCloudClient client = AccountUtils.getClientForCurrentAccount(requireContext());
+
setHasOptionsMenu(true);
ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
@@ -184,7 +186,7 @@ public class ContactListFragment extends FileFragment {
recyclerView = view.findViewById(R.id.contactlist_recyclerview);
if (savedInstanceState == null) {
- contactListAdapter = new ContactListAdapter(getContext(), vCards);
+ contactListAdapter = new ContactListAdapter(getContext(), client, vCards);
} else {
Set<Integer> checkedItems = new HashSet<>();
int[] itemsArray = savedInstanceState.getIntArray(CHECKED_ITEMS_ARRAY_KEY);
@@ -196,7 +198,7 @@ public class ContactListFragment extends FileFragment {
if (checkedItems.size() > 0) {
onMessageEvent(new VCardToggleEvent(true));
}
- contactListAdapter = new ContactListAdapter(getContext(), vCards, checkedItems);
+ contactListAdapter = new ContactListAdapter(getContext(), client, vCards, checkedItems);
}
recyclerView.setAdapter(contactListAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
@@ -572,20 +574,22 @@ class ContactListAdapter extends RecyclerView.Adapter<ContactListFragment.Contac
private List<VCard> vCards;
private Set<Integer> checkedVCards;
-
+ private OwnCloudClient client;
+
private Context context;
- ContactListAdapter(Context context, List<VCard> vCards) {
+ ContactListAdapter(Context context, OwnCloudClient client, List<VCard> vCards) {
this.vCards = vCards;
this.context = context;
this.checkedVCards = new HashSet<>();
+ this.client = client;
}
- ContactListAdapter(Context context, List<VCard> vCards,
- Set<Integer> checkedVCards) {
+ ContactListAdapter(Context context, OwnCloudClient client, List<VCard> vCards, Set<Integer> checkedVCards) {
this.vCards = vCards;
this.context = context;
this.checkedVCards = checkedVCards;
+ this.client = client;
}
public int getCheckedCount() {
@@ -667,20 +671,8 @@ class ContactListAdapter extends RecyclerView.Adapter<ContactListFragment.Contac
imageView.setImageDrawable(drawable);
} else if (url != null) {
- SimpleTarget target = new SimpleTarget<Drawable>() {
- @Override
- public void onResourceReady(Drawable resource, GlideAnimation glideAnimation) {
- imageView.setImageDrawable(resource);
- }
-
- @Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
- super.onLoadFailed(e, errorDrawable);
- imageView.setImageDrawable(errorDrawable);
- }
- };
- DisplayUtils.downloadIcon(context, url, target, R.drawable.ic_user, imageView.getWidth(),
- imageView.getHeight());
+ DisplayUtils.downloadImage(url, R.drawable.ic_user, R.drawable.ic_user, imageView, client,
+ GlideKey.url(url), context);
}
}
diff --git a/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java b/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
index de885ef389..b7bcedc266 100755
--- a/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
+++ b/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java
@@ -30,7 +30,9 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.graphics.Point;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -71,6 +73,9 @@ import com.owncloud.android.utils.ConnectivityUtils;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.UriUtils;
+import com.owncloud.android.utils.glide.GlideApp;
+import com.owncloud.android.utils.glide.GlideContainer;
+import com.owncloud.android.utils.glide.GlideKey;
import org.greenrobot.eventbus.EventBus;
@@ -83,6 +88,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -699,23 +705,81 @@ public class FileOperationsHelper {
public void sendCachedImage(OCFile file, String packageName, String activityName) {
if (file != null) {
- Context context = MainApp.getAppContext();
- Intent sendIntent = new Intent(Intent.ACTION_SEND);
- // set MimeType
- sendIntent.setType(file.getMimeType());
- sendIntent.setComponent(new ComponentName(packageName, activityName));
- sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" +
- context.getResources().getString(R.string.image_cache_provider_authority) +
- file.getRemotePath()));
- sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
-
- mFileActivity.startActivity(Intent.createChooser(sendIntent,
- context.getString(R.string.actionbar_send_file)));
+
+
+ LoadCachedImageAsyncTask loadTask = new LoadCachedImageAsyncTask(packageName, activityName, mFileActivity);
+ loadTask.execute(file);
+
+
} else {
Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
}
}
+ private static class LoadCachedImageAsyncTask extends AsyncTask<OCFile, Void, Uri> {
+ private OCFile file;
+ private String packageName;
+ private String activityName;
+ private FileActivity fileActivity;
+
+ LoadCachedImageAsyncTask(String packageName, String activityName, FileActivity fileActivity) {
+ this.packageName = packageName;
+ this.activityName = activityName;
+ this.fileActivity = fileActivity;
+ }
+
+ @Override
+ protected Uri doInBackground(OCFile... ocFiles) {
+ File cachedImage = null;
+ file = ocFiles[0];
+
+ try {
+ GlideContainer container = new GlideContainer();
+ container.key = GlideKey.resizedImage(file);
+
+ Point p = DisplayUtils.getScreenDimension();
+ int pxW = p.x;
+ int pxH = p.y;
+
+ cachedImage = GlideApp
+ .with(fileActivity)
+ .downloadOnly()
+ .load(container)
+ .submit(pxW, pxH)
+ .get(); // needs to be called on background thread
+ } catch (InterruptedException | ExecutionException e) {
+ Log_OC.e(TAG, "Error generating image", e);
+ }
+
+ Context context = MainApp.getAppContext();
+
+ return FileProvider.getUriForFile(context,
+ context.getResources().getString(R.string.file_provider_authority), cachedImage);
+ }
+
+ @Override
+ protected void onPostExecute(Uri uri) {
+ super.onPostExecute(uri);
+
+ if (uri != null) {
+ Context context = MainApp.getAppContext();
+ Intent sendIntent = new Intent(Intent.ACTION_SEND);
+
+ // set MimeType
+ sendIntent.setType(file.getMimeType());
+ sendIntent.setComponent(new ComponentName(packageName, activityName));
+// sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" +
+// context.getResources().getString(R.string.image_cache_provider_authority) +
+// file.getRemotePath()));
+ sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
+
+ fileActivity.startActivity(Intent.createChooser(sendIntent,
+ context.getString(R.string.actionbar_send_file)));
+ }
+ }
+ }
+
public void setPictureAs(OCFile file, View view) {
if (file != null) {
Context context = MainApp.getAppContext();
diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java b/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java
index b4b7dc6b7b..7177e467b3 100644
--- a/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java
+++ b/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java
@@ -29,12 +29,14 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.PictureDrawable;
+import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentStatePagerAdapter;
@@ -51,14 +53,20 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.request.target.SimpleTarget;
+import com.bumptech.glide.request.transition.Transition;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
import com.github.chrisbanes.photoview.PhotoView;
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.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.utils.Log_OC;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
@@ -67,11 +75,15 @@ import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimeType;
import com.owncloud.android.utils.MimeTypeUtil;
+import com.owncloud.android.utils.glide.GlideApp;
+import com.owncloud.android.utils.glide.GlideContainer;
+import com.owncloud.android.utils.glide.GlideKey;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.WeakReference;
+import java.net.URLEncoder;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import pl.droidsonroids.gif.GifDrawable;
@@ -221,54 +233,66 @@ public class PreviewImageFragment extends FileFragment {
public void onStart() {
super.onStart();
if (getFile() != null) {
- mImageView.setTag(getFile().getFileId());
-
if (mShowResizedImage) {
- Bitmap resizedImage = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(ThumbnailsCacheManager.PREFIX_RESIZED_IMAGE + getFile().getRemoteId()));
-
- if (resizedImage != null && !getFile().needsUpdateThumbnail()) {
- mImageView.setImageBitmap(resizedImage);
- mImageView.setVisibility(View.VISIBLE);
- mBitmap = resizedImage;
- } else {
- // show thumbnail while loading resized image
- Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
- String.valueOf(ThumbnailsCacheManager.PREFIX_THUMBNAIL + getFile().getRemoteId()));
-
- if (thumbnail != null) {
- mImageView.setImageBitmap(thumbnail);
- mImageView.setVisibility(View.VISIBLE);
- mBitmap = thumbnail;
- } else {
- thumbnail = ThumbnailsCacheManager.mDefaultImg;
- }
-
- // generate new resized image
- if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(getFile(), mImageView) &&
- mContainerActivity.getStorageManager() != null) {
- final ThumbnailsCacheManager.ResizedImageGenerationTask task =
- new ThumbnailsCacheManager.ResizedImageGenerationTask(this,
- mImageView,
- mContainerActivity.getStorageManager(),
- mContainerActivity.getStorageManager().getAccount());
- if (resizedImage == null) {
- resizedImage = thumbnail;
- }
- final ThumbnailsCacheManager.AsyncResizedImageDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncResizedImageDrawable(
- MainApp.getAppContext().getResources(),
- resizedImage,
- task
- );
- mImageView.setImageDrawable(asyncDrawable);
- task.execute(getFile());
- }
+ try {
+ Account account = AccountUtils.getCurrentOwnCloudAccount(getContext());
+ OwnCloudAccount ocAccount = new OwnCloudAccount(account, MainApp.getAppContext());
+
+ OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+ getClientFor(ocAccount, MainApp.getAppContext());
+
+ int thumbnailW = DisplayUtils.getThumbnailDimension();
+ int thumbnailH = DisplayUtils.getThumbnailDimension();
+
+ // Thumbnail
+ GlideContainer container = new GlideContainer();
+ int placeholder = MimeTypeUtil.isVideo(getFile()) ? R.drawable.file_movie : R.drawable.file_image;
+
+ container.url = mClient.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" +
+ thumbnailW + "/" + thumbnailH + Uri.encode(getFile().getRemotePath(), "/");
+ container.client = mClient;
+ container.key = GlideKey.serverThumbnail(getFile());
+
+ // resized image
+ GlideContainer containerResizedImage = new GlideContainer();
+
+ Point p = DisplayUtils.getScreenDimension();
+ int pxW = p.x;
+ int pxH = p.y;
+
+ containerResizedImage.url = mClient.getBaseUri() + "/index.php/core/preview.png?file="
+ + URLEncoder.encode(getFile().getRemotePath())
+ + "&x=" + pxW + "&y=" + pxH + "&a=1&mode=cover&forceIcon=0";
+ containerResizedImage.key = GlideKey.resizedImage(getFile());
+ containerResizedImage.client = mClient;
+
+ GlideApp.with(getContext())
+ .asBitmap()
+ .load(container)
+ .placeholder(placeholder)
+ .priority(Priority.IMMEDIATE)
+ .onlyRetrieveFromCache(true)
+ .into(new SimpleTarget<Bitmap>() {
+ @Override
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
+ mImageView.setImageResource(placeholder);
+ loadResizedImage(containerResizedImage);
+ }
+
+ @Override
+ public void onResourceReady(@NonNull Bitmap resource,
+ @Nullable Transition<? super Bitmap> transition) {
+ mImageView.setImageBitmap(resource);
+ loadResizedImage(containerResizedImage);
+ }
+ }
+ );
+ } catch (Exception e) {
+ Log_OC.e(TAG, e.getMessage());
}
+
mMultiView.setVisibility(View.GONE);
- if (getResources() != null) {
- mImageView.setBackgroundColor(getResources().getColor(R.color.black));
- }
+ mImageView.setBackgroundColor(getResources().getColor(R.color.black));
mImageView.setVisibility(View.VISIBLE);
} else {
@@ -280,6 +304,21 @@ public class PreviewImageFragment extends FileFragment {
}
}
+ private void loadResizedImage(GlideContainer containerResizedImage) {
+ GlideApp.with(requireContext())
+ .asBitmap()
+ .load(containerResizedImage)
+ .priority(Priority.IMMEDIATE)
+ .into(new SimpleTarget<Bitmap>() {
+ @Override
+ public void onResourceReady(@NonNull Bitmap resource,
+ @Nullable Transition<? super Bitmap> transition) {
+ mImageView.setImageBitmap(resource);
+ }
+ }
+ );
+ }
+
@Override
public void onStop() {
Log_OC.d(TAG, "onStop starts");
@@ -482,8 +521,7 @@ public class PreviewImageFragment extends FileFragment {
}
try {
- bitmapResult = BitmapUtils.decodeSampledBitmapFromFile(storagePath, minWidth,
- minHeight);
+ bitmapResult = BitmapUtils.decodeSampledBitmapFromFile(storagePath, minWidth, minHeight);
if (isCancelled()) {
return new LoadImage(bitmapResult, null, ocFile);
diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java b/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java
index 98325ebb62..bc408806ff 100644
--- a/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java
+++ b/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java
@@ -22,6 +22,7 @@ package com.owncloud.android.ui.preview;
import android.accounts.Account;
import android.content.Context;
import android.graphics.Matrix;
+import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
@@ -217,6 +218,7 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter {
return super.getItemPosition(object);
}
+ @NonNull
@Override
public Object instantiateItem(ViewGroup container, int position) {
Object fragment = super.instantiateItem(container, position);
diff --git a/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java b/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java
index e5c71aa39c..424839de63 100644
--- a/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java
+++ b/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.java
@@ -121,7 +121,7 @@ public class TrashbinActivity extends FileActivity implements TrashbinActivityIn
emptyContentMessage.setText(noResultsMessage);
emptyContentMessage.setVisibility(View.VISIBLE);
- trashbinListAdapter = new TrashbinListAdapter(this, getStorageManager(), this);
+ trashbinListAdapter = new TrashbinListAdapter(this, this);
recyclerView.setAdapter(trashbinListAdapter);
recyclerView.setHasFixedSize(true);
recyclerView.setHasFooter(true);
@@ -227,12 +227,6 @@ public class TrashbinActivity extends FileActivity implements TrashbinActivityIn
}
@Override
- protected void onPause() {
- super.onPause();
- trashbinListAdapter.cancelAllPendingTasks();
- }
-
- @Override
public void onBackPressed() {
trashbinPresenter.navigateUp();
}
@@ -286,4 +280,4 @@ public class TrashbinActivity extends FileActivity implements TrashbinActivityIn
emptyContentIcon.setVisibility(View.VISIBLE);
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/com/owncloud/android/utils/DisplayUtils.java b/src/main/java/com/owncloud/android/utils/DisplayUtils.java
index 049548561f..63bafa19da 100644
--- a/src/main/java/com/owncloud/android/utils/DisplayUtils.java
+++ b/src/main/java/com/owncloud/android/utils/DisplayUtils.java
@@ -36,6 +36,7 @@ import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -50,39 +51,50 @@ import android.text.format.DateUtils;
import android.text.style.StyleSpan;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.WindowManager;
+import android.widget.ImageView;
-import com.bumptech.glide.GenericRequestBuilder;
-import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
-import com.bumptech.glide.load.model.StreamEncoder;
-import com.bumptech.glide.load.resource.file.FileToStreamDecoder;
+import com.bumptech.glide.request.RequestOptions;
+import com.bumptech.glide.request.target.CustomViewTarget;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
-import com.caverock.androidsvg.SVG;
+import com.bumptech.glide.signature.ObjectKey;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.authentication.AccountUtils;
import com.owncloud.android.datamodel.ArbitraryDataProvider;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.datamodel.ThumbnailsCacheManager;
import com.owncloud.android.lib.common.OwnCloudAccount;
+import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.SearchOperation;
+import com.owncloud.android.lib.resources.files.ServerFileInterface;
import com.owncloud.android.ui.TextDrawable;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.events.MenuItemClickEvent;
import com.owncloud.android.ui.events.SearchEvent;
import com.owncloud.android.ui.fragment.OCFileListFragment;
-import com.owncloud.android.utils.svg.SvgDecoder;
-import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
-
+import com.owncloud.android.utils.glide.GlideApp;
+import com.owncloud.android.utils.glide.GlideAvatar;
+import com.owncloud.android.utils.glide.GlideContainer;
+import com.owncloud.android.utils.glide.GlideKey;
+import com.owncloud.android.utils.glide.GlideOCFileType;
+import com.owncloud.android.utils.glide.GlideOcFile;
+import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
import org.greenrobot.eventbus.EventBus;
import org.parceler.Parcels;
import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -90,6 +102,7 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.IDN;
+import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.util.Collection;
import java.util.Date;
@@ -98,6 +111,7 @@ import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ExecutionException;
/**
* A helper class for UI/display related operations.
@@ -117,6 +131,7 @@ public final class DisplayUtils {
private static final int BYTE_SIZE_DIVIDER = 1024;
private static final double BYTE_SIZE_DIVIDER_DOUBLE = 1024.0;
private static final int DATE_TIME_PARTS_SIZE = 2;
+ private static final String ETAG = "ETag";
private static Map<String, String> mimeType2HumanReadable;
@@ -433,18 +448,28 @@ public final class DisplayUtils {
* fetches and sets the avatar of the given account in the passed callContext
*
* @param account the account to be used to connect to server
- * @param avatarRadius the avatar radius
- * @param resources reference for density information
- * @param callContext which context is called to set the generated avatar
*/
- public static void setAvatar(@NonNull Account account, AvatarGenerationListener listener,
- float avatarRadius, Resources resources, Object callContext, Context context) {
+// public static void setAvatar(@NonNull Account account, Context context, SimpleTarget<Drawable> target) {
+//
+// AccountManager accountManager = AccountManager.get(context);
+// String userId = accountManager.getUserData(account,
+// com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
+//
+// setAvatar(account, userId, context, target);
+// }
+
+ /**
+ * fetches and sets the avatar of the given account in the passed callContext
+ *
+ * @param account the account to be used to connect to server
+ */
+ public static void setAvatar(@NonNull Account account, Context context, Object view, float radius) {
AccountManager accountManager = AccountManager.get(context);
String userId = accountManager.getUserData(account,
com.owncloud.android.lib.common.accounts.AccountUtils.Constants.KEY_USER_ID);
- setAvatar(account, userId, listener, avatarRadius, resources, callContext, context);
+ setAvatar(account, userId, context, view, radius);
}
/**
@@ -452,54 +477,158 @@ public final class DisplayUtils {
*
* @param account the account to be used to connect to server
* @param userId the userId which avatar should be set
- * @param avatarRadius the avatar radius
- * @param resources reference for density information
- * @param callContext which context is called to set the generated avatar
+ * @param view where the image is shown in
*/
- public static void setAvatar(@NonNull Account account, @NonNull String userId, AvatarGenerationListener listener,
- float avatarRadius, Resources resources, Object callContext, Context context) {
- if (callContext instanceof View) {
- ((View) callContext).setContentDescription(account.name);
+ public static void setAvatar(@NonNull Account account, @NonNull String userId, Context context, Object view,
+ float radius) {
+ Drawable placeholder = context.getResources().getDrawable(R.drawable.ic_user);
+
+ Drawable fallback;
+ try {
+ fallback = TextDrawable.createAvatar(account.name, radius);
+ } catch (NoSuchAlgorithmException e) {
+ fallback = placeholder;
+ }
+
+ // show avatar immediately, might be outdated
+ if (view instanceof ImageView) {
+ ImageView imageView = (ImageView) view;
+ imageView.setContentDescription(account.name);
+
+ GlideApp.with(context)
+ .asBitmap()
+ .load(new GlideAvatar(GlideKey.avatar(account, userId, context), null))
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(placeholder)
+ .error(fallback)
+ .onlyRetrieveFromCache(true)
+ .into(imageView);
+ } else {
+ GlideApp.with(context)
+ .load(new GlideAvatar(GlideKey.avatar(account, userId, context), null))
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(placeholder)
+ .error(fallback)
+ .onlyRetrieveFromCache(true)
+ .into((SimpleTarget<Drawable>) view);
}
+
+ AsyncTask task = new AsyncTask<Object, Void, InputStream>() {
+
+ GetMethod get;
+ ArbitraryDataProvider arbitraryDataProvider;
+ String accountName;
+
+ @Override
+ protected InputStream doInBackground(Object[] objects) {
+ InputStream inputStream = null;
+
+ // we need to create client here, as different servers can be used
+ OwnCloudClient client = AccountUtils.getClientForAccount(account, context);
+
+ int px = getAvatarDimension(context);
+
+ arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver());
+ String serverName = account.name.substring(account.name.lastIndexOf('@') + 1, account.name.length());
+ accountName = userId + "@" + serverName;
+ String eTag = arbitraryDataProvider.getValue(accountName, GlideKey.AVATAR_KEY);
+ Log_OC.d(TAG, "glide: old etag: " + eTag);
+
+ try {
+ String uri = client.getBaseUri() + "/index.php/avatar/" + Uri.encode(userId) + "/" + px;
+ Log_OC.d("Avatar", "URI: " + uri);
+ get = new GetMethod(uri);
+
+ // only use eTag if available
+ if (!eTag.isEmpty()) {
+ get.setRequestHeader("If-None-Match", eTag);
+ }
- ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver());
+ int status = client.executeMethod(get);
- String serverName = account.name.substring(account.name.lastIndexOf('@') + 1, account.name.length());
- String eTag = arbitraryDataProvider.getValue(userId + "@" + serverName, ThumbnailsCacheManager.AVATAR);
- String avatarKey = "a_" + userId + "_" + serverName + "_" + eTag;
+ Log_OC.d(TAG, "glide: status: " + status);
- // first show old one
- Drawable avatar = BitmapUtils.bitmapToCircularBitmapDrawable(resources,
- ThumbnailsCacheManager.getBitmapFromDiskCache(avatarKey));
+ // we are using eTag to download a new avatar only if it changed
+ switch (status) {
+ case HttpStatus.SC_OK:
+ case HttpStatus.SC_CREATED:
+ // new avatar
+ inputStream = get.getResponseBodyAsStream();
- // if no one exists, show colored icon with initial char
- if (avatar == null) {
- try {
- avatar = TextDrawable.createAvatarByUserId(userId, avatarRadius);
- } catch (Exception e) {
- Log_OC.e(TAG, "Error calculating RGB value for active account icon.", e);
- avatar = resources.getDrawable(R.drawable.account_circle_white);
+ if (get.getResponseHeader(ETAG) != null) {
+ String newETag = get.getResponseHeader(ETAG).getValue().replace("\"", "");
+ Log_OC.d(TAG, "glide: new etag: " + newETag);
+ arbitraryDataProvider.storeOrUpdateKeyValue(accountName, GlideKey.AVATAR_KEY, newETag);
+ }
+ break;
+
+ case HttpStatus.SC_NOT_MODIFIED:
+ default:
+ client.exhaustResponse(get.getResponseBodyAsStream());
+ break;
+
+ }
+ } catch (Exception e) {
+ // do nothing, fallback in glide
+ if (get != null) {
+ get.releaseConnection();
+ }
+ }
+
+ return inputStream;
}
- }
- // check for new avatar, eTag is compared, so only new one is downloaded
- if (ThumbnailsCacheManager.cancelPotentialAvatarWork(userId, callContext)) {
- final ThumbnailsCacheManager.AvatarGenerationTask task =
- new ThumbnailsCacheManager.AvatarGenerationTask(listener, callContext, account, resources,
- avatarRadius, userId, serverName, context);
+ @Override
+ protected void onPostExecute(InputStream inputStream) {
+ Drawable placeholder = context.getResources().getDrawable(R.drawable.ic_user);
+
+ Drawable fallback;
+ try {
+ fallback = TextDrawable.createAvatar(account.name, radius);
+ } catch (NoSuchAlgorithmException e) {
+ fallback = placeholder;
+ }
+
+ try {
+ if (view instanceof ImageView) {
+ ImageView imageView = (ImageView) view;
+ imageView.setContentDescription(account.name);
+
+ GlideApp.with(context)
+ .asBitmap()
+ .load(new GlideAvatar(GlideKey.avatar(account, userId, context), inputStream))
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(placeholder)
+ .error(fallback)
+ .onlyRetrieveFromCache(inputStream == null)
+ .into(imageView);
+ } else {
+ GlideApp.with(context)
+ .load(new GlideAvatar(GlideKey.avatar(account, userId, context), inputStream))
+ .apply(RequestOptions.circleCropTransform())
+ .placeholder(placeholder)
+ .error(fallback)
+ .onlyRetrieveFromCache(inputStream == null)
+ .into((SimpleTarget<Drawable>) view);
+ }
+
+ } catch (Exception e) {
+ Log_OC.e(TAG, "Avatar generation failed", e);
+ // reset eTag
+ arbitraryDataProvider.storeOrUpdateKeyValue(accountName, GlideKey.AVATAR_KEY, "");
+ // context may be null
+ }
+ }
+ };
- final ThumbnailsCacheManager.AsyncAvatarDrawable asyncDrawable =
- new ThumbnailsCacheManager.AsyncAvatarDrawable(resources, avatar, task);
- listener.avatarGenerated(asyncDrawable, callContext);
- task.execute(userId);
- }
+ task.execute();
}
- public static void downloadIcon(Context context, String iconUrl, SimpleTarget imageView, int placeholder,
- int width, int height) {
+ public static void downloadIcon(Context context, String iconUrl, SimpleTarget<Drawable> imageView, int placeholder,
+ int error) {
try {
if (iconUrl.endsWith(".svg")) {
- downloadSVGIcon(context, iconUrl, imageView, placeholder, width, height);
+ downloadSVG(iconUrl, placeholder, error, imageView, context);
} else {
downloadPNGIcon(context, iconUrl, imageView, placeholder);
}
@@ -508,44 +637,43 @@ public final class DisplayUtils {
}
}
- private static void downloadPNGIcon(Context context, String iconUrl, SimpleTarget imageView, int placeholder) {
- Glide
- .with(context)
+ private static void downloadPNGIcon(Context context, String iconUrl, SimpleTarget<Drawable> imageView,
+ int placeholder) {
+ GlideApp.with(context)
.load(iconUrl)
.centerCrop()
.placeholder(placeholder)
.error(placeholder)
- .crossFade()
.into(imageView);
}
- private static void downloadSVGIcon(Context context, String iconUrl, SimpleTarget imageView, int placeholder,
- int width, int height) {
- GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(context)
- .using(Glide.buildStreamModelLoader(Uri.class, context), InputStream.class)
- .from(Uri.class)
- .as(SVG.class)
- .transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
- .sourceEncoder(new StreamEncoder())
- .cacheDecoder(new FileToStreamDecoder<>(new SvgDecoder(height, width)))
- .decoder(new SvgDecoder(height, width))
+ public static void downloadSVG(String url, int placeholder, int error, ImageView imageView, Context context) {
+ GlideApp.with(context)
+ .as(PictureDrawable.class)
.placeholder(placeholder)
- .error(placeholder)
- .animate(android.R.anim.fade_in);
-
-
- Uri uri = Uri.parse(iconUrl);
- requestBuilder
- .diskCacheStrategy(DiskCacheStrategy.SOURCE)
- .load(uri)
+ .fitCenter()
+ .error(error)
+ .listener(new SvgSoftwareLayerSetter())
+ .load(url)
.into(imageView);
}
+ private static void downloadSVG(String url, int placeholder, int error, SimpleTarget<Drawable> imageView,
+ Context context) {
+ GlideApp.with(context)
+ .as(PictureDrawable.class)
+ .load(url)
+ .placeholder(placeholder)
+ .error(error)
+ .listener(new SvgSoftwareLayerSetter())
+ .into((SimpleTarget) imageView);
+ }
+
public static Bitmap downloadImageSynchronous(Context context, String imageUrl) {
try {
- return Glide.with(context)
- .load(imageUrl)
+ return GlideApp.with(context)
.asBitmap()
+ .load(imageUrl)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
.into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
@@ -556,6 +684,139 @@ public final class DisplayUtils {
}
}
+ public static void localImage(File file, int placeholder, int error, ImageView view, Key key, Context context) {
+ GlideApp.with(context)
+ .load(file)
+ .placeholder(placeholder)
+ .error(error)
+ .into(view);
+ }
+
+ public static void downloadThumbnail(OCFile file, Object view, OwnCloudClient client, Context context) {
+ GlideContainer container = new GlideContainer();
+
+ int placeholder = MimeTypeUtil.isVideo(file) ? R.drawable.file_movie : R.drawable.file_image;
+ int pxW = DisplayUtils.getThumbnailDimension();
+ int pxH = DisplayUtils.getThumbnailDimension();
+
+ container.url = client.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + pxW + "/" + pxH +
+ Uri.encode(file.getRemotePath(), "/");
+ container.client = client;
+ container.key = GlideKey.serverThumbnail(file);
+
+ if (view instanceof ImageView) {
+ GlideApp.with(context)
+ .load(container)
+ .placeholder(placeholder)
+ .error(placeholder)
+ .into((ImageView) view);
+ } else {
+ GlideApp.with(context)
+ .load(container)
+ .placeholder(placeholder)
+ .error(placeholder)
+ .into((CustomViewTarget<ImageView, Drawable>) view);
+ }
+ }
+
+ public static void downloadActivityThumbnail(OCFile file, ImageView view, OwnCloudClient client, Context context) {
+ GlideContainer container = new GlideContainer();
+
+ int placeholder = MimeTypeUtil.isVideo(file) ? R.drawable.file_movie : R.drawable.file_image;
+ int pxW = DisplayUtils.getThumbnailDimension();
+ int pxH = DisplayUtils.getThumbnailDimension();
+
+ container.url = client.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + pxW + "/" + pxH +
+ Uri.encode(file.getRemotePath(), "/");
+ container.client = client;
+ container.key = GlideKey.activityThumbnail(file);
+
+ GlideApp.with(context)
+ .load(container)
+ .placeholder(placeholder)
+ .into(view);
+ }
+
+ public static Drawable getThumbnail(OCFile file, ImageView view, OwnCloudClient client, Context context) {
+ GlideContainer container = new GlideContainer();
+
+ int placeholder = MimeTypeUtil.isVideo(file) ? R.drawable.file_movie : R.drawable.file_image;
+ int pxW = DisplayUtils.getThumbnailDimension();
+ int pxH = DisplayUtils.getThumbnailDimension();
+
+ container.url = client.getBaseUri() + "/index.php/apps/files/api/v1/thumbnail/" + pxW + "/" + pxH +
+ Uri.encode(file.getRemotePath(), "/");
+ container.client = client;
+ container.key = GlideKey.serverThumbnail(file);
+
+ try {
+ return GlideApp.with(context)
+ .load(container)
+ .placeholder(placeholder)
+ .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
+ .get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log_OC.e(TAG, "Could not download image " + container.url);
+ return context.getResources().getDrawable(placeholder);
+ }
+ }
+
+ public static void downloadImage(String uri, int placeholder, int error, ImageView view, OwnCloudClient client,
+ ObjectKey key, Context context) {
+ GlideContainer container = new GlideContainer();
+
+ container.url = uri;
+ container.key = key;
+ container.client = client;
+
+ GlideApp.with(context)
+ .load(container)
+ .placeholder(placeholder)
+ .error(error)
+ .into(view);
+ }
+
+ public static String getThumbnailUri(OwnCloudClient client, ServerFileInterface file, int size) {
+ return client.getBaseUri() + "/index.php/apps/files_trashbin/preview?fileId=" +
+ file.getLocalId() + "&x=" + size + "&y=" + size;
+ }
+
+ public static void downloadImage(String uri, int placeholder, int error, SimpleTarget<Drawable> target, Key key,
+ Context context) {
+ GlideApp.with(context)
+ .load(uri)
+ .placeholder(placeholder)
+ .error(error)
+ .into(target);
+ }
+
+ public static void generateResizedImage(OCFile file, Context context) {
+ Point p = DisplayUtils.getScreenDimension();
+ int pxW = p.x;
+ int pxH = p.y;
+
+ try {
+ GlideApp.with(context)
+ .load(new GlideOcFile(file, GlideOCFileType.resizedImage))
+ .downloadOnly(pxW, pxH).get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log_OC.e(TAG, "Thumbnail generation failed", e);
+ }
+ }
+
+ public static void generateThumbnail(OCFile file, String path, Context context) {
+ int pxW = DisplayUtils.getThumbnailDimension();
+ int pxH = DisplayUtils.getThumbnailDimension();
+
+ try {
+ GlideApp.with(context)
+ .load(new GlideOcFile(file, GlideOCFileType.thumbnail, path))
+ .downloadOnly(pxW, pxH).get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log_OC.e(TAG, "Thumbnail generation failed", e);
+ }
+ }
+
public static void setupBottomBar(BottomNavigationView view, Resources resources, final Activity activity,
int checkedMenuItem) {
@@ -773,4 +1034,40 @@ public final class DisplayUtils {
})
.show();
}
+
+ /**
+ * Converts size of file icon from dp to pixel
+ *
+ * @return int
+ */
+ public static int getThumbnailDimension() {
+ // Converts dp to pixel
+ Resources r = MainApp.getAppContext().getResources();
+ return Math.round(r.getDimension(R.dimen.file_icon_size_grid));
+ }
+
+ /**
+ * Converts dimension of screen as point
+ *
+ * @return Point
+ */
+ public static Point getScreenDimension() {
+ WindowManager wm = (WindowManager) MainApp.getAppContext().getSystemService(Context.WINDOW_SERVICE);
+
+ if (wm == null) {
+ // fallback to reasonable size for resized images
+ return new Point(1024, 868);
+ } else {
+ Display display = wm.getDefaultDisplay();
+ Point point = new Point();
+ display.getSize(point);
+ return point;
+ }
+ }
+
+ private static int getAvatarDimension(Context context) {
+ // Converts dp to pixel
+ Resources r = context.getResources();
+ return Math.round(r.getDimension(R.dimen.file_avatar_size));
+ }
}
diff --git a/src/main/java/com/owncloud/android/utils/FileStorageUtils.java b/src/main/java/com/owncloud/android/utils/FileStorageUtils.java
index 608279a317..151229fa1f 100644
--- a/src/main/java/com/owncloud/android/utils/FileStorageUtils.java
+++ b/src/main/java/com/owncloud/android/utils/FileStorageUtils.java
@@ -318,7 +318,7 @@ public final class FileStorageUtils {
return ret;
}
- public static boolean moveFile(File sourceFile, File targetFile) throws IOException {
+ public static boolean moveFile(File sourceFile, File targetFile) {
if (copyFile(sourceFile, targetFile)) {
return sourceFile.delete();
} else {
diff --git a/src/main/java/com/owncloud/android/utils/GlideUtils.java b/src/main/java/com/owncloud/android/utils/GlideUtils.java
new file mode 100644
index 0000000000..50a6c31dc5
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/GlideUtils.java
@@ -0,0 +1,25 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils;
+
+public class GlideUtils {
+}
diff --git a/src/main/java/com/owncloud/android/utils/MimeTypeUtil.java b/src/main/java/com/owncloud/android/utils/MimeTypeUtil.java
index 693e82003b..ca612ce1a2 100644
--- a/src/main/java/com/owncloud/android/utils/MimeTypeUtil.java
+++ b/src/main/java/com/owncloud/android/utils/MimeTypeUtil.java
@@ -281,6 +281,14 @@ public final class MimeTypeUtil {
|| MimeTypeUtil.isImage(getMimeTypeFromPath(file.getRemotePath()));
}
+ public static boolean isImageOrVideo(ServerFileInterface file) {
+ return isImage(file) || isVideo(file);
+ }
+
+ public static boolean isImageOrVideo(File file) {
+ return isImage(file) || isVideo(file);
+ }
+
/**
* @param file the file to be analyzed
* @return 'True' if the file is simple text (e.g. not application-dependent, like .doc or .docx)
diff --git a/src/main/java/com/owncloud/android/utils/glide/AvatarFetcher.java b/src/main/java/com/owncloud/android/utils/glide/AvatarFetcher.java
new file mode 100644
index 0000000000..daae2a0cb0
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/AvatarFetcher.java
@@ -0,0 +1,64 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.data.DataFetcher;
+
+import java.io.InputStream;
+
+public class AvatarFetcher implements DataFetcher<InputStream> {
+ private GlideAvatar avatar;
+
+ public AvatarFetcher(GlideAvatar avatar) {
+ this.avatar = avatar;
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
+ callback.onDataReady(avatar.getInputStream());
+ }
+
+ public void cleanup() {
+ // not needed
+ }
+
+ @Override
+ public void cancel() {
+ // not needed
+ }
+
+ @NonNull
+ @Override
+ public Class<InputStream> getDataClass() {
+ return InputStream.class;
+ }
+
+ @NonNull
+ @Override
+ public DataSource getDataSource() {
+ return DataSource.REMOTE;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/AvatarLoader.java b/src/main/java/com/owncloud/android/utils/glide/AvatarLoader.java
new file mode 100644
index 0000000000..c62711dbb1
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/AvatarLoader.java
@@ -0,0 +1,45 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ * <p>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ * <p>
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ * <p>
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.model.ModelLoader;
+
+import java.io.InputStream;
+
+/**
+ * Custom Model for OwnCloudClient
+ */
+
+public class AvatarLoader implements ModelLoader<GlideAvatar, InputStream> {
+ @Nullable
+ @Override
+ public LoadData<InputStream> buildLoadData(@NonNull GlideAvatar avatar, int width, int height, @NonNull Options options) {
+ return new LoadData<>(avatar.getKey(), new AvatarFetcher(avatar));
+ }
+
+ @Override
+ public boolean handles(@NonNull GlideAvatar a) {
+ return true;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/AvatarModelLoaderFactory.java b/src/main/java/com/owncloud/android/utils/glide/AvatarModelLoaderFactory.java
new file mode 100644
index 0000000000..f9cac4d111
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/AvatarModelLoaderFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+
+import java.io.InputStream;
+
+public class AvatarModelLoaderFactory implements ModelLoaderFactory<GlideAvatar, InputStream> {
+
+ @NonNull
+ @Override
+ public ModelLoader<GlideAvatar, InputStream> build(@NonNull MultiModelLoaderFactory unused) {
+ return new AvatarLoader();
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing.
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/FileFetcher.java b/src/main/java/com/owncloud/android/utils/glide/FileFetcher.java
new file mode 100644
index 0000000000..7ab9367356
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/FileFetcher.java
@@ -0,0 +1,84 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.owncloud.android.lib.common.utils.Log_OC;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class FileFetcher implements DataFetcher<InputStream> {
+ private final static String TAG = FileFetcher.class.getSimpleName();
+ private String storagePath;
+ private InputStream data;
+
+ public FileFetcher(String storagePath) {
+ this.storagePath = storagePath;
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
+ try {
+ data = new FileInputStream(storagePath);
+ } catch (FileNotFoundException e) {
+ Log_OC.d(TAG, "Failed to open file", e);
+ callback.onLoadFailed(e);
+ return;
+ }
+ callback.onDataReady(data);
+ }
+
+ @Override
+ public void cleanup() {
+ if (data != null) {
+ try {
+ data.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ @Override
+ public void cancel() {
+ // unused
+ }
+
+ @NonNull
+ @Override
+ public Class<InputStream> getDataClass() {
+ return InputStream.class;
+ }
+
+ @NonNull
+ @Override
+ public DataSource getDataSource() {
+ return DataSource.LOCAL;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/CustomGlideStreamLoader.java b/src/main/java/com/owncloud/android/utils/glide/GlideAvatar.java
index 648f265d0f..938281fc19 100644
--- a/src/main/java/com/owncloud/android/utils/glide/CustomGlideStreamLoader.java
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideAvatar.java
@@ -1,8 +1,9 @@
-/**
+/*
* Nextcloud Android client application
*
- * @author Alejandro Bautista
- * Copyright (C) 2017 Alejandro Bautista
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@@ -17,20 +18,27 @@
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
package com.owncloud.android.utils.glide;
-import com.bumptech.glide.load.data.DataFetcher;
-import com.bumptech.glide.load.model.stream.StreamModelLoader;
+import com.bumptech.glide.signature.ObjectKey;
import java.io.InputStream;
-/**
- * Custom Model for OwnCloudClient
- */
+public class GlideAvatar {
+ private ObjectKey key;
+ private InputStream inputStream;
+
+ public GlideAvatar(ObjectKey key, InputStream avatar) {
+ this.key = key;
+ this.inputStream = avatar;
+ }
+
+ public ObjectKey getKey() {
+ return key;
+ }
-public class CustomGlideStreamLoader implements StreamModelLoader<String> {
- @Override
- public DataFetcher<InputStream> getResourceFetcher(String url, int width, int height) {
- return new HttpStreamFetcher(url);
+ public InputStream getInputStream() {
+ return inputStream;
}
}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideContainer.java b/src/main/java/com/owncloud/android/utils/glide/GlideContainer.java
new file mode 100644
index 0000000000..51f9239bea
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideContainer.java
@@ -0,0 +1,31 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import com.bumptech.glide.signature.ObjectKey;
+import com.owncloud.android.lib.common.OwnCloudClient;
+
+public class GlideContainer {
+ public OwnCloudClient client;
+ public ObjectKey key;
+ public String url;
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideContainerModelLoaderFactory.java b/src/main/java/com/owncloud/android/utils/glide/GlideContainerModelLoaderFactory.java
new file mode 100644
index 0000000000..b2faf8bc35
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideContainerModelLoaderFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+
+import java.io.InputStream;
+
+public class GlideContainerModelLoaderFactory implements ModelLoaderFactory<GlideContainer, InputStream> {
+
+ @NonNull
+ @Override
+ public ModelLoader<GlideContainer, InputStream> build(@NonNull MultiModelLoaderFactory unused) {
+ return new GlideContainerStreamLoader();
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing.
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideContainerStreamLoader.java b/src/main/java/com/owncloud/android/utils/glide/GlideContainerStreamLoader.java
new file mode 100644
index 0000000000..0c41eff9be
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideContainerStreamLoader.java
@@ -0,0 +1,49 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.signature.ObjectKey;
+
+import java.io.InputStream;
+
+import static com.owncloud.android.utils.glide.GlideKey.RESIZED_IMAGE_KEY;
+import static com.owncloud.android.utils.glide.GlideKey.THUMBNAIL_KEY;
+
+/**
+ * Custom model for Nextcloud Client
+ */
+public class GlideContainerStreamLoader implements ModelLoader<GlideContainer, InputStream> {
+ @Nullable
+ @Override
+ public LoadData<InputStream> buildLoadData(@NonNull GlideContainer container, int width, int height,
+ @NonNull Options options) {
+ return new LoadData<>(container.key, new HttpStreamGlideContainerFetcher(container));
+ }
+
+ @Override
+ public boolean handles(@NonNull GlideContainer s) {
+ return !s.key.equals(new ObjectKey(THUMBNAIL_KEY)) && !s.key.equals(new ObjectKey(RESIZED_IMAGE_KEY));
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideKey.java b/src/main/java/com/owncloud/android/utils/glide/GlideKey.java
new file mode 100644
index 0000000000..8130b4d3e7
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideKey.java
@@ -0,0 +1,75 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.accounts.Account;
+import android.content.Context;
+
+import com.bumptech.glide.signature.ObjectKey;
+import com.owncloud.android.datamodel.ArbitraryDataProvider;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.lib.resources.files.TrashbinFile;
+
+import java.io.File;
+
+public final class GlideKey {
+ public static final String AVATAR_KEY = "AVATAR";
+ static final String THUMBNAIL_KEY = "THUMBNAIL_";
+ static final String RESIZED_IMAGE_KEY = "RESIZED_IMAGE_";
+
+ private GlideKey() {
+ // Required empty constructor
+ }
+
+ public static ObjectKey serverThumbnail(OCFile file) {
+ return new ObjectKey(THUMBNAIL_KEY + file.getEtagOnServer());
+ }
+
+ public static ObjectKey resizedImage(OCFile file) {
+ return new ObjectKey(RESIZED_IMAGE_KEY + file.getEtagOnServer());
+ }
+
+ public static ObjectKey localFile(File file) {
+ return new ObjectKey(file.hashCode());
+ }
+
+ public static ObjectKey url(String url) {
+ return new ObjectKey(url);
+ }
+
+ public static ObjectKey trashbinThumbnail(TrashbinFile file) {
+ return new ObjectKey(THUMBNAIL_KEY + file.getRemoteId());
+ }
+
+ public static ObjectKey activityThumbnail(OCFile file) {
+ return new ObjectKey(THUMBNAIL_KEY + file.getRemoteId());
+ }
+
+ public static ObjectKey avatar(Account account, String userId, Context context) {
+ ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(context.getContentResolver());
+
+ String serverName = account.name.substring(account.name.lastIndexOf('@') + 1, account.name.length());
+ String eTag = arbitraryDataProvider.getValue(userId + "@" + serverName, GlideKey.AVATAR_KEY);
+
+ return new ObjectKey("a_" + userId + "_" + serverName + "_" + eTag);
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideOCFileType.java b/src/main/java/com/owncloud/android/utils/glide/GlideOCFileType.java
new file mode 100644
index 0000000000..726d169e1f
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideOCFileType.java
@@ -0,0 +1,26 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+public enum GlideOCFileType {
+ resizedImage, thumbnail
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideOcFile.java b/src/main/java/com/owncloud/android/utils/glide/GlideOcFile.java
new file mode 100644
index 0000000000..d9f49cb12e
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideOcFile.java
@@ -0,0 +1,54 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import com.owncloud.android.datamodel.OCFile;
+
+public class GlideOcFile {
+ private OCFile file;
+ private GlideOCFileType type;
+ private String path = "";
+
+ public GlideOcFile(OCFile file, GlideOCFileType type) {
+ this.file = file;
+ this.type = type;
+ }
+
+ public GlideOcFile(OCFile file, GlideOCFileType type, String path) {
+ this.file = file;
+ this.type = type;
+ this.path = path;
+ }
+
+ public OCFile getFile() {
+ return file;
+ }
+
+ public GlideOCFileType getType() {
+ return type;
+ }
+
+ public String getPath() {
+ return path;
+ }
+}
+
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideStringStreamFetcher.java b/src/main/java/com/owncloud/android/utils/glide/GlideStringStreamFetcher.java
new file mode 100644
index 0000000000..faa5a55b5c
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideStringStreamFetcher.java
@@ -0,0 +1,94 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.owncloud.android.MainApp;
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.utils.Log_OC;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+
+import java.io.InputStream;
+
+/**
+ * Fetcher with Nextcloud client
+ */
+public class GlideStringStreamFetcher implements DataFetcher<InputStream> {
+
+ private static final String TAG = GlideStringStreamFetcher.class.getName();
+ private final String url;
+
+ public GlideStringStreamFetcher(String url) {
+ this.url = url;
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
+ OwnCloudClient client = AccountUtils.getClientForCurrentAccount(MainApp.getAppContext());
+
+ GetMethod get = null;
+ try {
+ get = new GetMethod(url);
+ get.setRequestHeader("Cookie", "nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
+ get.setRequestHeader(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE);
+ int status = client.executeMethod(get);
+ if (status == HttpStatus.SC_OK) {
+ callback.onDataReady(get.getResponseBodyAsStream());
+ } else {
+ client.exhaustResponse(get.getResponseBodyAsStream());
+ }
+ } catch (Exception e) {
+ Log_OC.e(TAG, e.getMessage(), e);
+ } finally {
+ if (get != null) {
+ get.releaseConnection();
+ }
+ }
+ }
+
+ public void cleanup() {
+ Log_OC.i(TAG, "Cleanup");
+ }
+
+ @Override
+ public void cancel() {
+ Log_OC.i(TAG, "Cancel");
+ }
+
+ @NonNull
+ @Override
+ public Class<InputStream> getDataClass() {
+ return InputStream.class;
+ }
+
+ @NonNull
+ @Override
+ public DataSource getDataSource() {
+ return DataSource.REMOTE;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/GlideStringStreamLoader.java b/src/main/java/com/owncloud/android/utils/glide/GlideStringStreamLoader.java
new file mode 100644
index 0000000000..e0b6120acf
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/GlideStringStreamLoader.java
@@ -0,0 +1,47 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.signature.ObjectKey;
+
+import java.io.InputStream;
+
+/**
+ * Custom model for Nextcloud client
+ */
+public class GlideStringStreamLoader implements ModelLoader<String, InputStream> {
+ @Nullable
+ @Override
+ public LoadData<InputStream> buildLoadData(@NonNull String url, int width, int height, @NonNull Options options) {
+ // TODO replace key with etag? and type? (avatar, thumbnail, resized image)
+ // TODO pass client to stream fetcher?
+ return new LoadData<>(new ObjectKey(url), new GlideStringStreamFetcher(url));
+ }
+
+ @Override
+ public boolean handles(@NonNull String s) {
+ return true;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/HttpStreamFetcher.java b/src/main/java/com/owncloud/android/utils/glide/HttpStreamFetcher.java
deleted file mode 100644
index 08ceb71e70..0000000000
--- a/src/main/java/com/owncloud/android/utils/glide/HttpStreamFetcher.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * Nextcloud Android client application
- *
- * @author Alejandro Bautista
- * Copyright (C) 2017 Alejandro Bautista
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-package com.owncloud.android.utils.glide;
-
-import android.accounts.Account;
-
-import com.bumptech.glide.Priority;
-import com.bumptech.glide.load.data.DataFetcher;
-import com.owncloud.android.MainApp;
-import com.owncloud.android.authentication.AccountUtils;
-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.RemoteOperation;
-import com.owncloud.android.lib.common.utils.Log_OC;
-
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.GetMethod;
-
-import java.io.InputStream;
-
-/**
- * Fetcher with OwnCloudClient
- */
-
-public class HttpStreamFetcher implements DataFetcher<InputStream> {
-
- private static final String TAG = HttpStreamFetcher.class.getName();
- private final String mURL;
-
- public HttpStreamFetcher(String url) {
- this.mURL = url;
-
- }
-
- @Override
- public InputStream loadData(Priority priority) throws Exception {
-
- Account mAccount = AccountUtils.getCurrentOwnCloudAccount(MainApp.getAppContext());
- OwnCloudAccount ocAccount = new OwnCloudAccount(mAccount, MainApp.getAppContext());
- OwnCloudClient mClient = OwnCloudClientManagerFactory.getDefaultSingleton().
- getClientFor(ocAccount, MainApp.getAppContext());
-
- if (mClient != null) {
- GetMethod get;
- try {
- get = new GetMethod(mURL);
- get.setRequestHeader("Cookie", "nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
- get.setRequestHeader(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE);
- int status = mClient.executeMethod(get);
- if (status == HttpStatus.SC_OK) {
- return get.getResponseBodyAsStream();
- } else {
- mClient.exhaustResponse(get.getResponseBodyAsStream());
- }
- } catch (Exception e) {
- Log_OC.e(TAG, e.getMessage(), e);
- }
- }
- return null;
- }
-
- @Override
- public void cleanup() {
- Log_OC.i(TAG,"Cleanup");
- }
-
- @Override
- public String getId() {
- return mURL;
- }
-
- @Override
- public void cancel() {
- Log_OC.i(TAG,"Cancel");
- }
-}
diff --git a/src/main/java/com/owncloud/android/utils/glide/HttpStreamGlideContainerFetcher.java b/src/main/java/com/owncloud/android/utils/glide/HttpStreamGlideContainerFetcher.java
new file mode 100644
index 0000000000..2f3bc0425b
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/HttpStreamGlideContainerFetcher.java
@@ -0,0 +1,89 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Alejandro Bautista
+ * Copyright (C) 2017 Alejandro Bautista
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.utils.Log_OC;
+
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+
+import java.io.InputStream;
+
+/**
+ * Fetcher with Nextcloud client
+ */
+public class HttpStreamGlideContainerFetcher implements DataFetcher<InputStream> {
+
+ private static final String TAG = HttpStreamGlideContainerFetcher.class.getName();
+ private final GlideContainer container;
+
+ public HttpStreamGlideContainerFetcher(GlideContainer container) {
+ this.container = container;
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
+ Log_OC.d(TAG, "load thumbnail for: " + container.url);
+
+ GetMethod get;
+ try {
+ get = new GetMethod(container.url);
+ get.setRequestHeader("Cookie", "nc_sameSiteCookielax=true;nc_sameSiteCookiestrict=true");
+ get.setRequestHeader(RemoteOperation.OCS_API_HEADER, RemoteOperation.OCS_API_HEADER_VALUE);
+
+ int status = container.client.executeMethod(get);
+ if (status == HttpStatus.SC_OK) {
+ callback.onDataReady(get.getResponseBodyAsStream());
+ } else {
+ container.client.exhaustResponse(get.getResponseBodyAsStream());
+ callback.onLoadFailed(new Exception("Thumbnail failed"));
+ }
+ } catch (Exception e) {
+ Log_OC.e(TAG, e.getMessage(), e);
+ }
+ }
+
+ public void cleanup() {
+ Log_OC.i(TAG, "Cleanup");
+ }
+
+ @Override
+ public void cancel() {
+ Log_OC.i(TAG, "Cancel");
+ }
+
+ @NonNull
+ @Override
+ public Class<InputStream> getDataClass() {
+ return InputStream.class;
+ }
+
+ @NonNull
+ @Override
+ public DataSource getDataSource() {
+ return DataSource.REMOTE;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/NextcloudGlideModule.java b/src/main/java/com/owncloud/android/utils/glide/NextcloudGlideModule.java
new file mode 100644
index 0000000000..3b9d4fbff0
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/NextcloudGlideModule.java
@@ -0,0 +1,58 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.content.Context;
+import android.graphics.drawable.PictureDrawable;
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.Registry;
+import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.module.AppGlideModule;
+import com.caverock.androidsvg.SVG;
+import com.owncloud.android.utils.svg.SvgDecoder;
+import com.owncloud.android.utils.svg.SvgDrawableTranscoder;
+
+import java.io.InputStream;
+
+/**
+ * Module for generating api.
+ */
+@GlideModule
+public class NextcloudGlideModule extends AppGlideModule {
+ @Override
+ public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
+ registry.prepend(GlideContainer.class, InputStream.class, new GlideContainerModelLoaderFactory());
+ registry.prepend(GlideOcFile.class, InputStream.class, new OCFileModelLoaderFactory());
+ registry.prepend(String.class, InputStream.class, new StringModelLoaderFactory());
+ registry.prepend(GlideAvatar.class, InputStream.class, new AvatarModelLoaderFactory());
+ registry.register(SVG.class, PictureDrawable.class, new SvgDrawableTranscoder())
+ .append(InputStream.class, SVG.class, new SvgDecoder());
+ }
+
+ // Disable manifest parsing to avoid adding similar modules twice.
+ @Override
+ public boolean isManifestParsingEnabled() {
+ return false;
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/OCFileModelLoader.java b/src/main/java/com/owncloud/android/utils/glide/OCFileModelLoader.java
new file mode 100644
index 0000000000..a9bf0ea563
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/OCFileModelLoader.java
@@ -0,0 +1,55 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.owncloud.android.datamodel.OCFile;
+
+import java.io.InputStream;
+
+public class OCFileModelLoader implements ModelLoader<GlideOcFile, InputStream> {
+ @Override
+ public boolean handles(@NonNull GlideOcFile model) {
+ return true;
+ }
+
+ @Override
+ public LoadData<InputStream> buildLoadData(@NonNull GlideOcFile model, int width, int height, @NonNull Options options) {
+ OCFile file = model.getFile();
+
+ if (GlideOCFileType.thumbnail.equals(model.getType())) {
+ String path;
+ if (model.getFile().getStoragePath().isEmpty()) {
+ path = model.getPath();
+ } else {
+ path = model.getFile().getStoragePath();
+ }
+
+ return new LoadData<>(GlideKey.serverThumbnail(file), new FileFetcher(path));
+ } else {
+ return new LoadData<>(GlideKey.resizedImage(file), new FileFetcher(file.getStoragePath()));
+ }
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/OCFileModelLoaderFactory.java b/src/main/java/com/owncloud/android/utils/glide/OCFileModelLoaderFactory.java
new file mode 100644
index 0000000000..7892095e51
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/OCFileModelLoaderFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+
+import java.io.InputStream;
+
+public class OCFileModelLoaderFactory implements ModelLoaderFactory<GlideOcFile, InputStream> {
+
+ @NonNull
+ @Override
+ public ModelLoader<GlideOcFile, InputStream> build(@NonNull MultiModelLoaderFactory unused) {
+ return new OCFileModelLoader();
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing.
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/glide/StringModelLoaderFactory.java b/src/main/java/com/owncloud/android/utils/glide/StringModelLoaderFactory.java
new file mode 100644
index 0000000000..e545abe09f
--- /dev/null
+++ b/src/main/java/com/owncloud/android/utils/glide/StringModelLoaderFactory.java
@@ -0,0 +1,44 @@
+/*
+ * Nextcloud Android client application
+ *
+ * @author Tobias Kaminsky
+ * Copyright (C) 2018 Tobias Kaminsky
+ * Copyright (C) 2018 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.owncloud.android.utils.glide;
+
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+
+import java.io.InputStream;
+
+public class StringModelLoaderFactory implements ModelLoaderFactory<String, InputStream> {
+
+ @NonNull
+ @Override
+ public ModelLoader<String, InputStream> build(@NonNull MultiModelLoaderFactory unused) {
+ return new GlideStringStreamLoader();
+ }
+
+ @Override
+ public void teardown() {
+ // Do nothing.
+ }
+}
diff --git a/src/main/java/com/owncloud/android/utils/svg/SvgDecoder.java b/src/main/java/com/owncloud/android/utils/svg/SvgDecoder.java
index 5a4f869f45..dea6be78f9 100644
--- a/src/main/java/com/owncloud/android/utils/svg/SvgDecoder.java
+++ b/src/main/java/com/owncloud/android/utils/svg/SvgDecoder.java
@@ -11,6 +11,9 @@
package com.owncloud.android.utils.svg;
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.SimpleResource;
@@ -25,19 +28,13 @@ import java.io.InputStream;
* Decodes an SVG internal representation from an {@link InputStream}.
*/
public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {
- private int height = -1;
- private int width = -1;
-
- public SvgDecoder(){
-
- }
-
- public SvgDecoder(int height, int width) {
- this.height = height;
- this.width = width;
+ @Override
+ public boolean handles(@NonNull InputStream source, @NonNull Options options) {
+ return true;
}
- public Resource<SVG> decode(InputStream source, int w, int h) throws IOException {
+ public Resource<SVG> decode(@NonNull InputStream source, int width, int height, @NonNull Options options)
+ throws IOException {
try {
SVG svg = SVG.getFromInputStream(source);
@@ -54,9 +51,4 @@ public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {
throw new IOException("Cannot load SVG from stream", ex);
}
}
-
- @Override
- public String getId() {
- return "SvgDecoder.com.owncloud.android";
- }
}
diff --git a/src/main/java/com/owncloud/android/utils/svg/SvgDrawableTranscoder.java b/src/main/java/com/owncloud/android/utils/svg/SvgDrawableTranscoder.java
index 38cb2fb06d..80f39fe3b2 100644
--- a/src/main/java/com/owncloud/android/utils/svg/SvgDrawableTranscoder.java
+++ b/src/main/java/com/owncloud/android/utils/svg/SvgDrawableTranscoder.java
@@ -12,7 +12,10 @@ package com.owncloud.android.utils.svg;
import android.graphics.Picture;
import android.graphics.drawable.PictureDrawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.resource.SimpleResource;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
@@ -22,16 +25,12 @@ import com.caverock.androidsvg.SVG;
* Convert the {@link SVG}'s internal representation to an Android-compatible one ({@link Picture}).
*/
public class SvgDrawableTranscoder implements ResourceTranscoder<SVG, PictureDrawable> {
+ @Nullable
@Override
- public Resource<PictureDrawable> transcode(Resource<SVG> toTranscode) {
+ public Resource<PictureDrawable> transcode(@NonNull Resource<SVG> toTranscode, @NonNull Options options) {
SVG svg = toTranscode.get();
Picture picture = svg.renderToPicture();
PictureDrawable drawable = new PictureDrawable(picture);
- return new SimpleResource<PictureDrawable>(drawable);
- }
-
- @Override
- public String getId() {
- return "";
+ return new SimpleResource<>(drawable);
}
}
diff --git a/src/main/java/com/owncloud/android/utils/svg/SvgSoftwareLayerSetter.java b/src/main/java/com/owncloud/android/utils/svg/SvgSoftwareLayerSetter.java
index ab6f05d323..e8ca8acaaf 100644
--- a/src/main/java/com/owncloud/android/utils/svg/SvgSoftwareLayerSetter.java
+++ b/src/main/java/com/owncloud/android/utils/svg/SvgSoftwareLayerSetter.java
@@ -10,34 +10,45 @@
*/
package com.owncloud.android.utils.svg;
-import android.annotation.TargetApi;
import android.graphics.drawable.PictureDrawable;
-import android.os.Build;
+import android.support.annotation.Nullable;
import android.widget.ImageView;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.ImageViewTarget;
import com.bumptech.glide.request.target.Target;
-@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class SvgSoftwareLayerSetter<T> implements RequestListener<T, PictureDrawable> {
-
+/**
+ * Listener which updates the {@link ImageView} to be software rendered, because
+ * {@link com.caverock.androidsvg.SVG SVG}/{@link android.graphics.Picture Picture} can't render on
+ * a hardware backed {@link android.graphics.Canvas Canvas}.
+ */
+public class SvgSoftwareLayerSetter implements RequestListener<PictureDrawable> {
@Override
- public boolean onException(Exception e, T model, Target<PictureDrawable> target, boolean isFirstResource) {
- ImageView view = ((ImageViewTarget<?>) target).getView();
- if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
+ public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<PictureDrawable> target,
+ boolean isFirstResource) {
+ try {
+ ImageView view = ((ImageViewTarget<?>) target).getView();
view.setLayerType(ImageView.LAYER_TYPE_NONE, null);
+ } catch (Exception e1) {
+ // ignore
}
+
return false;
}
@Override
- public boolean onResourceReady(PictureDrawable resource, T model, Target<PictureDrawable> target,
- boolean isFromMemoryCache, boolean isFirstResource) {
- ImageView view = ((ImageViewTarget<?>) target).getView();
- if (Build.VERSION_CODES.HONEYCOMB <= Build.VERSION.SDK_INT) {
+ public boolean onResourceReady(PictureDrawable resource, Object model, Target<PictureDrawable> target,
+ DataSource dataSource, boolean isFirstResource) {
+ try {
+ ImageView view = ((ImageViewTarget<?>) target).getView();
view.setLayerType(ImageView.LAYER_TYPE_SOFTWARE, null);
+ } catch (Exception e) {
+ // ignore
}
+
return false;
}
-} \ No newline at end of file
+}
diff --git a/src/main/res/layout/grid_image.xml b/src/main/res/layout/grid_image.xml
index 545bccd683..fb3c5134c4 100644
--- a/src/main/res/layout/grid_image.xml
+++ b/src/main/res/layout/grid_image.xml
@@ -38,6 +38,14 @@
android:src="@drawable/folder"
android:contentDescription="@null"/>
+ <ImageView
+ android:id="@+id/play_icon"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ android:contentDescription="@string/thumbnail"
+ android:src="@drawable/ic_play_arrow"/>
<ImageView
android:id="@+id/favorite_action"
diff --git a/src/main/res/layout/grid_item.xml b/src/main/res/layout/grid_item.xml
index 29f8afc9fb..3ca160ee4a 100644
--- a/src/main/res/layout/grid_item.xml
+++ b/src/main/res/layout/grid_item.xml
@@ -38,6 +38,15 @@
android:contentDescription="@null"/>
<ImageView
+ android:id="@+id/play_icon"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ android:contentDescription="@string/thumbnail"
+ android:src="@drawable/ic_play_arrow"/>
+
+ <ImageView
android:id="@+id/favorite_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -105,4 +114,4 @@
android:textColor="@color/textColor"
android:textSize="@dimen/grid_item_text_size" />
-</com.owncloud.android.ui.SquareLinearLayout> \ No newline at end of file
+</com.owncloud.android.ui.SquareLinearLayout>
diff --git a/src/main/res/layout/list_item.xml b/src/main/res/layout/list_item.xml
index f19f82a5c3..35d1852b84 100644
--- a/src/main/res/layout/list_item.xml
+++ b/src/main/res/layout/list_item.xml
@@ -1,203 +1,212 @@
-<?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/>.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ListItemLayout"
- android:layout_width="match_parent"
- android:layout_height="@dimen/standard_list_item_size"
- android:background="@drawable/list_selector"
- android:descendantFocusability="blocksDescendants"
- android:foreground="?android:attr/selectableItemBackground"
- android:baselineAligned="false"
- android:orientation="horizontal">
-
- <RelativeLayout
- android:layout_width="@dimen/standard_list_item_size"
- android:layout_height="@dimen/standard_list_item_size"
- android:paddingBottom="@dimen/standard_padding"
- android:paddingEnd="@dimen/standard_quarter_padding"
- android:paddingLeft="@dimen/zero"
- android:paddingRight="@dimen/standard_quarter_padding"
- android:paddingStart="@dimen/zero"
- android:paddingTop="@dimen/standard_padding">
-
- <ImageView
- android:id="@+id/thumbnail"
- android:layout_width="@dimen/file_icon_size"
- android:layout_height="@dimen/file_icon_size"
- android:layout_centerInParent="true"
- android:layout_marginLeft="@dimen/standard_half_margin"
- android:layout_marginStart="@dimen/standard_half_margin"
- android:contentDescription="@null"
- android:src="@drawable/folder" />
-
- <ImageView
- android:id="@+id/favorite_action"
- android:layout_width="@dimen/list_item_favorite_action_layout_width"
- android:layout_height="@dimen/list_item_favorite_action_layout_height"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_marginEnd="@dimen/standard_quarter_margin"
- android:layout_marginRight="@dimen/standard_quarter_margin"
- android:contentDescription="@string/favorite"
- android:src="@drawable/badge_favorite" />
-
- <ImageView
- android:id="@+id/keptOfflineIcon"
- android:layout_width="@dimen/list_item_kept_offline_icon_layout_width"
- android:layout_height="@dimen/list_item_kept_offline_icon_layout_height"
- android:layout_alignParentBottom="true"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_marginEnd="@dimen/list_item_kept_offline_icon_layout_right_end_margin"
- android:layout_marginRight="@dimen/list_item_kept_offline_icon_layout_right_end_margin"
- android:contentDescription="@string/available_offline_icon"
- android:src="@drawable/ic_available_offline" />
-
- <ImageView
- android:id="@+id/localFileIndicator"
- android:layout_width="@dimen/list_item_local_file_indicator_layout_width"
- android:layout_height="@dimen/list_item_local_file_indicator_layout_height"
- android:layout_alignParentBottom="true"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_marginEnd="@dimen/standard_quarter_margin"
- android:layout_marginRight="@dimen/standard_quarter_margin"
- android:contentDescription="@string/downloader_download_succeeded_ticker"
- android:scaleType="fitCenter"
- android:src="@drawable/ic_synced" />
-
- </RelativeLayout>
-
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:gravity="top"
- android:orientation="vertical"
- android:paddingTop="@dimen/standard_padding">
-
- <TextView
- android:id="@+id/Filename"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:ellipsize="middle"
- android:singleLine="true"
- android:text="@string/placeholder_filename"
- android:textColor="@color/textColor"
- android:textSize="@dimen/two_line_primary_text_size" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/file_size"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/placeholder_fileSize"
- android:textColor="@color/list_item_lastmod_and_filesize_text"
- android:textSize="@dimen/two_line_secondary_text_size" />
-
- <TextView
- android:id="@+id/file_separator"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="end"
- android:paddingEnd="@dimen/standard_quarter_padding"
- android:paddingLeft="@dimen/zero"
- android:paddingRight="@dimen/standard_quarter_padding"
- android:paddingStart="@dimen/zero"
- android:text="@string/info_separator"
- android:textColor="@color/list_item_lastmod_and_filesize_text"
- android:textSize="@dimen/two_line_secondary_text_size" />
-
- <TextView
- android:id="@+id/last_mod"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="end"
- android:text="@string/placeholder_media_time"
- android:textColor="@color/list_item_lastmod_and_filesize_text"
- android:textSize="@dimen/two_line_secondary_text_size" />
-
- </LinearLayout>
-
- </LinearLayout>
-
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingEnd="@dimen/zero"
- android:paddingLeft="@dimen/standard_half_padding"
- android:paddingRight="@dimen/zero"
- android:paddingStart="@dimen/standard_half_padding">
-
- <ImageView
- android:id="@+id/sharedIcon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:clickable="true"
- android:contentDescription="@string/shared_icon_share"
- android:focusable="true"
- android:paddingEnd="@dimen/list_item_share_right_margin"
- android:paddingLeft="@dimen/standard_half_padding"
- android:paddingRight="@dimen/list_item_share_right_margin"
- android:paddingStart="@dimen/standard_half_padding"
- android:src="@drawable/ic_unshared" />
-
- <ImageView
- android:id="@+id/custom_checkbox"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/sharedIcon"
- android:layout_toRightOf="@id/sharedIcon"
- android:clickable="false"
- android:contentDescription="@string/checkbox"
- android:focusable="false"
- android:paddingEnd="@dimen/alternate_padding"
- android:paddingLeft="@dimen/standard_half_padding"
- android:paddingRight="@dimen/alternate_padding"
- android:paddingStart="@dimen/standard_half_padding"
- android:src="@drawable/ic_checkbox_blank_outline" />
-
- <ImageView
- android:id="@+id/overflow_menu"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/custom_checkbox"
- android:layout_toRightOf="@id/custom_checkbox"
- android:clickable="true"
- android:contentDescription="@string/overflow_menu"
- android:focusable="true"
- android:paddingEnd="@dimen/alternate_padding"
- android:paddingLeft="@dimen/standard_half_padding"
- android:paddingRight="@dimen/alternate_padding"
- android:paddingStart="@dimen/standard_half_padding"
- android:src="@drawable/ic_dots_vertical" />
-
- </RelativeLayout>
-
-</LinearLayout>
+<?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/>.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ListItemLayout"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/standard_list_item_size"
+ android:background="@drawable/list_selector"
+ android:descendantFocusability="blocksDescendants"
+ android:foreground="?android:attr/selectableItemBackground"
+ android:baselineAligned="false"
+ android:orientation="horizontal">
+
+ <RelativeLayout
+ android:layout_width="@dimen/standard_list_item_size"
+ android:layout_height="@dimen/standard_list_item_size"
+ android:paddingBottom="@dimen/standard_padding"
+ android:paddingEnd="@dimen/standard_quarter_padding"
+ android:paddingLeft="@dimen/zero"
+ android:paddingRight="@dimen/standard_quarter_padding"
+ android:paddingStart="@dimen/zero"
+ android:paddingTop="@dimen/standard_padding">
+
+ <ImageView
+ android:id="@+id/thumbnail"
+ android:layout_width="@dimen/file_icon_size"
+ android:layout_height="@dimen/file_icon_size"
+ android:layout_centerInParent="true"
+ android:layout_marginLeft="@dimen/standard_half_margin"
+ android:layout_marginStart="@dimen/standard_half_margin"
+ android:contentDescription="@null"
+ android:src="@drawable/file_image"/>
+
+ <ImageView
+ android:id="@+id/play_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:visibility="gone"
+ android:contentDescription="@string/thumbnail"
+ android:src="@drawable/ic_play_arrow"/>
+
+ <ImageView
+ android:id="@+id/favorite_action"
+ android:layout_width="@dimen/list_item_favorite_action_layout_width"
+ android:layout_height="@dimen/list_item_favorite_action_layout_height"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_marginEnd="@dimen/standard_quarter_margin"
+ android:layout_marginRight="@dimen/standard_quarter_margin"
+ android:contentDescription="@string/favorite"
+ android:src="@drawable/badge_favorite" />
+
+ <ImageView
+ android:id="@+id/keptOfflineIcon"
+ android:layout_width="@dimen/list_item_kept_offline_icon_layout_width"
+ android:layout_height="@dimen/list_item_kept_offline_icon_layout_height"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginEnd="@dimen/list_item_kept_offline_icon_layout_right_end_margin"
+ android:layout_marginRight="@dimen/list_item_kept_offline_icon_layout_right_end_margin"
+ android:contentDescription="@string/available_offline_icon"
+ android:src="@drawable/ic_available_offline" />
+
+ <ImageView
+ android:id="@+id/localFileIndicator"
+ android:layout_width="@dimen/list_item_local_file_indicator_layout_width"
+ android:layout_height="@dimen/list_item_local_file_indicator_layout_height"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_marginEnd="@dimen/standard_quarter_margin"
+ android:layout_marginRight="@dimen/standard_quarter_margin"
+ android:contentDescription="@string/downloader_download_succeeded_ticker"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_synced" />
+
+ </RelativeLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="top"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/standard_padding">
+
+ <TextView
+ android:id="@+id/Filename"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:ellipsize="middle"
+ android:singleLine="true"
+ android:text="@string/placeholder_filename"
+ android:textColor="@color/textColor"
+ android:textSize="@dimen/two_line_primary_text_size" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <TextView
+ android:id="@+id/file_size"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/placeholder_fileSize"
+ android:textColor="@color/list_item_lastmod_and_filesize_text"
+ android:textSize="@dimen/two_line_secondary_text_size" />
+
+ <TextView
+ android:id="@+id/file_separator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="end"
+ android:paddingEnd="@dimen/standard_quarter_padding"
+ android:paddingLeft="@dimen/zero"
+ android:paddingRight="@dimen/standard_quarter_padding"
+ android:paddingStart="@dimen/zero"
+ android:text="@string/info_separator"
+ android:textColor="@color/list_item_lastmod_and_filesize_text"
+ android:textSize="@dimen/two_line_secondary_text_size" />
+
+ <TextView
+ android:id="@+id/last_mod"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="end"
+ android:text="@string/placeholder_media_time"
+ android:textColor="@color/list_item_lastmod_and_filesize_text"
+ android:textSize="@dimen/two_line_secondary_text_size" />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingEnd="@dimen/zero"
+ android:paddingLeft="@dimen/standard_half_padding"
+ android:paddingRight="@dimen/zero"
+ android:paddingStart="@dimen/standard_half_padding">
+
+ <ImageView
+ android:id="@+id/sharedIcon"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_centerVertical="true"
+ android:clickable="true"
+ android:contentDescription="@string/shared_icon_share"
+ android:focusable="true"
+ android:paddingEnd="@dimen/list_item_share_right_margin"
+ android:paddingLeft="@dimen/standard_half_padding"
+ android:paddingRight="@dimen/list_item_share_right_margin"
+ android:paddingStart="@dimen/standard_half_padding"
+ android:src="@drawable/ic_unshared" />
+
+ <ImageView
+ android:id="@+id/custom_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/sharedIcon"
+ android:layout_toRightOf="@id/sharedIcon"
+ android:clickable="false"
+ android:contentDescription="@string/checkbox"
+ android:focusable="false"
+ android:paddingEnd="@dimen/alternate_padding"
+ android:paddingLeft="@dimen/standard_half_padding"
+ android:paddingRight="@dimen/alternate_padding"
+ android:paddingStart="@dimen/standard_half_padding"
+ android:src="@drawable/ic_checkbox_blank_outline" />
+
+ <ImageView
+ android:id="@+id/overflow_menu"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@id/custom_checkbox"
+ android:layout_toRightOf="@id/custom_checkbox"
+ android:clickable="true"
+ android:contentDescription="@string/overflow_menu"
+ android:focusable="true"
+ android:paddingEnd="@dimen/alternate_padding"
+ android:paddingLeft="@dimen/standard_half_padding"
+ android:paddingRight="@dimen/alternate_padding"
+ android:paddingStart="@dimen/standard_half_padding"
+ android:src="@drawable/ic_dots_vertical" />
+
+ </RelativeLayout>
+
+</LinearLayout>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 43d64a0541..c781e4b0d9 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -818,9 +818,8 @@
<string name="file_rename">Rename</string>
<string name="fab_label">Add or upload</string>
<string name="account_creation_failed">Account creation failed</string>
-
<string name="single_sign_on_request_token" formatted="true">Allow %1$s to access your Nextcloud account %2$s?</string>
<string name="permission_deny">Deny</string>
<string name="permission_allow">Allow</string>
-
+ <string name="thumbnail">Thumbnail</string>
</resources>
diff --git a/src/main/res/xml/exposed_filepaths.xml b/src/main/res/xml/exposed_filepaths.xml
index 154694811d..fa1b6209aa 100644
--- a/src/main/res/xml/exposed_filepaths.xml
+++ b/src/main/res/xml/exposed_filepaths.xml
@@ -1,11 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
-<paths>
+<paths xmlns:tools="http://schemas.android.com/tools">
+ <cache-path
+ name="share"
+ path="image_manager_disk_cache"
+ tools:path="DiskCache.Factory.DEFAULT_DISK_CACHE_DIR"/>
<files-path name="user_files_internal" path="nextcloud/"/>
<files-path
path="log/"
name="log"/>
<external-path name="external_files" path="."/>
<root-path name="external_files" path="/storage/" />
+
<!-- yes, valid for ALL external storage and not only our app folder, since we can't use @string/data_folder
as a value for 'path' attribute; in practice, we will only generate URIs in our folders, of course -->
</paths>
diff --git a/src/main/res/xml/filepaths.xml b/src/main/res/xml/filepaths.xml
new file mode 100644
index 0000000000..9e8de1ed2e
--- /dev/null
+++ b/src/main/res/xml/filepaths.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Nextcloud Android client application
+
+ Copyright (C) 2018 Tobias Kaminsky
+ Copyright (C) 2018 Nextcloud
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+
+ You should have received a copy of the GNU Affero General Public
+ License along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+<paths xmlns:tools="http://schemas.android.com/tools">
+ <cache-path
+ name="share"
+ path="image_manager_disk_cache"
+ tools:path="DiskCache.Factory.DEFAULT_DISK_CACHE_DIR"/>
+</paths>