/* * ownCloud Android client application * * @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 . * */ package com.owncloud.android.ui.preview; import android.accounts.Account; import android.graphics.Matrix; import android.util.SparseArray; import android.view.ViewGroup; import com.nextcloud.client.preferences.AppPreferences; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.VirtualFolderType; import com.owncloud.android.ui.fragment.FileFragment; import com.owncloud.android.utils.FileSortOrder; import com.owncloud.android.utils.FileStorageUtils; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.annotation.Nullable; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; /** * Adapter class that provides Fragment instances */ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter { private List mImageFiles; private Account mAccount; private Set mObsoleteFragments; private Set mObsoletePositions; private Set mDownloadErrors; private FileDataStorageManager mStorageManager; private SparseArray mCachedFragments; /** * Constructor * * @param fragmentManager {@link FragmentManager} instance that will handle * the {@link Fragment}s provided by the adapter. * @param parentFolder Folder where images will be searched for. * @param storageManager Bridge to database. */ public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, Account account, FileDataStorageManager storageManager, boolean onlyOnDevice, AppPreferences preferences) { super(fragmentManager); if (fragmentManager == null) { throw new IllegalArgumentException("NULL FragmentManager instance"); } if (parentFolder == null) { throw new IllegalArgumentException("NULL parent folder"); } if (storageManager == null) { throw new IllegalArgumentException("NULL storage manager"); } mAccount = account; mStorageManager = storageManager; mImageFiles = mStorageManager.getFolderImages(parentFolder, onlyOnDevice); FileSortOrder sortOrder = preferences.getSortOrderByFolder(parentFolder); mImageFiles = sortOrder.sortCloudFiles(mImageFiles); mObsoleteFragments = new HashSet<>(); mObsoletePositions = new HashSet<>(); mDownloadErrors = new HashSet<>(); mCachedFragments = new SparseArray<>(); } /** * Constructor * * @param fragmentManager {@link FragmentManager} instance that will handle * the {@link Fragment}s provided by the adapter. * @param type Type of virtual folder, e.g. favorite or photos * @param storageManager Bridge to database. */ public PreviewImagePagerAdapter(FragmentManager fragmentManager, VirtualFolderType type, Account account, FileDataStorageManager storageManager) { super(fragmentManager); if (fragmentManager == null) { throw new IllegalArgumentException("NULL FragmentManager instance"); } if (type == null) { throw new IllegalArgumentException("NULL parent folder"); } if (storageManager == null) { throw new IllegalArgumentException("NULL storage manager"); } mAccount = account; mStorageManager = storageManager; mImageFiles = mStorageManager.getVirtualFolderContent(type, true); if (type == VirtualFolderType.PHOTOS) { mImageFiles = FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(mImageFiles); } mObsoleteFragments = new HashSet<>(); mObsoletePositions = new HashSet<>(); mDownloadErrors = new HashSet<>(); mCachedFragments = new SparseArray<>(); } /** * Returns the image files handled by the adapter. * * @return OCFile desired image or null if position is not in adapter */ @Nullable public OCFile getFileAt(int position) { try { return mImageFiles.get(position); } catch (IndexOutOfBoundsException exception) { return null; } } public Fragment getItem(int i) { OCFile file = getFileAt(i); Fragment fragment; if (file == null) { fragment = PreviewImageErrorFragment.newInstance(); } else if (file.isDown()) { fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), false); } else { if (mDownloadErrors.remove(i)) { fragment = FileDownloadFragment.newInstance(file, mAccount, true); ((FileDownloadFragment) fragment).setError(true); } else { if (file.isEncrypted()) { fragment = FileDownloadFragment.newInstance(file, mAccount, mObsoletePositions.contains(i)); } else { fragment = PreviewImageFragment.newInstance(file, mObsoletePositions.contains(i), true); } } } mObsoletePositions.remove(i); return fragment; } public int getFilePosition(OCFile file) { return mImageFiles.indexOf(file); } @Override public int getCount() { return mImageFiles.size(); } @Override public CharSequence getPageTitle(int position) { OCFile file = getFileAt(position); if (file != null) { return file.getFileName(); } else { return ""; } } public void updateFile(int position, OCFile file) { FileFragment fragmentToUpdate = mCachedFragments.get(position); if (fragmentToUpdate != null) { mObsoleteFragments.add(fragmentToUpdate); } mObsoletePositions.add(position); mImageFiles.set(position, file); } public void updateWithDownloadError(int position) { FileFragment fragmentToUpdate = mCachedFragments.get(position); if (fragmentToUpdate != null) { mObsoleteFragments.add(fragmentToUpdate); } mDownloadErrors.add(position); } @Override public int getItemPosition(@NonNull Object object) { if (mObsoleteFragments.remove(object)) { return POSITION_NONE; } return super.getItemPosition(object); } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { Object fragment = super.instantiateItem(container, position); mCachedFragments.put(position, (FileFragment) fragment); return fragment; } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { mCachedFragments.remove(position); super.destroyItem(container, position, object); } public boolean pendingErrorAt(int position) { return mDownloadErrors.contains(position); } /** * Reset the image zoom to default value for each CachedFragments */ public void resetZoom() { Matrix matrix = new Matrix(); for (int i = 0; i < mCachedFragments.size(); i++) { FileFragment fileFragment = mCachedFragments.valueAt(i); if (fileFragment instanceof PreviewImageFragment) { ((PreviewImageFragment) fileFragment).getImageView().setDisplayMatrix(matrix); ((PreviewImageFragment) fileFragment).getImageView().setSuppMatrix(matrix); } } } }