Skip to content

Commit 9460813

Browse files
committed
Add documentation to LongPressMenu and simplify code
Also add 2 tests to make sure all menu buttons are the same size Also simplify some code in LongPressMenu instantiation Also make the LongPressMenuEditor appear on top of the LongPressMenu instead of closing and reopening the LongPressMenu
1 parent 3fc4bc9 commit 9460813

4 files changed

Lines changed: 237 additions & 131 deletions

File tree

app/src/androidTest/java/org/schabi/newpipe/ui/components/menu/LongPressMenuTest.kt

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.compose.runtime.getValue
66
import androidx.compose.runtime.mutableStateOf
77
import androidx.compose.runtime.saveable.rememberSaveable
88
import androidx.compose.runtime.setValue
9+
import androidx.compose.ui.geometry.Rect
910
import androidx.compose.ui.semantics.SemanticsProperties.ProgressBarRangeInfo
1011
import androidx.compose.ui.test.SemanticsMatcher
1112
import androidx.compose.ui.test.assert
@@ -130,20 +131,17 @@ class LongPressMenuTest {
130131
composeRule.onNodeWithContentDescription(R.string.long_press_menu_actions_editor)
131132
.performClick()
132133
composeRule.waitUntil {
133-
composeRule.onNodeWithText(R.string.long_press_menu_enabled_actions)
134+
composeRule.onNodeWithText(R.string.long_press_menu_enabled_actions_description)
134135
.isDisplayed()
135136
}
136137

137-
composeRule.onNodeWithContentDescription(R.string.long_press_menu_actions_editor)
138-
.assertDoesNotExist()
139138
Espresso.pressBack()
140139
composeRule.waitUntil {
141-
composeRule.onNodeWithContentDescription(R.string.long_press_menu_actions_editor)
142-
.isDisplayed()
140+
composeRule.onNodeWithText(R.string.long_press_menu_enabled_actions_description)
141+
.isNotDisplayed()
143142
}
144-
145-
composeRule.onNodeWithText(R.string.long_press_menu_enabled_actions)
146-
.assertDoesNotExist()
143+
composeRule.onNodeWithContentDescription(R.string.long_press_menu_actions_editor)
144+
.assertIsDisplayed()
147145
}
148146

149147
@Test
@@ -392,14 +390,7 @@ class LongPressMenuTest {
392390
.assertIsDisplayed()
393391
}
394392

395-
@Test
396-
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) // setDisplaySize not available on API < 24
397-
fun testHeaderSpansAllWidthIfSmallScreen() {
398-
onDevice().setDisplaySize(
399-
widthSizeClass = WidthSizeClass.COMPACT,
400-
heightSizeClass = HeightSizeClass.MEDIUM
401-
)
402-
setLongPressMenu()
393+
private fun getFirstRowAndHeaderBounds(): Pair<Rect, Rect> {
403394
val row = composeRule
404395
.onAllNodesWithTag("LongPressMenuGridRow")
405396
.onFirst()
@@ -408,32 +399,58 @@ class LongPressMenuTest {
408399
val header = composeRule.onNodeWithTag("LongPressMenuHeader")
409400
.fetchSemanticsNode()
410401
.boundsInRoot
402+
return Pair(row, header)
403+
}
404+
405+
private fun assertAllButtonsSameSize() {
406+
composeRule.onAllNodesWithTag("LongPressMenuButton")
407+
.fetchSemanticsNodes()
408+
.reduce { prev, curr ->
409+
assertInRange(prev.size.height - 1, prev.size.height + 1, curr.size.height)
410+
assertInRange(prev.size.width - 1, prev.size.width + 1, curr.size.width)
411+
return@reduce curr
412+
}
413+
}
414+
415+
@Test
416+
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) // setDisplaySize not available on API < 24
417+
fun testHeaderSpansAllWidthIfSmallScreen() {
418+
onDevice().setDisplaySize(WidthSizeClass.COMPACT, HeightSizeClass.MEDIUM)
419+
setLongPressMenu()
411420
// checks that the header is roughly as large as the row that contains it
421+
val (row, header) = getFirstRowAndHeaderBounds()
412422
assertInRange(row.left, row.left + 24.dp.value, header.left)
413423
assertInRange(row.right - 24.dp.value, row.right, header.right)
414424
}
415425

416426
@Test
417427
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) // setDisplaySize not available on API < 24
418428
fun testHeaderIsNotFullWidthIfLargeScreen() {
419-
onDevice().setDisplaySize(
420-
widthSizeClass = WidthSizeClass.EXPANDED,
421-
heightSizeClass = HeightSizeClass.MEDIUM
422-
)
429+
onDevice().setDisplaySize(WidthSizeClass.EXPANDED, HeightSizeClass.MEDIUM)
423430
setLongPressMenu()
424-
val row = composeRule
425-
.onAllNodesWithTag("LongPressMenuGridRow")
426-
.onFirst()
427-
.fetchSemanticsNode()
428-
.boundsInRoot
429-
val header = composeRule.onNodeWithTag("LongPressMenuHeader")
430-
.fetchSemanticsNode()
431-
.boundsInRoot
431+
432432
// checks that the header is definitely smaller than the row that contains it
433+
val (row, header) = getFirstRowAndHeaderBounds()
433434
assertInRange(row.left, row.left + 24.dp.value, header.left)
434435
assertNotInRange(row.right - 24.dp.value, Float.MAX_VALUE, header.right)
435436
}
436437

438+
@Test
439+
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) // setDisplaySize not available on API < 24
440+
fun testAllButtonsSameSizeSmallScreen() {
441+
onDevice().setDisplaySize(WidthSizeClass.COMPACT, HeightSizeClass.MEDIUM)
442+
setLongPressMenu()
443+
assertAllButtonsSameSize()
444+
}
445+
446+
@Test
447+
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) // setDisplaySize not available on API < 24
448+
fun testAllButtonsSameSizeLargeScreen() {
449+
onDevice().setDisplaySize(WidthSizeClass.EXPANDED, HeightSizeClass.MEDIUM)
450+
setLongPressMenu()
451+
assertAllButtonsSameSize()
452+
}
453+
437454
/**
438455
* The tests below all call this function to test, under different conditions, that the shown
439456
* actions are the intersection between the available and the enabled actions.
@@ -545,7 +562,7 @@ class LongPressMenuTest {
545562
}
546563

547564
@Test
548-
fun testFewActionsOnLargeScreenAreNotScrollable() {
565+
fun testFewActionsOnNormalScreenAreNotScrollable() {
549566
assertOnlyAndAllArrangedActionsDisplayed(
550567
availableActions = listOf(ShowDetails, ShowChannelDetails),
551568
actionArrangement = listOf(ShowDetails, ShowChannelDetails),
@@ -570,10 +587,7 @@ class LongPressMenuTest {
570587
@Test
571588
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N) // setDisplaySize not available on API < 24
572589
fun testAllActionsOnSmallScreenAreScrollable() {
573-
onDevice().setDisplaySize(
574-
widthSizeClass = WidthSizeClass.COMPACT,
575-
heightSizeClass = HeightSizeClass.COMPACT
576-
)
590+
onDevice().setDisplaySize(WidthSizeClass.COMPACT, HeightSizeClass.COMPACT)
577591
assertOnlyAndAllArrangedActionsDisplayed(
578592
availableActions = LongPressAction.Type.entries,
579593
actionArrangement = LongPressAction.Type.entries,

app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressAction.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ data class LongPressAction(
102102
val action: suspend (context: Context) -> Unit
103103
) {
104104
/**
105+
* When adding a new action, make sure to pick a unique [id] for it. Also, if the newly added
106+
* action is to be considered a default action, add it to
107+
* `LongPressMenuSettings.DefaultEnabledActions`, and create a settings migration to add it to
108+
* the user's actions (otherwise the action will be disabled by default and the user will never
109+
* find out about it).
110+
*
105111
* @param id a unique ID that allows saving and restoring a list of action types from settings.
106112
* **MUST NOT CHANGE ACROSS APP VERSIONS!**
107113
* @param label a string label to show in the action's button
@@ -138,6 +144,7 @@ data class LongPressAction(
138144
Unsubscribe(23, R.string.unsubscribe, Icons.Default.RemoveCircle),
139145
Delete(24, R.string.delete, Icons.Default.Delete),
140146
Remove(25, R.string.play_queue_remove, Icons.Default.Delete)
147+
// READ THE Type ENUM JAVADOC BEFORE ADDING OR CHANGING ACTIONS!
141148
}
142149

143150
companion object {

0 commit comments

Comments
 (0)