Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fun FileMenuOption.toResId() =
FileMenuOption.SEND -> R.id.action_send_file
FileMenuOption.SET_AV_OFFLINE -> R.id.action_set_available_offline
FileMenuOption.UNSET_AV_OFFLINE -> R.id.action_unset_available_offline
FileMenuOption.ADD_TO_HOME_SCREEN -> R.id.action_add_to_home
}

fun FileMenuOption.toStringResId() =
Expand All @@ -59,6 +60,7 @@ fun FileMenuOption.toStringResId() =
FileMenuOption.SEND -> R.string.actionbar_send_file
FileMenuOption.SET_AV_OFFLINE -> R.string.set_available_offline
FileMenuOption.UNSET_AV_OFFLINE -> R.string.unset_available_offline
FileMenuOption.ADD_TO_HOME_SCREEN -> R.string.add_to_home_screen
}

fun FileMenuOption.toDrawableResId() =
Expand All @@ -78,4 +80,5 @@ fun FileMenuOption.toDrawableResId() =
FileMenuOption.SEND -> R.drawable.ic_send_white
FileMenuOption.SET_AV_OFFLINE -> R.drawable.ic_action_set_available_offline
FileMenuOption.UNSET_AV_OFFLINE -> R.drawable.ic_action_unset_available_offline
FileMenuOption.ADD_TO_HOME_SCREEN -> R.drawable.ic_action_add_to_home
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package eu.opencloud.android.presentation.files.addtohomescreen

import android.app.Dialog
import android.os.Bundle
import android.view.WindowManager
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.DialogFragment
import com.google.android.material.textfield.TextInputLayout
import eu.opencloud.android.R
import eu.opencloud.android.domain.files.model.OCFile
import eu.opencloud.android.presentation.files.filelist.MainFileListFragment.Companion.MAX_FILENAME_LENGTH
import eu.opencloud.android.presentation.files.filelist.MainFileListFragment.Companion.forbiddenChars
import eu.opencloud.android.utils.PreferenceUtils

class AddToHomeScreenDialogFragment : DialogFragment() {

private lateinit var folder: OCFile
private lateinit var listener: AddToHomeScreenListener

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
folder = requireArguments().getParcelable(ARG_FOLDER)!!
listener = parentFragment as AddToHomeScreenListener
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val inflater = requireActivity().layoutInflater
val view = inflater.inflate(R.layout.edit_box_dialog, null)

view.filterTouchesWhenObscured =
PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)

val coordinatorLayout: CoordinatorLayout = requireActivity().findViewById(R.id.coordinator_layout)
coordinatorLayout.filterTouchesWhenObscured =
PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context)

val inputText: EditText = view.findViewById(R.id.user_input)
val inputLayout: TextInputLayout = view.findViewById(R.id.edit_box_input_text_layout)

inputText.setText(folder.fileName)
inputText.selectAll()
inputText.requestFocus()

val builder = AlertDialog.Builder(requireActivity())
builder.setView(view)
.setPositiveButton(R.string.add_to_home_screen_dialog_add_button) { dialog, _ ->
val name = inputText.text.toString().trim()
if (name.isNotBlank()) {
listener.onAddToHomeScreen(name, folder)
}
dialog.dismiss()
}
.setNegativeButton(android.R.string.cancel, null)
.setTitle(R.string.add_to_home_screen_dialog_title)

val alertDialog = builder.create()

alertDialog.setOnShowListener {
val okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
okButton.isEnabled = inputText.text.isNullOrBlank().not()

okButton.setOnClickListener {
val name = inputText.text.toString().trim()
val error = when {
name.isBlank() -> getString(R.string.add_to_home_screen_dialog_error_empty)
name.length > MAX_FILENAME_LENGTH -> String.format(
getString(R.string.uploader_upload_text_dialog_filename_error_length_max),
MAX_FILENAME_LENGTH
)
forbiddenChars.any { name.contains(it) } -> getString(R.string.filename_forbidden_characters)
else -> null
}

if (error == null) {
listener.onAddToHomeScreen(name, folder)
alertDialog.dismiss()
} else {
inputLayout.error = error
}
}
}

inputText.doOnTextChanged { text, _, _, _ ->
val okButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
var error: String? = null

if (text.isNullOrBlank()) {
okButton.isEnabled = false
error = getString(R.string.add_to_home_screen_dialog_error_empty)
} else if (text.length > MAX_FILENAME_LENGTH) {
error = String.format(
getString(R.string.uploader_upload_text_dialog_filename_error_length_max),
MAX_FILENAME_LENGTH
)
} else if (forbiddenChars.any { text.contains(it) }) {
error = getString(R.string.filename_forbidden_characters)
} else {
okButton.isEnabled = true
}

if (error != null) {
okButton.isEnabled = false
inputLayout.error = error
} else {
inputLayout.error = null
}
}

alertDialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE)
return alertDialog
}

interface AddToHomeScreenListener {
fun onAddToHomeScreen(shortcutName: String, folder: OCFile)
}

companion object {
const val TAG = "ADD_TO_HOME_SCREEN_DIALOG"
private const val ARG_FOLDER = "ARG_FOLDER"

@JvmStatic
fun newInstance(folder: OCFile): AddToHomeScreenDialogFragment =
AddToHomeScreenDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(ARG_FOLDER, folder)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package eu.opencloud.android.presentation.files.addtohomescreen

import android.content.Context
import android.content.Intent
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.graphics.drawable.Icon
import android.os.Build
import android.widget.Toast
import androidx.annotation.RequiresApi
import eu.opencloud.android.R
import eu.opencloud.android.domain.files.model.OCFile
import eu.opencloud.android.ui.activity.FileDisplayActivity

object FolderShortcutHelper {

const val EXTRA_SHORTCUT_FOLDER_REMOTE_ID = "SHORTCUT_FOLDER_REMOTE_ID"
const val EXTRA_SHORTCUT_FOLDER_REMOTE_PATH = "SHORTCUT_FOLDER_REMOTE_PATH"
const val EXTRA_SHORTCUT_FOLDER_SPACE_ID = "SHORTCUT_FOLDER_SPACE_ID"

fun createPinnedShortcut(context: Context, folder: OCFile, shortcutName: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createPinnedShortcutApi26(context, folder, shortcutName)
} else {
Toast.makeText(context, context.getString(R.string.add_to_home_screen_shortcut_added), Toast.LENGTH_SHORT).show()
}
}

@RequiresApi(Build.VERSION_CODES.O)
private fun createPinnedShortcutApi26(context: Context, folder: OCFile, shortcutName: String) {
val shortcutManager = context.getSystemService(ShortcutManager::class.java)

if (shortcutManager?.isRequestPinShortcutSupported != true) {
Toast.makeText(context, context.getString(R.string.add_to_home_screen_shortcut_added), Toast.LENGTH_SHORT).show()
return
}

val shortcutId = "folder_${folder.id}"

val shortcutIntent = Intent(context, FileDisplayActivity::class.java).apply {
action = ACTION_OPEN_SHORTCUT
putExtra(EXTRA_SHORTCUT_FOLDER_REMOTE_ID, folder.remoteId)
putExtra(EXTRA_SHORTCUT_FOLDER_REMOTE_PATH, folder.remotePath)
putExtra(EXTRA_SHORTCUT_FOLDER_SPACE_ID, folder.spaceId)
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
}

val shortcut = ShortcutInfo.Builder(context, shortcutId)
.setShortLabel(shortcutName)
.setLongLabel(shortcutName)
.setIcon(Icon.createWithResource(context, R.mipmap.icon))
.setIntent(shortcutIntent)
.build()

shortcutManager.requestPinShortcut(shortcut, null)
Toast.makeText(context, context.getString(R.string.add_to_home_screen_shortcut_added), Toast.LENGTH_SHORT).show()
}

const val ACTION_OPEN_SHORTCUT = "eu.opencloud.android.ui.activity.action.OPEN_SHORTCUT"
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ import eu.opencloud.android.presentation.files.SortType
import eu.opencloud.android.presentation.files.ViewType
import eu.opencloud.android.presentation.files.createfolder.CreateFolderDialogFragment
import eu.opencloud.android.presentation.files.createshortcut.CreateShortcutDialogFragment
import eu.opencloud.android.presentation.files.addtohomescreen.AddToHomeScreenDialogFragment
import eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper
import eu.opencloud.android.presentation.files.operations.FileOperation
import eu.opencloud.android.presentation.files.operations.FileOperationsViewModel
import eu.opencloud.android.presentation.files.removefile.RemoveFilesDialogFragment
Expand Down Expand Up @@ -138,7 +140,8 @@ class MainFileListFragment : Fragment(),
SortDialogListener,
SortOptionsView.CreateFolderListener,
SortOptionsView.SortOptionsListener,
CreateShortcutDialogFragment.CreateShortcutListener {
CreateShortcutDialogFragment.CreateShortcutListener,
AddToHomeScreenDialogFragment.AddToHomeScreenListener {

private val mainFileListViewModel by viewModel<MainFileListViewModel> {
parametersOf(
Expand Down Expand Up @@ -737,6 +740,13 @@ class MainFileListFragment : Fragment(),
FileMenuOption.UNSET_AV_OFFLINE -> {
fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(file)))
}

FileMenuOption.ADD_TO_HOME_SCREEN -> {
if (file.isFolder) {
val dialog = AddToHomeScreenDialogFragment.newInstance(file)
dialog.show(childFragmentManager, DIALOG_ADD_TO_HOME_SCREEN)
}
}
}
dialog.hide()
dialog.dismiss()
Expand Down Expand Up @@ -1260,6 +1270,10 @@ class MainFileListFragment : Fragment(),
uploadActions?.uploadShortcutFileFromApp(arrayOf(shortcutFilePath))
}

override fun onAddToHomeScreen(shortcutName: String, folder: OCFile) {
FolderShortcutHelper.createPinnedShortcut(requireContext(), folder, shortcutName)
}

override fun onFolderNameSet(newFolderName: String, parentFolder: OCFile) {
fileOperationsViewModel.performOperation(FileOperation.CreateFolder(newFolderName, parentFolder))
fileOperationsViewModel.createFolder.observe(viewLifecycleOwner, Event.EventObserver { uiResult: UIResult<Unit> ->
Expand Down Expand Up @@ -1617,6 +1631,7 @@ class MainFileListFragment : Fragment(),

private const val DIALOG_CREATE_FOLDER = "DIALOG_CREATE_FOLDER"
private const val DIALOG_CREATE_SHORTCUT = "DIALOG_CREATE_SHORTCUT"
private const val DIALOG_ADD_TO_HOME_SCREEN = "DIALOG_ADD_TO_HOME_SCREEN"

private const val FILE_DOCXF_EXTENSION = "docxf"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ class FileDisplayActivity : FileActivity(),

private var isLightUser = false
private var isMultiPersonal = false
private var shortcutFolderToNavigate: OCFile? = null

override fun onCreate(savedInstanceState: Bundle?) {
Timber.v("onCreate() start")
Expand All @@ -216,6 +217,7 @@ class FileDisplayActivity : FileActivity(),
localBroadcastManager = LocalBroadcastManager.getInstance(this)

handleDeepLink()
handleShortcutIntent()

/// Load of saved instance state
if (savedInstanceState != null) {
Expand Down Expand Up @@ -348,7 +350,17 @@ class FileDisplayActivity : FileActivity(),
})
isLightUser = manageAccountsViewModel.checkUserLight(account.name)
isMultiPersonal = capabilitiesViewModel.checkMultiPersonal()
navigateTo(fileListOption, initialState = true)

if (shortcutFolderToNavigate != null) {
fileListOption = FileListOption.ALL_FILES
setFile(shortcutFolderToNavigate)
initAndShowListOfFiles(fileListOption)
refreshListOfFilesFragment()
updateToolbar(shortcutFolderToNavigate)
shortcutFolderToNavigate = null
} else {
navigateTo(fileListOption, initialState = true)
}

}

Expand Down Expand Up @@ -1966,6 +1978,24 @@ class FileDisplayActivity : FileActivity(),
}
}

private fun handleShortcutIntent() {
if (intent?.action != eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper.ACTION_OPEN_SHORTCUT) return

val shortcutRemotePath = intent?.getStringExtra(eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper.EXTRA_SHORTCUT_FOLDER_REMOTE_PATH)
val shortcutSpaceId = intent?.getStringExtra(eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper.EXTRA_SHORTCUT_FOLDER_SPACE_ID)
if (shortcutRemotePath != null) {
val file = storageManager.getFileByPath(shortcutRemotePath, shortcutSpaceId)
if (file != null) {
shortcutFolderToNavigate = file
} else {
showMessageInSnackbar(R.id.list_layout, getString(R.string.default_error_msg))
}
}
intent?.removeExtra(eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper.EXTRA_SHORTCUT_FOLDER_REMOTE_ID)
intent?.removeExtra(eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper.EXTRA_SHORTCUT_FOLDER_REMOTE_PATH)
intent?.removeExtra(eu.opencloud.android.presentation.files.addtohomescreen.FolderShortcutHelper.EXTRA_SHORTCUT_FOLDER_SPACE_ID)
}

private fun onDeepLinkManaged() {
collectLatestLifecycleFlow(fileOperationsViewModel.deepLinkFlow) {
it?.getContentIfNotHandled()?.let { uiResult ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ class FilterFileMenuOptionsUseCase(
if (!isAnyFileSynchronizing && !onlyAvailableOfflineFiles && !onlySharedByLinkFiles && hasRemovePermission) {
optionsToShow.add(FileMenuOption.REMOVE)
}
// Add to Home screen
if (isSingleSelection(files) && anyFolder(files)) {
optionsToShow.add(FileMenuOption.ADD_TO_HOME_SCREEN)
}

return optionsToShow
}
Expand Down
9 changes: 9 additions & 0 deletions opencloudApp/src/main/res/drawable/ic_action_add_to_home.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M18,2H6c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zM9,4h2v5l-1,-0.75L9,9V4zM18,20H6V4h1v9l3,-2.25L13,13V4H5v16h13V4h-2v9l-3,-2.25L7,13v1.25l5,3.5 5,-3.5V20z"/>
</vector>
6 changes: 6 additions & 0 deletions opencloudApp/src/main/res/menu/file_actions_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,11 @@
android:icon="@drawable/ic_action_delete_white"
app:showAsAction="ifRoom"
android:orderInCategory="1" />
<item
android:id="@+id/action_add_to_home"
android:title="@string/add_to_home_screen"
android:icon="@drawable/ic_action_add_to_home"
app:showAsAction="never"
android:orderInCategory="1" />

</menu>
6 changes: 6 additions & 0 deletions opencloudApp/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -861,4 +861,10 @@
<string name="release_notes_title_enhanced_bottom_nav_bar">Added text labels on bottom bar</string>
<string name="release_notes_subtitle_bottom_nav_bar">Text labels were added and default active indicator is used to show which section is selected on the bottom bar</string>

<string name="add_to_home_screen">Add to Home screen</string>
<string name="add_to_home_screen_dialog_title">Add to Home screen</string>
<string name="add_to_home_screen_dialog_add_button">Add</string>
<string name="add_to_home_screen_dialog_error_empty">The name cannot be empty</string>
<string name="add_to_home_screen_shortcut_added">Shortcut added to Home screen</string>

</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ package eu.opencloud.android.domain.files.model

enum class FileMenuOption {
SELECT_ALL, SELECT_INVERSE, DOWNLOAD, RENAME, MOVE, COPY, REMOVE, OPEN_WITH,
SYNC, CANCEL_SYNC, SHARE, DETAILS, SEND, SET_AV_OFFLINE, UNSET_AV_OFFLINE;
SYNC, CANCEL_SYNC, SHARE, DETAILS, SEND, SET_AV_OFFLINE, UNSET_AV_OFFLINE,
ADD_TO_HOME_SCREEN;
}
Loading