diff --git a/VERIFICATION-0.73.1.md b/VERIFICATION-0.73.1.md new file mode 100644 index 0000000..1a3d257 --- /dev/null +++ b/VERIFICATION-0.73.1.md @@ -0,0 +1,5 @@ +# Orbit TV 0.73.1: gear reach + +Found walking through 0.73 on the box. Up from All Channels did nothing, so the gear could only be reached through the picture; it now goes straight there. A leftover "Saved connection restored" message no longer sits at the top of Channels. + +On 0.73, by remote keys on the box: Settings opened, Channels showed 29 of 29 on, Watching and Back behaved, Terra and Paradox topped up again on 201 and 106, and the catalogue was unchanged. Checked here: build, lint and all unit tests pass. The fix isn't checked on the box until installed. diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index fade223..24c579c 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -9,8 +9,8 @@ android { applicationId = "tv.orbit.classic" minSdk = 26 targetSdk = 36 - versionCode = 76 - versionName = "0.73.0-only-whats-needed" + versionCode = 77 + versionName = "0.73.1-gear-reach" } buildFeatures { compose = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 } diff --git a/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt b/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt index 9744eb0..078e1fd 100644 --- a/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt +++ b/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt @@ -66,7 +66,7 @@ internal class HttpsEmbyTransport(internal val deviceId: String = UUID.randomUUI connection.connectTimeout = 10_000 connection.readTimeout = request.readTimeoutMs ?: if (request.path == "/Sessions/Logout") 5_000 else 15_000 connection.setRequestProperty("Accept", "application/json") - connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.73.0\"") + connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.73.1\"") request.token?.let { connection.setRequestProperty("X-Emby-Token", it) } if (request.method == "POST") { val bytes = request.body.orEmpty().toByteArray(Charsets.UTF_8) diff --git a/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt b/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt index 1383e31..d200bd6 100644 --- a/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt +++ b/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt @@ -188,7 +188,6 @@ internal fun EmbyConnectionScreen(modifier: Modifier = Modifier, visible: Boolea } catch (cancelled: CancellationException) { throw cancelled } catch (_: Exception) { emptyMap() } session = resumed; sample = resumed.sample; applyChoices(saved) saveTicket = savedStore.ticket() - message = "Saved connection restored." } else if (saved != null && session == null) message = "Sign in again to restore your saved channel choices." } catch (cancelled: CancellationException) { throw cancelled } catch (failure: EmbyCheckException) { diff --git a/android/app/src/main/java/tv/orbit/classic/HomeScreen.kt b/android/app/src/main/java/tv/orbit/classic/HomeScreen.kt index b231154..84df1b1 100644 --- a/android/app/src/main/java/tv/orbit/classic/HomeScreen.kt +++ b/android/app/src/main/java/tv/orbit/classic/HomeScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color @@ -127,12 +128,13 @@ internal fun HomeScreen(session: EmbySampleSession, channels: List - HomeCard(Modifier.fillMaxWidth().weight(1f), if (index == 0) firstFocus else null, onClick = { onCategory(category) }) { focused -> + HomeCard(Modifier.fillMaxWidth().weight(1f).focusProperties { if (index == 0 && gear != null) up = gear }, if (index == 0) firstFocus else null, onClick = { onCategory(category) }) { focused -> Row(Modifier.fillMaxSize().padding(horizontal = 10.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) { Image(painterResource(category.icon), null, Modifier.size(26.dp), colorFilter = if (focused) ColorFilter.tint(Navy) else null) Text(category.label, color = if (focused) Navy else Color.White, fontSize = 15.sp, fontWeight = FontWeight.SemiBold, maxLines = 1) diff --git a/android/app/src/main/java/tv/orbit/classic/MainActivity.kt b/android/app/src/main/java/tv/orbit/classic/MainActivity.kt index ef3e279..9841663 100644 --- a/android/app/src/main/java/tv/orbit/classic/MainActivity.kt +++ b/android/app/src/main/java/tv/orbit/classic/MainActivity.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter @@ -32,6 +33,8 @@ import java.text.SimpleDateFormat import java.util.Date import java.util.Locale +/** The gear, so the menu's top row can reach it directly. Left to itself, up finds nothing above the first column. */ +internal val LocalGearFocus = staticCompositionLocalOf { null } internal val Barlow = FontFamily(Font(R.font.barlow_regular), Font(R.font.barlow_semibold, FontWeight.SemiBold), Font(R.font.barlow_semibold, FontWeight.Bold)) internal val Navy = Color(0xFF071632) internal val Panel = Color(0xFF12356B) @@ -82,7 +85,9 @@ private fun OrbitApp() { } // Back on the main menu closes the app. BackHandler(realChannelAvailable && section != "TV Guide" && section != "Home") { section = "Home" } + val gearFocus = remember { FocusRequester() } Box(Modifier.fillMaxSize().background(Navy)) { + CompositionLocalProvider(LocalGearFocus provides gearFocus) { // The Drive-In takes the whole screen. Column(if (section == "Drive-In") Modifier.fillMaxSize() else Modifier.fillMaxSize().padding(horizontal = 36.dp, vertical = 16.dp)) { if (section != "Drive-In") { @@ -92,7 +97,7 @@ private fun OrbitApp() { Text(SimpleDateFormat("EEE d MMM HH:mm", Locale.UK).format(Date(now)), color = Color.White, fontSize = 17.sp) if (realChannelAvailable) { Spacer(Modifier.width(12.dp)) - HomeCard(Modifier.size(38.dp, 32.dp), onClick = { section = "Connect Emby" }) { focused -> + HomeCard(Modifier.size(38.dp, 32.dp), gearFocus, onClick = { section = "Connect Emby" }) { focused -> Image(painterResource(R.drawable.orbit_icon_gear), "Settings", Modifier.fillMaxSize().padding(5.dp), colorFilter = if (focused) ColorFilter.tint(Navy) else null) } } @@ -107,5 +112,6 @@ private fun OrbitApp() { onChannelAvailable = { realChannelAvailable = it }, onRestoreChecked = { restoreChecked = true }, onGuide = { section = "TV Guide" }, onHome = { section = "Home" }, onDriveIn = { section = "Drive-In" }) } + } } } diff --git a/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt b/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt index 1ffcff3..0978747 100644 --- a/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt +++ b/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt @@ -33,7 +33,7 @@ internal class SecureMediaDataSource(private val session: EmbySampleSession) : B next.instanceFollowRedirects = false next.connectTimeout = 10_000 next.readTimeout = 20_000 - next.setRequestProperty("User-Agent", "OrbitTV/0.73.0") + next.setRequestProperty("User-Agent", "OrbitTV/0.73.1") next.setRequestProperty("Accept-Encoding", "identity") session.mediaHeaders(address).forEach { (key, value) -> next.setRequestProperty(key, value) } if (dataSpec.position != 0L || dataSpec.length != C.LENGTH_UNSET.toLong()) {