diff --git a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt index bc03d32f8f..6422b0efa7 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt @@ -163,6 +163,7 @@ class FileUploadWorker( return Result.success() } + @Suppress("NestedBlockDepth") private fun uploadFiles(totalUploadSize: Int, uploadsPerPage: List, accountName: String) { val user = userAccountManager.getUser(accountName) setWorkerState(user.get(), uploadsPerPage) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index 98658dbf06..5caee6ea36 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -46,6 +46,7 @@ import com.bumptech.glide.load.model.StreamEncoder; import com.bumptech.glide.load.resource.file.FileToStreamDecoder; import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.target.SimpleTarget; +import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.button.MaterialButton; import com.google.android.material.navigation.NavigationView; import com.google.android.material.progressindicator.LinearProgressIndicator; @@ -123,6 +124,7 @@ import androidx.core.content.res.ResourcesCompat; import androidx.core.view.GravityCompat; import androidx.drawerlayout.widget.DrawerLayout; import androidx.fragment.app.Fragment; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hct.Hct; import static com.nextcloud.utils.extensions.DrawerActivityExtensionsKt.getMenuItemIdFromTitle; @@ -155,7 +157,7 @@ public abstract class DrawerActivity extends ToolbarActivity /** * Reference to the navigation view. */ - private NavigationView mNavigationView; + private NavigationView drawerNavigationView; /** * Reference to the navigation view header. @@ -196,6 +198,8 @@ public abstract class DrawerActivity extends ToolbarActivity private ExternalLinksProvider externalLinksProvider; private ArbitraryDataProvider arbitraryDataProvider; + private BottomNavigationView bottomNavigationView; + @Inject AppPreferences preferences; @@ -208,14 +212,14 @@ public abstract class DrawerActivity extends ToolbarActivity protected void setupDrawer() { mDrawerLayout = findViewById(R.id.drawer_layout); - mNavigationView = findViewById(R.id.nav_view); - if (mNavigationView != null) { + drawerNavigationView = findViewById(R.id.nav_view); + if (drawerNavigationView != null) { // Setting up drawer header - mNavigationViewHeader = mNavigationView.getHeaderView(0); + mNavigationViewHeader = drawerNavigationView.getHeaderView(0); updateHeader(); - setupDrawerMenu(mNavigationView); + setupDrawerMenu(drawerNavigationView); getAndDisplayUserQuota(); setupQuotaElement(); } @@ -225,6 +229,56 @@ public abstract class DrawerActivity extends ToolbarActivity if (getSupportActionBar() != null) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); } + + bottomNavigationView = findViewById(R.id.bottom_navigation); + if (bottomNavigationView != null) { + themeBottomNavigationMenu(); + checkAssistantBottomNavigationMenu(); + handleBottomNavigationViewClicks(); + } + } + + private void themeBottomNavigationMenu() { + viewThemeUtils.platform.colorBottomNavigationView(bottomNavigationView); + } + + @SuppressFBWarnings("RV") + private void checkAssistantBottomNavigationMenu() { + boolean isAssistantAvailable = getCapabilities().getAssistant().isTrue(); + + bottomNavigationView + .getMenu() + .findItem(R.id.nav_assistant) + .setVisible(isAssistantAvailable); + } + + @SuppressFBWarnings("RV") + private void handleBottomNavigationViewClicks() { + bottomNavigationView.setOnItemSelectedListener(menuItem -> { + menuItemId = menuItem.getItemId(); + + if (menuItemId == R.id.nav_all_files) { + showFiles(false,false); + if (this instanceof FileDisplayActivity fda) { + fda.browseToRoot(); + } + } else if (menuItemId == R.id.nav_favorites) { + handleSearchEvents(new SearchEvent("", SearchRemoteOperation.SearchType.FAVORITE_SEARCH), menuItemId); + } else if (menuItemId == R.id.nav_assistant) { + startComposeActivity(ComposeDestination.AssistantScreen, R.string.assistant_screen_top_bar_title); + } else if (menuItemId == R.id.nav_gallery) { + startPhotoSearch(menuItem.getItemId()); + } + + // Remove extra icon from the action bar + if (getSupportActionBar() != null) { + getSupportActionBar().setIcon(null); + } + + setNavigationViewItemChecked(); + + return false; + }); } /** @@ -242,7 +296,7 @@ public abstract class DrawerActivity extends ToolbarActivity if (menuItemIdFromTitle != null && menuItemIdFromTitle != menuItemId) { menuItemId = menuItemIdFromTitle; } - setDrawerMenuItemChecked(); + setNavigationViewItemChecked(); isMenuItemChecked = true; } } @@ -500,7 +554,7 @@ public abstract class DrawerActivity extends ToolbarActivity private void onNavigationItemClicked(final MenuItem menuItem) { int itemId = menuItem.getItemId(); menuItemId = itemId; - setDrawerMenuItemChecked(); + setNavigationViewItemChecked(); if (itemId == R.id.nav_all_files || itemId == R.id.nav_personal_files) { if (this instanceof FileDisplayActivity && @@ -809,9 +863,9 @@ public abstract class DrawerActivity extends ToolbarActivity } private void unsetAllDrawerMenuItems() { - if (mNavigationView != null) { - mNavigationView.getMenu(); - Menu menu = mNavigationView.getMenu(); + if (drawerNavigationView != null) { + drawerNavigationView.getMenu(); + Menu menu = drawerNavigationView.getMenu(); for (int i = 0; i < menu.size(); i++) { menu.getItem(i).setChecked(false); } @@ -879,29 +933,29 @@ public abstract class DrawerActivity extends ToolbarActivity } /** - * checks/highlights the provided menu item if the drawer has been initialized and the menu item exists. - * + * Sets the menu item as checked in both the drawer and bottom navigation views, if applicable. */ - public void setDrawerMenuItemChecked() { - if (mNavigationView == null) { - return; + @SuppressFBWarnings("RV") + public void setNavigationViewItemChecked() { + if (drawerNavigationView != null) { + MenuItem menuItem = drawerNavigationView.getMenu().findItem(menuItemId); + + if (menuItem != null && !menuItem.isChecked()) { + viewThemeUtils.platform.colorNavigationView(drawerNavigationView); + menuItem.setChecked(true); + } } - MenuItem menuItem = mNavigationView.getMenu().findItem(menuItemId); + if (bottomNavigationView != null) { + MenuItem menuItem = bottomNavigationView.getMenu().findItem(menuItemId); - if (menuItem == null) { - Log_OC.w(TAG, "setDrawerMenuItemChecked has been called with invalid menu-item-ID"); - return; - } - - if (menuItem.isChecked()) { - return; + // Don't highlight assistant bottom navigation item because Assistant screen doesn't have bottom navigation bar + if (menuItem != null && !menuItem.isChecked() && menuItem.getItemId() != R.id.nav_assistant) { + menuItem.setChecked(true); + } } Log_OC.d(TAG, "New menu item is: " + menuItemId); - - viewThemeUtils.platform.colorNavigationView(mNavigationView); - menuItem.setChecked(true); } /** @@ -971,14 +1025,14 @@ public abstract class DrawerActivity extends ToolbarActivity } private void updateExternalLinksInDrawer() { - if (mNavigationView != null && MDMConfig.INSTANCE.externalSiteSupport(this)) { - mNavigationView.getMenu().removeGroup(R.id.drawer_menu_external_links); + if (drawerNavigationView != null && MDMConfig.INSTANCE.externalSiteSupport(this)) { + drawerNavigationView.getMenu().removeGroup(R.id.drawer_menu_external_links); int greyColor = ContextCompat.getColor(this, R.color.drawer_menu_icon); for (final ExternalLink link : externalLinksProvider.getExternalLink(ExternalLinkType.LINK)) { - int id = mNavigationView.getMenu().add(R.id.drawer_menu_external_links, - MENU_ITEM_EXTERNAL_LINK + link.getId(), MENU_ORDER_EXTERNAL_LINKS, link.getName()) + int id = drawerNavigationView.getMenu().add(R.id.drawer_menu_external_links, + MENU_ITEM_EXTERNAL_LINK + link.getId(), MENU_ORDER_EXTERNAL_LINKS, link.getName()) .setCheckable(true).getItemId(); MenuSimpleTarget target = new MenuSimpleTarget(id) { @@ -1005,7 +1059,7 @@ public abstract class DrawerActivity extends ToolbarActivity } private void setExternalLinkIcon(int id, Drawable drawable, int greyColor) { - MenuItem menuItem = mNavigationView.getMenu().findItem(id); + MenuItem menuItem = drawerNavigationView.getMenu().findItem(id); if (menuItem != null) { if (drawable != null) { @@ -1037,7 +1091,7 @@ public abstract class DrawerActivity extends ToolbarActivity public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mIsAccountChooserActive = savedInstanceState.getBoolean(KEY_IS_ACCOUNT_CHOOSER_ACTIVE, false); - setDrawerMenuItemChecked(); + setNavigationViewItemChecked(); } @Override @@ -1312,10 +1366,10 @@ public abstract class DrawerActivity extends ToolbarActivity } private void handleNavItemClickEvent(@IdRes int menuItemId) { - if (mNavigationView == null) { - mNavigationView = findViewById(R.id.nav_view); + if (drawerNavigationView == null) { + drawerNavigationView = findViewById(R.id.nav_view); } - Menu navMenu = mNavigationView.getMenu(); + Menu navMenu = drawerNavigationView.getMenu(); onNavigationItemClicked(navMenu.findItem(menuItemId)); } } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index 955e3e8769..1fa32f5e33 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -1249,7 +1249,7 @@ public class FileDisplayActivity extends FileActivity menuItemId = R.id.nav_all_files; } - setDrawerMenuItemChecked(); + setNavigationViewItemChecked(); if (MainApp.isOnlyOnDevice()) { setupToolbar(); diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index 812974d980..7e4be1179a 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -1839,7 +1839,10 @@ public class OCFileListFragment extends ExtendedListFragment implements // avoid calling api multiple times if async task is already executing if (remoteOperationAsyncTask != null && remoteOperationAsyncTask.getStatus() != AsyncTask.Status.FINISHED) { - Log_OC.d(TAG, "OCFileListSearchAsyncTask already running skipping new api call for search event: " + searchEvent.getSearchType()); + if (searchEvent != null) { + Log_OC.d(TAG, "OCFileListSearchAsyncTask already running skipping new api call for search event: " + searchEvent.getSearchType()); + } + return; } diff --git a/app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.kt b/app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.kt index aa16d47b88..ebb94da68f 100644 --- a/app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/trashbin/TrashbinActivity.kt @@ -387,6 +387,7 @@ class TrashbinActivity : } } + @Suppress("ReturnCount") private fun onFileActionChosen(@IdRes itemId: Int, checkedFiles: Set): Boolean { if (checkedFiles.isEmpty()) { return false diff --git a/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java b/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java index 7292b1400e..0591b0d0c4 100644 --- a/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java +++ b/app/src/main/java/com/owncloud/android/utils/DrawerMenuUtil.java @@ -11,7 +11,6 @@ import android.content.res.Resources; import android.view.Menu; import com.nextcloud.client.account.User; -import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.lib.resources.status.OCCapability; diff --git a/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt b/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt index 25b4ced20b..b6d09c71c2 100644 --- a/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt +++ b/app/src/main/java/com/owncloud/android/utils/EncryptionUtilsV2.kt @@ -596,7 +596,7 @@ class EncryptionUtilsV2 { } @Throws(IllegalStateException::class) - @Suppress("TooGenericExceptionCaught") + @Suppress("TooGenericExceptionCaught", "LongMethod") fun parseAnyMetadata( metadataResponse: MetadataResponse, user: User, diff --git a/app/src/main/res/layout/files.xml b/app/src/main/res/layout/files.xml index a051c8f5be..4b75f4fcdf 100644 --- a/app/src/main/res/layout/files.xml +++ b/app/src/main/res/layout/files.xml @@ -45,18 +45,26 @@ + + diff --git a/app/src/main/res/menu/bottom_navigation_menu.xml b/app/src/main/res/menu/bottom_navigation_menu.xml new file mode 100644 index 0000000000..46c128bf92 --- /dev/null +++ b/app/src/main/res/menu/bottom_navigation_menu.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/values/dims.xml b/app/src/main/res/values/dims.xml index 1d1dba647e..11d07b70af 100644 --- a/app/src/main/res/values/dims.xml +++ b/app/src/main/res/values/dims.xml @@ -34,6 +34,7 @@ 16dp 32dp 8dp + 100dp 4dp 10dp 24dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 819e221131..8081780ac3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,6 +6,12 @@ ~ SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only --> + All files + Favorites + Assistant + Media + + %1$s Android app version %1$s version %1$s, build #%2$s