mirror of
https://github.com/nextcloud/android.git
synced 2024-12-22 00:34:31 +03:00
Merge remote-tracking branch 'origin/master' into dev
This commit is contained in:
commit
9755f912f7
17 changed files with 609 additions and 566 deletions
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:noble@sha256:e3f92abc0967a6c19d0dfa2d55838833e947b9d74edbcb0113e48535ad4be12a
|
||||
FROM ubuntu:noble@sha256:2e863c44b718727c860746568e1d54afd13b2fa71b160f5cd9058fc436217b30
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV ANDROID_HOME=/usr/lib/android-sdk
|
||||
|
|
20
.drone.yml
20
.drone.yml
|
@ -36,7 +36,7 @@ services:
|
|||
image: ghcr.io/nextcloud/continuous-integration-shallow-server:latest # also change in updateScreenshots.sh
|
||||
environment:
|
||||
EVAL: true
|
||||
SERVER_VERSION: 'stable27'
|
||||
SERVER_VERSION: 'stable29'
|
||||
commands:
|
||||
- BRANCH="$SERVER_VERSION" /usr/local/bin/initnc.sh
|
||||
- echo 127.0.0.1 server >> /etc/hosts
|
||||
|
@ -48,13 +48,13 @@ services:
|
|||
- su www-data -c "php /var/www/html/occ group:add users"
|
||||
- su www-data -c "php /var/www/html/occ group:adduser users user1"
|
||||
- su www-data -c "php /var/www/html/occ group:adduser users user2"
|
||||
- su www-data -c "git clone -b $SERVER_VERSION https://github.com/nextcloud/activity.git /var/www/html/apps/activity/"
|
||||
- su www-data -c "git clone --depth 1 -b $SERVER_VERSION https://github.com/nextcloud/activity.git /var/www/html/apps/activity/"
|
||||
- su www-data -c "php /var/www/html/occ app:enable activity"
|
||||
- su www-data -c "git clone -b $SERVER_VERSION https://github.com/nextcloud/text.git /var/www/html/apps/text/"
|
||||
- su www-data -c "git clone --depth 1 -b $SERVER_VERSION https://github.com/nextcloud/text.git /var/www/html/apps/text/"
|
||||
- su www-data -c "php /var/www/html/occ app:enable text"
|
||||
- su www-data -c "git clone -b $SERVER_VERSION https://github.com/nextcloud/end_to_end_encryption.git /var/www/html/apps/end_to_end_encryption/"
|
||||
- su www-data -c "git clone --depth 1 -b $SERVER_VERSION https://github.com/nextcloud/end_to_end_encryption.git /var/www/html/apps/end_to_end_encryption/"
|
||||
- su www-data -c "php /var/www/html/occ app:enable end_to_end_encryption"
|
||||
- su www-data -c "git clone -b $SERVER_VERSION https://github.com/nextcloud/photos.git /var/www/html/apps/photos/"
|
||||
- su www-data -c "git clone --depth 1 -b $SERVER_VERSION https://github.com/nextcloud/photos.git /var/www/html/apps/photos/"
|
||||
- su www-data -c "cd /var/www/html/apps/photos; composer install"
|
||||
- su www-data -c "php /var/www/html/occ app:enable -f photos"
|
||||
- /usr/local/bin/run.sh
|
||||
|
@ -106,13 +106,13 @@ services:
|
|||
- su www-data -c "php /var/www/html/occ group:add users"
|
||||
- su www-data -c "php /var/www/html/occ group:adduser users user1"
|
||||
- su www-data -c "php /var/www/html/occ group:adduser users user2"
|
||||
- su www-data -c "git clone -b master https://github.com/nextcloud/activity.git /var/www/html/apps/activity/"
|
||||
- su www-data -c "git clone --depth 1 -b master https://github.com/nextcloud/activity.git /var/www/html/apps/activity/"
|
||||
- su www-data -c "php /var/www/html/occ app:enable activity"
|
||||
- su www-data -c "git clone -b main https://github.com/nextcloud/text.git /var/www/html/apps/text/"
|
||||
- su www-data -c "git clone --depth 1 -b main https://github.com/nextcloud/text.git /var/www/html/apps/text/"
|
||||
- su www-data -c "php /var/www/html/occ app:enable text"
|
||||
- su www-data -c "git clone -b master https://github.com/nextcloud/end_to_end_encryption/ /var/www/html/apps/end_to_end_encryption/"
|
||||
- su www-data -c "git clone --depth 1 -b master https://github.com/nextcloud/end_to_end_encryption/ /var/www/html/apps/end_to_end_encryption/"
|
||||
- su www-data -c "php /var/www/html/occ app:enable end_to_end_encryption"
|
||||
- su www-data -c "git clone https://github.com/nextcloud/photos.git /var/www/html/apps/photos/"
|
||||
- su www-data -c "git clone --depth 1 https://github.com/nextcloud/photos.git /var/www/html/apps/photos/"
|
||||
- su www-data -c "cd /var/www/html/apps/photos; composer install"
|
||||
- su www-data -c "php /var/www/html/occ app:enable -f photos"
|
||||
- /usr/local/bin/run.sh
|
||||
|
@ -183,6 +183,6 @@ name: GIT_TOKEN
|
|||
data: XIoa9IYq+xQ+N5iln8dlpWv0jV6ROr7HuE24ioUr4uQ8m8SjyH0yognWYLYLqnbTKrFWlFZiEMQTH/sZiWjRFvV1iL0=
|
||||
---
|
||||
kind: signature
|
||||
hmac: 5d64f2d46fc49a1e7dad823b7ac9c0ee3762a748ab025782a20292887607d831
|
||||
hmac: a659f1f06a609743077c77b6a07a369e55db67adbd8343fc027ac1c9473d1a43
|
||||
|
||||
...
|
||||
|
|
4
.github/workflows/screenShotTest.yml
vendored
4
.github/workflows/screenShotTest.yml
vendored
|
@ -56,7 +56,7 @@ jobs:
|
|||
|
||||
- name: create AVD and generate snapshot for caching
|
||||
if: steps.avd-cache.outputs.cache-hit != 'true'
|
||||
uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # v2.30.1
|
||||
uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 # v2.31.0
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
force-avd-creation: false
|
||||
|
@ -84,7 +84,7 @@ jobs:
|
|||
- name: Run screenshot tests
|
||||
env:
|
||||
SHOT_TEST: "true"
|
||||
uses: reactivecircus/android-emulator-runner@6b0df4b0efb23bb0ec63d881db79aefbc976e4b2 # v2.30.1
|
||||
uses: reactivecircus/android-emulator-runner@77986be26589807b8ebab3fde7bbf5c60dabec32 # v2.31.0
|
||||
with:
|
||||
api-level: ${{ matrix.api-level }}
|
||||
force-avd-creation: false
|
||||
|
|
2
.github/workflows/unit-tests.yml
vendored
2
.github/workflows/unit-tests.yml
vendored
|
@ -33,7 +33,7 @@ jobs:
|
|||
if: ${{ always() }}
|
||||
run: scripts/deleteOldComments.sh "test" "Unit" ${{github.event.number}}
|
||||
- name: Run unit tests with coverage
|
||||
uses: gradle/gradle-build-action@4c39dd82cd5e1ec7c6fa0173bb41b4b6bb3b86ff # v3.3.2
|
||||
uses: gradle/gradle-build-action@66535aaf56f831b35e3a8481c9c99b665b84dd45 # v3.4.2
|
||||
with:
|
||||
arguments: jacocoTestGplayDebugUnitTest
|
||||
- name: Upload failing results
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.gradle.internal.jvm.Jvm
|
|||
buildscript {
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:$androidPluginVersion"
|
||||
classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:6.0.16'
|
||||
classpath 'com.github.spotbugs.snom:spotbugs-gradle-plugin:6.0.18'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.6"
|
||||
classpath "commons-httpclient:commons-httpclient:3.1@jar" // remove after entire switch to lib v2
|
||||
|
|
|
@ -227,7 +227,7 @@ class ChooseAccountDialogFragment :
|
|||
|
||||
binding.currentAccount.status.let {
|
||||
if (newStatus.message.isNullOrBlank()) {
|
||||
it.text = ""
|
||||
it.text = getString(R.string.empty)
|
||||
it.visibility = View.GONE
|
||||
} else {
|
||||
it.text = newStatus.message
|
||||
|
|
|
@ -188,7 +188,7 @@ class PassCodeActivity : AppCompatActivity(), Injectable {
|
|||
passCodeDigits?.set(passCodeIndex - 1, "")
|
||||
}
|
||||
|
||||
passCodeEditTexts[passCodeIndex - 1]?.setText("")
|
||||
passCodeEditTexts[passCodeIndex - 1]?.setText(R.string.empty)
|
||||
|
||||
changed = false
|
||||
} else if (!changed) {
|
||||
|
|
|
@ -92,7 +92,7 @@ class CreateFolderDialogFragment : DialogFragment(), DialogInterface.OnClickList
|
|||
val view: View = binding.root
|
||||
|
||||
// Setup layout
|
||||
binding.userInput.setText("")
|
||||
binding.userInput.setText(R.string.empty)
|
||||
viewThemeUtils?.material?.colorTextInputLayout(binding.userInputContainer)
|
||||
|
||||
val parentFolder = requireArguments().getParcelableArgument(ARG_PARENT_FOLDER, OCFile::class.java)
|
||||
|
|
|
@ -112,7 +112,7 @@ class SharePasswordDialogFragment : DialogFragment(), Injectable {
|
|||
binding = PasswordDialogBinding.inflate(inflater, null, false)
|
||||
|
||||
// Setup layout
|
||||
binding?.sharePassword?.setText("")
|
||||
binding?.sharePassword?.setText(R.string.empty)
|
||||
viewThemeUtils?.material?.colorTextInputLayout(binding!!.sharePasswordContainer)
|
||||
|
||||
val neutralButtonTextId: Int
|
||||
|
|
|
@ -402,7 +402,7 @@ class FileDetailsSharingProcessFragment :
|
|||
binding.noteText.setText(share?.note)
|
||||
} else {
|
||||
binding.shareProcessBtnNext.text = requireContext().resources.getString(R.string.send_share)
|
||||
binding.noteText.setText("")
|
||||
binding.noteText.setText(R.string.empty)
|
||||
}
|
||||
shareProcessStep = SCREEN_TYPE_NOTE
|
||||
}
|
||||
|
@ -447,7 +447,7 @@ class FileDetailsSharingProcessFragment :
|
|||
private fun showChangeNameInput(isChecked: Boolean) {
|
||||
binding.shareProcessChangeNameContainer.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||
if (!isChecked) {
|
||||
binding.shareProcessChangeName.setText("")
|
||||
binding.shareProcessChangeName.setText(R.string.empty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,7 +474,7 @@ class FileDetailsSharingProcessFragment :
|
|||
// reset the expiration date if switch is unchecked
|
||||
if (!isChecked) {
|
||||
chosenExpDateInMills = -1
|
||||
binding.shareProcessSelectExpDate.text = ""
|
||||
binding.shareProcessSelectExpDate.text = getString(R.string.empty)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -483,7 +483,7 @@ class FileDetailsSharingProcessFragment :
|
|||
|
||||
// reset the password if switch is unchecked
|
||||
if (!isChecked) {
|
||||
binding.shareProcessEnterPassword.setText("")
|
||||
binding.shareProcessEnterPassword.setText(R.string.empty)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,536 +0,0 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud Inc.
|
||||
* SPDX-FileCopyrightText: 2015 María Asensio Valverde <masensio@solidgear.es>
|
||||
* SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
|
||||
* SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
|
||||
*/
|
||||
package com.owncloud.android.ui.preview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.di.Injectable;
|
||||
import com.nextcloud.client.editimage.EditImageActivity;
|
||||
import com.nextcloud.client.jobs.download.FileDownloadHelper;
|
||||
import com.nextcloud.client.jobs.download.FileDownloadWorker;
|
||||
import com.nextcloud.client.jobs.upload.FileUploadWorker;
|
||||
import com.nextcloud.client.preferences.AppPreferences;
|
||||
import com.nextcloud.model.WorkerState;
|
||||
import com.nextcloud.model.WorkerStateLiveData;
|
||||
import com.nextcloud.utils.extensions.IntentExtensionsKt;
|
||||
import com.owncloud.android.MainApp;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.datamodel.VirtualFolderType;
|
||||
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation;
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.operations.RemoveFileOperation;
|
||||
import com.owncloud.android.operations.SynchronizeFileOperation;
|
||||
import com.owncloud.android.ui.activity.FileActivity;
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity;
|
||||
import com.owncloud.android.ui.fragment.FileFragment;
|
||||
import com.owncloud.android.ui.fragment.GalleryFragment;
|
||||
import com.owncloud.android.ui.fragment.OCFileListFragment;
|
||||
import com.owncloud.android.utils.MimeTypeUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
|
||||
/**
|
||||
* Holds a swiping gallery where image files contained in an Nextcloud directory are shown.
|
||||
*/
|
||||
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
|
||||
public class PreviewImageActivity extends FileActivity implements
|
||||
FileFragment.ContainerActivity,
|
||||
OnRemoteOperationListener,
|
||||
Injectable {
|
||||
|
||||
public static final String TAG = PreviewImageActivity.class.getSimpleName();
|
||||
public static final String EXTRA_VIRTUAL_TYPE = "EXTRA_VIRTUAL_TYPE";
|
||||
private static final String KEY_WAITING_FOR_BINDER = "WAITING_FOR_BINDER";
|
||||
private static final String KEY_SYSTEM_VISIBLE = "TRUE";
|
||||
|
||||
private OCFile livePhotoFile;
|
||||
private ViewPager2 viewPager;
|
||||
private PreviewImagePagerAdapter previewImagePagerAdapter;
|
||||
private int savedPosition;
|
||||
private boolean hasSavedPosition;
|
||||
private boolean requestWaitingForBinder;
|
||||
private DownloadFinishReceiver downloadFinishReceiver;
|
||||
private View fullScreenAnchorView;
|
||||
private boolean isDownloadWorkStarted = false;
|
||||
|
||||
@Inject AppPreferences preferences;
|
||||
@Inject LocalBroadcastManager localBroadcastManager;
|
||||
|
||||
private ActionBar actionBar;
|
||||
|
||||
public static Intent previewFileIntent(Context context, User user, OCFile file) {
|
||||
final Intent intent = new Intent(context, PreviewImageActivity.class);
|
||||
intent.putExtra(FileActivity.EXTRA_FILE, file);
|
||||
intent.putExtra(FileActivity.EXTRA_USER, user);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
actionBar = getSupportActionBar();
|
||||
|
||||
if (savedInstanceState != null && !savedInstanceState.getBoolean(KEY_SYSTEM_VISIBLE, true) &&
|
||||
actionBar != null) {
|
||||
actionBar.hide();
|
||||
}
|
||||
|
||||
setContentView(R.layout.preview_image_activity);
|
||||
|
||||
livePhotoFile = IntentExtensionsKt.getParcelableArgument(getIntent(), EXTRA_LIVE_PHOTO_FILE, OCFile.class);
|
||||
|
||||
// Navigation Drawer
|
||||
setupDrawer();
|
||||
|
||||
// ActionBar
|
||||
OCFile chosenFile = IntentExtensionsKt.getParcelableArgument(getIntent(), FileActivity.EXTRA_FILE, OCFile.class);
|
||||
updateActionBarTitleAndHomeButton(chosenFile);
|
||||
|
||||
if (actionBar != null) {
|
||||
viewThemeUtils.files.setWhiteBackButton(this, actionBar);
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
fullScreenAnchorView = getWindow().getDecorView();
|
||||
// to keep our UI controls visibility in line with system bars visibility
|
||||
setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
requestWaitingForBinder = savedInstanceState.getBoolean(KEY_WAITING_FOR_BINDER);
|
||||
} else {
|
||||
requestWaitingForBinder = false;
|
||||
}
|
||||
|
||||
observeWorkerState();
|
||||
}
|
||||
|
||||
public void toggleActionBarVisibility(boolean hide) {
|
||||
if (actionBar == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hide) {
|
||||
actionBar.hide();
|
||||
} else {
|
||||
actionBar.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void initViewPager(User user) {
|
||||
// virtual folder
|
||||
final Serializable virtualFolderType = IntentExtensionsKt.getSerializableArgument(getIntent(), EXTRA_VIRTUAL_TYPE, Serializable.class);
|
||||
if (virtualFolderType != null && virtualFolderType != VirtualFolderType.NONE) {
|
||||
VirtualFolderType type = (VirtualFolderType) virtualFolderType;
|
||||
|
||||
previewImagePagerAdapter = new PreviewImagePagerAdapter(this,
|
||||
type,
|
||||
user,
|
||||
getStorageManager());
|
||||
} else {
|
||||
// get parent from path
|
||||
OCFile parentFolder = getStorageManager().getFileById(getFile().getParentId());
|
||||
|
||||
if (parentFolder == null) {
|
||||
// should not be necessary
|
||||
parentFolder = getStorageManager().getFileByEncryptedRemotePath(OCFile.ROOT_PATH);
|
||||
}
|
||||
|
||||
previewImagePagerAdapter = new PreviewImagePagerAdapter(
|
||||
this,
|
||||
livePhotoFile,
|
||||
parentFolder,
|
||||
user,
|
||||
getStorageManager(),
|
||||
MainApp.isOnlyOnDevice(),
|
||||
preferences
|
||||
);
|
||||
}
|
||||
|
||||
viewPager = findViewById(R.id.fragmentPager);
|
||||
|
||||
int position = hasSavedPosition ? savedPosition : previewImagePagerAdapter.getFilePosition(getFile());
|
||||
position = Math.max(position, 0);
|
||||
|
||||
viewPager.setAdapter(previewImagePagerAdapter);
|
||||
viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
selectPage(position);
|
||||
}
|
||||
});
|
||||
viewPager.setCurrentItem(position, false);
|
||||
|
||||
if (position == 0 && !getFile().isDown()) {
|
||||
// this is necessary because mViewPager.setCurrentItem(0) just after setting the
|
||||
// adapter does not result in a call to #onPageSelected(0)
|
||||
requestWaitingForBinder = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
sendRefreshSearchEventBroadcast();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
sendRefreshSearchEventBroadcast();
|
||||
|
||||
if (isDrawerOpen()) {
|
||||
closeDrawer();
|
||||
} else {
|
||||
backToDisplayActivity();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRefreshSearchEventBroadcast() {
|
||||
Intent intent = new Intent(GalleryFragment.REFRESH_SEARCH_EVENT_RECEIVER);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Optional<User> optionalUser = getUser();
|
||||
if (optionalUser.isPresent()) {
|
||||
OCFile file = getFile();
|
||||
/// Validate handled file (first image to preview)
|
||||
if (file == null) {
|
||||
throw new IllegalStateException("Instanced with a NULL OCFile");
|
||||
}
|
||||
if (!MimeTypeUtil.isImage(file)) {
|
||||
throw new IllegalArgumentException("Non-image file passed as argument");
|
||||
}
|
||||
|
||||
// Update file according to DB file, if it is possible
|
||||
if (file.getFileId() > FileDataStorageManager.ROOT_PARENT_ID) {
|
||||
file = getStorageManager().getFileById(file.getFileId());
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
/// Refresh the activity according to the Account and OCFile set
|
||||
setFile(file); // reset after getting it fresh from storageManager
|
||||
updateActionBarTitle(getFile().getFileName());
|
||||
//if (!stateWasRecovered) {
|
||||
initViewPager(optionalUser.get());
|
||||
//}
|
||||
|
||||
} else {
|
||||
// handled file not in the current Account
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(KEY_WAITING_FOR_BINDER, requestWaitingForBinder);
|
||||
outState.putBoolean(KEY_SYSTEM_VISIBLE, isSystemUIVisible());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
|
||||
super.onRemoteOperationFinish(operation, result);
|
||||
|
||||
if (operation instanceof RemoveFileOperation) {
|
||||
int deletePosition = viewPager.getCurrentItem();
|
||||
int nextPosition = deletePosition > 0 ? deletePosition - 1 : 0;
|
||||
|
||||
if (previewImagePagerAdapter.getItemCount() <= 1) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
viewPager.setCurrentItem(nextPosition, true);
|
||||
previewImagePagerAdapter.delete(deletePosition);
|
||||
} else if (operation instanceof SynchronizeFileOperation) {
|
||||
onSynchronizeFileOperationFinish(result);
|
||||
}
|
||||
}
|
||||
|
||||
private void onSynchronizeFileOperationFinish(RemoteOperationResult result) {
|
||||
if (result.isSuccess()) {
|
||||
supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
private void observeWorkerState() {
|
||||
WorkerStateLiveData.Companion.instance().observe(this, state -> {
|
||||
if (state instanceof WorkerState.Download) {
|
||||
Log_OC.d(TAG, "Download worker started");
|
||||
isDownloadWorkStarted = true;
|
||||
|
||||
if (requestWaitingForBinder) {
|
||||
requestWaitingForBinder = false;
|
||||
Log_OC.d(TAG, "Simulating reselection of current page after connection " +
|
||||
"of download binder");
|
||||
selectPage(viewPager.getCurrentItem());
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(TAG, "Download worker stopped");
|
||||
isDownloadWorkStarted = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
downloadFinishReceiver = new DownloadFinishReceiver();
|
||||
IntentFilter downloadIntentFilter = new IntentFilter(FileDownloadWorker.Companion.getDownloadFinishMessage());
|
||||
localBroadcastManager.registerReceiver(downloadFinishReceiver, downloadIntentFilter);
|
||||
|
||||
UploadFinishReceiver uploadFinishReceiver = new UploadFinishReceiver();
|
||||
IntentFilter uploadIntentFilter = new IntentFilter(FileUploadWorker.Companion.getUploadFinishMessage());
|
||||
localBroadcastManager.registerReceiver(uploadFinishReceiver, uploadIntentFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostResume() {
|
||||
super.onPostResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (downloadFinishReceiver != null){
|
||||
localBroadcastManager.unregisterReceiver(downloadFinishReceiver);
|
||||
downloadFinishReceiver = null;
|
||||
}
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
private void backToDisplayActivity() {
|
||||
finish();
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("DLS")
|
||||
@Override
|
||||
public void showDetails(OCFile file) {
|
||||
final Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class);
|
||||
showDetailsIntent.setAction(FileDisplayActivity.ACTION_DETAILS);
|
||||
showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, file);
|
||||
showDetailsIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(showDetailsIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDetails(OCFile file, int activeTab) {
|
||||
showDetails(file);
|
||||
}
|
||||
|
||||
public void requestForDownload(OCFile file) {
|
||||
requestForDownload(file, null);
|
||||
}
|
||||
|
||||
public void requestForDownload(OCFile file, String downloadBehaviour) {
|
||||
final User user = getUser().orElseThrow(RuntimeException::new);
|
||||
FileDownloadHelper.Companion.instance().downloadFileIfNotStartedBefore(user, file);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be invoked when a new page becomes selected. Animation is not necessarily
|
||||
* complete.
|
||||
*
|
||||
* @param position Position index of the new selected page
|
||||
*/
|
||||
public void selectPage(int position) {
|
||||
savedPosition = position;
|
||||
hasSavedPosition = true;
|
||||
|
||||
OCFile currentFile = previewImagePagerAdapter.getFileAt(position);
|
||||
|
||||
if (!isDownloadWorkStarted) {
|
||||
requestWaitingForBinder = true;
|
||||
} else {
|
||||
if (currentFile != null) {
|
||||
if (currentFile.isEncrypted() && !currentFile.isDown() &&
|
||||
!previewImagePagerAdapter.pendingErrorAt(position)) {
|
||||
requestForDownload(currentFile);
|
||||
}
|
||||
|
||||
// Call to reset image zoom to initial state
|
||||
// ((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFile != null) {
|
||||
updateActionBarTitle(currentFile.getFileName());
|
||||
setDrawerIndicatorEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateActionBarTitle(String title) {
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class waiting for broadcast events from the {@link FileDownloadWorker} service.
|
||||
* <p>
|
||||
* Updates the UI when a download is started or finished, provided that it is relevant for the
|
||||
* folder displayed in the gallery.
|
||||
*/
|
||||
private class DownloadFinishReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
previewNewImage(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private class UploadFinishReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
previewNewImage(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void previewNewImage(Intent intent) {
|
||||
String accountName = intent.getStringExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME);
|
||||
String downloadedRemotePath = intent.getStringExtra(FileDownloadWorker.EXTRA_REMOTE_PATH);
|
||||
String downloadBehaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR);
|
||||
|
||||
if (getAccount().name.equals(accountName) && downloadedRemotePath != null) {
|
||||
OCFile file = getStorageManager().getFileByEncryptedRemotePath(downloadedRemotePath);
|
||||
boolean downloadWasFine = intent.getBooleanExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, false);
|
||||
|
||||
if (EditImageActivity.OPEN_IMAGE_EDITOR.equals(downloadBehaviour)) {
|
||||
startImageEditor(file);
|
||||
} else {
|
||||
int position = previewImagePagerAdapter.getFilePosition(file);
|
||||
if (position >= 0) {
|
||||
if (downloadWasFine) {
|
||||
previewImagePagerAdapter.updateFile(position, file);
|
||||
} else {
|
||||
previewImagePagerAdapter.updateWithDownloadError(position);
|
||||
}
|
||||
previewImagePagerAdapter.notifyItemChanged(position);
|
||||
} else if (downloadWasFine) {
|
||||
Optional<User> user = getUser();
|
||||
|
||||
if (user.isPresent()) {
|
||||
initViewPager(user.get());
|
||||
int newPosition = previewImagePagerAdapter.getFilePosition(file);
|
||||
if (newPosition >= 0) {
|
||||
viewPager.setCurrentItem(newPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSystemUIVisible() {
|
||||
return getSupportActionBar() == null || getSupportActionBar().isShowing();
|
||||
}
|
||||
|
||||
public void toggleFullScreen() {
|
||||
boolean visible = (fullScreenAnchorView.getSystemUiVisibility()
|
||||
& View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
|
||||
|
||||
if (visible) {
|
||||
hideSystemUI(fullScreenAnchorView);
|
||||
} else {
|
||||
showSystemUI(fullScreenAnchorView);
|
||||
}
|
||||
}
|
||||
|
||||
public void startImageEditor(OCFile file) {
|
||||
if (file.isDown()) {
|
||||
Intent editImageIntent = new Intent(this, EditImageActivity.class);
|
||||
editImageIntent.putExtra(EditImageActivity.EXTRA_FILE, file);
|
||||
startActivity(editImageIntent);
|
||||
} else {
|
||||
requestForDownload(file, EditImageActivity.OPEN_IMAGE_EDITOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBrowsedDownTo(OCFile folder) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private void hideSystemUI(View anchorView) {
|
||||
anchorView.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hides NAVIGATION BAR; Android >= 4.0
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN // hides STATUS BAR; Android >= 4.1
|
||||
| View.SYSTEM_UI_FLAG_IMMERSIVE // stays interactive; Android >= 4.4
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE // draw full window; Android >= 4.1
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // draw full window; Android >= 4.1
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // draw full window; Android >= 4.1
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
private void showSystemUI(View anchorView) {
|
||||
anchorView.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE // draw full window; Android >= 4.1
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // draw full window; Android >= 4.1
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // draw full window; Android >= 4.
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,527 @@
|
|||
/*
|
||||
* Nextcloud - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2020-2024 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper.ozturk@nextcloud.com>
|
||||
* SPDX-FileCopyrightText: 2022 Álvaro Brey <alvaro@alvarobrey.com>
|
||||
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
|
||||
* SPDX-FileCopyrightText: 2019 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* SPDX-FileCopyrightText: 2016 ownCloud Inc.
|
||||
* SPDX-FileCopyrightText: 2015 María Asensio Valverde <masensio@solidgear.es>
|
||||
* SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
|
||||
* SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
|
||||
*/
|
||||
package com.owncloud.android.ui.preview
|
||||
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowInsetsController
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
|
||||
import com.nextcloud.client.account.User
|
||||
import com.nextcloud.client.di.Injectable
|
||||
import com.nextcloud.client.editimage.EditImageActivity
|
||||
import com.nextcloud.client.jobs.download.FileDownloadHelper
|
||||
import com.nextcloud.client.jobs.download.FileDownloadWorker
|
||||
import com.nextcloud.client.jobs.download.FileDownloadWorker.Companion.getDownloadFinishMessage
|
||||
import com.nextcloud.client.jobs.upload.FileUploadWorker.Companion.getUploadFinishMessage
|
||||
import com.nextcloud.client.preferences.AppPreferences
|
||||
import com.nextcloud.model.WorkerState
|
||||
import com.nextcloud.model.WorkerStateLiveData
|
||||
import com.nextcloud.utils.extensions.getParcelableArgument
|
||||
import com.nextcloud.utils.extensions.getSerializableArgument
|
||||
import com.owncloud.android.MainApp
|
||||
import com.owncloud.android.R
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.datamodel.VirtualFolderType
|
||||
import com.owncloud.android.lib.common.operations.OnRemoteOperationListener
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperation
|
||||
import com.owncloud.android.lib.common.operations.RemoteOperationResult
|
||||
import com.owncloud.android.lib.common.utils.Log_OC
|
||||
import com.owncloud.android.operations.RemoveFileOperation
|
||||
import com.owncloud.android.operations.SynchronizeFileOperation
|
||||
import com.owncloud.android.ui.activity.FileActivity
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity
|
||||
import com.owncloud.android.ui.fragment.FileFragment
|
||||
import com.owncloud.android.ui.fragment.GalleryFragment
|
||||
import com.owncloud.android.ui.fragment.OCFileListFragment
|
||||
import com.owncloud.android.utils.MimeTypeUtil
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
|
||||
import java.io.Serializable
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* Holds a swiping gallery where image files contained in an Nextcloud directory are shown.
|
||||
*/
|
||||
class PreviewImageActivity : FileActivity(), FileFragment.ContainerActivity, OnRemoteOperationListener, Injectable {
|
||||
private var livePhotoFile: OCFile? = null
|
||||
private var viewPager: ViewPager2? = null
|
||||
private var previewImagePagerAdapter: PreviewImagePagerAdapter? = null
|
||||
private var savedPosition = 0
|
||||
private var hasSavedPosition = false
|
||||
private var requestWaitingForBinder = false
|
||||
private var downloadFinishReceiver: DownloadFinishReceiver? = null
|
||||
private var fullScreenAnchorView: View? = null
|
||||
private var isDownloadWorkStarted = false
|
||||
|
||||
@Inject
|
||||
lateinit var preferences: AppPreferences
|
||||
|
||||
@Inject
|
||||
lateinit var localBroadcastManager: LocalBroadcastManager
|
||||
|
||||
private var actionBar: ActionBar? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
actionBar = supportActionBar
|
||||
|
||||
if (savedInstanceState != null && !savedInstanceState.getBoolean(
|
||||
KEY_SYSTEM_VISIBLE,
|
||||
true
|
||||
) && actionBar != null
|
||||
) {
|
||||
actionBar?.hide()
|
||||
}
|
||||
|
||||
setContentView(R.layout.preview_image_activity)
|
||||
|
||||
livePhotoFile = intent.getParcelableArgument(EXTRA_LIVE_PHOTO_FILE, OCFile::class.java)
|
||||
|
||||
setupDrawer()
|
||||
|
||||
val chosenFile = intent.getParcelableArgument(EXTRA_FILE, OCFile::class.java)
|
||||
updateActionBarTitleAndHomeButton(chosenFile)
|
||||
|
||||
if (actionBar != null) {
|
||||
viewThemeUtils.files.setWhiteBackButton(this, actionBar!!)
|
||||
actionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
}
|
||||
|
||||
fullScreenAnchorView = window.decorView
|
||||
// to keep our UI controls visibility in line with system bars visibility
|
||||
setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
|
||||
|
||||
requestWaitingForBinder = savedInstanceState?.getBoolean(KEY_WAITING_FOR_BINDER) ?: false
|
||||
|
||||
observeWorkerState()
|
||||
}
|
||||
|
||||
fun toggleActionBarVisibility(hide: Boolean) {
|
||||
if (actionBar == null) {
|
||||
return
|
||||
}
|
||||
|
||||
if (hide) {
|
||||
actionBar?.hide()
|
||||
} else {
|
||||
actionBar?.show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initViewPager(user: User) {
|
||||
val virtualFolderType = intent.getSerializableArgument(EXTRA_VIRTUAL_TYPE, Serializable::class.java)
|
||||
if (virtualFolderType != null && virtualFolderType !== VirtualFolderType.NONE) {
|
||||
val type = virtualFolderType as VirtualFolderType
|
||||
|
||||
previewImagePagerAdapter = PreviewImagePagerAdapter(
|
||||
this,
|
||||
type,
|
||||
user,
|
||||
storageManager
|
||||
)
|
||||
} else {
|
||||
// get parent from path
|
||||
var parentFolder = storageManager.getFileById(file.parentId)
|
||||
|
||||
if (parentFolder == null) {
|
||||
// should not be necessary
|
||||
parentFolder = storageManager.getFileByEncryptedRemotePath(OCFile.ROOT_PATH)
|
||||
}
|
||||
|
||||
previewImagePagerAdapter = PreviewImagePagerAdapter(
|
||||
this,
|
||||
livePhotoFile,
|
||||
parentFolder,
|
||||
user,
|
||||
storageManager,
|
||||
MainApp.isOnlyOnDevice(),
|
||||
preferences
|
||||
)
|
||||
}
|
||||
|
||||
viewPager = findViewById(R.id.fragmentPager)
|
||||
|
||||
var position = if (hasSavedPosition) savedPosition else previewImagePagerAdapter?.getFilePosition(file)
|
||||
position = position?.toDouble()?.let { max(it, 0.0).toInt() }
|
||||
|
||||
viewPager?.setAdapter(previewImagePagerAdapter)
|
||||
viewPager?.registerOnPageChangeCallback(object : OnPageChangeCallback() {
|
||||
override fun onPageSelected(position: Int) {
|
||||
selectPage(position)
|
||||
}
|
||||
})
|
||||
if (position != null) {
|
||||
viewPager?.setCurrentItem(position, false)
|
||||
}
|
||||
|
||||
if (position == 0 && !file.isDown) {
|
||||
// this is necessary because mViewPager.setCurrentItem(0) just after setting the
|
||||
// adapter does not result in a call to #onPageSelected(0)
|
||||
requestWaitingForBinder = true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
sendRefreshSearchEventBroadcast()
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId != android.R.id.home) {
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
sendRefreshSearchEventBroadcast()
|
||||
|
||||
if (isDrawerOpen) {
|
||||
closeDrawer()
|
||||
} else {
|
||||
backToDisplayActivity()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun sendRefreshSearchEventBroadcast() {
|
||||
val intent = Intent(GalleryFragment.REFRESH_SEARCH_EVENT_RECEIVER)
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
|
||||
}
|
||||
|
||||
public override fun onStart() {
|
||||
super.onStart()
|
||||
val optionalUser = user
|
||||
if (optionalUser.isPresent) {
|
||||
var file: OCFile? = file ?: throw IllegalStateException("Instanced with a NULL OCFile")
|
||||
// / Validate handled file (first image to preview)
|
||||
require(MimeTypeUtil.isImage(file)) { "Non-image file passed as argument" }
|
||||
|
||||
// Update file according to DB file, if it is possible
|
||||
if (file!!.fileId > FileDataStorageManager.ROOT_PARENT_ID) {
|
||||
file = storageManager.getFileById(file.fileId)
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
// / Refresh the activity according to the Account and OCFile set
|
||||
setFile(file) // reset after getting it fresh from storageManager
|
||||
updateActionBarTitle(getFile().fileName)
|
||||
// if (!stateWasRecovered) {
|
||||
initViewPager(optionalUser.get())
|
||||
|
||||
// }
|
||||
} else {
|
||||
// handled file not in the current Account
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putBoolean(KEY_WAITING_FOR_BINDER, requestWaitingForBinder)
|
||||
outState.putBoolean(KEY_SYSTEM_VISIBLE, isSystemUIVisible)
|
||||
}
|
||||
|
||||
override fun onRemoteOperationFinish(operation: RemoteOperation<*>?, result: RemoteOperationResult<*>) {
|
||||
super.onRemoteOperationFinish(operation, result)
|
||||
|
||||
if (operation is RemoveFileOperation) {
|
||||
val deletePosition = viewPager?.currentItem ?: return
|
||||
val nextPosition = if (deletePosition > 0) deletePosition - 1 else 0
|
||||
|
||||
previewImagePagerAdapter?.let {
|
||||
if (it.itemCount <= 1) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
viewPager?.setCurrentItem(nextPosition, true)
|
||||
previewImagePagerAdapter?.delete(deletePosition)
|
||||
} else if (operation is SynchronizeFileOperation) {
|
||||
onSynchronizeFileOperationFinish(result)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSynchronizeFileOperationFinish(result: RemoteOperationResult<*>) {
|
||||
if (result.isSuccess) {
|
||||
supportInvalidateOptionsMenu()
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeWorkerState() {
|
||||
WorkerStateLiveData.instance().observe(this) { state: WorkerState? ->
|
||||
if (state is WorkerState.Download) {
|
||||
Log_OC.d(TAG, "Download worker started")
|
||||
isDownloadWorkStarted = true
|
||||
|
||||
if (requestWaitingForBinder) {
|
||||
requestWaitingForBinder = false
|
||||
Log_OC.d(
|
||||
TAG,
|
||||
"Simulating reselection of current page after connection " +
|
||||
"of download binder"
|
||||
)
|
||||
selectPage(viewPager?.currentItem)
|
||||
}
|
||||
} else {
|
||||
Log_OC.d(TAG, "Download worker stopped")
|
||||
isDownloadWorkStarted = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
downloadFinishReceiver = DownloadFinishReceiver()
|
||||
val downloadIntentFilter = IntentFilter(getDownloadFinishMessage())
|
||||
localBroadcastManager.registerReceiver(downloadFinishReceiver!!, downloadIntentFilter)
|
||||
|
||||
val uploadFinishReceiver = UploadFinishReceiver()
|
||||
val uploadIntentFilter = IntentFilter(getUploadFinishMessage())
|
||||
localBroadcastManager.registerReceiver(uploadFinishReceiver, uploadIntentFilter)
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
if (downloadFinishReceiver != null) {
|
||||
localBroadcastManager.unregisterReceiver(downloadFinishReceiver!!)
|
||||
downloadFinishReceiver = null
|
||||
}
|
||||
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
private fun backToDisplayActivity() {
|
||||
finish()
|
||||
}
|
||||
|
||||
@SuppressFBWarnings("DLS")
|
||||
override fun showDetails(file: OCFile) {
|
||||
val intent = Intent(this, FileDisplayActivity::class.java).apply {
|
||||
setAction(FileDisplayActivity.ACTION_DETAILS)
|
||||
putExtra(EXTRA_FILE, file)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
}
|
||||
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun showDetails(file: OCFile, activeTab: Int) {
|
||||
showDetails(file)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun requestForDownload(file: OCFile?, downloadBehaviour: String? = null) {
|
||||
if (file == null) return
|
||||
val user = user.orElseThrow { RuntimeException() }
|
||||
FileDownloadHelper.instance().downloadFileIfNotStartedBefore(user, file)
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be invoked when a new page becomes selected. Animation is not necessarily
|
||||
* complete.
|
||||
*
|
||||
* @param position Position index of the new selected page
|
||||
*/
|
||||
fun selectPage(position: Int?) {
|
||||
if (position == null) return
|
||||
savedPosition = position
|
||||
hasSavedPosition = true
|
||||
|
||||
val currentFile = previewImagePagerAdapter?.getFileAt(position)
|
||||
|
||||
if (!isDownloadWorkStarted) {
|
||||
requestWaitingForBinder = true
|
||||
} else {
|
||||
if (currentFile != null) {
|
||||
if (currentFile.isEncrypted && !currentFile.isDown &&
|
||||
previewImagePagerAdapter?.pendingErrorAt(position) == false
|
||||
) {
|
||||
requestForDownload(currentFile)
|
||||
}
|
||||
|
||||
// Call to reset image zoom to initial state
|
||||
// ((PreviewImagePagerAdapter) mViewPager.getAdapter()).resetZoom();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFile != null) {
|
||||
updateActionBarTitle(currentFile.fileName)
|
||||
setDrawerIndicatorEnabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateActionBarTitle(title: String?) {
|
||||
supportActionBar?.title = title
|
||||
}
|
||||
|
||||
/**
|
||||
* Class waiting for broadcast events from the [FileDownloadWorker] service.
|
||||
*
|
||||
*
|
||||
* Updates the UI when a download is started or finished, provided that it is relevant for the
|
||||
* folder displayed in the gallery.
|
||||
*/
|
||||
private inner class DownloadFinishReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
previewNewImage(intent)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class UploadFinishReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
previewNewImage(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("NestedBlockDepth", "ReturnCount")
|
||||
private fun previewNewImage(intent: Intent) {
|
||||
val accountName = intent.getStringExtra(FileDownloadWorker.EXTRA_ACCOUNT_NAME)
|
||||
val downloadedRemotePath = intent.getStringExtra(FileDownloadWorker.EXTRA_REMOTE_PATH)
|
||||
val downloadBehaviour = intent.getStringExtra(OCFileListFragment.DOWNLOAD_BEHAVIOUR)
|
||||
|
||||
if (account.name != accountName || downloadedRemotePath == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val file = storageManager.getFileByEncryptedRemotePath(downloadedRemotePath)
|
||||
val downloadWasFine = intent.getBooleanExtra(FileDownloadWorker.EXTRA_DOWNLOAD_RESULT, false)
|
||||
|
||||
if (EditImageActivity.OPEN_IMAGE_EDITOR == downloadBehaviour) {
|
||||
startImageEditor(file)
|
||||
} else {
|
||||
val position = previewImagePagerAdapter?.getFilePosition(file) ?: return
|
||||
|
||||
if (position >= 0) {
|
||||
if (downloadWasFine) {
|
||||
previewImagePagerAdapter?.updateFile(position, file)
|
||||
} else {
|
||||
previewImagePagerAdapter?.updateWithDownloadError(position)
|
||||
}
|
||||
previewImagePagerAdapter?.notifyItemChanged(position)
|
||||
} else if (downloadWasFine) {
|
||||
val user = user
|
||||
|
||||
if (user.isPresent) {
|
||||
initViewPager(user.get())
|
||||
val newPosition = previewImagePagerAdapter?.getFilePosition(file) ?: return
|
||||
if (newPosition >= 0) {
|
||||
viewPager?.currentItem = newPosition
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val isSystemUIVisible: Boolean
|
||||
get() = supportActionBar == null || supportActionBar?.isShowing == true
|
||||
|
||||
fun toggleFullScreen() {
|
||||
if (fullScreenAnchorView == null) return
|
||||
val visible = (
|
||||
fullScreenAnchorView!!.systemUiVisibility
|
||||
and View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
) == 0
|
||||
|
||||
if (visible) {
|
||||
hideSystemUI(fullScreenAnchorView!!)
|
||||
} else {
|
||||
showSystemUI(fullScreenAnchorView!!)
|
||||
}
|
||||
}
|
||||
|
||||
fun startImageEditor(file: OCFile) {
|
||||
if (file.isDown) {
|
||||
val editImageIntent = Intent(this, EditImageActivity::class.java)
|
||||
editImageIntent.putExtra(EditImageActivity.EXTRA_FILE, file)
|
||||
startActivity(editImageIntent)
|
||||
} else {
|
||||
requestForDownload(file, EditImageActivity.OPEN_IMAGE_EDITOR)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBrowsedDownTo(folder: OCFile) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
override fun onTransferStateChanged(file: OCFile, downloading: Boolean, uploading: Boolean) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
private fun hideSystemUI(anchorView: View) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
window.insetsController?.let { controller ->
|
||||
controller.hide(WindowInsets.Type.systemBars())
|
||||
controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
}
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
anchorView.systemUiVisibility = (
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hides NAVIGATION BAR; Android >= 4.0
|
||||
or View.SYSTEM_UI_FLAG_FULLSCREEN // hides STATUS BAR; Android >= 4.1
|
||||
or View.SYSTEM_UI_FLAG_IMMERSIVE // stays interactive; Android >= 4.4
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE // draw full window; Android >= 4.1
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // draw full window; Android >= 4.1
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSystemUI(anchorView: View) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
window.insetsController?.let { controller ->
|
||||
controller.show(WindowInsets.Type.systemBars())
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_DEFAULT
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
anchorView.systemUiVisibility = (
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE // draw full window; Android >= 4.1
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // draw full window; Android >= 4.1
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG: String = PreviewImageActivity::class.java.simpleName
|
||||
const val EXTRA_VIRTUAL_TYPE: String = "EXTRA_VIRTUAL_TYPE"
|
||||
private const val KEY_WAITING_FOR_BINDER = "WAITING_FOR_BINDER"
|
||||
private const val KEY_SYSTEM_VISIBLE = "TRUE"
|
||||
|
||||
fun previewFileIntent(context: Context?, user: User?, file: OCFile?): Intent {
|
||||
return Intent(context, PreviewImageActivity::class.java).apply {
|
||||
putExtra(EXTRA_FILE, file)
|
||||
putExtra(EXTRA_USER, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
buildscript {
|
||||
ext {
|
||||
androidLibraryVersion ="451cddeba122ff4d17dc8f88feb2fd7589f77567"
|
||||
androidPluginVersion = '8.4.0'
|
||||
androidPluginVersion = '8.5.0'
|
||||
androidxMediaVersion = '1.3.1'
|
||||
androidxTestVersion = "1.5.0"
|
||||
appCompatVersion = '1.7.0'
|
||||
|
|
|
@ -4457,6 +4457,43 @@ HBhD37R+PsUfSEPep+pmyBlX2nrKxxoRNsl5KWNiQw==
|
|||
=Phg6
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
pub 1669C4BB543E0445
|
||||
uid Emily Johnston <epmjohnston@google.com>
|
||||
|
||||
sub 5F6BA89D4B0869B9
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: BCPG v1.68
|
||||
|
||||
mQGNBF3TQCcBDAD177B+Btl8XBEkBQ5jFSezFrpEl4arwCEa7htCp6T3h55HvYwz
|
||||
P7Y9zWYXfhAC8XJlPQJYpqaQiiYtdlmOrOS4wbp5Lr+z/0XpFlJFzdKglxKYcdfP
|
||||
ntnGyoj7Dz03v+SitL9Ct1YZmOGz6onlifXsCTkWraSJTqR6/y2dL0Beu7dLZp94
|
||||
fgf+FAfr77bwGhUhOh0pPI6ZK2VwNMiQN92jS/RYb6i7QjzO654ALTBR6R2sqx26
|
||||
C0NNsTUZ1WawPreT/rmR4vux1pvgbC8DcXqdptVb+iQPymnysEr69J0f7YC579+7
|
||||
itFIh6efV75W9nDqp9QB/1G808oYx1rglUstOCI0axSgSNyazbInW9qOI58rLQ4v
|
||||
wnCSTWvesVNq+uO6aVrfpXIO3uUTI3t4mpBZgVYZ+g30BlCPRx52YofvQzYbbk9d
|
||||
wCMUDQAzKGJi+mazkgBhcz+neEuNUlR/0fBMObzb7cAT4gGo/sSzYVNN5oT3u/Mi
|
||||
J4hfzYUTFMsJBp0AEQEAAbQnRW1pbHkgSm9obnN0b24gPGVwbWpvaG5zdG9uQGdv
|
||||
b2dsZS5jb20+uQGNBF3TQCcBDADJ17PQ4z5UVGBVUefEkTXeVlGX4oc+vUOVn8Z9
|
||||
B34sQkFmgsORuwm+/1rGthrMatro1Jka4UXSxYFMCt6XBz4/OdJbquxs6D85iuda
|
||||
Id9aozCOJypkfprp+ez2PK7pWeOq6DQ/lqqNGyoHxA703wshI38sNcKRcypn/vf1
|
||||
VJlO3ZjfLCVDQw4+yNrdWiwklb4QS0xwjK9Bw9m8g6HiQGil8V/kL9Avpa76rGqa
|
||||
P9YnkTo7NQG0cwEbpcxNUrkO7fFKjTOMTmfPkh5pHAHVS+FsrCsxhRs6Eb6u/qes
|
||||
tHjpYj6qtMJ5V7oXeUI3OZ9nAPctSxoNVn6f0otsaatoBwcJNNhO/6ZIFH7NlgYQ
|
||||
NN3a5Pz6NrU13+zMGbsxYzlL4/nVwhdn/kHPQ2tl4e2R79da7ModAjeafimikA3n
|
||||
GZj1Zvo1iXKLfguM+U90kTrPKSxcJqwgV4QvrO9Z9llRTzhdBmrFePFhlxN3JdpS
|
||||
KYXFInq6JwncmOAeIDhNYYcVXhcAEQEAAYkBvAQYAQoAJhYhBHYVrVYUTfI3b0nZ
|
||||
ixZpxLtUPgRFBQJd00AnAhsMBQkDwmcAAAoJEBZpxLtUPgRF32gMAJoI+6dvnT7G
|
||||
OJB4S0HAB2qhizmQ5MWiO7QE1HKQ6ShylihJfAIMnAMlLPhorr1ITZXaNMFO+rWN
|
||||
O76BdsBxAkd0rKIIjMTU5r1HuS+XCGFzitffkJ2TgQ2K4vKnSgEpCsBilgCJzdJe
|
||||
vrYoCAudkZAaeBcT0fsTtQDnWHUJSkyWro0ovaaPF5tJzMkFZQBlaNyb+DmWPyNt
|
||||
5TP6iORnmeLNE0OajrUawFUcLUITdutn2t/PRE9LBDSlewE9Gabv79z8ZGAw7jPK
|
||||
x/p+ePpIj6J05TM0BR9KLrk3avMIK+eKwcvm+nCyYA1jKr7c9E4bg+6sRbc6igvV
|
||||
L4QeKzjeGll3vjifmghVXVKVBOW1fk10cMNKaTEkGng8OfLhJDQDXuNz4m8/pMA/
|
||||
wyGfH3HBGSx+F3GZUb00kU0HbxV2Vt0QlyjwT9vJfVGQ4Y+GhnMF6qErtdX8cBIW
|
||||
FJXLEW77wWHN+QpRD6BShYZDvUA2mtO0zlB8reU+VCxgnFfm66DkUg==
|
||||
=jYDe
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
pub 16F71868F1D3A389
|
||||
uid Lukhnos Liu <lukhnos@lukhnos.org>
|
||||
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
<trust group="com.fasterxml.jackson" name="jackson-base" version="2.14.2" reason="no keys available, no pom artifact to create a checksum"/>
|
||||
<trust file=".*-sources[.]jar" regex="true"/>
|
||||
</trusted-artifacts>
|
||||
<ignored-keys>
|
||||
<ignored-key id="1669C4BB543E0445" reason="Key couldn't be downloaded from any key server"/>
|
||||
</ignored-keys>
|
||||
<trusted-keys>
|
||||
<trusted-key id="015479E1055341431B4545AB72475FD306B9CAB7" group="com.googlecode.javaewah" name="JavaEWAH" version="1.2.3"/>
|
||||
<trusted-key id="042B29E928995B9DB963C636C7CA19B7B620D787" group="com.github.stephenc.jcip" name="jcip-annotations" version="1.0-1"/>
|
||||
|
@ -81,7 +78,10 @@
|
|||
<trusted-key id="2E52CCA3842FA13C188F1DB50B45DDD344B5FFD1" group="tools.fastlane" name="screengrab" version="2.1.1"/>
|
||||
<trusted-key id="2E8191ADD82E5C6ABD8E24D802499A5DAEC7ADA9" group="^com[.]twelvemonkeys($|([.].*))" regex="true"/>
|
||||
<trusted-key id="2E92113263FC31C74CCBAAB20E91C2DE43B72BB1" group="org.ec4j.core"/>
|
||||
<trusted-key id="3051D45031E13516A6E8FAFF280D66A55F5316C5" group="org.bitbucket.b_c" name="jose4j" version="0.7.0"/>
|
||||
<trusted-key id="3051D45031E13516A6E8FAFF280D66A55F5316C5">
|
||||
<trusting group="org.bitbucket.b_c" name="jose4j" version="0.7.0"/>
|
||||
<trusting group="org.bitbucket.b_c" name="jose4j" version="0.9.5"/>
|
||||
</trusted-key>
|
||||
<trusted-key id="31BAE2E51D95E0F8AD9B7BCC40A3C4432BD7308C" group="com.googlecode.juniversalchardet" name="juniversalchardet" version="1.0.3"/>
|
||||
<trusted-key id="3241A3ABA33FF6F69B75E2DDEC9458EED5C5AB12" group="id.zelory" name="compressor" version="3.0.1"/>
|
||||
<trusted-key id="324E460B9DB8F4515F3EAED9930C5B1EA41B1AA1" group="com.beust" name="jcommander" version="1.48"/>
|
||||
|
@ -241,11 +241,13 @@
|
|||
<trusting group="androidx.annotation"/>
|
||||
<trusting group="androidx.appcompat"/>
|
||||
<trusting group="androidx.core"/>
|
||||
<trusting group="androidx.databinding"/>
|
||||
<trusting group="androidx.fragment"/>
|
||||
<trusting group="androidx.lifecycle"/>
|
||||
<trusting group="androidx.transition" name="transition" version="1.5.0"/>
|
||||
<trusting group="androidx.webkit" name="webkit" version="1.11.0"/>
|
||||
<trusting group="^androidx[.]compose($|([.].*))" regex="true"/>
|
||||
<trusting group="^com[.]android($|([.].*))" regex="true"/>
|
||||
</trusted-key>
|
||||
<trusted-key id="A6D6C97108B8585F91B158748671A8DF71296252" group="^com[.]squareup($|([.].*))" regex="true"/>
|
||||
<trusted-key id="A7892505CF1A58076453E52D7999BEFBA1039E8B" group="net.bytebuddy"/>
|
||||
|
@ -1146,6 +1148,11 @@
|
|||
<sha256 value="b037fdfb267dc0141ab9f4e4e85daf87b175cf311248d54b501b58ec42345315" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.core" name="core-ktx" version="1.6.0">
|
||||
<artifact name="core-ktx-1.6.0.module">
|
||||
<sha256 value="e937bf22c0da28e872300fc6b96029b83ff75aa8d0ab1ec039aae3d8af6513dd" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="androidx.core" name="core-ktx" version="1.8.0">
|
||||
<artifact name="core-ktx-1.8.0.module">
|
||||
<sha256 value="a91bc3e02f209f643dd8275345a9e3003ce20d64fc0760eccf479c1709842f72" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
|
@ -3941,6 +3948,14 @@
|
|||
<sha256 value="745894f1d15599871b1c3a6cc09f0da03268f1373ce937ce35942b933d6518e6" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.build" name="bundletool" version="1.16.0">
|
||||
<artifact name="bundletool-1.16.0.jar">
|
||||
<sha256 value="1ea2bf5274bbac7a3bb5618521d2fa11fb04e900e33a8a646029ec6332fc08c8" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
<artifact name="bundletool-1.16.0.pom">
|
||||
<sha256 value="f2e8aad4455a42372462d5e18a26973d67571179a6757f3825f227e91af2f2db" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.android.tools.build" name="gradle" version="8.2.2">
|
||||
<artifact name="gradle-8.2.2.jar">
|
||||
<sha256 value="ca50f47cd13d347de7c89ecb2bd06487b03a88687c46c2b776bc0a9323958955" origin="Generated by Gradle" reason="Artifact is not signed"/>
|
||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
2
gradlew
vendored
2
gradlew
vendored
|
@ -55,7 +55,7 @@
|
|||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
|
Loading…
Reference in a new issue