Merge remote-tracking branch 'origin/master' into dev

This commit is contained in:
Tobias Kaminsky 2024-09-04 02:31:25 +02:00
commit afaef3bc3b
10 changed files with 108 additions and 63 deletions

View file

@ -6,47 +6,72 @@
*/
package com.nmc.android.ui
import androidx.annotation.UiThread
import androidx.test.core.app.launchActivity
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import org.junit.Rule
import com.owncloud.android.utils.EspressoIdlingResource
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class LauncherActivityIT : AbstractIT() {
@get:Rule
val activityRule = ActivityScenarioRule(LauncherActivity::class.java)
@Before
fun registerIdlingResource() {
IdlingRegistry.getInstance().register(EspressoIdlingResource.countingIdlingResource)
}
@Test
fun testSplashScreenWithEmptyTitlesShouldHideTitles() {
waitForIdleSync()
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.splashScreenBold)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
onView(withId(R.id.splashScreenNormal)).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
@After
fun unregisterIdlingResource() {
IdlingRegistry.getInstance().unregister(EspressoIdlingResource.countingIdlingResource)
}
@Test
fun testSplashScreenWithTitlesShouldShowTitles() {
waitForIdleSync()
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
activityRule.scenario.onActivity {
it.setSplashTitles("Example", "Cloud")
@UiThread
fun testSplashScreenWithEmptyTitlesShouldHideTitles() {
launchActivity<LauncherActivity>().use { scenario ->
scenario.onActivity { _ ->
onIdleSync {
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
onView(
withId(R.id.splashScreenBold)
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
onView(
withId(R.id.splashScreenNormal)
).check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
}
}
}
}
val onePercentArea = ViewMatchers.isDisplayingAtLeast(1)
onView(withId(R.id.splashScreenBold)).check(matches(onePercentArea))
onView(withId(R.id.splashScreenNormal)).check(matches(onePercentArea))
@Test
@UiThread
fun testSplashScreenWithTitlesShouldShowTitles() {
launchActivity<LauncherActivity>().use { scenario ->
scenario.onActivity {
onIdleSync {
onView(withId(R.id.ivSplash)).check(matches(isCompletelyDisplayed()))
EspressoIdlingResource.increment()
it.setSplashTitles("Example", "Cloud")
EspressoIdlingResource.decrement()
val onePercentArea = ViewMatchers.isDisplayingAtLeast(1)
onView(withId(R.id.splashScreenBold)).check(matches(onePercentArea))
onView(withId(R.id.splashScreenNormal)).check(matches(onePercentArea))
}
}
}
}
}

View file

@ -156,11 +156,11 @@ class FileDownloadWorker(
}
private fun setWorkerState(user: User?) {
WorkerStateLiveData.instance().setWorkState(WorkerState.Download(user, currentDownload))
WorkerStateLiveData.instance().setWorkState(WorkerState.DownloadStarted(user, currentDownload))
}
private fun setIdleWorkerState() {
WorkerStateLiveData.instance().setWorkState(WorkerState.Idle(getCurrentFile()))
WorkerStateLiveData.instance().setWorkState(WorkerState.DownloadFinished(getCurrentFile()))
}
private fun removePendingDownload(accountName: String?) {

View file

@ -102,6 +102,9 @@ class FileUploadWorker(
val result = retrievePagesBySortingUploadsByID()
backgroundJobManager.logEndOfWorker(BackgroundJobManagerImpl.formatClassTag(this::class), result)
notificationManager.dismissNotification()
if (result == Result.success()) {
setIdleWorkerState()
}
result
} catch (t: Throwable) {
Log_OC.e(TAG, "Error caught at FileUploadWorker $t")
@ -120,11 +123,11 @@ class FileUploadWorker(
}
private fun setWorkerState(user: User?, uploads: List<OCUpload>) {
WorkerStateLiveData.instance().setWorkState(WorkerState.Upload(user, uploads))
WorkerStateLiveData.instance().setWorkState(WorkerState.UploadStarted(user, uploads))
}
private fun setIdleWorkerState() {
WorkerStateLiveData.instance().setWorkState(WorkerState.Idle(currentUploadFileOperation?.file))
WorkerStateLiveData.instance().setWorkState(WorkerState.UploadFinished(currentUploadFileOperation?.file))
}
@Suppress("ReturnCount")

View file

@ -13,7 +13,8 @@ import com.owncloud.android.db.OCUpload
import com.owncloud.android.operations.DownloadFileOperation
sealed class WorkerState {
data class Idle(var currentFile: OCFile?) : WorkerState()
data class Download(var user: User?, var currentDownload: DownloadFileOperation?) : WorkerState()
data class Upload(var user: User?, var uploads: List<OCUpload>) : WorkerState()
data class DownloadFinished(var currentFile: OCFile?) : WorkerState()
data class DownloadStarted(var user: User?, var currentDownload: DownloadFileOperation?) : WorkerState()
data class UploadFinished(var currentFile: OCFile?) : WorkerState()
data class UploadStarted(var user: User?, var uploads: List<OCUpload>) : WorkerState()
}

View file

@ -35,7 +35,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
@ -98,7 +97,6 @@ import com.owncloud.android.ui.asynctasks.CheckAvailableSpaceTask;
import com.owncloud.android.ui.asynctasks.FetchRemoteFileTask;
import com.owncloud.android.ui.asynctasks.GetRemoteFileTask;
import com.owncloud.android.ui.dialog.SendShareDialog;
import com.owncloud.android.ui.dialog.setupEncryption.SetupEncryptionDialogFragment;
import com.owncloud.android.ui.dialog.SortingOrderDialogFragment;
import com.owncloud.android.ui.dialog.StoragePermissionDialogFragment;
import com.owncloud.android.ui.events.SearchEvent;
@ -158,7 +156,6 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import kotlin.Unit;
import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR;
import static com.owncloud.android.ui.dialog.setupEncryption.SetupEncryptionDialogFragment.SETUP_ENCRYPTION_DIALOG_TAG;
import static com.owncloud.android.utils.PermissionUtil.PERMISSION_CHOICE_DIALOG_TAG;
/**
@ -1593,11 +1590,13 @@ public class FileDisplayActivity extends FileActivity
private void observeWorkerState() {
WorkerStateLiveData.Companion.instance().observe(this, state -> {
if (state instanceof WorkerState.Download) {
if (state instanceof WorkerState.DownloadStarted) {
Log_OC.d(TAG, "Download worker started");
handleDownloadWorkerState();
} else if (state instanceof WorkerState.Idle) {
} else if (state instanceof WorkerState.DownloadFinished) {
fileDownloadProgressListener = null;
} else if (state instanceof WorkerState.UploadFinished) {
refreshList();
}
});
}

View file

@ -16,7 +16,6 @@ import android.accounts.AccountManagerCallback;
import android.accounts.AccountManagerFuture;
import android.accounts.OperationCanceledException;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.view.MenuItem;
@ -460,10 +459,10 @@ public class ManageAccountsActivity extends FileActivity implements UserListAdap
private void observeWorkerState() {
WorkerStateLiveData.Companion.instance().observe(this, state -> {
if (state instanceof WorkerState.Download) {
if (state instanceof WorkerState.DownloadStarted) {
Log_OC.d(TAG, "Download worker started");
workerAccountName = ((WorkerState.Download) state).getUser().getAccountName();
workerCurrentDownload = ((WorkerState.Download) state).getCurrentDownload();
workerAccountName = ((WorkerState.DownloadStarted) state).getUser().getAccountName();
workerCurrentDownload = ((WorkerState.DownloadStarted) state).getCurrentDownload();
}
});
}

View file

@ -34,7 +34,6 @@ import com.nextcloud.model.WorkerStateLiveData;
import com.owncloud.android.R;
import com.owncloud.android.databinding.UploadListLayoutBinding;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.datamodel.SyncedFolder;
import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.UploadsStorageManager;
import com.owncloud.android.lib.common.operations.RemoteOperation;
@ -140,7 +139,7 @@ public class UploadListActivity extends FileActivity {
private void observeWorkerState() {
WorkerStateLiveData.Companion.instance().observe(this, state -> {
if (state instanceof WorkerState.Upload) {
if (state instanceof WorkerState.UploadStarted) {
Log_OC.d(TAG, "Upload worker started");
handleUploadWorkerState();
}

View file

@ -1015,6 +1015,15 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
return lastTimestamp;
}
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
super.onViewRecycled(holder);
if (holder instanceof ListGridImageViewHolder listGridImageViewHolder) {
LoaderImageView thumbnailShimmer = listGridImageViewHolder.getShimmerThumbnail();
DisplayUtils.stopShimmer(thumbnailShimmer, listGridImageViewHolder.getThumbnail());
}
}
@Override
public void avatarGenerated(Drawable avatarDrawable, Object callContext) {
((ImageView) callContext).setImageDrawable(avatarDrawable);

View file

@ -279,7 +279,7 @@ class PreviewImageActivity : FileActivity(), FileFragment.ContainerActivity, OnR
private fun observeWorkerState() {
WorkerStateLiveData.instance().observe(this) { state: WorkerState? ->
when (state) {
is WorkerState.Download -> {
is WorkerState.DownloadStarted -> {
Log_OC.d(TAG, "Download worker started")
isDownloadWorkStarted = true
@ -288,7 +288,7 @@ class PreviewImageActivity : FileActivity(), FileFragment.ContainerActivity, OnR
}
}
is WorkerState.Idle -> {
is WorkerState.DownloadFinished -> {
Log_OC.d(TAG, "Download worker stopped")
isDownloadWorkStarted = false
@ -298,7 +298,7 @@ class PreviewImageActivity : FileActivity(), FileFragment.ContainerActivity, OnR
}
else -> {
Log_OC.d(TAG, "Download worker stopped")
Log_OC.d(TAG, "Worker stopped")
isDownloadWorkStarted = false
}
}

View file

@ -927,12 +927,20 @@ public final class DisplayUtils {
Bitmap thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(
ThumbnailsCacheManager.PREFIX_THUMBNAIL + file.getRemoteId());
if (thumbnail != null) {
// If thumbnail is already in cache, display it immediately
thumbnailView.setImageBitmap(thumbnail);
stopShimmer(shimmerThumbnail, thumbnailView);
return;
}
for (ThumbnailsCacheManager.ThumbnailGenerationTask task : asyncTasks) {
if (file.getRemoteId() != null && task.getImageKey() != null &&
file.getRemoteId().equals(task.getImageKey())) {
return;
}
}
try {
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
new ThumbnailsCacheManager.ThumbnailGenerationTask(thumbnailView,
@ -941,32 +949,34 @@ public final class DisplayUtils {
asyncTasks,
gridView,
file.getRemoteId());
if (thumbnail == null) {
Drawable drawable = MimeTypeUtil.getFileTypeIcon(file.getMimeType(),
file.getFileName(),
context,
viewThemeUtils);
if (drawable == null) {
drawable = ResourcesCompat.getDrawable(context.getResources(),
R.drawable.file_image,
null);
}
if (drawable == null) {
drawable = new ColorDrawable(Color.GRAY);
}
int px = ThumbnailsCacheManager.getThumbnailDimension();
thumbnail = BitmapUtils.drawableToBitmap(drawable, px, px);
Drawable drawable = MimeTypeUtil.getFileTypeIcon(file.getMimeType(),
file.getFileName(),
context,
viewThemeUtils);
if (drawable == null) {
drawable = ResourcesCompat.getDrawable(context.getResources(),
R.drawable.file_image,
null);
}
if (drawable == null) {
drawable = new ColorDrawable(Color.GRAY);
}
int px = ThumbnailsCacheManager.getThumbnailDimension();
thumbnail = BitmapUtils.drawableToBitmap(drawable, px, px);
final ThumbnailsCacheManager.AsyncThumbnailDrawable asyncDrawable =
new ThumbnailsCacheManager.AsyncThumbnailDrawable(context.getResources(),
thumbnail, task);
if (shimmerThumbnail != null && shimmerThumbnail.getVisibility() == View.GONE) {
if (gridView) {
configShimmerGridImageSize(shimmerThumbnail, preferences.getGridColumns());
}
startShimmer(shimmerThumbnail, thumbnailView);
if (shimmerThumbnail != null) {
shimmerThumbnail.postDelayed(() -> {
if (thumbnailView.getDrawable() == null) {
if (gridView) {
configShimmerGridImageSize(shimmerThumbnail, preferences.getGridColumns());
}
startShimmer(shimmerThumbnail, thumbnailView);
}
}, 100);
}
task.setListener(new ThumbnailsCacheManager.ThumbnailGenerationTask.Listener() {