mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Add settings to show the current time (#155)
Closes #154 Adds a settings to show the current time in the upper right corner. If enabled, it will also show the end time for the playback on the overlay.
This commit is contained in:
parent
40a8249469
commit
77c787b51f
14 changed files with 118 additions and 15 deletions
|
|
@ -642,6 +642,18 @@ sealed interface AppPreference<T> {
|
|||
indexToValue = { ShowNextUpWhen.forNumber(it) },
|
||||
valueToIndex = { it.number },
|
||||
)
|
||||
|
||||
val ShowClock =
|
||||
AppSwitchPreference(
|
||||
title = R.string.show_clock,
|
||||
defaultValue = true,
|
||||
getter = { it.interfacePreferences.showClock },
|
||||
setter = { prefs, value ->
|
||||
prefs.updateInterfacePreferences { showClock = value }
|
||||
},
|
||||
summaryOn = R.string.enabled,
|
||||
summaryOff = R.string.disabled,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -709,6 +721,7 @@ val advancedPreferences =
|
|||
title = R.string.ui_interface,
|
||||
preferences =
|
||||
listOf(
|
||||
AppPreference.ShowClock,
|
||||
AppPreference.CombineContinueNext,
|
||||
// Temporarily disabled, see https://github.com/damontecres/Wholphin/pull/127#issuecomment-3478058418
|
||||
// AppPreference.NavDrawerSwitchOnFocus,
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class AppPreferencesSerializer
|
|||
appThemeColors = AppPreference.ThemeColors.defaultValue
|
||||
navDrawerSwitchOnFocus =
|
||||
AppPreference.NavDrawerSwitchOnFocus.defaultValue
|
||||
showClock = AppPreference.ShowClock.defaultValue
|
||||
}.build()
|
||||
}.build()
|
||||
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ fun RecommendedMovie(
|
|||
onClickItem = onClickItem,
|
||||
onLongClickItem = {},
|
||||
onFocusPosition = onFocusPosition,
|
||||
showClock = preferences.appPreferences.interfacePreferences.showClock,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ fun RecommendedTvShow(
|
|||
onClickItem = onClickItem,
|
||||
onLongClickItem = {},
|
||||
onFocusPosition = onFocusPosition,
|
||||
showClock = preferences.appPreferences.interfacePreferences.showClock,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,6 +132,12 @@ fun SeriesOverviewContent(
|
|||
modifier = Modifier,
|
||||
) {
|
||||
item {
|
||||
val paddingValues =
|
||||
if (preferences.appPreferences.interfacePreferences.showClock) {
|
||||
PaddingValues(start = 16.dp, end = 100.dp)
|
||||
} else {
|
||||
PaddingValues(start = 16.dp, end = 16.dp)
|
||||
}
|
||||
TabRow(
|
||||
selectedTabIndex = focusTabIndex,
|
||||
modifier =
|
||||
|
|
@ -140,7 +146,7 @@ fun SeriesOverviewContent(
|
|||
focusRequesters.size > selectedTabIndex,
|
||||
{ Modifier.focusRestorer(focusRequesters[selectedTabIndex]) },
|
||||
).focusRequester(tabRowFocusRequester)
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(paddingValues)
|
||||
.fillMaxWidth()
|
||||
.onFocusChanged {
|
||||
if (!it.isFocused) {
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ fun HomePage(
|
|||
)
|
||||
},
|
||||
loadingState = loading,
|
||||
showClock = preferences.appPreferences.interfacePreferences.showClock,
|
||||
modifier = modifier,
|
||||
)
|
||||
dialog?.let { params ->
|
||||
|
|
@ -205,6 +206,7 @@ fun HomePageContent(
|
|||
homeRows: List<HomeRow>,
|
||||
onClickItem: (BaseItem) -> Unit,
|
||||
onLongClickItem: (BaseItem) -> Unit,
|
||||
showClock: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onFocusPosition: ((RowColumn) -> Unit)? = null,
|
||||
loadingState: LoadingState? = null,
|
||||
|
|
@ -342,7 +344,7 @@ fun HomePageContent(
|
|||
Box(
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(16.dp)
|
||||
.padding(if (showClock) 40.dp else 20.dp)
|
||||
.size(40.dp)
|
||||
.align(Alignment.TopEnd),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.Box
|
|||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
|
|
@ -27,6 +28,7 @@ import androidx.compose.runtime.derivedStateOf
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
|
|
@ -74,13 +76,16 @@ import com.github.damontecres.wholphin.ui.setValueOnMain
|
|||
import com.github.damontecres.wholphin.ui.spacedByWithFooter
|
||||
import com.github.damontecres.wholphin.ui.toServerString
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.TimeFormatter
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.jellyfin.sdk.model.api.CollectionType
|
||||
import org.jellyfin.sdk.model.api.DeviceProfile
|
||||
import timber.log.Timber
|
||||
import java.time.LocalTime
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -431,13 +436,35 @@ fun NavDrawer(
|
|||
}
|
||||
},
|
||||
) {
|
||||
// Drawer content
|
||||
DestinationContent(
|
||||
destination = destination,
|
||||
preferences = preferences,
|
||||
deviceProfile = deviceProfile,
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
) {
|
||||
// Drawer content
|
||||
DestinationContent(
|
||||
destination = destination,
|
||||
preferences = preferences,
|
||||
deviceProfile = deviceProfile,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
if (preferences.appPreferences.interfacePreferences.showClock) {
|
||||
var now by remember { mutableStateOf(LocalTime.now()) }
|
||||
LaunchedEffect(Unit) {
|
||||
if (isActive) {
|
||||
now = LocalTime.now()
|
||||
}
|
||||
}
|
||||
Text(
|
||||
text = TimeFormatter.format(now),
|
||||
// style = MaterialTheme.typography.titleMedium,
|
||||
fontSize = 18.sp,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier =
|
||||
Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.padding(vertical = 16.dp, horizontal = 24.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ fun SeekBar(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
val remaining = ((player.duration - position) / 1000).seconds
|
||||
Text(
|
||||
text = (position / 1000).seconds.toString(),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
|
|
@ -291,7 +292,7 @@ fun SeekBar(
|
|||
.padding(8.dp),
|
||||
)
|
||||
Text(
|
||||
text = "-" + ((player.duration - position) / 1000).seconds.toString(),
|
||||
text = "-$remaining",
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier =
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Arrangement
|
|||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
|
|
@ -56,9 +57,15 @@ import com.github.damontecres.wholphin.ui.ifElse
|
|||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.TimeFormatter
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import org.jellyfin.sdk.model.api.MediaSegmentDto
|
||||
import org.jellyfin.sdk.model.api.TrickplayInfo
|
||||
import java.time.LocalTime
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
private val titleTextSize = 28.sp
|
||||
private val subtitleTextSize = 18.sp
|
||||
|
|
@ -74,6 +81,7 @@ fun PlaybackOverlay(
|
|||
playerControls: Player,
|
||||
controllerViewState: ControllerViewState,
|
||||
showPlay: Boolean,
|
||||
showClock: Boolean,
|
||||
previousEnabled: Boolean,
|
||||
nextEnabled: Boolean,
|
||||
seekEnabled: Boolean,
|
||||
|
|
@ -144,6 +152,7 @@ fun PlaybackOverlay(
|
|||
playerControls = playerControls,
|
||||
controllerViewState = controllerViewState,
|
||||
showPlay = showPlay,
|
||||
showClock = showClock,
|
||||
previousEnabled = previousEnabled,
|
||||
nextEnabled = nextEnabled,
|
||||
seekEnabled = seekEnabled,
|
||||
|
|
@ -415,6 +424,7 @@ fun Controller(
|
|||
subtitleStreams: List<SubtitleStream>,
|
||||
playerControls: Player,
|
||||
controllerViewState: ControllerViewState,
|
||||
showClock: Boolean,
|
||||
showPlay: Boolean,
|
||||
previousEnabled: Boolean,
|
||||
nextEnabled: Boolean,
|
||||
|
|
@ -453,12 +463,40 @@ fun Controller(
|
|||
fontSize = titleTextSize,
|
||||
)
|
||||
}
|
||||
subtitle?.let {
|
||||
Text(
|
||||
text = it,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontSize = subtitleTextSize,
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.End),
|
||||
) {
|
||||
subtitle?.let {
|
||||
Text(
|
||||
text = it,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontSize = subtitleTextSize,
|
||||
)
|
||||
}
|
||||
if (showClock) {
|
||||
var remaining by remember { mutableStateOf((playerControls.duration - playerControls.currentPosition).milliseconds) }
|
||||
LaunchedEffect(playerControls) {
|
||||
while (isActive) {
|
||||
remaining =
|
||||
(playerControls.duration - playerControls.currentPosition).milliseconds
|
||||
delay(1.seconds)
|
||||
}
|
||||
}
|
||||
val endTime = LocalTime.now().plusSeconds(remaining.inWholeSeconds)
|
||||
val endTimeStr = TimeFormatter.format(endTime)
|
||||
Text(
|
||||
text = "Ends $endTimeStr",
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier =
|
||||
Modifier
|
||||
.padding(end = 32.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
PlaybackControls(
|
||||
|
|
|
|||
|
|
@ -387,6 +387,7 @@ fun PlaybackPage(
|
|||
viewModel.playItemInPlaylist(it)
|
||||
},
|
||||
currentSegment = currentSegment,
|
||||
showClock = preferences.appPreferences.interfacePreferences.showClock,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,4 +89,11 @@ suspend fun upgradeApp(
|
|||
}
|
||||
}
|
||||
}
|
||||
if (previous.isEqualOrBefore(Version.fromString("0.2.5-11-g0"))) {
|
||||
appPreferences.updateData {
|
||||
it.updateInterfacePreferences {
|
||||
showClock = AppPreference.ShowClock.defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,11 @@ import org.jellyfin.sdk.model.api.MediaStreamType
|
|||
import java.time.LocalDate
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.FormatStyle
|
||||
import java.util.Locale
|
||||
|
||||
val TimeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
|
||||
|
||||
/**
|
||||
* Format a [LocalDateTime] as `Aug 24, 2000`
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ message InterfacePreferences {
|
|||
map<string, int32> remembered_tabs = 3;
|
||||
AppThemeColors app_theme_colors = 4;
|
||||
bool nav_drawer_switch_on_focus = 5;
|
||||
bool show_clock = 6;
|
||||
}
|
||||
|
||||
message AppPreferences {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@
|
|||
<string name="watch_live">Watch live</string>
|
||||
<string name="years_old">%1$d years old</string>
|
||||
<string name="play_with_transcoding">Play with transcoding</string>
|
||||
<string name="show_clock">Show Clock</string>
|
||||
<string name="aired_episode_order">Aired Episode Order</string>
|
||||
<string name="create_playlist">Create new playlist</string>
|
||||
<string name="add_to_playlist">Add to playlist</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue