diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a098c8ff9..afb39eef3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -170,7 +170,11 @@
+ android:theme="@style/AppTheme" />
+
+
- * Copyright (C) 2017-2018 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.adapters.items;
-
-import android.content.Context;
-import android.text.format.Formatter;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.Toast;
-
-import com.facebook.drawee.backends.pipeline.Fresco;
-import com.facebook.drawee.interfaces.DraweeController;
-import com.nextcloud.talk.R;
-import com.nextcloud.talk.application.NextcloudTalkApplication;
-import com.nextcloud.talk.components.filebrowser.models.BrowserFile;
-import com.nextcloud.talk.databinding.RvItemBrowserFileBinding;
-import com.nextcloud.talk.interfaces.SelectionInterface;
-import com.nextcloud.talk.models.database.UserEntity;
-import com.nextcloud.talk.utils.ApiUtils;
-import com.nextcloud.talk.utils.DateUtils;
-import com.nextcloud.talk.utils.DisplayUtils;
-import com.nextcloud.talk.utils.DrawableUtils;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import androidx.appcompat.content.res.AppCompatResources;
-import autodagger.AutoInjector;
-import eu.davidea.flexibleadapter.FlexibleAdapter;
-import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
-import eu.davidea.flexibleadapter.items.IFilterable;
-import eu.davidea.flexibleadapter.items.IFlexible;
-import eu.davidea.viewholders.FlexibleViewHolder;
-
-@AutoInjector(NextcloudTalkApplication.class)
-public class BrowserFileItem extends AbstractFlexibleItem implements IFilterable {
- @Inject
- Context context;
- private final BrowserFile browserFile;
- private final UserEntity activeUser;
- private final SelectionInterface selectionInterface;
- private boolean selected;
-
- public BrowserFileItem(BrowserFile browserFile, UserEntity activeUser, SelectionInterface selectionInterface) {
- this.browserFile = browserFile;
- this.activeUser = activeUser;
- this.selectionInterface = selectionInterface;
- NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof BrowserFileItem) {
- BrowserFileItem inItem = (BrowserFileItem) o;
- return browserFile.getPath().equals(inItem.getModel().getPath());
- }
-
- return false;
- }
-
- public BrowserFile getModel() {
- return browserFile;
- }
-
- @Override
- public int getLayoutRes() {
- return R.layout.rv_item_browser_file;
- }
-
- @Override
- public BrowserFileItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
- return new BrowserFileItemViewHolder(view, adapter);
- }
-
- private boolean isSelected() {
- return selected;
- }
-
- private void setSelected(boolean selected) {
- this.selected = selected;
- }
-
- @Override
- public void bindViewHolder(FlexibleAdapter adapter,
- BrowserFileItemViewHolder holder,
- int position,
- List payloads) {
- holder.binding.fileIcon.setController(null);
- if (!browserFile.isAllowedToReShare() || browserFile.isEncrypted()) {
- holder.itemView.setEnabled(false);
- holder.itemView.setAlpha(0.38f);
- } else {
- holder.itemView.setEnabled(true);
- holder.itemView.setAlpha(1.0f);
- }
-
- if (browserFile.isEncrypted()) {
- holder.binding.fileEncryptedImageView.setVisibility(View.VISIBLE);
-
- } else {
- holder.binding.fileEncryptedImageView.setVisibility(View.GONE);
- }
-
- if (browserFile.isFavorite()) {
- holder.binding.fileFavoriteImageView.setVisibility(View.VISIBLE);
- } else {
- holder.binding.fileFavoriteImageView.setVisibility(View.GONE);
- }
-
- if (selectionInterface.shouldOnlySelectOneImageFile()) {
- if (browserFile.isFile() && browserFile.getMimeType().startsWith("image/")) {
- holder.binding.selectFileCheckbox.setVisibility(View.VISIBLE);
- } else {
- holder.binding.selectFileCheckbox.setVisibility(View.GONE);
- }
- } else {
- holder.binding.selectFileCheckbox.setVisibility(View.VISIBLE);
- }
-
- if (context != null) {
- holder
- .binding
- .fileIcon
- .getHierarchy()
- .setPlaceholderImage(
- AppCompatResources.getDrawable(
- context, DrawableUtils.INSTANCE.getDrawableResourceIdForMimeType(browserFile.getMimeType())));
- }
-
- if (browserFile.getHasPreview()) {
- String path = ApiUtils.getUrlForFilePreviewWithRemotePath(activeUser.getBaseUrl(),
- browserFile.getPath(),
- context.getResources().getDimensionPixelSize(R.dimen.small_item_height));
-
- if (path.length() > 0) {
- DraweeController draweeController = Fresco.newDraweeControllerBuilder()
- .setAutoPlayAnimations(true)
- .setImageRequest(DisplayUtils.getImageRequestForUrl(path, null))
- .build();
- holder.binding.fileIcon.setController(draweeController);
- }
- }
-
- holder.binding.filenameTextView.setText(browserFile.getDisplayName());
- holder.binding.fileModifiedInfo.setText(String.format(context.getString(R.string.nc_last_modified),
- Formatter.formatShortFileSize(context, browserFile.getSize()),
- DateUtils.INSTANCE.getLocalDateTimeStringFromTimestamp(browserFile.getModifiedTimestamp())));
- setSelected(selectionInterface.isPathSelected(browserFile.getPath()));
- holder.binding.selectFileCheckbox.setChecked(isSelected());
-
- if (!browserFile.isEncrypted()) {
- holder.binding.selectFileCheckbox.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (!browserFile.isAllowedToReShare()) {
- ((CheckBox) v).setChecked(false);
- Toast.makeText(
- context,
- context.getResources().getString(R.string.nc_file_browser_reshare_forbidden),
- Toast.LENGTH_LONG)
- .show();
- } else if (((CheckBox) v).isChecked() != isSelected()) {
- setSelected(((CheckBox) v).isChecked());
- selectionInterface.toggleBrowserItemSelection(browserFile.getPath());
- }
- }
- });
- }
-
- holder.binding.filenameTextView.setSelected(true);
- holder.binding.fileModifiedInfo.setSelected(true);
- }
-
- @Override
- public boolean filter(String constraint) {
- return false;
- }
-
- static class BrowserFileItemViewHolder extends FlexibleViewHolder {
-
- RvItemBrowserFileBinding binding;
-
- BrowserFileItemViewHolder(View view, FlexibleAdapter adapter) {
- super(view, adapter);
- binding = RvItemBrowserFileBinding.bind(view);
- }
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserController.kt b/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserController.kt
deleted file mode 100644
index c32c534fe..000000000
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserController.kt
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Andy Scherzinger
- * Copyright (C) 2021 Andy Scherzinger
- * Copyright (C) 2017-2018 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.controllers
-
-import android.annotation.SuppressLint
-import android.os.Bundle
-import android.os.Parcelable
-import android.util.Log
-import android.view.Menu
-import android.view.MenuInflater
-import android.view.MenuItem
-import android.view.View
-import androidx.fragment.app.DialogFragment
-import androidx.recyclerview.widget.RecyclerView
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-import autodagger.AutoInjector
-import com.nextcloud.talk.R
-import com.nextcloud.talk.activities.MainActivity
-import com.nextcloud.talk.application.NextcloudTalkApplication
-import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
-import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem
-import com.nextcloud.talk.components.filebrowser.interfaces.ListingInterface
-import com.nextcloud.talk.components.filebrowser.models.BrowserFile
-import com.nextcloud.talk.components.filebrowser.models.DavResponse
-import com.nextcloud.talk.components.filebrowser.operations.DavListing
-import com.nextcloud.talk.components.filebrowser.operations.ListingAbstractClass
-import com.nextcloud.talk.controllers.base.NewBaseController
-import com.nextcloud.talk.controllers.util.viewBinding
-import com.nextcloud.talk.databinding.ControllerBrowserBinding
-import com.nextcloud.talk.interfaces.SelectionInterface
-import com.nextcloud.talk.models.database.UserEntity
-import com.nextcloud.talk.ui.dialog.SortingOrderDialogFragment
-import com.nextcloud.talk.utils.DisplayUtils
-import com.nextcloud.talk.utils.FileSortOrder
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BROWSER_TYPE
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY
-import com.nextcloud.talk.utils.database.user.UserUtils
-import eu.davidea.flexibleadapter.FlexibleAdapter
-import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
-import kotlinx.android.parcel.Parcelize
-import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener
-import okhttp3.OkHttpClient
-import org.parceler.Parcels
-import java.io.File
-import java.util.ArrayList
-import java.util.Collections
-import java.util.TreeSet
-import javax.inject.Inject
-
-@AutoInjector(NextcloudTalkApplication::class)
-abstract class BrowserController(args: Bundle) :
- NewBaseController(
- R.layout.controller_browser,
- args
- ),
- ListingInterface,
- FlexibleAdapter.OnItemClickListener,
- SwipeRefreshLayout.OnRefreshListener,
- SelectionInterface {
-
- private val binding: ControllerBrowserBinding by viewBinding(ControllerBrowserBinding::bind)
-
- @JvmField
- protected val selectedPaths: MutableSet
-
- @JvmField
- @Inject
- var userUtils: UserUtils? = null
-
- @JvmField
- @Inject
- var okHttpClient: OkHttpClient? = null
-
- @JvmField
- protected var activeUser: UserEntity
-
- private var filesSelectionDoneMenuItem: MenuItem? = null
- private var layoutManager: RecyclerView.LayoutManager? = null
- private var adapter: FlexibleAdapter? = null
- private var recyclerViewItems: List = ArrayList()
- private var listingAbstractClass: ListingAbstractClass? = null
- private val browserType: BrowserType
- private var currentPath: String
-
- private var sortingChangeListener: OnPreferenceValueChangedListener? = null
-
- override fun onViewBound(view: View) {
- super.onViewBound(view)
- if (adapter == null) {
- adapter = FlexibleAdapter(recyclerViewItems, context, false)
- }
-
- appPreferences!!.registerSortingChangeListener(
- SortingChangeListener(this).also {
- sortingChangeListener = it
- }
- )
-
- changeEnabledStatusForBarItems(true)
- prepareViews()
- }
-
- abstract fun onFileSelectionDone()
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- super.onCreateOptionsMenu(menu, inflater)
- inflater.inflate(R.menu.menu_share_files, menu)
- filesSelectionDoneMenuItem = menu.findItem(R.id.files_selection_done)
- filesSelectionDoneMenuItem?.isVisible = selectedPaths.size > 0
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == R.id.files_selection_done) {
- onFileSelectionDone()
- return true
- }
- return super.onOptionsItemSelected(item)
- }
-
- override fun onAttach(view: View) {
- super.onAttach(view)
-
- binding.pathNavigation.menu.findItem(R.id.action_back)?.setOnMenuItemClickListener { goBack() }
- binding.sortButton.setOnClickListener { changeSorting() }
-
- binding.sortButton.setText(
- DisplayUtils.getSortOrderStringId(FileSortOrder.getFileSortOrder(appPreferences?.sorting))
- )
-
- refreshCurrentPath()
- }
-
- override fun onRefresh() {
- refreshCurrentPath()
- }
-
- fun changeSorting() {
- val newFragment: DialogFragment = SortingOrderDialogFragment
- .newInstance(FileSortOrder.getFileSortOrder(appPreferences?.sorting))
- newFragment.show(
- (activity as MainActivity?)!!.supportFragmentManager,
- SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT
- )
- }
-
- public override fun onDestroy() {
- super.onDestroy()
- listingAbstractClass!!.tearDown()
- }
-
- override val title: String
- get() =
- currentPath
-
- fun goBack(): Boolean {
- fetchPath(File(currentPath).parent)
- return true
- }
-
- fun refreshCurrentPath(): Boolean {
- fetchPath(currentPath)
- return true
- }
-
- @SuppressLint("RestrictedApi")
- private fun changeEnabledStatusForBarItems(shouldBeEnabled: Boolean) {
- binding.pathNavigation.menu.findItem(R.id.action_back)?.isEnabled = shouldBeEnabled && currentPath != "/"
- }
-
- private fun fetchPath(path: String) {
- listingAbstractClass!!.cancelAllJobs()
- changeEnabledStatusForBarItems(false)
- listingAbstractClass!!.getFiles(
- path,
- activeUser,
- if (BrowserType.DAV_BROWSER == browserType) okHttpClient else null
- )
- }
-
- override fun listingResult(davResponse: DavResponse) {
- recyclerViewItems = ArrayList()
- if (davResponse.getData() != null) {
- val objectList = davResponse.getData() as List
- currentPath = objectList[0].path!!
- if (activity != null) {
- activity!!.runOnUiThread { setTitle() }
- }
- for (i in 1 until objectList.size) {
- (recyclerViewItems as ArrayList).add(BrowserFileItem(objectList[i], activeUser, this))
- }
- }
-
- FileSortOrder.getFileSortOrder(appPreferences?.sorting).sortCloudFiles(recyclerViewItems)
-
- if (activity != null) {
- activity!!.runOnUiThread {
- adapter!!.clear()
- adapter!!.addItems(0, recyclerViewItems)
- adapter!!.notifyDataSetChanged()
- changeEnabledStatusForBarItems(true)
- }
- }
-
- binding.swipeRefreshList.isRefreshing = false
- }
-
- private fun shouldPathBeSelectedDueToParent(currentPath: String): Boolean {
- if (selectedPaths.size > 0) {
- var file = File(currentPath)
- if (file.parent != "/") {
- while (file.parent != null) {
- var parent = file.parent!!
- if (File(file.parent!!).parent != null) {
- parent += "/"
- }
- if (selectedPaths.contains(parent)) {
- return true
- }
- file = File(file.parent!!)
- }
- }
- }
- return false
- }
-
- private fun checkAndRemoveAnySelectedParents(currentPath: String) {
- var file = File(currentPath)
- selectedPaths.remove(currentPath)
- while (file.parent != null) {
- selectedPaths.remove(file.parent!! + "/")
- file = File(file.parent!!)
- }
- if (activity != null) {
- activity!!.runOnUiThread {
- adapter!!.notifyDataSetChanged()
- }
- }
- }
-
- override fun onItemClick(view: View, position: Int): Boolean {
- val browserFile = (adapter!!.getItem(position) as BrowserFileItem).model
- if ("inode/directory" == browserFile.mimeType) {
- fetchPath(browserFile.path!!)
- return true
- }
- return false
- }
-
- private fun prepareViews() {
- if (activity != null) {
- layoutManager = SmoothScrollLinearLayoutManager(activity)
- binding.recyclerView.layoutManager = layoutManager
- binding.recyclerView.setHasFixedSize(true)
- binding.recyclerView.adapter = adapter
- adapter!!.addListener(this)
-
- binding.swipeRefreshList.setOnRefreshListener(this)
- binding.swipeRefreshList.setColorSchemeResources(R.color.colorPrimary)
- binding.swipeRefreshList.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background)
- }
- }
-
- @SuppressLint("RestrictedApi")
- override fun toggleBrowserItemSelection(path: String) {
- if (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
- checkAndRemoveAnySelectedParents(path)
- } else {
- // TOOD: if it's a folder, remove all the children we added manually
- selectedPaths.add(path)
- }
- filesSelectionDoneMenuItem?.isVisible = selectedPaths.size > 0
- }
-
- override fun isPathSelected(path: String): Boolean {
- return selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)
- }
-
- abstract override fun shouldOnlySelectOneImageFile(): Boolean
-
- @Parcelize
- enum class BrowserType : Parcelable {
- FILE_BROWSER, DAV_BROWSER
- }
-
- init {
- setHasOptionsMenu(true)
- sharedApplication!!.componentApplication.inject(this)
- browserType = Parcels.unwrap(args.getParcelable(KEY_BROWSER_TYPE))
- activeUser = Parcels.unwrap(args.getParcelable(KEY_USER_ENTITY))
- currentPath = "/"
- if (BrowserType.DAV_BROWSER == browserType) {
- listingAbstractClass = DavListing(this)
- } // else {
- // listingAbstractClass = new LocalListing(this);
- // }
- selectedPaths = Collections.synchronizedSet(TreeSet())
- }
-
- @Suppress("Detekt.TooGenericExceptionCaught")
- private class SortingChangeListener(private val browserController: BrowserController) :
- OnPreferenceValueChangedListener {
- override fun onChanged(newValue: String) {
- try {
- val sortOrder = FileSortOrder.getFileSortOrder(newValue)
-
- browserController.binding.sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder))
- browserController.recyclerViewItems = sortOrder.sortCloudFiles(browserController.recyclerViewItems)
-
- if (browserController.activity != null) {
- browserController.activity!!.runOnUiThread {
- browserController.adapter!!.updateDataSet(browserController.recyclerViewItems)
- browserController.changeEnabledStatusForBarItems(true)
- }
- }
- } catch (npe: NullPointerException) {
- // view binding can be null
- // since this is called asynchronously and UI might have been destroyed in the meantime
- Log.i(BrowserController.TAG, "UI destroyed - view binding already gone")
- }
- }
- }
-
- companion object {
- private const val TAG = "BrowserController"
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserForAvatarController.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserForAvatarController.java
deleted file mode 100644
index 9075d3788..000000000
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserForAvatarController.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Tobias Kaminsky
- * Copyright (C) 2021 Tobias Kaminsky
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.controllers;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-import com.nextcloud.talk.controllers.ProfileController;
-
-import androidx.annotation.Nullable;
-
-public class BrowserForAvatarController extends BrowserController {
- private ProfileController controller;
-
- public BrowserForAvatarController(Bundle args) {
- super(args);
- }
-
- public BrowserForAvatarController(Bundle args, ProfileController controller) {
- super(args);
-
- this.controller = controller;
- }
-
- @Override
- public void onFileSelectionDone() {
- controller.handleAvatar(selectedPaths.iterator().next());
-
- getRouter().popCurrentController();
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- }
-
- @Override
- public boolean shouldOnlySelectOneImageFile() {
- return true;
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserForSharingController.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserForSharingController.java
deleted file mode 100644
index f0b0e640a..000000000
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/controllers/BrowserForSharingController.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Tobias Kaminsky
- * Copyright (C) 2021 Tobias Kaminsky
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.controllers;
-
-import android.os.Bundle;
-
-import com.nextcloud.talk.jobs.ShareOperationWorker;
-import com.nextcloud.talk.utils.bundle.BundleKeys;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import androidx.work.Data;
-import androidx.work.OneTimeWorkRequest;
-import androidx.work.WorkManager;
-
-public class BrowserForSharingController extends BrowserController {
- private final String roomToken;
-
- public BrowserForSharingController(Bundle args) {
- super(args);
-
- roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
- }
-
- @Override
- public void onFileSelectionDone() {
- synchronized (selectedPaths) {
- Iterator iterator = selectedPaths.iterator();
-
- List paths = new ArrayList<>();
- Data data;
- OneTimeWorkRequest shareWorker;
-
- while (iterator.hasNext()) {
- String path = iterator.next();
- paths.add(path);
- iterator.remove();
- if (paths.size() == 10 || !iterator.hasNext()) {
- data = new Data.Builder()
- .putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), activeUser.getId())
- .putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken)
- .putStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS(), paths.toArray(new String[0]))
- .build();
- shareWorker = new OneTimeWorkRequest.Builder(ShareOperationWorker.class)
- .setInputData(data)
- .build();
- WorkManager.getInstance().enqueue(shareWorker);
- paths = new ArrayList<>();
- }
- }
- }
-
- getRouter().popCurrentController();
- }
-
- @Override
- public boolean shouldOnlySelectOneImageFile() {
- return false;
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/operations/DavListing.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/operations/DavListing.java
deleted file mode 100644
index dc69a1422..000000000
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/operations/DavListing.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * @author Andy Scherzinger
- * Copyright (C) 2022 Andy Scherzinger
- * Copyright (C) 2017-2018 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.operations;
-
-import android.util.Log;
-
-import com.nextcloud.talk.components.filebrowser.interfaces.ListingInterface;
-import com.nextcloud.talk.components.filebrowser.models.DavResponse;
-import com.nextcloud.talk.components.filebrowser.webdav.ReadFilesystemOperation;
-import com.nextcloud.talk.models.database.UserEntity;
-
-import java.util.concurrent.Callable;
-
-import androidx.annotation.Nullable;
-import io.reactivex.Single;
-import io.reactivex.SingleObserver;
-import io.reactivex.annotations.NonNull;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-import okhttp3.OkHttpClient;
-
-public class DavListing extends ListingAbstractClass {
- private static final String TAG = DavListing.class.getSimpleName();
-
- private DavResponse davResponse = new DavResponse();
-
- public DavListing(ListingInterface listingInterface) {
- super(listingInterface);
- }
-
- @Override
- public void getFiles(String path, UserEntity currentUser, @Nullable OkHttpClient okHttpClient) {
- Single.fromCallable(new Callable() {
- @Override
- public ReadFilesystemOperation call() {
- return new ReadFilesystemOperation(okHttpClient, currentUser, path, 1);
- }
- }).subscribeOn(Schedulers.io())
- .subscribe(new SingleObserver() {
- @Override
- public void onSubscribe(@NonNull Disposable d) {
-
- }
-
- @Override
- public void onSuccess(@NonNull ReadFilesystemOperation readFilesystemOperation) {
- davResponse = readFilesystemOperation.readRemotePath();
- try {
- listingInterface.listingResult(davResponse);
- } catch (NullPointerException npe) {
- Log.i(TAG, "Error loading remote folder - due to view already been terminated", npe);
- }
- }
-
- @Override
- public void onError(@NonNull Throwable e) {
- listingInterface.listingResult(davResponse);
- }
- });
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/operations/ListingAbstractClass.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/operations/ListingAbstractClass.java
deleted file mode 100644
index b01bc31cc..000000000
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/operations/ListingAbstractClass.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Mario Danic
- * Copyright (C) 2017-2018 Mario Danic
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.operations;
-
-import android.os.Handler;
-import androidx.annotation.Nullable;
-import com.nextcloud.talk.components.filebrowser.interfaces.ListingInterface;
-import com.nextcloud.talk.models.database.UserEntity;
-import okhttp3.OkHttpClient;
-
-public abstract class ListingAbstractClass {
- Handler handler;
- ListingInterface listingInterface;
-
- ListingAbstractClass(ListingInterface listingInterface) {
- handler = new Handler();
- this.listingInterface = listingInterface;
- }
-
- public abstract void getFiles(String path, UserEntity currentUser, @Nullable OkHttpClient okHttpClient);
-
- public void cancelAllJobs() {
- handler.removeCallbacksAndMessages(null);
- }
-
- public void tearDown() {
- cancelAllJobs();
- handler = null;
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java
index ed8e978cf..09c1fc2b7 100644
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java
+++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFilesystemOperation.java
@@ -91,7 +91,7 @@ public class ReadFilesystemOperation {
}
});
} catch (IOException | DavException e) {
- Log.w("", "Error reading remote path");
+ Log.w(TAG, "Error reading remote path");
}
remoteFiles.add(BrowserFile.Companion.getModelFromResponse(rootElement[0],
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFolderListingOperation.kt b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFolderListingOperation.kt
new file mode 100644
index 000000000..b14035ca2
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/components/filebrowser/webdav/ReadFolderListingOperation.kt
@@ -0,0 +1,179 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Mario Danic
+ * Copyright (C) 2022 Andy Scherzinger
+ * Copyright (C) 2017-2019 Mario Danic
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.components.filebrowser.webdav
+
+import android.net.Uri
+import android.text.TextUtils
+import android.util.Log
+import at.bitfire.dav4jvm.DavResource
+import at.bitfire.dav4jvm.Property
+import at.bitfire.dav4jvm.Response
+import at.bitfire.dav4jvm.Response.HrefRelation
+import at.bitfire.dav4jvm.exception.DavException
+import at.bitfire.dav4jvm.property.DisplayName
+import at.bitfire.dav4jvm.property.GetContentType
+import at.bitfire.dav4jvm.property.GetLastModified
+import at.bitfire.dav4jvm.property.ResourceType
+import com.nextcloud.talk.components.filebrowser.models.DavResponse
+import com.nextcloud.talk.components.filebrowser.models.properties.NCEncrypted
+import com.nextcloud.talk.components.filebrowser.models.properties.NCPermission
+import com.nextcloud.talk.components.filebrowser.models.properties.NCPreview
+import com.nextcloud.talk.components.filebrowser.models.properties.OCFavorite
+import com.nextcloud.talk.components.filebrowser.models.properties.OCId
+import com.nextcloud.talk.components.filebrowser.models.properties.OCSize
+import com.nextcloud.talk.dagger.modules.RestModule.MagicAuthenticator
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import com.nextcloud.talk.utils.ApiUtils
+import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
+import okhttp3.OkHttpClient
+import java.io.File
+import java.io.IOException
+
+class ReadFolderListingOperation(okHttpClient: OkHttpClient, currentUser: UserEntity, path: String, depth: Int) {
+ private val okHttpClient: OkHttpClient
+ private val url: String
+ private val depth: Int
+ private val basePath: String
+
+ init {
+ val okHttpClientBuilder: OkHttpClient.Builder = okHttpClient.newBuilder()
+ okHttpClientBuilder.followRedirects(false)
+ okHttpClientBuilder.followSslRedirects(false)
+ okHttpClientBuilder.authenticator(
+ MagicAuthenticator(
+ ApiUtils.getCredentials(
+ currentUser.username,
+ currentUser.token
+ ),
+ "Authorization"
+ )
+ )
+ this.okHttpClient = okHttpClientBuilder.build()
+ basePath = currentUser.baseUrl + DavUtils.DAV_PATH + currentUser.userId
+ url = basePath + path
+ this.depth = depth
+ }
+
+ fun readRemotePath(): DavResponse {
+ val davResponse = DavResponse()
+ val memberElements: MutableList = ArrayList()
+ val rootElement = arrayOfNulls(1)
+ val remoteFiles: MutableList = ArrayList()
+ try {
+ DavResource(
+ okHttpClient,
+ url.toHttpUrlOrNull()!!
+ ).propfind(
+ depth = depth,
+ reqProp = DavUtils.getAllPropSet()
+ ) { response: Response, hrefRelation: HrefRelation? ->
+ davResponse.setResponse(response)
+ when (hrefRelation) {
+ HrefRelation.MEMBER -> memberElements.add(response)
+ HrefRelation.SELF -> rootElement[0] = response
+ HrefRelation.OTHER -> {}
+ else -> {}
+ }
+ Unit
+ }
+ } catch (e: IOException) {
+ Log.w(TAG, "Error reading remote path")
+ } catch (e: DavException) {
+ Log.w(TAG, "Error reading remote path")
+ }
+ for (memberElement in memberElements) {
+ remoteFiles.add(
+ getModelFromResponse(
+ memberElement,
+ memberElement
+ .href
+ .toString()
+ .substring(basePath.length)
+ )
+ )
+ }
+ davResponse.setData(remoteFiles)
+ return davResponse
+ }
+
+ private fun getModelFromResponse(response: Response, remotePath: String): RemoteFileBrowserItem {
+ val remoteFileBrowserItem = RemoteFileBrowserItem()
+ remoteFileBrowserItem.path = Uri.decode(remotePath)
+ remoteFileBrowserItem.displayName = Uri.decode(File(remotePath).name)
+ val properties = response.properties
+ for (property in properties) {
+ mapPropertyToBrowserFile(property, remoteFileBrowserItem)
+ }
+ if (remoteFileBrowserItem.permissions != null &&
+ remoteFileBrowserItem.permissions!!.contains(READ_PERMISSION)
+ ) {
+ remoteFileBrowserItem.isAllowedToReShare = true
+ }
+ if (TextUtils.isEmpty(remoteFileBrowserItem.mimeType) && !remoteFileBrowserItem.isFile) {
+ remoteFileBrowserItem.mimeType = "inode/directory"
+ }
+
+ return remoteFileBrowserItem
+ }
+
+ @Suppress("Detekt.ComplexMethod")
+ private fun mapPropertyToBrowserFile(property: Property, remoteFileBrowserItem: RemoteFileBrowserItem) {
+ when (property) {
+ is OCId -> {
+ remoteFileBrowserItem.remoteId = property.ocId
+ }
+ is ResourceType -> {
+ remoteFileBrowserItem.isFile = !property.types.contains(ResourceType.COLLECTION)
+ }
+ is GetLastModified -> {
+ remoteFileBrowserItem.modifiedTimestamp = property.lastModified
+ }
+ is GetContentType -> {
+ remoteFileBrowserItem.mimeType = property.type
+ }
+ is OCSize -> {
+ remoteFileBrowserItem.size = property.ocSize
+ }
+ is NCPreview -> {
+ remoteFileBrowserItem.hasPreview = property.isNcPreview
+ }
+ is OCFavorite -> {
+ remoteFileBrowserItem.isFavorite = property.isOcFavorite
+ }
+ is DisplayName -> {
+ remoteFileBrowserItem.displayName = property.displayName
+ }
+ is NCEncrypted -> {
+ remoteFileBrowserItem.isEncrypted = property.isNcEncrypted
+ }
+ is NCPermission -> {
+ remoteFileBrowserItem.permissions = property.ncPermission
+ }
+ }
+ }
+
+ companion object {
+ private const val TAG = "ReadFilesystemOperation"
+ private const val READ_PERMISSION = "R"
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
index 15fbbe98f..9c719f32e 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
@@ -91,7 +91,6 @@ import autodagger.AutoInjector
import coil.load
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
-import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
import com.facebook.common.executors.UiThreadImmediateExecutorService
import com.facebook.common.references.CloseableReference
import com.facebook.datasource.DataSource
@@ -121,14 +120,13 @@ import com.nextcloud.talk.adapters.messages.VoiceMessageInterface
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.callbacks.MentionAutocompleteCallback
-import com.nextcloud.talk.components.filebrowser.controllers.BrowserController
-import com.nextcloud.talk.components.filebrowser.controllers.BrowserForSharingController
import com.nextcloud.talk.controllers.base.NewBaseController
import com.nextcloud.talk.controllers.util.viewBinding
import com.nextcloud.talk.databinding.ControllerChatBinding
import com.nextcloud.talk.events.UserMentionClickEvent
import com.nextcloud.talk.events.WebSocketCommunicationEvent
import com.nextcloud.talk.jobs.DownloadFileToCacheWorker
+import com.nextcloud.talk.jobs.ShareOperationWorker
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
import com.nextcloud.talk.messagesearch.MessageSearchActivity
import com.nextcloud.talk.models.database.CapabilitiesUtil
@@ -143,6 +141,7 @@ import com.nextcloud.talk.models.json.conversations.RoomsOverall
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.mention.Mention
import com.nextcloud.talk.presenters.MentionAutocompletePresenter
+import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
import com.nextcloud.talk.ui.dialog.AttachmentDialog
@@ -164,6 +163,8 @@ import com.nextcloud.talk.utils.UriUtils
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ACTIVE_CONVERSATION
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_FILE_PATHS
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_INTERNAL_USER_ID
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_ID
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY
@@ -1352,6 +1353,24 @@ class ChatController(args: Bundle) :
}
when (requestCode) {
+ REQUEST_CODE_SELECT_REMOTE_FILES -> {
+ val pathList = intent?.getStringArrayListExtra(RemoteFileBrowserActivity.EXTRA_SELECTED_PATHS)
+ if (pathList?.size!! >= 1) {
+ pathList
+ .chunked(10)
+ .forEach { paths ->
+ val data = Data.Builder()
+ .putLong(KEY_INTERNAL_USER_ID, conversationUser!!.id)
+ .putString(KEY_ROOM_TOKEN, roomToken)
+ .putStringArray(KEY_FILE_PATHS, paths.toTypedArray())
+ .build()
+ val worker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
+ .setInputData(data)
+ .build()
+ WorkManager.getInstance().enqueue(worker)
+ }
+ }
+ }
REQUEST_CODE_CHOOSE_FILE -> {
try {
checkNotNull(intent)
@@ -1606,16 +1625,9 @@ class ChatController(args: Bundle) :
requestReadContacts()
}
- fun showBrowserScreen(browserType: BrowserController.BrowserType) {
- val bundle = Bundle()
- bundle.putParcelable(BundleKeys.KEY_BROWSER_TYPE, Parcels.wrap(browserType))
- bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap(conversationUser))
- bundle.putString(KEY_ROOM_TOKEN, roomToken)
- router.pushController(
- RouterTransaction.with(BrowserForSharingController(bundle))
- .pushChangeHandler(VerticalChangeHandler())
- .popChangeHandler(VerticalChangeHandler())
- )
+ fun showBrowserScreen() {
+ val sharingFileBrowserIntent = Intent(activity, RemoteFileBrowserActivity::class.java)
+ startActivityForResult(sharingFileBrowserIntent, REQUEST_CODE_SELECT_REMOTE_FILES)
}
fun showShareLocationScreen() {
@@ -3142,6 +3154,7 @@ class ChatController(args: Bundle) :
private const val REQUEST_READ_CONTACT_PERMISSION = 234
private const val REQUEST_CAMERA_PERMISSION = 223
private const val REQUEST_CODE_PICK_CAMERA: Int = 333
+ private const val REQUEST_CODE_SELECT_REMOTE_FILES = 888
private const val OBJECT_MESSAGE: String = "{object}"
private const val MINIMUM_VOICE_RECORD_DURATION: Int = 1000
private const val VOICE_RECORD_CANCEL_SLIDER_X: Int = -50
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt
index 19aa363e0..fa604250e 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt
@@ -29,7 +29,6 @@ import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
-import android.os.Environment
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
@@ -48,8 +47,6 @@ import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView
import autodagger.AutoInjector
-import com.bluelinelabs.conductor.RouterTransaction
-import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
import com.github.dhaval2404.imagepicker.ImagePicker
import com.github.dhaval2404.imagepicker.ImagePicker.Companion.getError
import com.github.dhaval2404.imagepicker.ImagePicker.Companion.getFile
@@ -58,8 +55,6 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
-import com.nextcloud.talk.components.filebrowser.controllers.BrowserController.BrowserType
-import com.nextcloud.talk.components.filebrowser.controllers.BrowserForAvatarController
import com.nextcloud.talk.controllers.base.NewBaseController
import com.nextcloud.talk.controllers.util.viewBinding
import com.nextcloud.talk.databinding.ControllerProfileBinding
@@ -71,12 +66,12 @@ import com.nextcloud.talk.models.json.userprofile.Scope
import com.nextcloud.talk.models.json.userprofile.UserProfileData
import com.nextcloud.talk.models.json.userprofile.UserProfileFieldsOverall
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall
+import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity
import com.nextcloud.talk.ui.dialog.ScopeDialog
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_BROWSER_TYPE
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
-import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_USER_ENTITY
+import com.nextcloud.talk.utils.FileUtils
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MIME_TYPE_FILTER
import com.nextcloud.talk.utils.database.user.UserUtils
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
@@ -86,7 +81,6 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import okhttp3.ResponseBody
-import org.parceler.Parcels
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
@@ -199,7 +193,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
currentUser = userUtils.currentUser
val credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
binding.avatarUpload.setOnClickListener { sendSelectLocalFileIntent() }
- binding.avatarChoose.setOnClickListener { showBrowserScreen(BrowserType.DAV_BROWSER) }
+ binding.avatarChoose.setOnClickListener { showBrowserScreen() }
binding.avatarDelete.setOnClickListener {
ncApi.deleteAvatar(
credentials,
@@ -486,22 +480,14 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
startActivityForResult(intent, 1)
}
- private fun showBrowserScreen(browserType: BrowserType) {
+ private fun showBrowserScreen() {
val bundle = Bundle()
- bundle.putParcelable(
- KEY_BROWSER_TYPE,
- Parcels.wrap(BrowserType::class.java, browserType)
- )
- bundle.putParcelable(
- KEY_USER_ENTITY,
- Parcels.wrap(UserEntity::class.java, currentUser)
- )
- bundle.putString(KEY_ROOM_TOKEN, "123")
- router.pushController(
- RouterTransaction.with(BrowserForAvatarController(bundle, this))
- .pushChangeHandler(VerticalChangeHandler())
- .popChangeHandler(VerticalChangeHandler())
- )
+ bundle.putString(KEY_MIME_TYPE_FILTER, "image/")
+
+ val avatarIntent = Intent(activity, RemoteFileBrowserActivity::class.java)
+ avatarIntent.putExtras(bundle)
+
+ startActivityForResult(avatarIntent, REQUEST_CODE_SELECT_REMOTE_FILES)
}
fun handleAvatar(remotePath: String?) {
@@ -526,9 +512,13 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
private fun saveBitmapAndPassToImagePicker(bitmap: Bitmap) {
var file: File? = null
try {
- file = File.createTempFile(
- "avatar", "png",
- Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
+ FileUtils.removeTempCacheFile(
+ this.context!!,
+ AVATAR_PATH
+ )
+ file = FileUtils.getTempCacheFile(
+ this.context!!,
+ AVATAR_PATH
)
try {
FileOutputStream(file).use { out -> bitmap.compress(Bitmap.CompressFormat.PNG, FULL_QUALITY, out) }
@@ -553,13 +543,22 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
startActivityForResult(intent, REQUEST_CODE_IMAGE_PICKER)
}
- override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
if (resultCode == Activity.RESULT_OK) {
- uploadAvatar(getFile(data))
+ if (requestCode == REQUEST_CODE_IMAGE_PICKER) {
+ uploadAvatar(getFile(intent))
+ } else if (requestCode == REQUEST_CODE_SELECT_REMOTE_FILES) {
+ val pathList = intent?.getStringArrayListExtra(RemoteFileBrowserActivity.EXTRA_SELECTED_PATHS)
+ if (pathList?.size!! >= 1) {
+ handleAvatar(pathList[0])
+ }
+ } else {
+ Log.w(TAG, "Unknown intent request code")
+ }
} else if (resultCode == ImagePicker.RESULT_ERROR) {
- Toast.makeText(activity, getError(data), Toast.LENGTH_SHORT).show()
+ Toast.makeText(activity, getError(intent), Toast.LENGTH_SHORT).show()
} else {
- Toast.makeText(activity, "Task Cancelled", Toast.LENGTH_SHORT).show()
+ Log.i(TAG, "Task Cancelled")
}
}
@@ -809,6 +808,8 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
companion object {
private const val TAG: String = "ProfileController"
+ private const val AVATAR_PATH = "photos/avatar.png"
+ private const val REQUEST_CODE_SELECT_REMOTE_FILES = 22
private const val DEFAULT_CACHE_SIZE: Int = 20
private const val DEFAULT_RETRIES: Long = 3
private const val MAX_SIZE: Int = 1024
diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
index 0e62a8645..267ab6b41 100644
--- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
+++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt
@@ -22,6 +22,8 @@
package com.nextcloud.talk.dagger.modules
import com.nextcloud.talk.api.NcApi
+import com.nextcloud.talk.remotefilebrowser.repositories.RemoteFileBrowserItemsRepository
+import com.nextcloud.talk.remotefilebrowser.repositories.RemoteFileBrowserItemsRepositoryImpl
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepositoryImpl
import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository
@@ -29,6 +31,7 @@ import com.nextcloud.talk.shareditems.repositories.SharedItemsRepositoryImpl
import com.nextcloud.talk.utils.database.user.CurrentUserProvider
import dagger.Module
import dagger.Provides
+import okhttp3.OkHttpClient
@Module
class RepositoryModule {
@@ -41,4 +44,10 @@ class RepositoryModule {
fun provideUnifiedSearchRepository(ncApi: NcApi, userProvider: CurrentUserProvider): UnifiedSearchRepository {
return UnifiedSearchRepositoryImpl(ncApi, userProvider)
}
+
+ @Provides
+ fun provideRemoteFileBrowserItemsRepository(okHttpClient: OkHttpClient, userProvider: CurrentUserProvider):
+ RemoteFileBrowserItemsRepository {
+ return RemoteFileBrowserItemsRepositoryImpl(okHttpClient, userProvider)
+ }
}
diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt
index b0f7170d8..f2356d0ab 100644
--- a/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt
+++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt
@@ -23,6 +23,7 @@ package com.nextcloud.talk.dagger.modules
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
+import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
import com.nextcloud.talk.messagesearch.MessageSearchViewModel
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
import dagger.Binds
@@ -59,4 +60,9 @@ abstract class ViewModelModule {
@IntoMap
@ViewModelKey(MessageSearchViewModel::class)
abstract fun messageSearchViewModel(viewModel: MessageSearchViewModel): ViewModel
+
+ @Binds
+ @IntoMap
+ @ViewModelKey(RemoteFileBrowserItemsViewModel::class)
+ abstract fun remoteFileBrowserItemsViewModel(viewModel: RemoteFileBrowserItemsViewModel): ViewModel
}
diff --git a/app/src/main/java/com/nextcloud/talk/interfaces/SelectionInterface.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/SelectionInterface.kt
similarity index 85%
rename from app/src/main/java/com/nextcloud/talk/interfaces/SelectionInterface.kt
rename to app/src/main/java/com/nextcloud/talk/remotefilebrowser/SelectionInterface.kt
index 23fda533b..0ddfe8ffd 100644
--- a/app/src/main/java/com/nextcloud/talk/interfaces/SelectionInterface.kt
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/SelectionInterface.kt
@@ -2,6 +2,8 @@
* Nextcloud Talk application
*
* @author Mario Danic
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger
* Copyright (C) 2017-2018 Mario Danic
*
* This program is free software: you can redistribute it and/or modify
@@ -18,12 +20,8 @@
* along with this program. If not, see .
*/
-package com.nextcloud.talk.interfaces
+package com.nextcloud.talk.remotefilebrowser
interface SelectionInterface {
- fun toggleBrowserItemSelection(path: String)
-
fun isPathSelected(path: String): Boolean
-
- fun shouldOnlySelectOneImageFile(): Boolean
}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt
new file mode 100644
index 000000000..3e3caf29e
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt
@@ -0,0 +1,260 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Álvaro Brey
+ * Copyright (C) 2022 Andy Scherzinger
+ * Copyright (C) 2022 Álvaro Brey
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.activities
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.res.ResourcesCompat
+import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.recyclerview.widget.GridLayoutManager
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+import autodagger.AutoInjector
+import com.nextcloud.talk.R
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.databinding.ActivityRemoteFileBrowserBinding
+import com.nextcloud.talk.remotefilebrowser.SelectionInterface
+import com.nextcloud.talk.remotefilebrowser.adapters.RemoteFileBrowserItemsAdapter
+import com.nextcloud.talk.remotefilebrowser.viewmodels.RemoteFileBrowserItemsViewModel
+import com.nextcloud.talk.ui.dialog.SortingOrderDialogFragment
+import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.FileSortOrder
+import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_MIME_TYPE_FILTER
+import com.nextcloud.talk.utils.database.user.CurrentUserProvider
+import javax.inject.Inject
+
+@AutoInjector(NextcloudTalkApplication::class)
+class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, SwipeRefreshLayout.OnRefreshListener {
+
+ @Inject
+ lateinit var viewModelFactory: ViewModelProvider.Factory
+
+ @Inject
+ lateinit var currentUserProvider: CurrentUserProvider
+
+ private lateinit var binding: ActivityRemoteFileBrowserBinding
+ private lateinit var viewModel: RemoteFileBrowserItemsViewModel
+
+ private var filesSelectionDoneMenuItem: MenuItem? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
+
+ binding = ActivityRemoteFileBrowserBinding.inflate(layoutInflater)
+ setSupportActionBar(binding.remoteFileBrowserItemsToolbar)
+ setContentView(binding.root)
+
+ DisplayUtils.applyColorToStatusBar(
+ this,
+ ResourcesCompat.getColor(
+ resources, R.color.appbar, null
+ )
+ )
+ DisplayUtils.applyColorToNavigationBar(
+ this.window,
+ ResourcesCompat.getColor(resources, R.color.bg_default, null)
+ )
+
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+
+ val extras = intent.extras
+ val mimeTypeSelectionFilter = extras?.getString(KEY_MIME_TYPE_FILTER, null)
+
+ initViewModel(mimeTypeSelectionFilter)
+
+ binding.swipeRefreshList.setOnRefreshListener(this)
+ binding.swipeRefreshList.setColorSchemeResources(R.color.colorPrimary)
+ binding.swipeRefreshList.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background)
+
+ binding.pathNavigationBackButton.setOnClickListener { viewModel.navigateUp() }
+ binding.sortButton.setOnClickListener { changeSorting() }
+
+ viewModel.loadItems()
+ }
+
+ private fun initViewModel(mimeTypeSelectionFilter: String?) {
+ viewModel = ViewModelProvider(this, viewModelFactory)[RemoteFileBrowserItemsViewModel::class.java]
+
+ viewModel.viewState.observe(this) { state ->
+ clearEmptyLoading()
+ when (state) {
+ is RemoteFileBrowserItemsViewModel.LoadingItemsState, RemoteFileBrowserItemsViewModel.InitialState -> {
+ showLoading()
+ }
+ is RemoteFileBrowserItemsViewModel.NoRemoteFileItemsState -> {
+ showEmpty()
+ }
+ is RemoteFileBrowserItemsViewModel.LoadedState -> {
+ loadList(state, mimeTypeSelectionFilter)
+ }
+ is RemoteFileBrowserItemsViewModel.FinishState -> {
+ finishWithResult(state.selectedPaths)
+ }
+ }
+ }
+
+ viewModel.fileSortOrder.observe(this) { sortOrder ->
+ if (sortOrder != null) {
+ binding.sortButton.setText(DisplayUtils.getSortOrderStringId(sortOrder))
+ }
+ }
+
+ viewModel.currentPath.observe(this) { path ->
+ if (path != null) {
+ supportActionBar?.title = path
+ }
+ }
+
+ viewModel.selectedPaths.observe(this) { selectedPaths ->
+ filesSelectionDoneMenuItem?.isVisible = !selectedPaths.isNullOrEmpty()
+ binding.recyclerView.adapter?.notifyDataSetChanged()
+ }
+ }
+
+ private fun loadList(
+ state: RemoteFileBrowserItemsViewModel.LoadedState,
+ mimeTypeSelectionFilter: String?
+ ) {
+ val remoteFileBrowserItems = state.items
+ Log.d(TAG, "Items received: $remoteFileBrowserItems")
+
+ // TODO make showGrid based on preferences (when available)
+ val showGrid = false
+ val layoutManager = if (showGrid) {
+ GridLayoutManager(this, SPAN_COUNT)
+ } else {
+ LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
+ }
+
+ // TODO do not needlessly recreate adapter if it can be reused
+ val adapter = RemoteFileBrowserItemsAdapter(
+ showGrid = showGrid,
+ mimeTypeSelectionFilter = mimeTypeSelectionFilter,
+ userEntity = currentUserProvider.currentUser!!,
+ selectionInterface = this,
+ onItemClicked = viewModel::onItemClicked
+ )
+ adapter.items = remoteFileBrowserItems
+
+ binding.recyclerView.adapter = adapter
+ binding.recyclerView.layoutManager = layoutManager
+ binding.recyclerView.setHasFixedSize(true)
+
+ showList()
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ super.onCreateOptionsMenu(menu)
+ menuInflater.inflate(R.menu.menu_share_files, menu)
+ filesSelectionDoneMenuItem = menu?.findItem(R.id.files_selection_done)
+ return true
+ }
+
+ override fun onBackPressed() {
+ setResult(Activity.RESULT_CANCELED)
+ super.onBackPressed()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ refreshCurrentPath()
+ }
+
+ private fun changeSorting() {
+ val newFragment: DialogFragment = SortingOrderDialogFragment
+ .newInstance(FileSortOrder.getFileSortOrder(viewModel.fileSortOrder.value!!.name))
+ newFragment.show(
+ supportFragmentManager,
+ SortingOrderDialogFragment.SORTING_ORDER_FRAGMENT
+ )
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ android.R.id.home -> {
+ onBackPressed()
+ true
+ }
+ R.id.files_selection_done -> {
+ viewModel.onSelectionDone()
+ true
+ }
+ else -> {
+ return super.onOptionsItemSelected(item)
+ }
+ }
+ }
+
+ private fun finishWithResult(selectedPaths: Set) {
+ val data = Intent()
+ data.putStringArrayListExtra(EXTRA_SELECTED_PATHS, ArrayList(selectedPaths))
+ setResult(Activity.RESULT_OK, data)
+ finish()
+ }
+
+ private fun clearEmptyLoading() {
+ binding.emptyContainer.emptyListView.visibility = View.GONE
+ }
+
+ private fun showLoading() {
+ binding.emptyContainer.emptyListViewHeadline.text = getString(R.string.file_list_loading)
+ binding.emptyContainer.emptyListView.visibility = View.VISIBLE
+ binding.recyclerView.visibility = View.GONE
+ }
+
+ private fun showEmpty() {
+ binding.emptyContainer.emptyListViewHeadline.text = getString(R.string.nc_shared_items_empty)
+ binding.emptyContainer.emptyListView.visibility = View.VISIBLE
+ binding.recyclerView.visibility = View.GONE
+ }
+
+ private fun showList() {
+ binding.recyclerView.visibility = View.VISIBLE
+ }
+
+ override fun onRefresh() {
+ refreshCurrentPath()
+ }
+
+ private fun refreshCurrentPath() {
+ viewModel.loadItems()
+ }
+
+ override fun isPathSelected(path: String): Boolean {
+ return viewModel.isPathSelected(path)
+ }
+
+ companion object {
+ private val TAG = RemoteFileBrowserActivity::class.simpleName
+ const val SPAN_COUNT: Int = 4
+ const val EXTRA_SELECTED_PATHS = "EXTRA_SELECTED_PATH"
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsAdapter.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsAdapter.kt
new file mode 100644
index 000000000..2d6020394
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsAdapter.kt
@@ -0,0 +1,86 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.adapters
+
+import android.annotation.SuppressLint
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.nextcloud.talk.databinding.RvItemBrowserFileBinding
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.remotefilebrowser.SelectionInterface
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+
+class RemoteFileBrowserItemsAdapter(
+ private val showGrid: Boolean = false,
+ private val mimeTypeSelectionFilter: String? = null,
+ private val userEntity: UserEntity,
+ private val selectionInterface: SelectionInterface,
+ private val onItemClicked: (RemoteFileBrowserItem) -> Unit
+) : RecyclerView.Adapter() {
+
+ var items: List = emptyList()
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RemoteFileBrowserItemsViewHolder {
+
+ return if (showGrid) {
+ RemoteFileBrowserItemsListViewHolder(
+ RvItemBrowserFileBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ ),
+ mimeTypeSelectionFilter,
+ userEntity,
+ selectionInterface
+ ) {
+ onItemClicked(items[it])
+ }
+ } else {
+ RemoteFileBrowserItemsListViewHolder(
+ RvItemBrowserFileBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ ),
+ mimeTypeSelectionFilter,
+ userEntity,
+ selectionInterface
+ ) {
+ onItemClicked(items[it])
+ }
+ }
+ }
+
+ override fun onBindViewHolder(holder: RemoteFileBrowserItemsViewHolder, position: Int) {
+ holder.onBind(items[position])
+ }
+
+ override fun getItemCount(): Int {
+ return items.size
+ }
+
+ @SuppressLint("NotifyDataSetChanged")
+ fun updateDataSet(browserItems: List) {
+ items = browserItems
+ notifyDataSetChanged()
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt
new file mode 100644
index 000000000..64f21207c
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt
@@ -0,0 +1,153 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.adapters
+
+import android.text.format.Formatter
+import android.view.View
+import androidx.appcompat.content.res.AppCompatResources
+import autodagger.AutoInjector
+import com.facebook.drawee.backends.pipeline.Fresco
+import com.facebook.drawee.interfaces.DraweeController
+import com.facebook.drawee.view.SimpleDraweeView
+import com.nextcloud.talk.R
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.databinding.RvItemBrowserFileBinding
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.remotefilebrowser.SelectionInterface
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DateUtils.getLocalDateTimeStringFromTimestamp
+import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.DrawableUtils.getDrawableResourceIdForMimeType
+
+@AutoInjector(NextcloudTalkApplication::class)
+class RemoteFileBrowserItemsListViewHolder(
+ override val binding: RvItemBrowserFileBinding,
+ mimeTypeSelectionFilter: String?,
+ currentUser: UserEntity,
+ selectionInterface: SelectionInterface,
+ onItemClicked: (Int) -> Unit
+) : RemoteFileBrowserItemsViewHolder(binding, mimeTypeSelectionFilter, currentUser, selectionInterface) {
+
+ override val fileIcon: SimpleDraweeView
+ get() = binding.fileIcon
+
+ private var selectable: Boolean = true
+ private var clickable: Boolean = true
+
+ init {
+ itemView.setOnClickListener {
+ if (clickable) {
+ onItemClicked(bindingAdapterPosition)
+ if (selectable) {
+ binding.selectFileCheckbox.toggle()
+ }
+ }
+ }
+ }
+
+ override fun onBind(item: RemoteFileBrowserItem) {
+
+ super.onBind(item)
+
+ binding.fileIcon.controller = null
+ if (!item.isAllowedToReShare || item.isEncrypted) {
+ binding.root.isEnabled = false
+ binding.root.alpha = DISABLED_ALPHA
+ } else {
+ binding.root.isEnabled = true
+ binding.root.alpha = ENABLED_ALPHA
+ }
+
+ binding.fileEncryptedImageView.visibility =
+ if (item.isEncrypted) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ binding.fileFavoriteImageView.visibility =
+ if (item.isFavorite) {
+ View.VISIBLE
+ } else {
+ View.GONE
+ }
+
+ calculateSelectability(item)
+ calculateClickability(item, selectable)
+ setSelectability()
+
+ binding.fileIcon
+ .hierarchy
+ .setPlaceholderImage(
+ AppCompatResources.getDrawable(
+ binding.fileIcon.context, getDrawableResourceIdForMimeType(item.mimeType)
+ )
+ )
+
+ if (item.hasPreview) {
+ val path = ApiUtils.getUrlForFilePreviewWithRemotePath(
+ currentUser.baseUrl,
+ item.path,
+ binding.fileIcon.context.resources.getDimensionPixelSize(R.dimen.small_item_height)
+ )
+ if (path.isNotEmpty()) {
+ val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
+ .setAutoPlayAnimations(true)
+ .setImageRequest(DisplayUtils.getImageRequestForUrl(path, null))
+ .build()
+ binding.fileIcon.controller = draweeController
+ }
+ }
+
+ binding.filenameTextView.text = item.displayName
+ binding.fileModifiedInfo.text = String.format(
+ binding.fileModifiedInfo.context.getString(R.string.nc_last_modified),
+ Formatter.formatShortFileSize(binding.fileModifiedInfo.context, item.size),
+ getLocalDateTimeStringFromTimestamp(item.modifiedTimestamp)
+ )
+
+ binding.selectFileCheckbox.isChecked = selectionInterface.isPathSelected(item.path!!)
+ }
+
+ private fun setSelectability() {
+ if (selectable) {
+ binding.selectFileCheckbox.visibility = View.VISIBLE
+ } else {
+ binding.selectFileCheckbox.visibility = View.GONE
+ }
+ }
+
+ private fun calculateSelectability(item: RemoteFileBrowserItem) {
+ selectable = item.isFile &&
+ (mimeTypeSelectionFilter == null || item.mimeType?.startsWith(mimeTypeSelectionFilter) == true) &&
+ (item.isAllowedToReShare && !item.isEncrypted)
+ }
+
+ private fun calculateClickability(item: RemoteFileBrowserItem, selectableItem: Boolean) {
+ clickable = selectableItem || "inode/directory" == item.mimeType
+ }
+
+ companion object {
+ private const val DISABLED_ALPHA: Float = 0.38f
+ private const val ENABLED_ALPHA: Float = 1.0f
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsViewHolder.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsViewHolder.kt
new file mode 100644
index 000000000..71f343eb9
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsViewHolder.kt
@@ -0,0 +1,53 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.adapters
+
+import android.graphics.drawable.Drawable
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.RecyclerView
+import androidx.viewbinding.ViewBinding
+import com.facebook.drawee.view.SimpleDraweeView
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.remotefilebrowser.SelectionInterface
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import com.nextcloud.talk.utils.DrawableUtils
+
+abstract class RemoteFileBrowserItemsViewHolder(
+ open val binding: ViewBinding,
+ val mimeTypeSelectionFilter: String? = null,
+ val currentUser: UserEntity,
+ val selectionInterface: SelectionInterface,
+) : RecyclerView.ViewHolder(binding.root) {
+
+ abstract val fileIcon: SimpleDraweeView
+
+ open fun onBind(item: RemoteFileBrowserItem) {
+ fileIcon.hierarchy.setPlaceholderImage(staticImage(item.mimeType, fileIcon))
+ }
+
+ private fun staticImage(
+ mimeType: String?,
+ image: SimpleDraweeView
+ ): Drawable {
+ val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimeType)
+ return ContextCompat.getDrawable(image.context, drawableResourceId)!!
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/model/RemoteFileBrowserItem.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/model/RemoteFileBrowserItem.kt
new file mode 100644
index 000000000..e4eb2c044
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/model/RemoteFileBrowserItem.kt
@@ -0,0 +1,44 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Mario Danic
+ * Copyright (C) 2022 Andy Scherzinger
+ * Copyright (C) 2017-2018 Mario Danic
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.model
+
+import android.os.Parcelable
+import kotlinx.android.parcel.Parcelize
+
+@Parcelize
+data class RemoteFileBrowserItem(
+ var path: String? = null,
+ var displayName: String? = null,
+ var mimeType: String? = null,
+ var modifiedTimestamp: Long = 0,
+ var size: Long = 0,
+ var isFile: Boolean = false,
+
+ // Used for remote files
+ var remoteId: String? = null,
+ var hasPreview: Boolean = false,
+ var isFavorite: Boolean = false,
+ var isEncrypted: Boolean = false,
+ var permissions: String? = null,
+ var isAllowedToReShare: Boolean = false
+) : Parcelable
diff --git a/app/src/main/java/com/nextcloud/talk/components/filebrowser/interfaces/ListingInterface.java b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/repositories/RemoteFileBrowserItemsRepository.kt
similarity index 64%
rename from app/src/main/java/com/nextcloud/talk/components/filebrowser/interfaces/ListingInterface.java
rename to app/src/main/java/com/nextcloud/talk/remotefilebrowser/repositories/RemoteFileBrowserItemsRepository.kt
index c953d8a59..6f2239d83 100644
--- a/app/src/main/java/com/nextcloud/talk/components/filebrowser/interfaces/ListingInterface.java
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/repositories/RemoteFileBrowserItemsRepository.kt
@@ -1,8 +1,8 @@
/*
* Nextcloud Talk application
*
- * @author Mario Danic
- * Copyright (C) 2017-2018 Mario Danic
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,10 +18,12 @@
* along with this program. If not, see .
*/
-package com.nextcloud.talk.components.filebrowser.interfaces;
+package com.nextcloud.talk.remotefilebrowser.repositories
-import com.nextcloud.talk.components.filebrowser.models.DavResponse;
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import io.reactivex.Observable
-public interface ListingInterface {
- void listingResult(DavResponse davResponse);
+interface RemoteFileBrowserItemsRepository {
+
+ fun listFolder(path: String): Observable>
}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/repositories/RemoteFileBrowserItemsRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/repositories/RemoteFileBrowserItemsRepositoryImpl.kt
new file mode 100644
index 000000000..33b89c244
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/repositories/RemoteFileBrowserItemsRepositoryImpl.kt
@@ -0,0 +1,56 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2022 Andy Scherzinger
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.repositories
+
+import com.nextcloud.talk.components.filebrowser.webdav.ReadFolderListingOperation
+import com.nextcloud.talk.models.database.UserEntity
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import com.nextcloud.talk.utils.database.user.CurrentUserProvider
+import io.reactivex.Observable
+import okhttp3.OkHttpClient
+import javax.inject.Inject
+
+class RemoteFileBrowserItemsRepositoryImpl @Inject constructor(
+ private val okHttpClient: OkHttpClient,
+ private val userProvider: CurrentUserProvider
+) : RemoteFileBrowserItemsRepository {
+
+ private val userEntity: UserEntity
+ get() = userProvider.currentUser!!
+
+ override fun listFolder(path: String):
+ Observable> {
+ return Observable.fromCallable {
+ val operation =
+ ReadFolderListingOperation(
+ okHttpClient,
+ userEntity,
+ path,
+ 1
+ )
+ val davResponse = operation.readRemotePath()
+ if (davResponse.getData() != null) {
+ return@fromCallable davResponse.getData() as List
+ }
+ return@fromCallable emptyList()
+ }
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/viewmodels/RemoteFileBrowserItemsViewModel.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/viewmodels/RemoteFileBrowserItemsViewModel.kt
new file mode 100644
index 000000000..3c0bb4cbe
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/viewmodels/RemoteFileBrowserItemsViewModel.kt
@@ -0,0 +1,230 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Álvaro Brey
+ * Copyright (C) 2022 Andy Scherzinger
+ * Copyright (C) 2022 Álvaro Brey
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.remotefilebrowser.viewmodels
+
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import com.nextcloud.talk.remotefilebrowser.repositories.RemoteFileBrowserItemsRepository
+import com.nextcloud.talk.utils.FileSortOrder
+import com.nextcloud.talk.utils.preferences.AppPreferences
+import io.reactivex.Observer
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
+import net.orange_box.storebox.listeners.OnPreferenceValueChangedListener
+import java.io.File
+import javax.inject.Inject
+
+/**
+ * @startuml
+ * hide empty description
+ * [*] --> InitialState
+ * InitialState --> LoadingItemsState
+ * LoadingItemsState --> NoRemoteFileItemsState
+ * NoRemoteFileItemsState --> LoadingItemsState
+ * LoadingItemsState --> LoadedState
+ * LoadedState --> LoadingItemsState
+ * LoadedState --> FinishState
+ * FinishState --> [*]
+ * @enduml
+ */
+class RemoteFileBrowserItemsViewModel @Inject constructor(
+ private val repository: RemoteFileBrowserItemsRepository,
+ private val appPreferences: AppPreferences
+) :
+ ViewModel() {
+
+ sealed interface ViewState
+ object InitialState : ViewState
+ object NoRemoteFileItemsState : ViewState
+ object LoadingItemsState : ViewState
+ class LoadedState(val items: List) : ViewState
+ class FinishState(val selectedPaths: Set) : ViewState
+
+ private val initialSortOrder = FileSortOrder.getFileSortOrder(appPreferences.sorting)
+ private val sortingPrefListener: SortChangeListener = SortChangeListener()
+
+ private val _viewState: MutableLiveData = MutableLiveData(InitialState)
+ val viewState: LiveData
+ get() = _viewState
+
+ // TODO incorporate into view state object?
+ private val _fileSortOrder: MutableLiveData = MutableLiveData(initialSortOrder)
+ val fileSortOrder: LiveData
+ get() = _fileSortOrder
+
+ private val _currentPath: MutableLiveData = MutableLiveData(ROOT_PATH)
+ val currentPath: LiveData
+ get() = _currentPath
+
+ private val _selectedPaths: MutableLiveData> = MutableLiveData(emptySet())
+ val selectedPaths: LiveData>
+ get() = _selectedPaths
+
+ init {
+ appPreferences.registerSortingChangeListener(sortingPrefListener)
+ }
+
+ inner class SortChangeListener : OnPreferenceValueChangedListener {
+ override fun onChanged(newValue: String) {
+ onSelectSortOrder(newValue)
+ }
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ appPreferences.unregisterSortingChangeListener(sortingPrefListener)
+ }
+
+ fun loadItems() {
+ _viewState.value = LoadingItemsState
+ repository.listFolder(currentPath.value!!).subscribeOn(Schedulers.io())
+ ?.observeOn(AndroidSchedulers.mainThread())
+ ?.subscribe(RemoteFileBrowserItemsObserver())
+ }
+
+ inner class RemoteFileBrowserItemsObserver : Observer> {
+
+ var newRemoteFileBrowserItems: List? = null
+
+ override fun onSubscribe(d: Disposable) = Unit
+
+ override fun onNext(response: List) {
+ newRemoteFileBrowserItems = fileSortOrder.value!!.sortCloudFiles(response)
+ }
+
+ override fun onError(e: Throwable) {
+ Log.d(TAG, "An error occurred: $e")
+ }
+
+ override fun onComplete() {
+ if (newRemoteFileBrowserItems.isNullOrEmpty()) {
+ this@RemoteFileBrowserItemsViewModel._viewState.value = NoRemoteFileItemsState
+ } else {
+ setCurrentState(newRemoteFileBrowserItems!!)
+ }
+ }
+
+ private fun setCurrentState(items: List) {
+ when (this@RemoteFileBrowserItemsViewModel._viewState.value) {
+ is LoadedState, LoadingItemsState -> {
+ this@RemoteFileBrowserItemsViewModel._viewState.value = LoadedState(items)
+ }
+ else -> return
+ }
+ }
+ }
+
+ private fun onSelectSortOrder(newSortOrderString: String) {
+ val newSortOrder = FileSortOrder.getFileSortOrder(newSortOrderString)
+ if (newSortOrder.name != fileSortOrder.value?.name) {
+ _fileSortOrder.value = newSortOrder
+ val currentState = viewState.value
+ if (currentState is LoadedState) {
+ val sortedItems = newSortOrder.sortCloudFiles(currentState.items)
+ _viewState.value = LoadedState(sortedItems)
+ }
+ }
+ }
+
+ private fun changePath(path: String) {
+ _currentPath.value = path
+ loadItems()
+ }
+
+ fun navigateUp() {
+ val path = _currentPath.value
+ if (path!! != ROOT_PATH) {
+ _currentPath.value = File(path).parent!!
+ loadItems()
+ }
+ }
+
+ fun onSelectionDone() {
+ val selection = selectedPaths.value
+ if (!selection.isNullOrEmpty()) {
+ _viewState.value = FinishState(selection)
+ }
+ }
+
+ fun onItemClicked(remoteFileBrowserItem: RemoteFileBrowserItem) {
+ if (remoteFileBrowserItem.mimeType == MIME_DIRECTORY) {
+ changePath(remoteFileBrowserItem.path!!)
+ } else {
+ toggleBrowserItemSelection(remoteFileBrowserItem.path!!)
+ }
+ }
+
+ private fun toggleBrowserItemSelection(path: String) {
+ val paths = selectedPaths.value!!.toMutableSet()
+ if (paths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
+ checkAndRemoveAnySelectedParents(path)
+ } else {
+ // TODO if it's a folder, remove all the children we added manually
+ paths.add(path)
+ _selectedPaths.value = paths
+ }
+ }
+
+ private fun checkAndRemoveAnySelectedParents(currentPath: String) {
+ var file = File(currentPath)
+ val paths = selectedPaths.value!!.toMutableSet()
+ paths.remove(currentPath)
+ while (file.parent != null) {
+ paths.remove(file.parent!! + File.pathSeparator)
+ file = File(file.parent!!)
+ }
+ _selectedPaths.value = paths
+ }
+
+ private fun shouldPathBeSelectedDueToParent(currentPath: String): Boolean {
+ var file = File(currentPath)
+ val paths = selectedPaths.value!!
+ if (paths.isNotEmpty() && file.parent != ROOT_PATH) {
+ while (file.parent != null) {
+ var parent = file.parent!!
+ if (File(file.parent!!).parent != null) {
+ parent += File.pathSeparator
+ }
+ if (paths.contains(parent)) {
+ return true
+ }
+ file = File(file.parent!!)
+ }
+ }
+ return false
+ }
+
+ fun isPathSelected(path: String): Boolean {
+ return selectedPaths.value?.contains(path) == true || shouldPathBeSelectedDueToParent(path)
+ }
+
+ companion object {
+ private val TAG = RemoteFileBrowserItemsViewModel::class.simpleName
+ private const val ROOT_PATH = "/"
+ private const val MIME_DIRECTORY = "inode/directory"
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt
index 77c5acbfb..c88db9ca6 100644
--- a/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt
+++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt
@@ -29,7 +29,6 @@ import android.view.ViewGroup
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.R
-import com.nextcloud.talk.components.filebrowser.controllers.BrowserController
import com.nextcloud.talk.controllers.ChatController
import com.nextcloud.talk.databinding.DialogAttachmentBinding
import com.nextcloud.talk.models.database.CapabilitiesUtil
@@ -76,7 +75,7 @@ class AttachmentDialog(val activity: Activity, var chatController: ChatControlle
}
dialogAttachmentBinding.menuAttachFileFromCloud.setOnClickListener {
- chatController.showBrowserScreen(BrowserController.BrowserType.DAV_BROWSER)
+ chatController.showBrowserScreen()
dismiss()
}
diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java
index 715abb9a6..f2d5c8d66 100644
--- a/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java
+++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java
@@ -39,6 +39,8 @@ import com.nextcloud.talk.databinding.SortingOrderFragmentBinding;
import com.nextcloud.talk.utils.FileSortOrder;
import com.nextcloud.talk.utils.preferences.AppPreferences;
+import org.jetbrains.annotations.NotNull;
+
import javax.inject.Inject;
import androidx.annotation.NonNull;
@@ -67,11 +69,11 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
private View[] taggedViews;
private String currentSortOrderName;
- public static SortingOrderDialogFragment newInstance(FileSortOrder sortOrder) {
+ public static SortingOrderDialogFragment newInstance(@NotNull FileSortOrder sortOrder) {
SortingOrderDialogFragment dialogFragment = new SortingOrderDialogFragment();
Bundle args = new Bundle();
- args.putString(KEY_SORT_ORDER, sortOrder.name);
+ args.putString(KEY_SORT_ORDER, sortOrder.getName());
dialogFragment.setArguments(args);
return dialogFragment;
@@ -84,7 +86,8 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
setRetainInstance(true);
if (getArguments() != null) {
- currentSortOrderName = getArguments().getString(KEY_SORT_ORDER, FileSortOrder.sort_a_to_z.name);
+ currentSortOrderName = getArguments().getString(KEY_SORT_ORDER,
+ FileSortOrder.Companion.getSort_a_to_z().getName());
}
}
@@ -120,29 +123,29 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
taggedViews = new View[12];
taggedViews[0] = binding.sortByNameAscending;
- taggedViews[0].setTag(FileSortOrder.sort_a_to_z);
+ taggedViews[0].setTag(FileSortOrder.Companion.getSort_a_to_z());
taggedViews[1] = binding.sortByNameAZText;
- taggedViews[1].setTag(FileSortOrder.sort_a_to_z);
+ taggedViews[1].setTag(FileSortOrder.Companion.getSort_a_to_z());
taggedViews[2] = binding.sortByNameDescending;
- taggedViews[2].setTag(FileSortOrder.sort_z_to_a);
+ taggedViews[2].setTag(FileSortOrder.Companion.getSort_z_to_a());
taggedViews[3] = binding.sortByNameZAText;
- taggedViews[3].setTag(FileSortOrder.sort_z_to_a);
+ taggedViews[3].setTag(FileSortOrder.Companion.getSort_z_to_a());
taggedViews[4] = binding.sortByModificationDateAscending;
- taggedViews[4].setTag(FileSortOrder.sort_old_to_new);
+ taggedViews[4].setTag(FileSortOrder.Companion.getSort_old_to_new());
taggedViews[5] = binding.sortByModificationDateOldestFirstText;
- taggedViews[5].setTag(FileSortOrder.sort_old_to_new);
+ taggedViews[5].setTag(FileSortOrder.Companion.getSort_old_to_new());
taggedViews[6] = binding.sortByModificationDateDescending;
- taggedViews[6].setTag(FileSortOrder.sort_new_to_old);
+ taggedViews[6].setTag(FileSortOrder.Companion.getSort_new_to_old());
taggedViews[7] = binding.sortByModificationDateNewestFirstText;
- taggedViews[7].setTag(FileSortOrder.sort_new_to_old);
+ taggedViews[7].setTag(FileSortOrder.Companion.getSort_new_to_old());
taggedViews[8] = binding.sortBySizeAscending;
- taggedViews[8].setTag(FileSortOrder.sort_small_to_big);
+ taggedViews[8].setTag(FileSortOrder.Companion.getSort_small_to_big());
taggedViews[9] = binding.sortBySizeSmallestFirstText;
- taggedViews[9].setTag(FileSortOrder.sort_small_to_big);
+ taggedViews[9].setTag(FileSortOrder.Companion.getSort_small_to_big());
taggedViews[10] = binding.sortBySizeDescending;
- taggedViews[10].setTag(FileSortOrder.sort_big_to_small);
+ taggedViews[10].setTag(FileSortOrder.Companion.getSort_big_to_small());
taggedViews[11] = binding.sortBySizeBiggestFirstText;
- taggedViews[11].setTag(FileSortOrder.sort_big_to_small);
+ taggedViews[11].setTag(FileSortOrder.Companion.getSort_big_to_small());
setupActiveOrderSelection();
}
@@ -154,8 +157,8 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
final int color = getResources().getColor(R.color.colorPrimary);
Log.i("SortOrder", "currentSortOrderName="+currentSortOrderName);
for (View view : taggedViews) {
- Log.i("SortOrder", ((FileSortOrder) view.getTag()).name);
- if (!((FileSortOrder) view.getTag()).name.equals(currentSortOrderName)) {
+ Log.i("SortOrder", ((FileSortOrder) view.getTag()).getName());
+ if (!((FileSortOrder) view.getTag()).getName().equals(currentSortOrderName)) {
continue;
}
if (view instanceof MaterialButton) {
@@ -192,7 +195,7 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
@Override
public void onClick(View v) {
- appPreferences.setSorting(((FileSortOrder) v.getTag()).name);
+ appPreferences.setSorting(((FileSortOrder) v.getTag()).getName());
dismiss();
}
}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java
index b51b589e2..526b09c04 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java
+++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java
@@ -619,7 +619,7 @@ public class DisplayUtils {
public static @StringRes
int getSortOrderStringId(FileSortOrder sortOrder) {
- switch (sortOrder.name) {
+ switch (sortOrder.getName()) {
case sort_z_to_a_id:
return R.string.menu_item_sort_by_name_z_a;
case sort_new_to_old_id:
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrder.java b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrder.java
deleted file mode 100644
index ec88d0e4a..000000000
--- a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrder.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Sven R. Kunze
- * @author Andy Scherzinger
- * Copyright (C) 2021 Andy Scherzinger
- * Copyright (C) 2017 Sven R. Kunze
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.utils;
-
-import android.text.TextUtils;
-
-import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import androidx.annotation.Nullable;
-
-/**
- * Sort order
- */
-public class FileSortOrder {
- public static final String sort_a_to_z_id = "sort_a_to_z";
- public static final String sort_z_to_a_id = "sort_z_to_a";
- public static final String sort_old_to_new_id = "sort_old_to_new";
- public static final String sort_new_to_old_id = "sort_new_to_old";
- public static final String sort_small_to_big_id = "sort_small_to_big";
- public static final String sort_big_to_small_id = "sort_big_to_small";
-
- public static final FileSortOrder sort_a_to_z = new FileSortOrderByName(sort_a_to_z_id, true);
- public static final FileSortOrder sort_z_to_a = new FileSortOrderByName(sort_z_to_a_id, false);
- public static final FileSortOrder sort_old_to_new = new FileSortOrderByDate(sort_old_to_new_id, true);
- public static final FileSortOrder sort_new_to_old = new FileSortOrderByDate(sort_new_to_old_id, false);
- public static final FileSortOrder sort_small_to_big = new FileSortOrderBySize(sort_small_to_big_id, true);
- public static final FileSortOrder sort_big_to_small = new FileSortOrderBySize(sort_big_to_small_id, false);
-
- public static final Map sortOrders;
-
- static {
- HashMap temp = new HashMap<>();
- temp.put(sort_a_to_z.name, sort_a_to_z);
- temp.put(sort_z_to_a.name, sort_z_to_a);
- temp.put(sort_old_to_new.name, sort_old_to_new);
- temp.put(sort_new_to_old.name, sort_new_to_old);
- temp.put(sort_small_to_big.name, sort_small_to_big);
- temp.put(sort_big_to_small.name, sort_big_to_small);
-
- sortOrders = Collections.unmodifiableMap(temp);
- }
-
- public String name;
- public boolean isAscending;
-
- public FileSortOrder(String name, boolean ascending) {
- this.name = name;
- isAscending = ascending;
- }
-
- public static FileSortOrder getFileSortOrder(@Nullable String key) {
- if (TextUtils.isEmpty(key) || !sortOrders.containsKey(key)) {
- return sort_a_to_z;
- } else {
- return sortOrders.get(key);
- }
- }
-
- public List sortCloudFiles(List files) {
- return sortCloudFilesByFavourite(files);
- }
-
- /**
- * Sorts list by Favourites.
- *
- * @param files files to sort
- */
- public static List sortCloudFilesByFavourite(List files) {
- Collections.sort(files, (o1, o2) -> {
- if (o1.getModel().isFavorite() && o2.getModel().isFavorite()) {
- return 0;
- } else if (o1.getModel().isFavorite()) {
- return -1;
- } else if (o2.getModel().isFavorite()) {
- return 1;
- }
- return 0;
- });
-
- return files;
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrder.kt b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrder.kt
new file mode 100644
index 000000000..53511b7a6
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrder.kt
@@ -0,0 +1,95 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Sven R. Kunze
+ * @author Andy Scherzinger
+ * Copyright (C) 2021-2022 Andy Scherzinger
+ * Copyright (C) 2017 Sven R. Kunze
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.utils
+
+import android.text.TextUtils
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import java.util.Collections
+
+open class FileSortOrder(var name: String, var isAscending: Boolean) {
+ companion object {
+ const val sort_a_to_z_id = "sort_a_to_z"
+ const val sort_z_to_a_id = "sort_z_to_a"
+ const val sort_old_to_new_id = "sort_old_to_new"
+ const val sort_new_to_old_id = "sort_new_to_old"
+ const val sort_small_to_big_id = "sort_small_to_big"
+ const val sort_big_to_small_id = "sort_big_to_small"
+
+ val sort_a_to_z: FileSortOrder = FileSortOrderByName(sort_a_to_z_id, true)
+ val sort_z_to_a: FileSortOrder = FileSortOrderByName(sort_z_to_a_id, false)
+ val sort_old_to_new: FileSortOrder = FileSortOrderByDate(sort_old_to_new_id, true)
+ val sort_new_to_old: FileSortOrder = FileSortOrderByDate(sort_new_to_old_id, false)
+ val sort_small_to_big: FileSortOrder = FileSortOrderBySize(sort_small_to_big_id, true)
+ val sort_big_to_small: FileSortOrder = FileSortOrderBySize(sort_big_to_small_id, false)
+
+ val sortOrders: Map = mapOf(
+ sort_a_to_z.name to sort_a_to_z,
+ sort_z_to_a.name to sort_z_to_a,
+ sort_old_to_new.name to sort_old_to_new,
+ sort_new_to_old.name to sort_new_to_old,
+ sort_small_to_big.name to sort_small_to_big,
+ sort_big_to_small.name to sort_big_to_small,
+ )
+
+ fun getFileSortOrder(key: String?): FileSortOrder {
+ return if (TextUtils.isEmpty(key) || !sortOrders.containsKey(key)) {
+ sort_a_to_z
+ } else {
+ sortOrders[key]!!
+ }
+ }
+
+ /**
+ * Sorts list by Favourites.
+ *
+ * @param files files to sort
+ */
+ fun sortCloudFilesByFavourite(files: List): List {
+ Collections.sort(files, RemoteFileBrowserItemFavoriteComparator())
+ return files
+ }
+ }
+
+ val multiplier: Int
+ get() = if (isAscending) 1 else -1
+
+ open fun sortCloudFiles(files: List): List {
+ return sortCloudFilesByFavourite(files)
+ }
+
+ /**
+ * Comparator for RemoteFileBrowserItems, sorts favorite state.
+ */
+ class RemoteFileBrowserItemFavoriteComparator : Comparator {
+ override fun compare(left: RemoteFileBrowserItem, right: RemoteFileBrowserItem): Int {
+ return if (left.isFavorite && right.isFavorite) {
+ 0
+ } else if (left.isFavorite) {
+ -1
+ } else if (right.isFavorite) {
+ 1
+ } else {
+ 0
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByDate.java b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByDate.java
deleted file mode 100644
index 2d24e88b0..000000000
--- a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByDate.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Sven R. Kunze
- * @author Andy Scherzinger
- * Copyright (C) 2021 Andy Scherzinger
- * Copyright (C) 2017 Sven R. Kunze
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.utils;
-
-import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Created by srkunze on 28.08.17.
- */
-public class FileSortOrderByDate extends FileSortOrder {
-
- FileSortOrderByDate(String name, boolean ascending) {
- super(name, ascending);
- }
-
- /**
- * Sorts list by Date.
- *
- * @param files list of files to sort
- */
- public List sortCloudFiles(List files) {
- final int multiplier = isAscending ? 1 : -1;
-
- Collections.sort(files, (o1, o2) ->
- multiplier * Long.compare(o1.getModel().getModifiedTimestamp(), o2.getModel().getModifiedTimestamp()));
-
- return super.sortCloudFiles(files);
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByDate.kt b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByDate.kt
new file mode 100644
index 000000000..f7bcc5e05
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByDate.kt
@@ -0,0 +1,47 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Sven R. Kunze
+ * @author Andy Scherzinger
+ * Copyright (C) 2021-2022 Andy Scherzinger
+ * Copyright (C) 2017 Sven R. Kunze
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.utils
+
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import java.util.Collections
+
+class FileSortOrderByDate internal constructor(name: String, ascending: Boolean) : FileSortOrder(name, ascending) {
+ /**
+ * Sorts list by Date.
+ *
+ * @param files list of files to sort
+ */
+ override fun sortCloudFiles(files: List): List {
+ Collections.sort(files, RemoteFileBrowserItemDateComparator(multiplier))
+ return super.sortCloudFiles(files)
+ }
+
+ /**
+ * Comparator for RemoteFileBrowserItems, sorts by modified timestamp.
+ */
+ class RemoteFileBrowserItemDateComparator(private val multiplier: Int) : Comparator {
+
+ override fun compare(left: RemoteFileBrowserItem, right: RemoteFileBrowserItem): Int {
+ return multiplier * left.modifiedTimestamp.compareTo(right.modifiedTimestamp)
+ }
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByName.java b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByName.java
deleted file mode 100644
index c5035fd60..000000000
--- a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByName.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Sven R. Kunze
- * @author Andy Scherzinger
- * Copyright (C) 2021 Andy Scherzinger
- * Copyright (C) 2017 Sven R. Kunze
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.utils;
-
-import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem;
-
-import java.util.Collections;
-import java.util.List;
-
-import third_parties.daveKoeller.AlphanumComparator;
-
-/**
- * Created by srkunze on 28.08.17.
- */
-public class FileSortOrderByName extends FileSortOrder {
-
- FileSortOrderByName(String name, boolean ascending) {
- super(name, ascending);
- }
-
- /**
- * Sorts list by Name.
- *
- * @param files files to sort
- */
- @SuppressWarnings("Bx")
- public List sortCloudFiles(List files) {
- final int multiplier = isAscending ? 1 : -1;
-
- Collections.sort(files, (o1, o2) -> {
- if (!o1.getModel().isFile() && !o2.getModel().isFile()) {
- return multiplier * new AlphanumComparator().compare(o1, o2);
- } else if (!o1.getModel().isFile()) {
- return -1;
- } else if (!o2.getModel().isFile()) {
- return 1;
- }
- return multiplier * new AlphanumComparator().compare(o1, o2);
- });
-
- return super.sortCloudFiles(files);
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByName.kt b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByName.kt
new file mode 100644
index 000000000..2b4f3524a
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderByName.kt
@@ -0,0 +1,57 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Sven R. Kunze
+ * @author Andy Scherzinger
+ * Copyright (C) 2021-2022 Andy Scherzinger
+ * Copyright (C) 2017 Sven R. Kunze
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.utils
+
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import third_parties.daveKoeller.AlphanumComparator
+import java.util.Collections
+
+class FileSortOrderByName internal constructor(name: String, ascending: Boolean) : FileSortOrder(name, ascending) {
+ /**
+ * Sorts list by Name.
+ *
+ * @param files files to sort
+ */
+ override fun sortCloudFiles(files: List): List {
+ Collections.sort(files, RemoteFileBrowserItemNameComparator(multiplier))
+ return super.sortCloudFiles(files)
+ }
+
+ /**
+ * Comparator for RemoteFileBrowserItems, sorts by name.
+ */
+ class RemoteFileBrowserItemNameComparator(private val multiplier: Int) : Comparator {
+ private val alphanumComparator = AlphanumComparator()
+
+ override fun compare(left: RemoteFileBrowserItem, right: RemoteFileBrowserItem): Int {
+ return if (!left.isFile && !right.isFile) {
+ return multiplier * alphanumComparator.compare(left.path, right.path)
+ } else if (!left.isFile) {
+ -1
+ } else if (!right.isFile) {
+ 1
+ } else {
+ multiplier * alphanumComparator.compare(left.path, right.path)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderBySize.java b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderBySize.java
deleted file mode 100644
index 4eab78668..000000000
--- a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderBySize.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Sven R. Kunze
- * @author Andy Scherzinger
- * Copyright (C) 2021 Andy Scherzinger
- * Copyright (C) 2017 Sven R. Kunze
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 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.nextcloud.talk.utils;
-
-import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Sorts files by sizes
- */
-public class FileSortOrderBySize extends FileSortOrder {
-
- FileSortOrderBySize(String name, boolean ascending) {
- super(name, ascending);
- }
-
- /**
- * Sorts list by Size.
- *
- * @param files list of files to sort
- */
- public List sortCloudFiles(List files) {
- final int multiplier = isAscending ? 1 : -1;
-
- Collections.sort(files, (o1, o2) -> {
- if (!o1.getModel().isFile() && !o2.getModel().isFile()) {
- return multiplier * Long.compare(o1.getModel().getSize(), o2.getModel().getSize());
- } else if (!o1.getModel().isFile()) {
- return -1;
- } else if (!o2.getModel().isFile()) {
- return 1;
- } else {
- return multiplier * Long.compare(o1.getModel().getSize(), o2.getModel().getSize());
- }
- });
-
- return super.sortCloudFiles(files);
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderBySize.kt b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderBySize.kt
new file mode 100644
index 000000000..9beab94a4
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/utils/FileSortOrderBySize.kt
@@ -0,0 +1,55 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Sven R. Kunze
+ * @author Andy Scherzinger
+ * Copyright (C) 2021-2022 Andy Scherzinger
+ * Copyright (C) 2017 Sven R. Kunze
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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 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.nextcloud.talk.utils
+
+import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
+import java.util.Collections
+
+class FileSortOrderBySize internal constructor(name: String, ascending: Boolean) : FileSortOrder(name, ascending) {
+ /**
+ * Sorts list by Size.
+ *
+ * @param files list of files to sort
+ */
+ override fun sortCloudFiles(files: List): List {
+ Collections.sort(files, RemoteFileBrowserItemSizeComparator(multiplier))
+ return super.sortCloudFiles(files)
+ }
+
+ /**
+ * Comparator for RemoteFileBrowserItems, sorts by name.
+ */
+ class RemoteFileBrowserItemSizeComparator(private val multiplier: Int) : Comparator {
+
+ override fun compare(left: RemoteFileBrowserItem, right: RemoteFileBrowserItem): Int {
+ return if (!left.isFile && !right.isFile) {
+ return multiplier * left.size.compareTo(right.size)
+ } else if (!left.isFile) {
+ -1
+ } else if (!right.isFile) {
+ 1
+ } else {
+ multiplier * left.size.compareTo(right.size)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/FileUtils.java b/app/src/main/java/com/nextcloud/talk/utils/FileUtils.java
index 796337f83..ceb8f1bb9 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/FileUtils.java
+++ b/app/src/main/java/com/nextcloud/talk/utils/FileUtils.java
@@ -65,4 +65,21 @@ public class FileUtils {
return cacheFile;
}
+
+ /**
+ * Creates a new {@link File}
+ */
+ public static void removeTempCacheFile(@NonNull Context context, String fileName) throws IOException {
+ File cacheFile = new File(context.getApplicationContext().getFilesDir().getAbsolutePath() + "/" + fileName);
+
+ Log.v(TAG, "Full path for new cache file:" + cacheFile.getAbsolutePath());
+
+ if (cacheFile.exists()) {
+ if(cacheFile.delete()) {
+ Log.v(TAG, "Deletion successful");
+ } else {
+ throw new IOException("Directory for temporary file does not exist and could not be created.");
+ }
+ }
+ }
}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
index 02e1b0abe..75ca6b9d3 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
+++ b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
@@ -74,4 +74,5 @@ object BundleKeys {
val KEY_FORWARD_HIDE_SOURCE_ROOM = "KEY_FORWARD_HIDE_SOURCE_ROOM"
val KEY_SYSTEM_NOTIFICATION_ID = "KEY_SYSTEM_NOTIFICATION_ID"
const val KEY_MESSAGE_ID = "KEY_MESSAGE_ID"
+ const val KEY_MIME_TYPE_FILTER = "KEY_MIME_TYPE_FILTER"
}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java
index 6ff15688c..fd141a4d1 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java
+++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/AppPreferences.java
@@ -25,7 +25,6 @@
package com.nextcloud.talk.utils.preferences;
import com.nextcloud.talk.R;
-import com.nextcloud.talk.utils.FileSortOrder;
import net.orange_box.storebox.annotations.method.ClearMethod;
import net.orange_box.storebox.annotations.method.DefaultValue;
diff --git a/app/src/main/java/third_parties/daveKoeller/AlphanumComparator.java b/app/src/main/java/third_parties/daveKoeller/AlphanumComparator.java
index af25c47b2..35cd76177 100644
--- a/app/src/main/java/third_parties/daveKoeller/AlphanumComparator.java
+++ b/app/src/main/java/third_parties/daveKoeller/AlphanumComparator.java
@@ -24,9 +24,6 @@
package third_parties.daveKoeller;
-import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem;
-
-import java.io.File;
import java.io.Serializable;
import java.math.BigInteger;
import java.text.Collator;
@@ -87,13 +84,6 @@ public class AlphanumComparator implements Comparator, Serializable {
return chunk.toString();
}
- public int compare(BrowserFileItem f1, BrowserFileItem f2) {
- String s1 = f1.getModel().getPath();
- String s2 = f2.getModel().getPath();
-
- return compare(s1, s2);
- }
-
public int compare(T t1, T t2) {
return compare(t1.toString(), t2.toString());
}
diff --git a/app/src/main/res/drawable/round_corner.xml b/app/src/main/res/drawable/round_corner.xml
index ecc82cfd1..6888a97bf 100644
--- a/app/src/main/res/drawable/round_corner.xml
+++ b/app/src/main/res/drawable/round_corner.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/app/src/main/res/layout/activity_remote_file_browser.xml b/app/src/main/res/layout/activity_remote_file_browser.xml
new file mode 100644
index 000000000..52db0abfc
--- /dev/null
+++ b/app/src/main/res/layout/activity_remote_file_browser.xml
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/controller_browser.xml b/app/src/main/res/layout/controller_browser.xml
deleted file mode 100644
index 294136883..000000000
--- a/app/src/main/res/layout/controller_browser.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/controller_profile.xml b/app/src/main/res/layout/controller_profile.xml
index 9b6e7de19..9cf360582 100644
--- a/app/src/main/res/layout/controller_profile.xml
+++ b/app/src/main/res/layout/controller_profile.xml
@@ -78,8 +78,8 @@
diff --git a/app/src/main/res/menu/file_browser_path.xml b/app/src/main/res/menu/file_browser_path.xml
deleted file mode 100644
index 67c6dfd52..000000000
--- a/app/src/main/res/menu/file_browser_path.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index deecee935..fc3942e1a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -358,7 +358,6 @@
Back
%1$s | Last modified: %2$s
- You are not allowed to re-share this file
Sort by
file_browser_sort_by
sort_a_to_z
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index d16b13034..02455e83e 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -63,11 +63,7 @@
- @color/fontAppbar
-
-
-
+