Various fixes (#1030)

## Description
Fixes several small issues throughout the app

- Adds 1440p as a resolution option
- Removes the delay when d-pad seeking on the seek bar & reduces it
slightly when controls are hidden
- Fixes padding one home customize pages
- Adds a title to the search for dialog

### Related issues
Fixes #1017

### Testing
Emulator mostly

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-03-03 13:46:55 -05:00 committed by GitHub
parent 0004701296
commit be90a42c57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 75 additions and 42 deletions

View file

@ -23,6 +23,7 @@ import com.github.damontecres.wholphin.services.ScreensaverService
import com.github.damontecres.wholphin.services.UserPreferencesService import com.github.damontecres.wholphin.services.UserPreferencesService
import com.github.damontecres.wholphin.ui.components.AppScreensaverContent import com.github.damontecres.wholphin.ui.components.AppScreensaverContent
import com.github.damontecres.wholphin.ui.theme.WholphinTheme import com.github.damontecres.wholphin.ui.theme.WholphinTheme
import com.github.damontecres.wholphin.ui.util.ProvideLocalClock
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import javax.inject.Inject import javax.inject.Inject
@ -69,16 +70,18 @@ class WholphinDreamService :
} }
prefs?.let { prefs -> prefs?.let { prefs ->
WholphinTheme(appThemeColors = prefs.appPreferences.interfacePreferences.appThemeColors) { WholphinTheme(appThemeColors = prefs.appPreferences.interfacePreferences.appThemeColors) {
val screensaverPrefs = ProvideLocalClock {
prefs.appPreferences.interfacePreferences.screensaverPreference val screensaverPrefs =
val currentItem by itemFlow.collectAsState(null) prefs.appPreferences.interfacePreferences.screensaverPreference
AppScreensaverContent( val currentItem by itemFlow.collectAsState(null)
currentItem = currentItem, AppScreensaverContent(
showClock = screensaverPrefs.showClock, currentItem = currentItem,
duration = screensaverPrefs.duration.milliseconds, showClock = screensaverPrefs.showClock,
animate = screensaverPrefs.animate, duration = screensaverPrefs.duration.milliseconds,
modifier = Modifier.fillMaxSize(), animate = screensaverPrefs.animate,
) modifier = Modifier.fillMaxSize(),
)
}
} }
} }
} }

View file

@ -165,6 +165,7 @@ fun AppScreensaverContent(
) { ) {
Text( Text(
text = currentItem?.title ?: "", text = currentItem?.title ?: "",
color = MaterialTheme.colorScheme.onSurface,
style = MaterialTheme.typography.displaySmall, style = MaterialTheme.typography.displaySmall,
maxLines = 2, maxLines = 2,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,

View file

@ -656,6 +656,9 @@ fun chooseStream(
) )
add( add(
DialogItem( DialogItem(
leadingContent = {
SelectedLeadingContent(currentIndex == TrackIndex.ONLY_FORCED)
},
headlineContent = { headlineContent = {
Text(text = stringResource(R.string.only_forced_subtitles)) Text(text = stringResource(R.string.only_forced_subtitles))
}, },

View file

@ -32,6 +32,7 @@ import androidx.compose.ui.input.key.type
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
@ -91,10 +92,25 @@ fun SearchForContent(
} }
} }
} }
val titleRes =
remember {
when (searchType) {
BaseItemKind.BOX_SET -> R.string.collections
BaseItemKind.PLAYLIST -> R.string.playlists
else -> null
}
}
val title = titleRes?.let { stringResource(it) } ?: ""
Column( Column(
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = modifier, modifier = modifier,
) { ) {
Text(
text = stringResource(R.string.search_for, title),
style = MaterialTheme.typography.titleLarge,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
)
Box( Box(
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@ -190,16 +206,8 @@ fun SearchForContent(
text = stringResource(R.string.no_results), text = stringResource(R.string.no_results),
) )
} else { } else {
val titleRes =
remember {
when (searchType) {
BaseItemKind.BOX_SET -> R.string.collections
BaseItemKind.PLAYLIST -> R.string.playlists
else -> null
}
}
ItemRow( ItemRow(
title = titleRes?.let { stringResource(it) } ?: "", title = "",
items = st.items, items = st.items,
onClickItem = { _, item -> onClick.invoke(item) }, onClickItem = { _, item -> onClick.invoke(item) },
onLongClickItem = { _, _ -> }, onLongClickItem = { _, _ -> },

View file

@ -240,6 +240,7 @@ fun HomeSettingsPage(
onClick = { type -> onClick = { type ->
addRow { viewModel.addFavoriteRow(type) } addRow { viewModel.addFavoriteRow(type) }
}, },
modifier = destModifier,
) )
} }

View file

@ -1,6 +1,6 @@
package com.github.damontecres.wholphin.ui.playback package com.github.damontecres.wholphin.ui.playback
internal const val HOLD_TO_SEEK_REPEAT_START_COUNT = 12 internal const val HOLD_TO_SEEK_REPEAT_START_COUNT = 8
/** /**
* Shared seek acceleration profile for hold-to-seek behavior. * Shared seek acceleration profile for hold-to-seek behavior.

View file

@ -182,14 +182,10 @@ fun SeekBarDisplay(
KeyEventType.KeyDown -> { KeyEventType.KeyDown -> {
val repeatCount = event.nativeKeyEvent.repeatCount val repeatCount = event.nativeKeyEvent.repeatCount
if (repeatCount > 0) { if (repeatCount > 0) {
if (repeatCount < HOLD_TO_SEEK_REPEAT_START_COUNT) {
leftHandledByRepeat = false
return@onPreviewKeyEvent true
}
leftHandledByRepeat = true leftHandledByRepeat = true
onLeft.invoke( onLeft.invoke(
calculateSeekAccelerationMultiplier( calculateSeekAccelerationMultiplier(
repeatCount = repeatCount - HOLD_TO_SEEK_REPEAT_START_COUNT, repeatCount = repeatCount,
durationMs = durationMs, durationMs = durationMs,
), ),
) )
@ -217,14 +213,10 @@ fun SeekBarDisplay(
KeyEventType.KeyDown -> { KeyEventType.KeyDown -> {
val repeatCount = event.nativeKeyEvent.repeatCount val repeatCount = event.nativeKeyEvent.repeatCount
if (repeatCount > 0) { if (repeatCount > 0) {
if (repeatCount < HOLD_TO_SEEK_REPEAT_START_COUNT) {
rightHandledByRepeat = false
return@onPreviewKeyEvent true
}
rightHandledByRepeat = true rightHandledByRepeat = true
onRight.invoke( onRight.invoke(
calculateSeekAccelerationMultiplier( calculateSeekAccelerationMultiplier(
repeatCount = repeatCount - HOLD_TO_SEEK_REPEAT_START_COUNT, repeatCount = repeatCount,
durationMs = durationMs, durationMs = durationMs,
), ),
) )

View file

@ -27,18 +27,18 @@ object StreamFormatting {
resolutionString(height, width, interlaced) resolutionString(height, width, interlaced)
} else { } else {
when { when {
width <= 256 && height <= 144 -> "144" + interlaced(interlaced) width > 5120 || height > 4320 -> "8K"
width <= 426 && height <= 240 -> "240" + interlaced(interlaced) width > 2560 || height > 1440 -> "4K"
width <= 640 && height <= 360 -> "360" + interlaced(interlaced) width > 1920 || height > 1080 -> "1440" + interlaced(interlaced)
width <= 682 && height <= 384 -> "384" + interlaced(interlaced) width > 1280 || height > 962 -> "1080" + interlaced(interlaced)
width <= 720 && height <= 404 -> "404" + interlaced(interlaced) width > 1024 || height > 576 -> "720" + interlaced(interlaced)
width <= 854 && height <= 480 -> "480" + interlaced(interlaced) width > 960 || height > 544 -> "576" + interlaced(interlaced)
width <= 960 && height <= 544 -> "540" + interlaced(interlaced) width > 845 || height > 480 -> "540" + interlaced(interlaced)
width <= 1024 && height <= 576 -> "576" + interlaced(interlaced) width > 720 || height > 404 -> "480" + interlaced(interlaced)
width <= 1280 && height <= 962 -> "720" + interlaced(interlaced) width > 682 || height > 384 -> "404" + interlaced(interlaced)
width <= 2560 && height <= 1440 -> "1080" + interlaced(interlaced) width > 640 || height > 360 -> "384" + interlaced(interlaced)
width <= 4096 && height <= 3072 -> "4K" width > 426 || height > 240 -> "360" + interlaced(interlaced)
width <= 8192 && height <= 6144 -> "8K" width > 256 || height > 144 -> "240" + interlaced(interlaced)
else -> height.toString() + interlaced(interlaced) else -> height.toString() + interlaced(interlaced)
} }
} }

View file

@ -107,6 +107,7 @@ void *event_thread(void *arg)
case MPV_EVENT_END_FILE: case MPV_EVENT_END_FILE:
mp_end_file = (mpv_event_end_file*)mp_event->data; mp_end_file = (mpv_event_end_file*)mp_event->data;
sendEndFileEventToJava(env, mp_end_file); sendEndFileEventToJava(env, mp_end_file);
break;
default: default:
ALOGV("event: %s\n", mpv_event_name(mp_event->event_id)); ALOGV("event: %s\n", mpv_event_name(mp_event->event_id));
sendEventToJava(env, mp_event->event_id); sendEventToJava(env, mp_event->event_id);

View file

@ -718,5 +718,6 @@
<string name="mixer">Mixer</string> <string name="mixer">Mixer</string>
<string name="creator">Creator</string> <string name="creator">Creator</string>
<string name="artist">Artist</string> <string name="artist">Artist</string>
<string name="search_for">Search %s</string>
</resources> </resources>

View file

@ -0,0 +1,23 @@
package com.github.damontecres.wholphin.test
import com.github.damontecres.wholphin.ui.util.StreamFormatting.resolutionString
import org.junit.Assert
import org.junit.Test
class FormattingTests {
@Test
fun testResolutionStrings() {
Assert.assertEquals("4K", resolutionString(3840, 2160, false))
Assert.assertEquals("1080p", resolutionString(1920, 1080, false))
Assert.assertEquals("720p", resolutionString(1280, 720, false))
Assert.assertEquals("480i", resolutionString(640, 480, true))
Assert.assertEquals("576p", resolutionString(1024, 576, false))
Assert.assertEquals("576p", resolutionString(960, 576, false))
// 21:9
Assert.assertEquals("1080p", resolutionString(1920, 822, false))
Assert.assertEquals("1440p", resolutionString(2560, 1440, false))
}
}