Skip to content

Commit

Permalink
Updated empty state view icons for light and dark mode with test cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
surinder-tsys committed Aug 16, 2024
1 parent 15b3380 commit e2077fc
Show file tree
Hide file tree
Showing 34 changed files with 540 additions and 55 deletions.
186 changes: 186 additions & 0 deletions app/src/androidTest/java/com/nmc/android/ui/EmptyStateViewIT.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package com.nmc.android.ui

import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.nextcloud.test.TestActivity
import com.owncloud.android.AbstractIT
import com.owncloud.android.R
import com.owncloud.android.lib.resources.notifications.models.Notification
import com.owncloud.android.ui.activity.FolderPickerActivity
import com.owncloud.android.ui.activity.NotificationsActivity
import com.owncloud.android.ui.activity.ReceiveExternalFilesActivity
import com.owncloud.android.ui.activity.UploadListActivity
import com.owncloud.android.ui.fragment.GalleryFragment
import com.owncloud.android.ui.fragment.OCFileListFragment
import com.owncloud.android.ui.fragment.SearchType
import com.owncloud.android.ui.trashbin.TrashbinActivity
import org.junit.Rule
import org.junit.Test

/**
* test to validate empty state on different screens
*/
class EmptyStateViewIT : AbstractIT() {

@get:Rule
val testActivityRule = ActivityScenarioRule(TestActivity::class.java)

@Test
fun validate_emptyState_NoSearch() {
loadOCFileListFragmentWithSearchType(SearchType.NO_SEARCH)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No files here")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Upload some content or sync with your devices.")))
}

@Test
fun validate_emptyState_FileSearch() {
loadOCFileListFragmentWithSearchType(SearchType.FILE_SEARCH)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No results")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Search for a file (at least 2 characters)")))
}

@Test
fun validate_emptyState_FavoriteSearch() {
loadOCFileListFragmentWithSearchType(SearchType.FAVORITE_SEARCH)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("Nothing favorited yet")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Files and folders you mark as favorites will show up here.")))
}

@Test
fun validate_emptyState_RecentSearch() {
loadOCFileListFragmentWithSearchType(SearchType.RECENTLY_MODIFIED_SEARCH)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No results")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Found no files modified within the last 7 days")))
}

@Test
fun validate_emptyState_SharedSearch() {
loadOCFileListFragmentWithSearchType(SearchType.SHARED_FILTER)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("Nothing shared yet")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Files and folders you share will show up here.")))
}

@Test
fun validate_emptyState_GallerySearch() {
loadGalleryFragment()
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No files here")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("No photos or videos uploaded yet")))
}

@Test
fun validate_emptyState_Notification() {
val activityScenario = ActivityScenario.launch(NotificationsActivity::class.java)
waitForIdleSync()
activityScenario.onActivity {
it.runOnUiThread { it.populateList(ArrayList<Notification>()) }
}

onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No notifications")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Please check back later.")))
}

@Test
fun validate_errorState_Trashbin() {
ActivityScenario.launch(TrashbinActivity::class.java)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("Error")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Loading trash bin failed!")))
}

@Test
fun validate_emptyState_Trashbin() {
val activityScenario = ActivityScenario.launch(TrashbinActivity::class.java)
activityScenario.onActivity {
it.showTrashbinFolder(emptyList())
}
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No deleted files")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("You will be able to recover deleted files from here.")))
}

@Test
fun validate_emptyState_FolderPicker() {
ActivityScenario.launch(FolderPickerActivity::class.java)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No files here")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Upload some content or sync with your devices.")))
}

@Test
fun validate_emptyState_ReceivedExternalFiles() {
ActivityScenario.launch(ReceiveExternalFilesActivity::class.java)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No files here")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("")))
}

@Test
fun validate_emptyState_UploadList() {
ActivityScenario.launch(UploadListActivity::class.java)
onView(withId(R.id.empty_list_icon)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_headline)).check(matches(withText("No uploads available")))
onView(withId(R.id.empty_list_view_text)).check(matches(isCompletelyDisplayed()))
onView(withId(R.id.empty_list_view_text)).check(matches(withText("Upload some content or activate auto upload.")))
}

private fun loadOCFileListFragmentWithSearchType(searchType: SearchType) {
testActivityRule.scenario.onActivity {
it.addFragment(OCFileListFragment())
}

waitForIdleSync()

testActivityRule.scenario.onActivity {
val fragment = (it.fragment as OCFileListFragment)
fragment.setEmptyListMessage(searchType)
}
}

private fun loadGalleryFragment() {
testActivityRule.scenario.onActivity {
it.addFragment(GalleryFragment())
}

waitForIdleSync()

testActivityRule.scenario.onActivity {
val fragment = (it.fragment as GalleryFragment)
fragment.setEmptyListMessage(SearchType.GALLERY_SEARCH)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ open class FolderPickerActivity :
it.setMessageForEmptyList(
R.string.folder_list_empty_headline,
R.string.file_list_empty_moving,
R.drawable.ic_list_empty_create_folder,
R.drawable.ic_list_empty_folder,
true
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class NotificationsActivity : DrawerActivity(), NotificationsContract.View {
* sets up the UI elements and loads all notification items.
*/
private fun setupContent() {
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_notification)
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_list_empty_notification)
setLoadingMessageEmpty()
val layoutManager = LinearLayoutManager(this)
binding.list.layoutManager = layoutManager
Expand Down Expand Up @@ -298,7 +298,7 @@ class NotificationsActivity : DrawerActivity(), NotificationsContract.View {
binding.emptyList.emptyListView.visibility = View.VISIBLE
binding.emptyList.emptyListViewHeadline.text = headline
binding.emptyList.emptyListViewText.text = message
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_notification)
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_list_empty_notification)
binding.emptyList.emptyListViewText.visibility = View.VISIBLE
binding.emptyList.emptyListIcon.visibility = View.VISIBLE
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ private void populateDirectoryList() {

if (files.isEmpty()) {
setMessageForEmptyList(R.string.file_list_empty_headline, R.string.empty,
R.drawable.uploads);
R.drawable.ic_list_empty_uploads);
mEmptyListContainer.setVisibility(View.VISIBLE);
binding.list.setVisibility(View.GONE);
} else {
Expand Down Expand Up @@ -799,7 +799,7 @@ public void setMessageForEmptyList(@StringRes final int headline, @StringRes fin
if (mEmptyListContainer != null && mEmptyListMessage != null) {
mEmptyListHeadline.setText(headline);
mEmptyListMessage.setText(message);
mEmptyListIcon.setImageDrawable(viewThemeUtils.platform.tintPrimaryDrawable(this, icon));
mEmptyListIcon.setImageResource(icon);
mEmptyListIcon.setVisibility(View.VISIBLE);
mEmptyListMessage.setVisibility(View.VISIBLE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ class SyncedFoldersActivity :
binding.list.layoutManager = lm
binding.list.adapter = adapter
load(getItemsDisplayedPerFolder(), false)
//NMC customization
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_list_empty_synced_folders)
}

private fun showHiddenItems() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,7 @@ private void handleUploadWorkerState() {
private void setupContent() {
binding.list.setEmptyView(binding.emptyList.getRoot());
binding.emptyList.getRoot().setVisibility(View.GONE);
binding.emptyList.emptyListIcon.setImageResource(R.drawable.uploads);
binding.emptyList.emptyListIcon.getDrawable().mutate();
binding.emptyList.emptyListIcon.setAlpha(0.5f);
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_list_empty_uploads);
binding.emptyList.emptyListIcon.setVisibility(View.VISIBLE);
binding.emptyList.emptyListViewHeadline.setText(getString(R.string.upload_list_empty_headline));
binding.emptyList.emptyListViewText.setText(getString(R.string.upload_list_empty_text_auto_upload));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,16 +585,8 @@ public void run() {
if (mEmptyListContainer != null && mEmptyListMessage != null) {
mEmptyListHeadline.setText(headline);
mEmptyListMessage.setText(message);

if (tintIcon) {
if (getContext() != null) {
mEmptyListIcon.setImageDrawable(
viewThemeUtils.platform.tintPrimaryDrawable(getContext(), icon));
}
} else {
mEmptyListIcon.setImageResource(icon);
}

//tinting is not required in NMC
mEmptyListIcon.setImageResource(icon);
mEmptyListIcon.setVisibility(View.VISIBLE);
mEmptyListMessage.setVisibility(View.VISIBLE);
}
Expand All @@ -614,8 +606,8 @@ public void run() {
true);
} else if (searchType == SearchType.FILE_SEARCH) {
setMessageForEmptyList(R.string.file_list_empty_headline_server_search,
R.string.file_list_empty,
R.drawable.ic_search_light_grey);
R.string.search_result_empty,
R.drawable.ic_search_empty);
} else if (searchType == SearchType.FAVORITE_SEARCH) {
setMessageForEmptyList(R.string.file_list_empty_favorite_headline,
R.string.file_list_empty_favorites_filter_list,
Expand All @@ -627,15 +619,15 @@ public void run() {
} else if (searchType == SearchType.REGULAR_FILTER) {
setMessageForEmptyList(R.string.file_list_empty_headline_search,
R.string.file_list_empty_search,
R.drawable.ic_search_light_grey);
R.drawable.ic_search_empty);
} else if (searchType == SearchType.SHARED_FILTER) {
setMessageForEmptyList(R.string.file_list_empty_shared_headline,
R.string.file_list_empty_shared,
R.drawable.ic_list_empty_shared);
} else if (searchType == SearchType.GALLERY_SEARCH) {
setMessageForEmptyList(R.string.file_list_empty_headline_server_search,
R.string.file_list_empty_gallery,
R.drawable.file_image);
setMessageForEmptyList(R.string.file_list_empty_headline,
R.string.gallery_list_empty,
R.drawable.ic_list_empty_media);
} else if (searchType == SearchType.LOCAL_SEARCH) {
setMessageForEmptyList(R.string.file_list_empty_headline_server_search,
R.string.file_list_empty_local_search,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,8 @@ class UnifiedSearchFragment :
requireContext().getString(R.string.file_list_empty_headline_server_search)
binding.emptyList.emptyListViewText.text =
requireContext().getString(R.string.file_list_empty_unified_search_no_results)
binding.emptyList.emptyListIcon.setImageDrawable(
viewThemeUtils.platform.tintDrawable(requireContext(), R.drawable.ic_search_grey)
)
//NMC Customization
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_search_empty)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class TrashbinActivity :
recyclerView.setEmptyView(binding.emptyList.emptyListView)

binding.emptyList.emptyListView.visibility = View.GONE
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete)
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_list_empty_trashbin)
binding.emptyList.emptyListIcon.visibility = View.VISIBLE
binding.emptyList.emptyListViewHeadline.text = getString(R.string.trashbin_empty_headline)
binding.emptyList.emptyListViewText.text = getString(R.string.trashbin_empty_message)
Expand Down Expand Up @@ -258,7 +258,7 @@ class TrashbinActivity :
trashbinListAdapter?.setTrashbinFiles(trashbinFiles, true)
binding.swipeContainingList.isRefreshing = false
binding.loadingContent.visibility = View.GONE
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_delete)
binding.emptyList.emptyListIcon.setImageResource(R.drawable.ic_list_empty_trashbin)
binding.emptyList.emptyListViewHeadline.text = getString(R.string.trashbin_empty_headline)
binding.emptyList.emptyListViewText.text = getString(R.string.trashbin_empty_message)
binding.list.visibility = View.VISIBLE
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/res/drawable-night/ic_list_empty_error.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="@color/empty_list_icon_color_dark"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,1C5.9249,1 1,5.9249 1,12C1,18.0751 5.9249,23 12,23C18.0751,23 23,18.0751 23,12C23,9.0826 21.8411,6.2847 19.7782,4.2218C17.7153,2.1589 14.9174,1 12,1ZM11,6.75L13,6.75L13,13.25L11,13.25L11,6.75ZM12,17.25C11.3096,17.25 10.75,16.6904 10.75,16C10.75,15.3096 11.3096,14.75 12,14.75C12.6904,14.75 13.25,15.3096 13.25,16C13.25,16.6904 12.6904,17.25 12,17.25L12,17.25Z"
android:strokeWidth="1"
android:fillColor="#262626"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</vector>
Loading

0 comments on commit e2077fc

Please sign in to comment.