mirror of
https://github.com/nextcloud/android.git
synced 2024-11-23 21:55:48 +03:00
Merge master
Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
commit
28d4220e67
6 changed files with 336 additions and 273 deletions
|
@ -86,7 +86,7 @@ class StackRemoteViewsFactory(
|
|||
val userAccountManager: UserAccountManager,
|
||||
val clientFactory: ClientFactory,
|
||||
val intent: Intent,
|
||||
val widgetRepository: WidgetRepository
|
||||
private val widgetRepository: WidgetRepository
|
||||
) : RemoteViewsService.RemoteViewsFactory {
|
||||
|
||||
private lateinit var widgetConfiguration: WidgetConfiguration
|
||||
|
@ -163,58 +163,20 @@ class StackRemoteViewsFactory(
|
|||
|
||||
// we will switch soon to coil and then streamline all of this
|
||||
// Kotlin cannot catch multiple exception types at same time
|
||||
@Suppress("NestedBlockDepth", "TooGenericExceptionCaught")
|
||||
@Suppress("NestedBlockDepth")
|
||||
private fun createItemView(position: Int): RemoteViews {
|
||||
return RemoteViews(context.packageName, R.layout.widget_item).apply {
|
||||
if (widgetItems.isEmpty()) {
|
||||
return@apply
|
||||
}
|
||||
|
||||
val widgetItem = widgetItems[position]
|
||||
|
||||
// icon bitmap/svg
|
||||
if (widgetItem.iconUrl.isNotEmpty()) {
|
||||
val glide: FutureTarget<Bitmap>
|
||||
if (Uri.parse(widgetItem.iconUrl).encodedPath!!.endsWith(".svg")) {
|
||||
glide = Glide.with(context)
|
||||
.using(
|
||||
CustomGlideUriLoader(userAccountManager.user, clientFactory),
|
||||
InputStream::class.java
|
||||
)
|
||||
.from(Uri::class.java)
|
||||
.`as`(SVGorImage::class.java)
|
||||
.transcode(SvgOrImageBitmapTranscoder(SVG_SIZE, SVG_SIZE), Bitmap::class.java)
|
||||
.sourceEncoder(StreamEncoder())
|
||||
.cacheDecoder(FileToStreamDecoder(SvgOrImageDecoder()))
|
||||
.decoder(SvgOrImageDecoder())
|
||||
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
|
||||
.load(Uri.parse(widgetItem.iconUrl))
|
||||
.into(SVG_SIZE, SVG_SIZE)
|
||||
} else {
|
||||
glide = Glide.with(context)
|
||||
.using(CustomGlideStreamLoader(widgetConfiguration.user.get(), clientFactory))
|
||||
.load(widgetItem.iconUrl)
|
||||
.asBitmap()
|
||||
.into(SVG_SIZE, SVG_SIZE)
|
||||
}
|
||||
|
||||
try {
|
||||
if (widgetConfiguration.roundIcon) {
|
||||
setImageViewBitmap(R.id.icon, BitmapUtils.roundBitmap(glide.get()))
|
||||
} else {
|
||||
setImageViewBitmap(R.id.icon, glide.get())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log_OC.d(TAG, "Error setting icon", e)
|
||||
setImageViewResource(R.id.icon, R.drawable.ic_dashboard)
|
||||
}
|
||||
loadIcon(widgetItem, this)
|
||||
}
|
||||
|
||||
// text
|
||||
setTextViewText(R.id.title, widgetItem.title)
|
||||
|
||||
if (widgetItem.subtitle.isNotEmpty()) {
|
||||
setViewVisibility(R.id.subtitle, View.VISIBLE)
|
||||
setTextViewText(R.id.subtitle, widgetItem.subtitle)
|
||||
} else {
|
||||
setViewVisibility(R.id.subtitle, View.GONE)
|
||||
}
|
||||
updateTexts(widgetItem, this)
|
||||
|
||||
if (widgetItem.link.isNotEmpty()) {
|
||||
val clickIntent = Intent(Intent.ACTION_VIEW, Uri.parse(widgetItem.link))
|
||||
|
@ -223,6 +185,65 @@ class StackRemoteViewsFactory(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
private fun loadIcon(widgetItem: DashboardWidgetItem, remoteViews: RemoteViews) {
|
||||
val isIconSVG = Uri.parse(widgetItem.iconUrl).encodedPath!!.endsWith(".svg")
|
||||
val source: FutureTarget<Bitmap> = if (isIconSVG) {
|
||||
loadSVGIcon(widgetItem)
|
||||
} else {
|
||||
loadBitmapIcon(widgetItem)
|
||||
}
|
||||
|
||||
try {
|
||||
val bitmap: Bitmap = if (widgetConfiguration.roundIcon) {
|
||||
BitmapUtils.roundBitmap(source.get())
|
||||
} else {
|
||||
source.get()
|
||||
}
|
||||
|
||||
remoteViews.setImageViewBitmap(R.id.icon, bitmap)
|
||||
} catch (e: Exception) {
|
||||
Log_OC.d(TAG, "Error setting icon", e)
|
||||
remoteViews.setImageViewResource(R.id.icon, R.drawable.ic_dashboard)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadSVGIcon(widgetItem: DashboardWidgetItem): FutureTarget<Bitmap> {
|
||||
return Glide.with(context)
|
||||
.using(
|
||||
CustomGlideUriLoader(userAccountManager.user, clientFactory),
|
||||
InputStream::class.java
|
||||
)
|
||||
.from(Uri::class.java)
|
||||
.`as`(SVGorImage::class.java)
|
||||
.transcode(SvgOrImageBitmapTranscoder(SVG_SIZE, SVG_SIZE), Bitmap::class.java)
|
||||
.sourceEncoder(StreamEncoder())
|
||||
.cacheDecoder(FileToStreamDecoder(SvgOrImageDecoder()))
|
||||
.decoder(SvgOrImageDecoder())
|
||||
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
|
||||
.load(Uri.parse(widgetItem.iconUrl))
|
||||
.into(SVG_SIZE, SVG_SIZE)
|
||||
}
|
||||
|
||||
private fun loadBitmapIcon(widgetItem: DashboardWidgetItem): FutureTarget<Bitmap> {
|
||||
return Glide.with(context)
|
||||
.using(CustomGlideStreamLoader(widgetConfiguration.user.get(), clientFactory))
|
||||
.load(widgetItem.iconUrl)
|
||||
.asBitmap()
|
||||
.into(SVG_SIZE, SVG_SIZE)
|
||||
}
|
||||
|
||||
private fun updateTexts(widgetItem: DashboardWidgetItem, remoteViews: RemoteViews) {
|
||||
remoteViews.setTextViewText(R.id.title, widgetItem.title)
|
||||
|
||||
if (widgetItem.subtitle.isNotEmpty()) {
|
||||
remoteViews.setViewVisibility(R.id.subtitle, View.VISIBLE)
|
||||
remoteViews.setTextViewText(R.id.subtitle, widgetItem.subtitle)
|
||||
} else {
|
||||
remoteViews.setViewVisibility(R.id.subtitle, View.GONE)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLoadingView(): RemoteViews? {
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -41,10 +41,21 @@ import android.os.Looper;
|
|||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateFormat;
|
||||
import android.view.*;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.widget.*;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.nextcloud.client.account.User;
|
||||
|
@ -66,13 +77,21 @@ import com.owncloud.android.operations.CreateFolderOperation;
|
|||
import com.owncloud.android.operations.RefreshFolderOperation;
|
||||
import com.owncloud.android.operations.UploadFileOperation;
|
||||
import com.owncloud.android.syncadapter.FileSyncAdapter;
|
||||
import com.owncloud.android.ui.adapter.UploaderAdapter;
|
||||
import com.owncloud.android.ui.adapter.ReceiveExternalFilesAdapter;
|
||||
import com.owncloud.android.ui.asynctasks.CopyAndUploadContentUrisTask;
|
||||
import com.owncloud.android.ui.dialog.*;
|
||||
import com.owncloud.android.ui.dialog.AccountChooserInterface;
|
||||
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
|
||||
import com.owncloud.android.ui.dialog.MultipleAccountsDialog;
|
||||
import com.owncloud.android.ui.dialog.SortingOrderDialogFragment;
|
||||
import com.owncloud.android.ui.fragment.TaskRetainerFragment;
|
||||
import com.owncloud.android.ui.helpers.FileOperationsHelper;
|
||||
import com.owncloud.android.ui.helpers.UriUploader;
|
||||
import com.owncloud.android.utils.*;
|
||||
import com.owncloud.android.utils.DataHolderUtil;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
import com.owncloud.android.utils.ErrorMessageAdapter;
|
||||
import com.owncloud.android.utils.FileSortOrder;
|
||||
import com.owncloud.android.utils.MimeType;
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -80,7 +99,12 @@ import java.io.FileWriter;
|
|||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -96,6 +120,7 @@ import androidx.core.view.MenuItemCompat;
|
|||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFragment;
|
||||
|
||||
|
@ -103,8 +128,8 @@ import static com.owncloud.android.utils.DisplayUtils.openSortingOrderDialogFrag
|
|||
* This can be used to upload things to an ownCloud instance.
|
||||
*/
|
||||
public class ReceiveExternalFilesActivity extends FileActivity
|
||||
implements OnItemClickListener, View.OnClickListener, CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener,
|
||||
SortingOrderDialogFragment.OnSortingOrderListener, Injectable, AccountChooserInterface {
|
||||
implements View.OnClickListener, CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener,
|
||||
SortingOrderDialogFragment.OnSortingOrderListener, Injectable, AccountChooserInterface, ReceiveExternalFilesAdapter.OnItemClickListener {
|
||||
|
||||
private static final String TAG = ReceiveExternalFilesActivity.class.getSimpleName();
|
||||
|
||||
|
@ -125,6 +150,7 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
private OCFile mFile;
|
||||
|
||||
private SyncBroadcastReceiver mSyncBroadcastReceiver;
|
||||
private ReceiveExternalFilesAdapter receiveExternalFilesAdapter;
|
||||
private boolean mSyncInProgress;
|
||||
|
||||
private final static int REQUEST_CODE__SETUP_ACCOUNT = REQUEST_CODE__LAST_SHARED + 1;
|
||||
|
@ -273,6 +299,22 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
populateDirectoryList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectFile(OCFile file) {
|
||||
if (file.isFolder()) {
|
||||
if (file.isEncrypted() &&
|
||||
!FileOperationsHelper.isEndToEndEncryptionSetup(this, getUser().orElseThrow(IllegalAccessError::new))) {
|
||||
DisplayUtils.showSnackMessage(this, R.string.e2e_not_yet_setup);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
startSyncFolderOperation(file);
|
||||
mParents.push(file.getFileName());
|
||||
populateDirectoryList();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DialogNoAccount extends DialogFragment {
|
||||
@NonNull
|
||||
@Override
|
||||
|
@ -611,39 +653,6 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
// click on folder in the list
|
||||
Log_OC.d(TAG, "on item click");
|
||||
List<OCFile> tmpFiles = getStorageManager().getFolderContent(mFile, false);
|
||||
tmpFiles = sortFileList(tmpFiles);
|
||||
|
||||
if (tmpFiles.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// filter on dirtype
|
||||
Vector<OCFile> files = new Vector<>();
|
||||
files.addAll(tmpFiles);
|
||||
|
||||
if (files.size() < position) {
|
||||
throw new IndexOutOfBoundsException("Incorrect item selected");
|
||||
}
|
||||
OCFile ocFile = files.get(position);
|
||||
if (ocFile.isFolder()) {
|
||||
if (ocFile.isEncrypted() &&
|
||||
!FileOperationsHelper.isEndToEndEncryptionSetup(this, getUser().orElseThrow(IllegalAccessError::new))) {
|
||||
DisplayUtils.showSnackMessage(this, R.string.e2e_not_yet_setup);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
OCFile folderToEnter = files.get(position);
|
||||
startSyncFolderOperation(folderToEnter);
|
||||
mParents.push(folderToEnter.getFileName());
|
||||
populateDirectoryList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// click on button
|
||||
|
@ -740,29 +749,10 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
binding.list.setVisibility(View.GONE);
|
||||
} else {
|
||||
mEmptyListContainer.setVisibility(View.GONE);
|
||||
|
||||
files = sortFileList(files);
|
||||
|
||||
List<Map<String, Object>> data = new LinkedList<>();
|
||||
for (OCFile f : files) {
|
||||
Map<String, Object> h = new HashMap<>();
|
||||
h.put("dirname", f);
|
||||
data.add(h);
|
||||
}
|
||||
|
||||
UploaderAdapter sa = new UploaderAdapter(this,
|
||||
data,
|
||||
R.layout.uploader_list_item_layout,
|
||||
new String[]{"dirname"},
|
||||
new int[]{R.id.filename},
|
||||
getStorageManager(),
|
||||
getUser().get(),
|
||||
syncedFolderProvider,
|
||||
viewThemeUtils);
|
||||
|
||||
binding.list.setAdapter(sa);
|
||||
binding.list.setVisibility(View.VISIBLE);
|
||||
setupReceiveExternalFilesAdapter(files);
|
||||
}
|
||||
|
||||
MaterialButton btnChooseFolder = binding.uploaderChooseFolder;
|
||||
viewThemeUtils.material.colorMaterialButtonPrimaryFilled(btnChooseFolder);
|
||||
btnChooseFolder.setOnClickListener(this);
|
||||
|
@ -774,8 +764,6 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
viewThemeUtils.material.colorMaterialButtonPrimaryOutlined(binding.uploaderCancel);
|
||||
binding.uploaderCancel.setOnClickListener(this);
|
||||
|
||||
binding.list.setOnItemClickListener(this);
|
||||
|
||||
sortButton = binding.toolbarLayout.sortButton;
|
||||
FileSortOrder sortOrder = preferences.getSortOrderByFolder(mFile);
|
||||
sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder));
|
||||
|
@ -783,6 +771,21 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
}
|
||||
}
|
||||
|
||||
private void setupReceiveExternalFilesAdapter(List<OCFile> files) {
|
||||
receiveExternalFilesAdapter = new ReceiveExternalFilesAdapter(files,
|
||||
this,
|
||||
getUser().get(),
|
||||
getStorageManager(),
|
||||
viewThemeUtils,
|
||||
syncedFolderProvider,
|
||||
this);
|
||||
|
||||
|
||||
binding.list.setLayoutManager(new LinearLayoutManager(this));
|
||||
binding.list.setAdapter(receiveExternalFilesAdapter);
|
||||
binding.list.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
protected void setupEmptyList() {
|
||||
mEmptyListContainer = binding.emptyView.emptyListView;
|
||||
mEmptyListMessage = binding.emptyView.emptyListViewText;
|
||||
|
@ -1016,19 +1019,35 @@ public class ReceiveExternalFilesActivity extends FileActivity
|
|||
menu.findItem(R.id.action_create_dir).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
}
|
||||
|
||||
// tint search event
|
||||
final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
|
||||
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
|
||||
setupSearchView(menu);
|
||||
|
||||
MenuItem newFolderMenuItem = menu.findItem(R.id.action_create_dir);
|
||||
newFolderMenuItem.setEnabled(mFile.canWrite());
|
||||
|
||||
// hacky as no default way is provided
|
||||
viewThemeUtils.androidx.themeToolbarSearchView(searchView);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setupSearchView(Menu menu) {
|
||||
final MenuItem searchMenuItem = menu.findItem(R.id.action_search);
|
||||
|
||||
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
|
||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||
@Override
|
||||
public boolean onQueryTextSubmit(String query) {
|
||||
receiveExternalFilesAdapter.filter(query);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
receiveExternalFilesAdapter.filter(newText);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
viewThemeUtils.androidx.themeToolbarSearchView(searchView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
boolean retval = true;
|
||||
|
|
|
@ -178,6 +178,8 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
|
|||
viewThemeUtils,
|
||||
syncedFolderProvider);
|
||||
|
||||
setHasStableIds(true);
|
||||
|
||||
// initialise thumbnails cache on background thread
|
||||
new ThumbnailsCacheManager.InitDiskCacheTask().execute();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Alper Ozturk
|
||||
* Copyright (C) 2023 Alper Ozturk
|
||||
* Copyright (C) 2023 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.ui.adapter
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.nextcloud.client.account.User
|
||||
import com.owncloud.android.databinding.UploaderListItemLayoutBinding
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.datamodel.SyncedFolderProvider
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncThumbnailDrawable
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager.ThumbnailGenerationTask
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager.ThumbnailGenerationTaskObject
|
||||
import com.owncloud.android.utils.DisplayUtils
|
||||
import com.owncloud.android.utils.MimeTypeUtil
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
class ReceiveExternalFilesAdapter(
|
||||
private val files: List<OCFile>,
|
||||
private val context: Context,
|
||||
private val user: User,
|
||||
private val storageManager: FileDataStorageManager,
|
||||
private val viewThemeUtils: ViewThemeUtils,
|
||||
private val syncedFolderProvider: SyncedFolderProvider,
|
||||
private val onItemClickListener: OnItemClickListener
|
||||
) : RecyclerView.Adapter<ReceiveExternalFilesAdapter.ReceiveExternalViewHolder>() {
|
||||
|
||||
private var filteredFiles: List<OCFile> = files
|
||||
|
||||
interface OnItemClickListener {
|
||||
fun selectFile(file: OCFile)
|
||||
}
|
||||
|
||||
inner class ReceiveExternalViewHolder(val binding: UploaderListItemLayoutBinding) :
|
||||
RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
binding.root.setOnClickListener {
|
||||
val position = bindingAdapterPosition
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
onItemClickListener.selectFile(filteredFiles[position])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun filter(query: String) {
|
||||
filteredFiles = if (query.isEmpty()) {
|
||||
files
|
||||
} else {
|
||||
files.filter { file ->
|
||||
file.fileName.contains(query, ignoreCase = true)
|
||||
}
|
||||
}
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ReceiveExternalViewHolder {
|
||||
val binding = UploaderListItemLayoutBinding
|
||||
.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
|
||||
return ReceiveExternalViewHolder(binding)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: ReceiveExternalViewHolder, position: Int) {
|
||||
val file = filteredFiles[position]
|
||||
|
||||
viewHolder.binding.filename.text = file.fileName
|
||||
viewHolder.binding.lastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
|
||||
|
||||
if (!file.isFolder) {
|
||||
viewHolder.binding.fileSize.text = DisplayUtils.bytesToHumanReadable(file.fileLength)
|
||||
}
|
||||
|
||||
viewHolder.binding.fileSize.visibility = if (file.isFolder) {
|
||||
View.GONE
|
||||
} else {
|
||||
View.VISIBLE
|
||||
}
|
||||
viewHolder.binding.fileSeparator.visibility = if (file.isFolder) {
|
||||
View.GONE
|
||||
} else {
|
||||
View.VISIBLE
|
||||
}
|
||||
|
||||
val thumbnailImageView = viewHolder.binding.thumbnail
|
||||
setupThumbnail(thumbnailImageView, file)
|
||||
}
|
||||
|
||||
private fun setupThumbnail(thumbnailImageView: ImageView, file: OCFile) {
|
||||
thumbnailImageView.tag = file.fileId
|
||||
|
||||
if (file.isFolder) {
|
||||
setupThumbnailForFolder(thumbnailImageView, file)
|
||||
} else if (MimeTypeUtil.isImage(file) && file.remoteId != null) {
|
||||
setupThumbnailForImage(thumbnailImageView, file)
|
||||
} else {
|
||||
setupDefaultThumbnail(thumbnailImageView, file)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupThumbnailForFolder(thumbnailImageView: ImageView, file: OCFile) {
|
||||
val isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user)
|
||||
val isDarkModeActive = syncedFolderProvider.preferences.isDarkModeEnabled
|
||||
val overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder)
|
||||
val icon = MimeTypeUtil.getFileIcon(isDarkModeActive, overlayIconId, context, viewThemeUtils)
|
||||
thumbnailImageView.setImageDrawable(icon)
|
||||
}
|
||||
|
||||
@Suppress("NestedBlockDepth")
|
||||
private fun setupThumbnailForImage(thumbnailImageView: ImageView, file: OCFile) {
|
||||
var thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(file.remoteId.toString())
|
||||
if (thumbnail != null && !file.isUpdateThumbnailNeeded) {
|
||||
thumbnailImageView.setImageBitmap(thumbnail)
|
||||
} else {
|
||||
// generate new Thumbnail
|
||||
if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, thumbnailImageView)) {
|
||||
val task = ThumbnailGenerationTask(thumbnailImageView, storageManager, user)
|
||||
if (thumbnail == null) {
|
||||
thumbnail = if (MimeTypeUtil.isVideo(file)) {
|
||||
ThumbnailsCacheManager.mDefaultVideo
|
||||
} else {
|
||||
ThumbnailsCacheManager.mDefaultImg
|
||||
}
|
||||
}
|
||||
val asyncDrawable = AsyncThumbnailDrawable(
|
||||
context.resources,
|
||||
thumbnail,
|
||||
task
|
||||
)
|
||||
thumbnailImageView.setImageDrawable(asyncDrawable)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
task.execute(ThumbnailGenerationTaskObject(file, file.remoteId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDefaultThumbnail(thumbnailImageView: ImageView, file: OCFile) {
|
||||
val icon = MimeTypeUtil.getFileTypeIcon(
|
||||
file.mimeType,
|
||||
file.fileName,
|
||||
context,
|
||||
viewThemeUtils
|
||||
)
|
||||
thumbnailImageView.setImageDrawable(icon)
|
||||
}
|
||||
|
||||
override fun getItemCount() = filteredFiles.size
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* Copyright (C) 2016 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.ui.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.SimpleAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.nextcloud.client.account.User;
|
||||
import com.nextcloud.client.preferences.DarkMode;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.datamodel.SyncedFolderProvider;
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager;
|
||||
import com.owncloud.android.datamodel.ThumbnailsCacheManager.AsyncThumbnailDrawable;
|
||||
import com.owncloud.android.utils.DisplayUtils;
|
||||
import com.owncloud.android.utils.MimeTypeUtil;
|
||||
import com.owncloud.android.utils.theme.ViewThemeUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UploaderAdapter extends SimpleAdapter {
|
||||
|
||||
private final Context mContext;
|
||||
private final User user;
|
||||
private final FileDataStorageManager mStorageManager;
|
||||
private final LayoutInflater inflater;
|
||||
private final ViewThemeUtils viewThemeUtils;
|
||||
private SyncedFolderProvider syncedFolderProvider;
|
||||
|
||||
public UploaderAdapter(Context context,
|
||||
List<? extends Map<String, ?>> data,
|
||||
int resource,
|
||||
String[] from,
|
||||
int[] to,
|
||||
FileDataStorageManager storageManager,
|
||||
User user,
|
||||
SyncedFolderProvider syncedFolderProvider,
|
||||
ViewThemeUtils viewThemeUtils) {
|
||||
super(context, data, resource, from, to);
|
||||
this.user = user;
|
||||
mStorageManager = storageManager;
|
||||
mContext = context;
|
||||
this.syncedFolderProvider = syncedFolderProvider;
|
||||
inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
this.viewThemeUtils = viewThemeUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View vi = convertView;
|
||||
if (convertView == null) {
|
||||
vi = inflater.inflate(R.layout.uploader_list_item_layout, parent, false);
|
||||
}
|
||||
|
||||
HashMap<String, OCFile> data = (HashMap<String, OCFile>) getItem(position);
|
||||
OCFile file = data.get("dirname");
|
||||
|
||||
TextView filename = vi.findViewById(R.id.filename);
|
||||
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()));
|
||||
|
||||
TextView fileSizeV = vi.findViewById(R.id.file_size);
|
||||
TextView fileSizeSeparatorV = vi.findViewById(R.id.file_separator);
|
||||
|
||||
if(!file.isFolder()) {
|
||||
fileSizeV.setVisibility(View.VISIBLE);
|
||||
fileSizeSeparatorV.setVisibility(View.VISIBLE);
|
||||
fileSizeV.setText(DisplayUtils.bytesToHumanReadable(file.getFileLength()));
|
||||
} else {
|
||||
fileSizeV.setVisibility(View.GONE);
|
||||
fileSizeSeparatorV.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (file.isFolder()) {
|
||||
boolean isAutoUploadFolder = SyncedFolderProvider.isAutoUploadFolder(syncedFolderProvider, file, user);
|
||||
boolean isDarkModeActive = syncedFolderProvider.getPreferences().isDarkModeEnabled();
|
||||
|
||||
Integer overlayIconId = file.getFileOverlayIconId(isAutoUploadFolder);
|
||||
final LayerDrawable icon = MimeTypeUtil.getFileIcon(isDarkModeActive, overlayIconId, mContext, viewThemeUtils);
|
||||
fileIcon.setImageDrawable(icon);
|
||||
} 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.isUpdateThumbnailNeeded()) {
|
||||
fileIcon.setImageBitmap(thumbnail);
|
||||
} else {
|
||||
// generate new Thumbnail
|
||||
if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(file, fileIcon)) {
|
||||
final ThumbnailsCacheManager.ThumbnailGenerationTask task =
|
||||
new ThumbnailsCacheManager.ThumbnailGenerationTask(fileIcon, mStorageManager, user);
|
||||
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()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final Drawable icon = MimeTypeUtil.getFileTypeIcon(file.getMimeType(),
|
||||
file.getFileName(),
|
||||
mContext,
|
||||
viewThemeUtils);
|
||||
fileIcon.setImageDrawable(icon);
|
||||
}
|
||||
}
|
||||
|
||||
return vi;
|
||||
}
|
||||
}
|
|
@ -34,10 +34,11 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<ListView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/bg_default"
|
||||
android:divider="@color/transparent"
|
||||
android:dividerHeight="0dip"
|
||||
|
|
Loading…
Reference in a new issue