mirror of
https://github.com/nextcloud/android.git
synced 2024-11-26 07:05:49 +03:00
Merge pull request #10484 from nextcloud/media-view-options
Media view filter options
This commit is contained in:
commit
5baa1c8f45
15 changed files with 621 additions and 20 deletions
|
@ -1,9 +1,11 @@
|
|||
/*
|
||||
* ownCloud Android client application
|
||||
*
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2012 Bartek Przybylski
|
||||
* Copyright (C) 2015 ownCloud Inc.
|
||||
* Copyright (C) 2021 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
|
@ -2367,4 +2369,8 @@ public class FileDataStorageManager {
|
|||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public OCFile getDefaultRootPath(){
|
||||
return new OCFile(OCFile.ROOT_PATH);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
* @author David A. Velasco
|
||||
* @author Andy Scherzinger
|
||||
* @author Chris Narkiewicz
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2011 Bartek Przybylski
|
||||
* Copyright (C) 2016 ownCloud Inc.
|
||||
* Copyright (C) 2018 Andy Scherzinger
|
||||
* Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
|
@ -551,6 +553,10 @@ public class FileDisplayActivity extends FileActivity
|
|||
searchView.post(() -> searchView.setQuery(searchQuery, true));
|
||||
}
|
||||
setDrawerIndicatorEnabled(false);
|
||||
|
||||
//clear the subtitle while navigating to any other screen from Media screen
|
||||
clearToolbarSubtitle();
|
||||
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
transaction.addToBackStack(null);
|
||||
transaction.replace(R.id.left_fragment_container, fragment, TAG_LIST_OF_FILES);
|
||||
|
|
|
@ -108,6 +108,12 @@ open class FolderPickerActivity :
|
|||
mSearchOnlyFolders = true
|
||||
isDoNotEnterEncryptedFolder = true
|
||||
}
|
||||
CHOOSE_LOCATION -> {
|
||||
caption = resources.getText(R.string.choose_location).toString()
|
||||
mSearchOnlyFolders = true
|
||||
isDoNotEnterEncryptedFolder = true
|
||||
mChooseBtn!!.text = resources.getString(R.string.common_select)
|
||||
}
|
||||
else -> caption = themeUtils.getDefaultDisplayNameForRootFolder(this)
|
||||
}
|
||||
} else {
|
||||
|
@ -550,6 +556,7 @@ open class FolderPickerActivity :
|
|||
|
||||
const val MOVE = "MOVE"
|
||||
const val COPY = "COPY"
|
||||
const val CHOOSE_LOCATION = "CHOOSE_LOCATION"
|
||||
private val TAG = FolderPickerActivity::class.java.simpleName
|
||||
protected const val TAG_LIST_OF_FOLDERS = "LIST_OF_FOLDERS"
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Andy Scherzinger
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2016 Andy Scherzinger
|
||||
* Copyright (C) 2016 Nextcloud
|
||||
* Copyright (C) 2016 ownCloud Inc.
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
|
@ -51,6 +53,7 @@ import com.owncloud.android.utils.theme.ThemeUtils;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
|
@ -285,4 +288,16 @@ public abstract class ToolbarActivity extends BaseActivity implements Injectable
|
|||
public FrameLayout getPreviewImageContainer() {
|
||||
return mPreviewImageContainer;
|
||||
}
|
||||
|
||||
public void updateToolbarSubtitle(@NonNull String subtitle) {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
themeToolbarUtils.setColoredSubtitle(actionBar, subtitle, this);
|
||||
}
|
||||
|
||||
public void clearToolbarSubtitle() {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if(actionBar != null){
|
||||
actionBar.setSubtitle(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2022 Tobias Kaminsky
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -39,11 +41,14 @@ import com.owncloud.android.datamodel.FileDataStorageManager
|
|||
import com.owncloud.android.datamodel.GalleryItems
|
||||
import com.owncloud.android.datamodel.OCFile
|
||||
import com.owncloud.android.ui.activity.ComponentsGetter
|
||||
import com.owncloud.android.ui.fragment.GalleryFragment
|
||||
import com.owncloud.android.ui.fragment.GalleryFragmentBottomSheetDialog
|
||||
import com.owncloud.android.ui.fragment.SearchType
|
||||
import com.owncloud.android.ui.interfaces.OCFileListFragmentInterface
|
||||
import com.owncloud.android.utils.DisplayUtils
|
||||
import com.owncloud.android.utils.FileSortOrder
|
||||
import com.owncloud.android.utils.FileStorageUtils
|
||||
import com.owncloud.android.utils.MimeTypeUtil
|
||||
import com.owncloud.android.utils.theme.ThemeColorUtils
|
||||
import com.owncloud.android.utils.theme.ThemeDrawableUtils
|
||||
import me.zhanghai.android.fastscroll.PopupTextProvider
|
||||
|
@ -157,10 +162,46 @@ class GalleryAdapter(
|
|||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun showAllGalleryItems() {
|
||||
fun showAllGalleryItems(
|
||||
remotePath: String,
|
||||
mediaState: GalleryFragmentBottomSheetDialog.MediaState,
|
||||
photoFragment: GalleryFragment
|
||||
) {
|
||||
|
||||
val items = storageManager.allGalleryItems
|
||||
|
||||
files = items
|
||||
val filteredList = items.filter { it != null && it.remotePath.startsWith(remotePath) }
|
||||
|
||||
setMediaFilter(
|
||||
filteredList,
|
||||
mediaState,
|
||||
photoFragment
|
||||
)
|
||||
}
|
||||
|
||||
// Set Image/Video List According to Selection of Hide/Show Image/Video
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun setMediaFilter(
|
||||
items: List<OCFile>,
|
||||
mediaState: GalleryFragmentBottomSheetDialog.MediaState,
|
||||
photoFragment: GalleryFragment
|
||||
) {
|
||||
|
||||
val finalSortedList: List<OCFile> = when (mediaState) {
|
||||
GalleryFragmentBottomSheetDialog.MediaState.MEDIA_STATE_PHOTOS_ONLY -> {
|
||||
items.filter { MimeTypeUtil.isImage(it.mimeType) }.distinct()
|
||||
}
|
||||
GalleryFragmentBottomSheetDialog.MediaState.MEDIA_STATE_VIDEOS_ONLY -> {
|
||||
items.filter { MimeTypeUtil.isVideo(it.mimeType) }.distinct()
|
||||
}
|
||||
else -> items
|
||||
}
|
||||
|
||||
if (finalSortedList.isEmpty()) {
|
||||
photoFragment.setEmptyListMessage(SearchType.GALLERY_SEARCH)
|
||||
}
|
||||
|
||||
files = finalSortedList
|
||||
.groupBy { firstOfMonth(it.modificationTimestamp) }
|
||||
.map { GalleryItems(it.key, FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(it.value)) }
|
||||
.sortedBy { it.date }.reversed()
|
||||
|
@ -168,6 +209,12 @@ class GalleryAdapter(
|
|||
Handler(Looper.getMainLooper()).post { notifyDataSetChanged() }
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun clear() {
|
||||
files = emptyList()
|
||||
Handler(Looper.getMainLooper()).post { notifyDataSetChanged() }
|
||||
}
|
||||
|
||||
private fun firstOfMonth(timestamp: Long): Long {
|
||||
val cal = Calendar.getInstance()
|
||||
cal.time = Date(timestamp)
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
* Nextcloud Android client application
|
||||
*
|
||||
* @author Tobias Kaminsky
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2019 Tobias Kaminsky
|
||||
* Copyright (C) 2019 Nextcloud GmbH
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
*
|
||||
* 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
|
||||
|
@ -21,24 +23,36 @@
|
|||
|
||||
package com.owncloud.android.ui.fragment;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.nextcloud.utils.view.FastScroll;
|
||||
import com.owncloud.android.R;
|
||||
import com.owncloud.android.datamodel.FileDataStorageManager;
|
||||
import com.owncloud.android.datamodel.OCFile;
|
||||
import com.owncloud.android.lib.common.utils.Log_OC;
|
||||
import com.owncloud.android.ui.activity.FileDisplayActivity;
|
||||
import com.owncloud.android.ui.activity.FolderPickerActivity;
|
||||
import com.owncloud.android.ui.activity.ToolbarActivity;
|
||||
import com.owncloud.android.ui.adapter.CommonOCFileListAdapterInterface;
|
||||
import com.owncloud.android.ui.adapter.GalleryAdapter;
|
||||
import com.owncloud.android.ui.asynctasks.GallerySearchTask;
|
||||
import com.owncloud.android.ui.events.ChangeMenuEvent;
|
||||
import com.owncloud.android.ui.fragment.util.GalleryFastScrollViewHelper;
|
||||
import com.owncloud.android.utils.theme.ThemeMenuUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
@ -46,7 +60,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
/**
|
||||
* A Fragment that lists all files and folders in a given path
|
||||
*/
|
||||
public class GalleryFragment extends OCFileListFragment {
|
||||
public class GalleryFragment extends OCFileListFragment implements GalleryFragmentBottomSheetActions {
|
||||
private static final int MAX_ITEMS_PER_ROW = 10;
|
||||
private boolean photoSearchQueryRunning = false;
|
||||
private AsyncTask<Void, Void, GallerySearchTask.Result> photoSearchTask;
|
||||
|
@ -56,10 +70,23 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
private int limit = 300;
|
||||
private GalleryAdapter mAdapter;
|
||||
|
||||
private static final int SELECT_LOCATION_REQUEST_CODE = 212;
|
||||
private OCFile remoteFile;
|
||||
private GalleryFragmentBottomSheetDialog galleryFragmentBottomSheetDialog;
|
||||
|
||||
@Inject ThemeMenuUtils themeMenuUtils;
|
||||
@Inject FileDataStorageManager fileDataStorageManager;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
searchFragment = true;
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
if (galleryFragmentBottomSheetDialog == null) {
|
||||
galleryFragmentBottomSheetDialog = new GalleryFragmentBottomSheetDialog(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -78,6 +105,8 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View v = super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
remoteFile = fileDataStorageManager.getDefaultRootPath();
|
||||
|
||||
getRecyclerView().addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
|
@ -98,6 +127,8 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
menuItemAddRemoveValue = MenuItemAddRemove.REMOVE_GRID_AND_SORT;
|
||||
requireActivity().invalidateOptionsMenu();
|
||||
|
||||
updateSubtitle(galleryFragmentBottomSheetDialog.getCurrMediaState());
|
||||
|
||||
handleSearchEvent();
|
||||
}
|
||||
|
||||
|
@ -128,7 +159,6 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
@Override
|
||||
public void onRefresh() {
|
||||
super.onRefresh();
|
||||
|
||||
handleSearchEvent();
|
||||
}
|
||||
|
||||
|
@ -159,7 +189,7 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
setEmptyListLoadingMessage();
|
||||
|
||||
// always show first stored items
|
||||
mAdapter.showAllGalleryItems();
|
||||
showAllGalleryItems();
|
||||
|
||||
setFabVisible(false);
|
||||
|
||||
|
@ -174,18 +204,14 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
startDate = (System.currentTimeMillis() / 1000) - 30 * 24 * 60 * 60;
|
||||
endDate = System.currentTimeMillis() / 1000;
|
||||
|
||||
photoSearchTask = new GallerySearchTask(this,
|
||||
accountManager.getUser(),
|
||||
mContainerActivity.getStorageManager(),
|
||||
startDate,
|
||||
endDate,
|
||||
limit)
|
||||
.execute();
|
||||
runGallerySearchTask();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
public void searchCompleted(boolean emptySearch, long lastTimeStamp) {
|
||||
photoSearchQueryRunning = false;
|
||||
mAdapter.notifyDataSetChanged();
|
||||
|
||||
if (mAdapter.isEmpty()) {
|
||||
setEmptyListMessage(SearchType.GALLERY_SEARCH);
|
||||
|
@ -214,6 +240,54 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
|
||||
startDate = endDate - (daySpan * 24 * 60 * 60);
|
||||
|
||||
runGallerySearchTask();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, @NonNull MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
inflater.inflate(R.menu.fragment_gallery_three_dots, menu);
|
||||
|
||||
MenuItem menuItem = menu.findItem(R.id.action_three_dot_icon);
|
||||
|
||||
if (menuItem != null) {
|
||||
themeMenuUtils.tintMenuIcon(menuItem,
|
||||
themeColorUtils.appBarPrimaryFontColor(requireContext()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
// Handle item selection
|
||||
if (item.getItemId() == R.id.action_three_dot_icon && !photoSearchQueryRunning
|
||||
&& galleryFragmentBottomSheetDialog != null) {
|
||||
galleryFragmentBottomSheetDialog.show(getChildFragmentManager(),"data" );
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if (requestCode == SELECT_LOCATION_REQUEST_CODE && data != null) {
|
||||
OCFile chosenFolder = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
|
||||
if (chosenFolder != null) {
|
||||
remoteFile = chosenFolder;
|
||||
searchAndDisplayAfterChangingFolder();
|
||||
}
|
||||
}
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void searchAndDisplayAfterChangingFolder() {
|
||||
mAdapter.clear();
|
||||
runGallerySearchTask();
|
||||
}
|
||||
|
||||
private void runGallerySearchTask() {
|
||||
photoSearchTask = new GallerySearchTask(this,
|
||||
accountManager.getUser(),
|
||||
mContainerActivity.getStorageManager(),
|
||||
|
@ -252,19 +326,43 @@ public class GalleryFragment extends OCFileListFragment {
|
|||
startDate = endDate - (daySpan * 24 * 60 * 60);
|
||||
|
||||
photoSearchQueryRunning = true;
|
||||
photoSearchTask = new GallerySearchTask(this,
|
||||
accountManager.getUser(),
|
||||
mContainerActivity.getStorageManager(),
|
||||
startDate,
|
||||
endDate,
|
||||
limit)
|
||||
.execute();
|
||||
runGallerySearchTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateMediaContent(GalleryFragmentBottomSheetDialog.MediaState mediaState) {
|
||||
showAllGalleryItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectMediaFolder() {
|
||||
Intent action = new Intent(requireActivity(), FolderPickerActivity.class);
|
||||
action.putExtra(FolderPickerActivity.EXTRA_ACTION, FolderPickerActivity.CHOOSE_LOCATION);
|
||||
startActivityForResult(action, SELECT_LOCATION_REQUEST_CODE);
|
||||
}
|
||||
|
||||
public void showAllGalleryItems() {
|
||||
mAdapter.showAllGalleryItems();
|
||||
mAdapter.showAllGalleryItems(remoteFile.getRemotePath(),
|
||||
galleryFragmentBottomSheetDialog.getCurrMediaState(),
|
||||
this);
|
||||
|
||||
updateSubtitle(galleryFragmentBottomSheetDialog.getCurrMediaState());
|
||||
}
|
||||
|
||||
private void updateSubtitle(GalleryFragmentBottomSheetDialog.MediaState mediaState) {
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
String subTitle = requireContext().getResources().getString(R.string.subtitle_photos_videos);
|
||||
if (mediaState == GalleryFragmentBottomSheetDialog.MediaState.MEDIA_STATE_PHOTOS_ONLY) {
|
||||
subTitle = requireContext().getResources().getString(R.string.subtitle_photos_only);
|
||||
} else if (mediaState == GalleryFragmentBottomSheetDialog.MediaState.MEDIA_STATE_VIDEOS_ONLY) {
|
||||
subTitle = requireContext().getResources().getString(R.string.subtitle_videos_only);
|
||||
}
|
||||
if (requireActivity() instanceof ToolbarActivity) {
|
||||
((ToolbarActivity) requireActivity()).updateToolbarSubtitle(subTitle);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.owncloud.android.ui.fragment
|
||||
|
||||
interface GalleryFragmentBottomSheetActions {
|
||||
/**
|
||||
* show/hide all the images & videos in particular Folder.
|
||||
*/
|
||||
fun updateMediaContent(mediaState: GalleryFragmentBottomSheetDialog.MediaState)
|
||||
|
||||
/**
|
||||
* load all media of a particular folder.
|
||||
*/
|
||||
fun selectMediaFolder()
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Nextcloud Android client application
|
||||
*
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
* Copyright (C) 2022 Nextcloud GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.owncloud.android.ui.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.owncloud.android.databinding.FragmentGalleryBottomSheetBinding
|
||||
|
||||
class GalleryFragmentBottomSheetDialog(
|
||||
private val actions: GalleryFragmentBottomSheetActions
|
||||
) : BottomSheetDialogFragment() {
|
||||
private lateinit var binding: FragmentGalleryBottomSheetBinding
|
||||
private lateinit var mBottomBehavior: BottomSheetBehavior<*>
|
||||
private var currentMediaState: MediaState = MediaState.MEDIA_STATE_DEFAULT
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
binding = FragmentGalleryBottomSheetBinding.inflate(layoutInflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupLayout()
|
||||
setupClickListener()
|
||||
mBottomBehavior = BottomSheetBehavior.from(binding.root.parent as View)
|
||||
}
|
||||
|
||||
public override fun onStart() {
|
||||
super.onStart()
|
||||
mBottomBehavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
||||
private fun setupLayout() {
|
||||
when (currentMediaState) {
|
||||
MediaState.MEDIA_STATE_PHOTOS_ONLY -> {
|
||||
binding.tickMarkShowImages.visibility = View.VISIBLE
|
||||
binding.tickMarkShowVideo.visibility = View.GONE
|
||||
}
|
||||
MediaState.MEDIA_STATE_VIDEOS_ONLY -> {
|
||||
binding.tickMarkShowImages.visibility = View.GONE
|
||||
binding.tickMarkShowVideo.visibility = View.VISIBLE
|
||||
}
|
||||
else -> {
|
||||
binding.tickMarkShowImages.visibility = View.VISIBLE
|
||||
binding.tickMarkShowVideo.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupClickListener() {
|
||||
binding.hideImages.setOnClickListener { v: View? ->
|
||||
currentMediaState = if (currentMediaState == MediaState.MEDIA_STATE_VIDEOS_ONLY) {
|
||||
MediaState.MEDIA_STATE_DEFAULT
|
||||
} else {
|
||||
MediaState.MEDIA_STATE_VIDEOS_ONLY
|
||||
}
|
||||
notifyStateChange()
|
||||
dismiss()
|
||||
}
|
||||
binding.hideVideo.setOnClickListener { v: View? ->
|
||||
currentMediaState = if (currentMediaState == MediaState.MEDIA_STATE_PHOTOS_ONLY) {
|
||||
MediaState.MEDIA_STATE_DEFAULT
|
||||
} else {
|
||||
MediaState.MEDIA_STATE_PHOTOS_ONLY
|
||||
}
|
||||
notifyStateChange()
|
||||
dismiss()
|
||||
}
|
||||
binding.selectMediaFolder.setOnClickListener { v: View? ->
|
||||
actions.selectMediaFolder()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private fun notifyStateChange() {
|
||||
setupLayout()
|
||||
actions.updateMediaContent(currentMediaState)
|
||||
}
|
||||
|
||||
val currMediaState: MediaState
|
||||
get() = currentMediaState
|
||||
|
||||
enum class MediaState {
|
||||
MEDIA_STATE_DEFAULT,
|
||||
MEDIA_STATE_PHOTOS_ONLY,
|
||||
MEDIA_STATE_VIDEOS_ONLY
|
||||
}
|
||||
}
|
|
@ -3,9 +3,11 @@
|
|||
*
|
||||
* @author Tobias Kaminsky
|
||||
* @author Andy Scherzinger
|
||||
* @author TSI-mc
|
||||
* Copyright (C) 2017 Tobias Kaminsky
|
||||
* Copyright (C) 2017 Nextcloud GmbH
|
||||
* Copyright (C) 2018 Andy Scherzinger
|
||||
* Copyright (C) 2022 TSI-mc
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -22,11 +24,15 @@
|
|||
*/
|
||||
package com.owncloud.android.utils.theme;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.graphics.drawable.DrawableCompat;
|
||||
|
||||
/**
|
||||
* Utility class with methods for client side checkable theming.
|
||||
*/
|
||||
|
@ -43,4 +49,17 @@ public final class ThemeMenuUtils {
|
|||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
item.setTitle(newItemTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* tinting menu item color
|
||||
*
|
||||
* @param item the menu item object
|
||||
* @param color the color wanted as a color resource
|
||||
*/
|
||||
public void tintMenuIcon(@NonNull MenuItem item, int color) {
|
||||
Drawable normalDrawable = item.getIcon();
|
||||
Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable);
|
||||
DrawableCompat.setTint(wrapDrawable, color);
|
||||
item.setIcon(wrapDrawable);
|
||||
}
|
||||
}
|
||||
|
|
32
app/src/main/res/drawable/ic_tick.xml
Normal file
32
app/src/main/res/drawable/ic_tick.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!--
|
||||
Nextcloud Android client application
|
||||
|
||||
@author TSI-mc
|
||||
Copyright (C) 2022 TSI-mc
|
||||
Copyright (C) 2022 Nextcloud GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M9,20.215L1.695,12.91C1.2205,12.4202 1.2262,11.6405 1.7077,11.1577C2.1892,10.6748 2.9689,10.6669 3.46,11.14L9,16.68L21,4.68C21.4944,4.238 22.248,4.2591 22.7169,4.7281C23.1859,5.197 23.207,5.9506 22.765,6.445L9,20.215Z"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#262626"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
32
app/src/main/res/drawable/ic_video_camera.xml
Normal file
32
app/src/main/res/drawable/ic_video_camera.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!--
|
||||
Nextcloud Android client application
|
||||
|
||||
@author TSI-mc
|
||||
Copyright (C) 2022 TSI-mc
|
||||
Copyright (C) 2022 Nextcloud GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M20,5L20,8.8L21.8,7L23.5,7L23.5,17L21.8,17L20,15.2L20,17C20,18.65 18.65,20 17,20L17,20L5,20C3.35,20 2,18.65 2,17L2,17L2,10.5L0.5,10.5L0.5,6.5L2,6.5L2,5L20,5ZM18.5,6.5L3.5,6.5L3.5,17C3.5,17.85 4.15,18.5 5,18.5L5,18.5L17,18.5C17.85,18.5 18.5,17.85 18.5,17L18.5,17L18.5,6.5ZM9,9.25L14,12.5L9,15.75L9,9.25ZM22,8.9L20,10.9L20,13.1L22,15.1L22,8.9Z"
|
||||
android:strokeWidth="1"
|
||||
android:fillColor="#262626"
|
||||
android:fillType="evenOdd"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
146
app/src/main/res/layout/fragment_gallery_bottom_sheet.xml
Normal file
146
app/src/main/res/layout/fragment_gallery_bottom_sheet.xml
Normal file
|
@ -0,0 +1,146 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Nextcloud Android client application
|
||||
|
||||
@author TSI-mc
|
||||
Copyright (C) 2022 TSI-mc
|
||||
Copyright (C) 2022 Nextcloud GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/standard_half_padding">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/hideImages"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/standard_padding"
|
||||
android:paddingTop="@dimen/standard_padding"
|
||||
android:paddingRight="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_half_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/hideImagesImageview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_camera"
|
||||
app:tint="@color/primary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hideImagesTextview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_marginEnd="30dp"
|
||||
android:layout_toEndOf="@id/hideImagesImageview"
|
||||
android:text="@string/show_images"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/tickMarkShowImages"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_tick"
|
||||
android:visibility="gone"
|
||||
app:tint="@color/primary"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/hideVideo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/standard_padding"
|
||||
android:paddingTop="@dimen/standard_half_padding"
|
||||
android:paddingRight="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_half_padding">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/hideVideoImageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_video_camera"
|
||||
app:tint="@color/primary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/hideVideoTextview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:layout_toEndOf="@id/hideVideoImageView"
|
||||
android:text="@string/show_video"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/tickMarkShowVideo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_tick"
|
||||
android:visibility="gone"
|
||||
app:tint="@color/primary"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/selectMediaFolder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/standard_padding"
|
||||
android:paddingTop="@dimen/standard_half_padding"
|
||||
android:paddingRight="@dimen/standard_padding"
|
||||
android:paddingBottom="@dimen/standard_half_padding">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/nav_photos"
|
||||
app:tint="@color/primary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/standard_margin"
|
||||
android:text="@string/select_media_folder"
|
||||
android:textColor="@color/text_color"
|
||||
android:textSize="@dimen/bottom_sheet_text_size" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
33
app/src/main/res/menu/fragment_gallery_three_dots.xml
Normal file
33
app/src/main/res/menu/fragment_gallery_three_dots.xml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Nextcloud Android client application
|
||||
|
||||
@author TSI-mc
|
||||
Copyright (C) 2022 TSI-mc
|
||||
Copyright (C) 2022 Nextcloud GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_three_dot_icon"
|
||||
android:contentDescription="@string/more"
|
||||
android:orderInCategory="1"
|
||||
android:title="@string/more"
|
||||
app:showAsAction="always"
|
||||
android:icon="@drawable/ic_dots_vertical"/>
|
||||
|
||||
</menu>
|
|
@ -910,4 +910,12 @@
|
|||
<item quantity="one">%d ausgewählt</item>
|
||||
<item quantity="other">%d ausgewählt</item>
|
||||
</plurals>
|
||||
<string name="subtitle_photos_videos">Fotos & videos</string>
|
||||
<string name="show_images">Bilder anzeigen</string>
|
||||
<string name="subtitle_photos_only">Nur Fotos</string>
|
||||
<string name="show_video">Videos anzeigen</string>
|
||||
<string name="subtitle_videos_only">Nur Videos</string>
|
||||
<string name="select_media_folder">Medienordner festlegen</string>
|
||||
<string name="choose_location">Speicherort wählen</string>
|
||||
<string name="common_select">Auswählen</string>
|
||||
</resources>
|
||||
|
|
|
@ -1024,6 +1024,14 @@
|
|||
<string name="pdf_zoom_tip">Tap on a page to zoom in</string>
|
||||
<string name="storage_permission_full_access">Full access</string>
|
||||
<string name="storage_permission_media_read_only">Media read-only</string>
|
||||
<string name="subtitle_photos_videos">Photos & videos</string>
|
||||
<string name="show_images">Show photos</string>
|
||||
<string name="subtitle_photos_only">Photos only</string>
|
||||
<string name="show_video">Show videos</string>
|
||||
<string name="subtitle_videos_only">Videos only</string>
|
||||
<string name="select_media_folder">Set media folder</string>
|
||||
<string name="choose_location">Choose location</string>
|
||||
<string name="common_select">Select</string>
|
||||
<string name="lock_file">Lock file</string>
|
||||
<string name="unlock_file">Unlock file</string>
|
||||
<string name="error_file_lock">Error changing file lock status</string>
|
||||
|
|
Loading…
Reference in a new issue