Skip to content

Commit 1e6d108

Browse files
committed
fix: bottombar highlight on snackbar action
1 parent ff6802d commit 1e6d108

9 files changed

Lines changed: 116 additions & 15 deletions

File tree

changelog/unreleased/4802

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Enhancement: Show destination folder snackbar for copy/move operations
2+
3+
A snackbar message has been displayed after copy or move operations with an action button that allows users to quickly navigate to the destination folder.
4+
5+
https://github.com/owncloud/android/issues/4379
6+
https://github.com/owncloud/android/pull/4802

owncloudApp/src/main/java/com/owncloud/android/extensions/ActivityExt.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ fun Activity.showMessageInSnackbar(
9090
Snackbar.make(findViewById(layoutId), message, duration).show()
9191
}
9292

93+
fun Activity.showSnackbarWithAction(
94+
message: CharSequence,
95+
actionText: CharSequence,
96+
action: () -> Unit,
97+
duration: Int = Snackbar.LENGTH_LONG,
98+
layoutId: Int = android.R.id.content
99+
) {
100+
Snackbar.make(findViewById(layoutId), message, duration)
101+
.setAction(actionText) { action() }
102+
.show()
103+
}
104+
93105
fun Activity.showErrorInToast(
94106
genericErrorMessageId: Int,
95107
throwable: Throwable?,

owncloudApp/src/main/java/com/owncloud/android/extensions/FragmentExt.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ fun Fragment.showMessageInSnackbar(
5151
Snackbar.make(requiredView, message, duration).show()
5252
}
5353

54+
fun Fragment.showSnackbarWithAction(
55+
message: CharSequence,
56+
actionText: CharSequence,
57+
action: () -> Unit,
58+
duration: Int = Snackbar.LENGTH_LONG
59+
) {
60+
val requiredView = view ?: return
61+
Snackbar.make(requiredView, message, duration)
62+
.setAction(actionText) { action() }
63+
.show()
64+
}
65+
5466
fun Fragment.showAlertDialog(
5567
title: String,
5668
message: String,

owncloudApp/src/main/java/com/owncloud/android/presentation/files/details/FileDetailsFragment.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import com.owncloud.android.extensions.openOCFile
5757
import com.owncloud.android.extensions.sendDownloadedFilesByShareSheet
5858
import com.owncloud.android.extensions.showErrorInSnackbar
5959
import com.owncloud.android.extensions.showMessageInSnackbar
60+
import com.owncloud.android.extensions.showSnackbarWithAction
6061
import com.owncloud.android.presentation.authentication.ACTION_UPDATE_EXPIRED_TOKEN
6162
import com.owncloud.android.presentation.authentication.EXTRA_ACCOUNT
6263
import com.owncloud.android.presentation.authentication.EXTRA_ACTION
@@ -163,16 +164,19 @@ class FileDetailsFragment : FileFragment() {
163164
when (uiResult) {
164165
is UIResult.Error -> {
165166
if (uiResult.error is AccountNotFoundException) {
166-
Snackbar.make(view, getString(R.string.sync_fail_ticker_unauthorized), Snackbar.LENGTH_INDEFINITE)
167-
.setAction(R.string.auth_oauth_failure_snackbar_action) {
167+
showSnackbarWithAction(
168+
message = getString(R.string.sync_fail_ticker_unauthorized),
169+
actionText = getString(R.string.auth_oauth_failure_snackbar_action),
170+
action = {
168171
val updateAccountCredentials = Intent(requireActivity(), LoginActivity::class.java)
169172
updateAccountCredentials.apply {
170173
putExtra(EXTRA_ACCOUNT, fileDetailsViewModel.getAccount())
171174
putExtra(EXTRA_ACTION, ACTION_UPDATE_EXPIRED_TOKEN)
172175
addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
173176
}
174177
startActivity(updateAccountCredentials)
175-
}.show()
178+
},
179+
duration = Snackbar.LENGTH_INDEFINITE)
176180
} else {
177181
showErrorInSnackbar(R.string.sync_fail_ticker, uiResult.error)
178182
fileDetailsViewModel.updateActionInDetailsView(NONE)

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ class FileListAdapter(
288288
params -> params.marginStart = if (isFolderInKw) 0 else
289289
context.resources.getDimensionPixelSize(R.dimen.standard_quarter_margin) }
290290
it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
291-
it.threeDotMenu.isVisible = getCheckedItems().isEmpty()
291+
it.threeDotMenu.isVisible = !isPickerMode && getCheckedItems().isEmpty()
292292
it.threeDotMenu.contentDescription = context.getString(R.string.content_description_file_operations, file.fileName)
293293
if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) {
294294
it.spacePathLine.path.apply {

owncloudApp/src/main/java/com/owncloud/android/presentation/releasenotes/ReleaseNotesViewModel.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ class ReleaseNotesViewModel(
6363
subtitle = R.string.release_notes_4_8_0_subtitle_spaces_permanent_links,
6464
type = ReleaseNoteType.ENHANCEMENT
6565
),
66+
ReleaseNote(
67+
title = R.string.release_notes_4_8_0_title_action_to_copy_or_move_destination_folder,
68+
subtitle = R.string.release_notes_4_8_0_subtitle_action_to_copy_or_move_destination_folder,
69+
type = ReleaseNoteType.ENHANCEMENT
70+
),
6671
ReleaseNote(
6772
title = R.string.release_notes_bugfixes_title,
6873
subtitle = R.string.release_notes_bugfixes_subtitle,

owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileActivity.java

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,11 @@
5858
import com.owncloud.android.ui.dialog.SslUntrustedCertDialog;
5959
import com.owncloud.android.ui.errorhandling.ErrorMessageAdapter;
6060
import com.owncloud.android.ui.helpers.FileOperationsHelper;
61+
import kotlin.Unit;
6162
import timber.log.Timber;
6263

64+
import static com.owncloud.android.extensions.ActivityExtKt.showSnackbarWithAction;
65+
6366
/**
6467
* Activity with common behaviour for activities handling {@link OCFile}s in ownCloud {@link Account}s .
6568
*/
@@ -278,18 +281,32 @@ protected void showRequestAccountChangeNotice(String errorMessage, boolean mustC
278281
.setCancelable(false)
279282
.show();
280283
} else {
281-
Snackbar.make(findViewById(android.R.id.content), errorMessage, Snackbar.LENGTH_INDEFINITE)
282-
.setAction(R.string.auth_oauth_failure_snackbar_action, v ->
283-
requestCredentialsUpdate())
284-
.show();
284+
showSnackbarWithAction(
285+
this,
286+
errorMessage,
287+
getString(R.string.auth_oauth_failure_snackbar_action),
288+
() -> {
289+
requestCredentialsUpdate();
290+
return Unit.INSTANCE;
291+
},
292+
Snackbar.LENGTH_INDEFINITE,
293+
android.R.id.content
294+
);
285295
}
286296
}
287297

288298
protected void showRequestRegainAccess() {
289-
Snackbar.make(findViewById(android.R.id.content), R.string.auth_oauth_failure, Snackbar.LENGTH_INDEFINITE)
290-
.setAction(R.string.auth_oauth_failure_snackbar_action, v ->
291-
requestCredentialsUpdate())
292-
.show();
299+
showSnackbarWithAction(
300+
this,
301+
getString(R.string.auth_oauth_failure),
302+
getString(R.string.auth_oauth_failure_snackbar_action),
303+
() -> {
304+
requestCredentialsUpdate();
305+
return Unit.INSTANCE;
306+
},
307+
Snackbar.LENGTH_INDEFINITE,
308+
android.R.id.content
309+
);
293310
}
294311

295312
/**

owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ import com.owncloud.android.extensions.parseError
8484
import com.owncloud.android.extensions.sendDownloadedFilesByShareSheet
8585
import com.owncloud.android.extensions.showErrorInSnackbar
8686
import com.owncloud.android.extensions.showMessageInSnackbar
87+
import com.owncloud.android.extensions.showSnackbarWithAction
8788
import com.owncloud.android.lib.common.accounts.AccountUtils
8889
import com.owncloud.android.lib.common.authentication.OwnCloudBearerCredentials
8990
import com.owncloud.android.lib.common.network.CertificateCombinedException
@@ -181,6 +182,8 @@ class FileDisplayActivity : FileActivity(),
181182
private var waitingToSend: OCFile? = null
182183
private var waitingToOpen: OCFile? = null
183184

185+
private var copyMoveTargetFolder: OCFile? = null
186+
184187
private var localBroadcastManager: LocalBroadcastManager? = null
185188

186189
private val fileOperationsViewModel: FileOperationsViewModel by viewModel()
@@ -707,6 +710,7 @@ class FileDisplayActivity : FileActivity(),
707710
private fun requestMoveOperation(data: Intent) {
708711
val folderToMoveAt = data.getParcelableExtra<OCFile>(FolderPickerActivity.EXTRA_FOLDER) ?: return
709712
val files = data.getParcelableArrayListExtra<OCFile>(FolderPickerActivity.EXTRA_FILES) ?: return
713+
copyMoveTargetFolder = folderToMoveAt
710714
val moveOperation = FileOperation.MoveOperation(
711715
listOfFilesToMove = files.toList(),
712716
targetFolder = folderToMoveAt,
@@ -723,6 +727,7 @@ class FileDisplayActivity : FileActivity(),
723727
private fun requestCopyOperation(data: Intent) {
724728
val folderToCopyAt = data.getParcelableExtra<OCFile>(FolderPickerActivity.EXTRA_FOLDER) ?: return
725729
val files = data.getParcelableArrayListExtra<OCFile>(FolderPickerActivity.EXTRA_FILES) ?: return
730+
copyMoveTargetFolder = folderToCopyAt
726731
val copyOperation = FileOperation.CopyOperation(
727732
listOfFilesToCopy = files.toList(),
728733
targetFolder = folderToCopyAt,
@@ -808,12 +813,10 @@ class FileDisplayActivity : FileActivity(),
808813
Timber.v("onResume() start")
809814
super.onResume()
810815

816+
updateBottombar(mainFileListFragment?.getCurrentSpace())
811817
if (mainFileListFragment?.getCurrentSpace()?.isProject == true ||
812818
(mainFileListFragment?.getCurrentSpace()?.isPersonal == true && isMultiPersonal)) {
813-
setCheckedItemAtBottomBar(getMenuItemForFileListOption(FileListOption.SPACES_LIST))
814819
updateToolbar(null, mainFileListFragment?.getCurrentSpace())
815-
} else {
816-
setCheckedItemAtBottomBar(getMenuItemForFileListOption(fileListOption))
817820
}
818821

819822
if (secondFragment == null) {
@@ -1082,6 +1085,9 @@ class FileDisplayActivity : FileActivity(),
10821085
// Refresh the spaces and update the quota
10831086
spacesListViewModel.refreshSpacesFromServer()
10841087
}
1088+
if (uiResult.data.isNullOrEmpty()) {
1089+
showCopyMoveSuccessSnackbar(isCopy = false)
1090+
}
10851091
}
10861092

10871093
is UIResult.Error -> {
@@ -1130,6 +1136,9 @@ class FileDisplayActivity : FileActivity(),
11301136

11311137
// Refresh the spaces and update the quota
11321138
spacesListViewModel.refreshSpacesFromServer()
1139+
if (uiResult.data.isNullOrEmpty()) {
1140+
showCopyMoveSuccessSnackbar(isCopy = true)
1141+
}
11331142
}
11341143

11351144
is UIResult.Error -> {
@@ -1148,6 +1157,25 @@ class FileDisplayActivity : FileActivity(),
11481157
}
11491158
}
11501159

1160+
private fun showCopyMoveSuccessSnackbar(isCopy: Boolean) {
1161+
val message = getString(if (isCopy) R.string.copy_file_correctly else R.string.move_file_correctly)
1162+
val targetFolderId = copyMoveTargetFolder?.id
1163+
if (targetFolderId != null) {
1164+
showSnackbarWithAction(
1165+
message = message,
1166+
actionText = getString(R.string.go_to_destination_folder),
1167+
action = {
1168+
val fileListFragment = mainFileListFragment
1169+
?: supportFragmentManager.findFragmentById(R.id.left_fragment_container) as? MainFileListFragment
1170+
fileListFragment?.navigateToFolderId(targetFolderId)
1171+
},
1172+
layoutId = R.id.list_layout
1173+
)
1174+
} else {
1175+
showMessageInSnackbar(R.id.list_layout, message)
1176+
}
1177+
}
1178+
11511179
private fun showConflictDecisionDialog(
11521180
uiResult: UIResult.Success<List<OCFile>>,
11531181
data: List<OCFile>,
@@ -1863,9 +1891,20 @@ class FileDisplayActivity : FileActivity(),
18631891

18641892
override fun onCurrentFolderUpdated(newCurrentFolder: OCFile, currentSpace: OCSpace?) {
18651893
updateToolbar(newCurrentFolder, currentSpace)
1894+
val newCurrentFolderSpace = spacesListViewModel.spacesList.value.spaces.find { it.id == newCurrentFolder.spaceId }
1895+
updateBottombar(newCurrentFolderSpace)
18661896
file = newCurrentFolder
18671897
}
18681898

1899+
private fun updateBottombar(currentSpace: OCSpace?) {
1900+
val bottomBarOption = if (currentSpace?.isProject == true) {
1901+
FileListOption.SPACES_LIST
1902+
} else {
1903+
fileListOption
1904+
}
1905+
setCheckedItemAtBottomBar(getMenuItemForFileListOption(bottomBarOption))
1906+
}
1907+
18691908
override fun onFileClicked(file: OCFile) {
18701909
when {
18711910
PreviewImageFragment.canBePreviewed(file) -> {

owncloudApp/src/main/res/values/strings.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,14 +543,18 @@
543543
<string name="move_file_invalid_into_descendent">It is not possible to move a folder into a descendant.</string>
544544
<string name="move_file_invalid_overwrite">The file exists already in the destination folder.</string>
545545
<string name="move_file_error">An error occurred while trying to move this file or folder.</string>
546+
<string name="move_file_correctly">File moved correctly</string>
546547
<string name="forbidden_permissions_move">to move this file</string>
547548

548549
<string name="copy_file_not_found">Unable to copy. Please check whether the file exists.</string>
549550
<string name="copy_file_invalid_into_descendent">It is not possible to copy a folder into a descendant.</string>
550551
<string name="copy_file_invalid_overwrite">The file exists already in the destination folder.</string>
551552
<string name="copy_file_error">An error occurred while trying to copy this file or folder.</string>
553+
<string name="copy_file_correctly">File copied correctly</string>
552554
<string name="forbidden_permissions_copy">to copy this file</string>
553555

556+
<string name="go_to_destination_folder">Open Folder</string>
557+
554558
<string name="prefs_category_camera_upload">Camera uploads</string>
555559

556560
<string name="sync_folder_failed_content">Synchronization of %1$s folder could not be completed</string>
@@ -747,6 +751,8 @@
747751
<string name="release_notes_4_8_0_subtitle_spaces_permanent_links">Infinite Scale users can now get a permanent link for a space and share it with other members</string>
748752
<string name="release_notes_4_8_0_title_space_public_links">Space public links</string>
749753
<string name="release_notes_4_8_0_subtitle_space_public_links">Infinite Scale users can see all public links of a space and manage them with right permissions</string>
754+
<string name="release_notes_4_8_0_title_action_to_copy_or_move_destination_folder">Navigation to target folder</string>
755+
<string name="release_notes_4_8_0_subtitle_action_to_copy_or_move_destination_folder">New action to navigate to the destination folder when a file or folder is copied or moved</string>
750756

751757
<!-- Open in web -->
752758
<string name="ic_action_open_in_web">Open in web</string>

0 commit comments

Comments
 (0)