Rename to SleepyOwl, add logo

This commit is contained in:
2026-10-25 00:53:19 +03:00
parent 33643707f1
commit f63b09a9d3
130 changed files with 8010 additions and 7797 deletions

View File

@@ -7,11 +7,11 @@ plugins {
} }
android { android {
namespace = "ru.stenfredd.movies" namespace = "ru.stenfredd.sleepyowl"
compileSdk = 37 compileSdk = 37
defaultConfig { defaultConfig {
applicationId = "ru.stenfredd.movies" applicationId = "ru.stenfredd.sleepyowl"
minSdk = 26 minSdk = 26
targetSdk = 36 targetSdk = 36
versionCode = 1 versionCode = 1

View File

@@ -12,15 +12,15 @@
<uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<application <application
android:name=".MoviesApp" android:name=".SleepyOwlApp"
android:allowBackup="false" android:allowBackup="false"
android:banner="@drawable/banner" android:banner="@drawable/banner"
android:icon="@drawable/banner" android:icon="@mipmap/ic_launcher"
android:largeHeap="true" android:largeHeap="true"
android:label="@string/app_name" android:label="@string/app_name"
android:supportsRtl="true" android:supportsRtl="true"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/Theme.Movies"> android:theme="@style/Theme.SleepyOwl">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies package ru.stenfredd.sleepyowl
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
@@ -15,14 +15,14 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import ru.stenfredd.movies.core.data.ImageUrls import ru.stenfredd.sleepyowl.core.data.ImageUrls
import ru.stenfredd.movies.core.data.SessionCache import ru.stenfredd.sleepyowl.core.data.SessionCache
import ru.stenfredd.movies.core.data.WatchRepository import ru.stenfredd.sleepyowl.core.data.WatchRepository
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import ru.stenfredd.movies.ui.model.landscape import ru.stenfredd.sleepyowl.ui.model.landscape
import ru.stenfredd.movies.ui.model.remaining import ru.stenfredd.sleepyowl.ui.model.remaining
import timber.log.Timber import timber.log.Timber
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies package ru.stenfredd.sleepyowl
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
@@ -30,34 +30,34 @@ import androidx.navigation3.ui.NavDisplay
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.model.LibraryType import ru.stenfredd.sleepyowl.core.data.model.LibraryType
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import ru.stenfredd.movies.playback.api.EngineId import ru.stenfredd.sleepyowl.playback.api.EngineId
import ru.stenfredd.movies.playback.api.StreamSelection import ru.stenfredd.sleepyowl.playback.api.StreamSelection
import ru.stenfredd.movies.ui.ItemsScreen import ru.stenfredd.sleepyowl.ui.ItemsScreen
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.TourScreen import ru.stenfredd.sleepyowl.ui.TourScreen
import ru.stenfredd.movies.ui.details.DetailsScreen import ru.stenfredd.sleepyowl.ui.details.DetailsScreen
import ru.stenfredd.movies.ui.home.HomeScreen import ru.stenfredd.sleepyowl.ui.home.HomeScreen
import ru.stenfredd.movies.ui.favorites.FavoritesScreen import ru.stenfredd.sleepyowl.ui.favorites.FavoritesScreen
import ru.stenfredd.movies.ui.library.LibraryMemory import ru.stenfredd.sleepyowl.ui.library.LibraryMemory
import ru.stenfredd.movies.ui.library.LibraryScreen import ru.stenfredd.sleepyowl.ui.library.LibraryScreen
import ru.stenfredd.movies.ui.person.PersonScreen import ru.stenfredd.sleepyowl.ui.person.PersonScreen
import ru.stenfredd.movies.ui.search.SearchScreen import ru.stenfredd.sleepyowl.ui.search.SearchScreen
import ru.stenfredd.movies.ui.settings.LicenseScreen import ru.stenfredd.sleepyowl.ui.settings.LicenseScreen
import ru.stenfredd.movies.ui.settings.SettingsScreen import ru.stenfredd.sleepyowl.ui.settings.SettingsScreen
import ru.stenfredd.movies.ui.player.PlayerScreen import ru.stenfredd.sleepyowl.ui.player.PlayerScreen
import ru.stenfredd.movies.ui.series.SeriesScreen import ru.stenfredd.sleepyowl.ui.series.SeriesScreen
import ru.stenfredd.movies.ui.login.LoginScreen import ru.stenfredd.sleepyowl.ui.login.LoginScreen
import ru.stenfredd.movies.ui.menu.WatchMenuHost import ru.stenfredd.sleepyowl.ui.menu.WatchMenuHost
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.shell.RailLibrary import ru.stenfredd.sleepyowl.ui.shell.RailLibrary
import ru.stenfredd.movies.ui.shell.Shell import ru.stenfredd.sleepyowl.ui.shell.Shell
import ru.stenfredd.movies.ui.shell.Tab import ru.stenfredd.sleepyowl.ui.shell.Tab
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppTheme import ru.stenfredd.sleepyowl.ui.theme.AppTheme
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
@@ -230,7 +230,7 @@ class MainActivity : ComponentActivity() {
/** /**
* Opens an item from the launch intent: * Opens an item from the launch intent:
* `adb shell am start -S -n ru.stenfredd.movies/.MainActivity --es item <id> [--ez play true] [--el start <ms>] * `adb shell am start -S -n ru.stenfredd.sleepyowl/.MainActivity --es item <id> [--ez play true] [--el start <ms>]
* [--ei audio <index>] [--ei sub <index>]` (stream indexes as Jellyfin numbers them; with one given, the other is off), * [--ei audio <index>] [--ei sub <index>]` (stream indexes as Jellyfin numbers them; with one given, the other is off),
* or a series page: `--es series <id> [--es episode <id>]`. With both `item` (an episode) and `series`, the page * or a series page: `--es series <id> [--es episode <id>]`. With both `item` (an episode) and `series`, the page
* under the player is the series page on that episode, as from the app's own cards (the TV's home screen does so). * under the player is the series page on that episode, as from the app's own cards (the TV's home screen does so).

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies package ru.stenfredd.sleepyowl
import android.app.Application import android.app.Application
import coil3.ImageLoader import coil3.ImageLoader
@@ -21,7 +21,7 @@ import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@HiltAndroidApp @HiltAndroidApp
class MoviesApp : Application(), SingletonImageLoader.Factory { class SleepyOwlApp : Application(), SingletonImageLoader.Factory {
/** The API's client: images go to the server's LAN address at home too (`ServerRouting`), sharing its connections. */ /** The API's client: images go to the server's LAN address at home too (`ServerRouting`), sharing its connections. */
@Inject lateinit var httpClient: OkHttpClient @Inject lateinit var httpClient: OkHttpClient
@Inject lateinit var launcherFeed: Lazy<LauncherFeed> @Inject lateinit var launcherFeed: Lazy<LauncherFeed>

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui package ru.stenfredd.sleepyowl.ui
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -39,11 +39,11 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import ru.stenfredd.movies.ui.components.TextInput import ru.stenfredd.sleepyowl.ui.components.TextInput
import ru.stenfredd.movies.ui.components.rememberTextInputState import ru.stenfredd.sleepyowl.ui.components.rememberTextInputState
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui package ru.stenfredd.sleepyowl.ui
import org.jellyfin.sdk.api.client.extensions.imageApi import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.api.client.extensions.libraryApi import org.jellyfin.sdk.api.client.extensions.libraryApi
@@ -6,7 +6,7 @@ import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.BaseItemKind import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.ImageType import org.jellyfin.sdk.model.api.ImageType
import org.jellyfin.sdk.model.api.ItemSortBy import org.jellyfin.sdk.model.api.ItemSortBy
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,7 +1,7 @@
package ru.stenfredd.movies.ui package ru.stenfredd.sleepyowl.ui
import ru.stenfredd.movies.playback.api.EngineId import ru.stenfredd.sleepyowl.playback.api.EngineId
import ru.stenfredd.movies.playback.api.StreamSelection import ru.stenfredd.sleepyowl.playback.api.StreamSelection
import java.util.UUID import java.util.UUID
sealed interface Screen { sealed interface Screen {
@@ -13,7 +13,7 @@ sealed interface Screen {
* after a profile switch the stack is rebuilt, and an equal entry would be kept with the old account's state. * after a profile switch the stack is rebuilt, and an equal entry would be kept with the old account's state.
* [library]: the library tab opened on a library from the rail; a new entry, so the tab starts over on it. * [library]: the library tab opened on a library from the rail; a new entry, so the tab starts over on it.
*/ */
data class Root(val tab: ru.stenfredd.movies.ui.shell.Tab, val account: String, val library: UUID? = null) : Screen data class Root(val tab: ru.stenfredd.sleepyowl.ui.shell.Tab, val account: String, val library: UUID? = null) : Screen
/** Collections and folders: the prototype's plain grid until they get a real screen. */ /** Collections and folders: the prototype's plain grid until they get a real screen. */
data class Items(val parentId: UUID, val title: String) : Screen data class Items(val parentId: UUID, val title: String) : Screen

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui package ru.stenfredd.sleepyowl.ui
import android.content.Context import android.content.Context
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
@@ -34,9 +34,9 @@ import androidx.tv.material3.Text
import java.util.UUID import java.util.UUID
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import org.json.JSONArray import org.json.JSONArray
import ru.stenfredd.movies.playback.api.StreamSelection import ru.stenfredd.sleepyowl.playback.api.StreamSelection
import ru.stenfredd.movies.ui.player.PlayerScreen import ru.stenfredd.sleepyowl.ui.player.PlayerScreen
import ru.stenfredd.movies.ui.player.TourInfo import ru.stenfredd.sleepyowl.ui.player.TourInfo
import timber.log.Timber import timber.log.Timber
/** /**

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapShader import android.graphics.BitmapShader

View File

@@ -0,0 +1,33 @@
package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import ru.stenfredd.sleepyowl.R
/**
* The app's logo: the owl and the "SleepyOwl" wordmark from `design/logo/sleepyowl.png`, cut out of its navy
* background by `tools/logo/make_assets.py`. The pictures are made at the default sizes here (xhdpi), so on the TV
* they are drawn pixel for pixel; other sizes resample them.
*/
@Composable
fun OwlMark(modifier: Modifier = Modifier, size: Dp = 36.dp) {
Image(painterResource(R.drawable.logo_owl), null, modifier.size(size))
}
@Composable
fun Wordmark(modifier: Modifier = Modifier, height: Dp = 18.dp) {
val painter = painterResource(R.drawable.logo_wordmark)
Image(
painter,
stringResource(R.string.app_name),
modifier.height(height).aspectRatio(painter.intrinsicSize.width / painter.intrinsicSize.height),
)
}

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -27,8 +27,8 @@ import androidx.compose.ui.unit.sp
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
private val PrimaryFocus = FocusStyle( private val PrimaryFocus = FocusStyle(
scale = 1.05f, scale = 1.05f,

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapShader import android.graphics.BitmapShader

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -27,11 +27,11 @@ import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ru.stenfredd.movies.ui.menu.WatchTarget import ru.stenfredd.sleepyowl.ui.menu.WatchTarget
import ru.stenfredd.movies.ui.menu.clickableWithMenu import ru.stenfredd.sleepyowl.ui.menu.clickableWithMenu
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** What a poster card shows. Built by view models from server data; composables never see SDK DTOs. */ /** What a poster card shows. Built by view models from server data; composables never see SDK DTOs. */
@Immutable @Immutable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import android.graphics.DashPathEffect import android.graphics.DashPathEffect
import android.graphics.Paint import android.graphics.Paint

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
@@ -26,7 +26,7 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
/** Focus look of a card: scale, outer ring and glow, as `style-focus` in the mockup (sizes in dp). */ /** Focus look of a card: scale, outer ring and glow, as `style-focus` in the mockup (sizes in dp). */
@Immutable @Immutable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BlurMaskFilter import android.graphics.BlurMaskFilter
@@ -9,7 +9,7 @@ import android.util.LruCache
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.toArgb import java.nio.ByteBuffer
import kotlin.math.roundToInt import kotlin.math.roundToInt
/** /**
@@ -46,20 +46,63 @@ object GlowCache {
val margin = key.layers.maxOf { it.blurPx + it.spreadPx } val margin = key.layers.maxOf { it.blurPx + it.spreadPx }
val w = ((key.w + 2 * margin) * SCALE).roundToInt().coerceAtLeast(1) val w = ((key.w + 2 * margin) * SCALE).roundToInt().coerceAtLeast(1)
val h = ((key.h + 2 * margin) * SCALE).roundToInt().coerceAtLeast(1) val h = ((key.h + 2 * margin) * SCALE).roundToInt().coerceAtLeast(1)
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888) // Each layer's coverage is drawn at full strength (255 levels) and the layers are composited in float:
val canvas = Canvas(bitmap) // a dim colour stored directly in 8 bits has only 15–60 levels per channel, so the tail shows bands
// several px wide and R, G, B step at different places — a visible staircase with colour shifts.
val mask = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8)
val canvas = Canvas(mask)
canvas.scale(SCALE, SCALE) canvas.scale(SCALE, SCALE)
val paint = Paint(Paint.ANTI_ALIAS_FLAG) val paint = Paint(Paint.ANTI_ALIAS_FLAG)
val stride = mask.rowBytes
val coverage = ByteBuffer.allocate(stride * h)
val premul = FloatArray(w * h * 4)
for (layer in key.layers) { for (layer in key.layers) {
mask.eraseColor(0)
// CSS blur radius B is a Gaussian with sigma B/2; BlurMaskFilter's radius r has sigma ≈ 0.57735·r + 0.5. // CSS blur radius B is a Gaussian with sigma B/2; BlurMaskFilter's radius r has sigma ≈ 0.57735·r + 0.5.
val radius = ((layer.blurPx / 2 - 0.5f) / 0.57735f).coerceAtLeast(0.5f) val radius = ((layer.blurPx / 2 - 0.5f) / 0.57735f).coerceAtLeast(0.5f)
paint.maskFilter = BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL) paint.maskFilter = BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL)
paint.color = layer.color.toArgb()
val s = layer.spreadPx val s = layer.spreadPx
val rect = RectF(margin - s, margin - s, margin + key.w + s, margin + key.h + s) val rect = RectF(margin - s, margin - s, margin + key.w + s, margin + key.h + s)
val corner = key.corner + s val corner = key.corner + s
canvas.drawRoundRect(rect, corner, corner, paint) canvas.drawRoundRect(rect, corner, corner, paint)
coverage.rewind()
mask.copyPixelsToBuffer(coverage)
val px = coverage.array()
val c = layer.color
for (y in 0 until h) for (x in 0 until w) {
val v = px[y * stride + x].toInt() and 0xFF
if (v == 0) continue
val a = c.alpha * v / 255f
val i = (y * w + x) * 4
premul[i] = c.red * a + premul[i] * (1 - a)
premul[i + 1] = c.green * a + premul[i + 1] * (1 - a)
premul[i + 2] = c.blue * a + premul[i + 2] * (1 - a)
premul[i + 3] = a + premul[i + 3] * (1 - a)
} }
}
// To 8 bits with ±1.5 levels of noise: invisible, but the average is smooth. White noise rather than
// a finer pattern, since the bitmap is upscaled 2× and the filtering would average a fine pattern out.
val out = ByteBuffer.allocate(w * h * 4)
val bytes = out.array()
for (i in 0 until w * h) {
val o = i * 4
if (premul[o + 3] <= 0f) continue
val n = 3f * noise(i) - 1.5f
val a = (premul[o + 3] * 255f + n).roundToInt().coerceIn(0, 255)
for (k in 0..2) bytes[o + k] = (premul[o + k] * 255f + n).roundToInt().coerceIn(0, a).toByte()
bytes[o + 3] = a.toByte()
}
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
bitmap.copyPixelsFromBuffer(out)
return Glow(bitmap.asImageBitmap(), margin) return Glow(bitmap.asImageBitmap(), margin)
} }
/** Hash-based white noise, 0..1. */
private fun noise(i: Int): Float {
var x = i * 0x27d4eb2d
x = (x xor (x ushr 15)) * 0x2c1b3c6d
x = (x xor (x ushr 12)) * 0x297a2d39
x = x xor (x ushr 15)
return (x ushr 8) / 16777216f
}
} }

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyGridScope import androidx.compose.foundation.lazy.grid.LazyGridScope

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -27,7 +27,7 @@ import coil3.request.ImageRequest
import coil3.request.transformations import coil3.request.transformations
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
/** A server image: URL of exactly the displayed size and the BlurHash shown while it loads. */ /** A server image: URL of exactly the displayed size and the BlurHash shown while it loads. */
@Immutable @Immutable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -14,8 +14,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusRestorer import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** "Недавно добавлено 12" */ /** "Недавно добавлено 12" */
@Composable @Composable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.components package ru.stenfredd.sleepyowl.ui.components
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
@@ -52,7 +52,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
/** /**
* Remote-friendly text field state. D-pad focus lands on the field's frame only; OK (or [edit]) puts the cursor in * Remote-friendly text field state. D-pad focus lands on the field's frame only; OK (or [edit]) puts the cursor in

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.details package ru.stenfredd.sleepyowl.ui.details
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
@@ -11,7 +11,7 @@ import androidx.compose.ui.graphics.toArgb
import coil3.size.Dimension import coil3.size.Dimension
import coil3.size.Size import coil3.size.Size
import coil3.transform.Transformation import coil3.transform.Transformation
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
/** /**
* The item page backdrop as one opaque bitmap: the image dimmed to 70 % over the app background and the mockup's * The item page backdrop as one opaque bitmap: the image dimmed to 70 % over the app background and the mockup's

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.details package ru.stenfredd.sleepyowl.ui.details
import android.graphics.RectF import android.graphics.RectF
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -52,32 +52,32 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import coil3.request.ImageRequest import coil3.request.ImageRequest
import coil3.request.transformations import coil3.request.transformations
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AnchoredScrolling import ru.stenfredd.sleepyowl.ui.components.AnchoredScrolling
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.Chip import ru.stenfredd.sleepyowl.ui.components.Chip
import ru.stenfredd.movies.ui.components.CircleButton import ru.stenfredd.sleepyowl.ui.components.CircleButton
import ru.stenfredd.movies.ui.components.ContentRow import ru.stenfredd.sleepyowl.ui.components.ContentRow
import ru.stenfredd.movies.ui.components.DefaultScrolling import ru.stenfredd.sleepyowl.ui.components.DefaultScrolling
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.FormatBadge import ru.stenfredd.sleepyowl.ui.components.FormatBadge
import ru.stenfredd.movies.ui.components.PosterCard import ru.stenfredd.sleepyowl.ui.components.PosterCard
import ru.stenfredd.movies.ui.components.PrimaryButton import ru.stenfredd.sleepyowl.ui.components.PrimaryButton
import ru.stenfredd.movies.ui.components.RemoteImage import ru.stenfredd.sleepyowl.ui.components.RemoteImage
import ru.stenfredd.movies.ui.components.SecondaryButton import ru.stenfredd.sleepyowl.ui.components.SecondaryButton
import ru.stenfredd.movies.ui.components.SectionTitle import ru.stenfredd.sleepyowl.ui.components.SectionTitle
import ru.stenfredd.movies.ui.components.anchorViewport import ru.stenfredd.sleepyowl.ui.components.anchorViewport
import ru.stenfredd.movies.ui.components.anchoredRow import ru.stenfredd.sleepyowl.ui.components.anchoredRow
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import ru.stenfredd.movies.ui.details.DetailsLayout as L import ru.stenfredd.sleepyowl.ui.details.DetailsLayout as L
/** Movie (or episode) page, the mockup's "Фильм" screen. Full screen, without the side rail. */ /** Movie (or episode) page, the mockup's "Фильм" screen. Full screen, without the side rail. */
@Composable @Composable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.details package ru.stenfredd.sleepyowl.ui.details
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -17,20 +17,20 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.ImageUrls import ru.stenfredd.sleepyowl.core.data.ImageUrls
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.SessionCache import ru.stenfredd.sleepyowl.core.data.SessionCache
import ru.stenfredd.movies.core.data.WatchRepository import ru.stenfredd.sleepyowl.core.data.WatchRepository
import ru.stenfredd.movies.core.data.model.ItemDetails import ru.stenfredd.sleepyowl.core.data.model.ItemDetails
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.core.data.model.PersonKind import ru.stenfredd.sleepyowl.core.data.model.PersonKind
import ru.stenfredd.movies.playback.api.StreamSelection import ru.stenfredd.sleepyowl.playback.api.StreamSelection
import ru.stenfredd.movies.playback.core.PlaybackPreferences import ru.stenfredd.sleepyowl.playback.core.PlaybackPreferences
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.components.RemoteImageSpec import ru.stenfredd.sleepyowl.ui.components.RemoteImageSpec
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import timber.log.Timber import timber.log.Timber
import java.util.Locale import java.util.Locale
import java.util.UUID import java.util.UUID

View File

@@ -1,9 +1,9 @@
package ru.stenfredd.movies.ui.details package ru.stenfredd.sleepyowl.ui.details
import ru.stenfredd.movies.core.data.model.AudioTrack import ru.stenfredd.sleepyowl.core.data.model.AudioTrack
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.core.data.model.SubtitleTrack import ru.stenfredd.sleepyowl.core.data.model.SubtitleTrack
import ru.stenfredd.movies.core.data.model.VideoRange import ru.stenfredd.sleepyowl.core.data.model.VideoRange
import java.util.Locale import java.util.Locale
/** How the item page names languages, codecs and formats: "Русский", "TrueHD Atmos 7.1", "HEVC 2160p HDR10 · 62.4 ГБ". */ /** How the item page names languages, codecs and formats: "Русский", "TrueHD Atmos 7.1", "HEVC 2160p HDR10 · 62.4 ГБ". */

View File

@@ -1,8 +1,8 @@
package ru.stenfredd.movies.ui.details package ru.stenfredd.sleepyowl.ui.details
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.playback.core.PlaybackPreferences import ru.stenfredd.sleepyowl.playback.core.PlaybackPreferences
import ru.stenfredd.movies.playback.core.TrackPick import ru.stenfredd.sleepyowl.playback.core.TrackPick
import java.util.UUID import java.util.UUID
/** Audio and subtitle choices of a file as the movie page and the series tray show them. */ /** Audio and subtitle choices of a file as the movie page and the series tray show them. */

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.favorites package ru.stenfredd.sleepyowl.ui.favorites
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -22,20 +22,20 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AnchoredScrolling import ru.stenfredd.sleepyowl.ui.components.AnchoredScrolling
import ru.stenfredd.movies.ui.components.Chip import ru.stenfredd.sleepyowl.ui.components.Chip
import ru.stenfredd.movies.ui.components.PosterCard import ru.stenfredd.sleepyowl.ui.components.PosterCard
import ru.stenfredd.movies.ui.components.anchorViewport import ru.stenfredd.sleepyowl.ui.components.anchorViewport
import ru.stenfredd.movies.ui.components.anchoredRow import ru.stenfredd.sleepyowl.ui.components.anchoredRow
import ru.stenfredd.movies.ui.components.fullItem import ru.stenfredd.sleepyowl.ui.components.fullItem
import ru.stenfredd.movies.ui.focus.ForgetMissing import ru.stenfredd.sleepyowl.ui.focus.ForgetMissing
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** Favourites tab (mockup screen «Избранное»): title with the count, library filter chips, grid of posters. */ /** Favourites tab (mockup screen «Избранное»): title with the count, library filter chips, grid of posters. */
@Composable @Composable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.favorites package ru.stenfredd.sleepyowl.ui.favorites
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -15,15 +15,15 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.SessionCache import ru.stenfredd.sleepyowl.core.data.SessionCache
import ru.stenfredd.movies.core.data.WatchRepository import ru.stenfredd.sleepyowl.core.data.WatchRepository
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.LibraryView import ru.stenfredd.sleepyowl.core.data.model.LibraryView
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import ru.stenfredd.movies.ui.model.plural import ru.stenfredd.sleepyowl.ui.model.plural
import timber.log.Timber import timber.log.Timber
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.focus package ru.stenfredd.sleepyowl.ui.focus
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.home package ru.stenfredd.sleepyowl.ui.home
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -20,20 +20,20 @@ import androidx.compose.ui.focus.focusRestorer
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AnchoredScrolling import ru.stenfredd.sleepyowl.ui.components.AnchoredScrolling
import ru.stenfredd.movies.ui.components.anchorViewport import ru.stenfredd.sleepyowl.ui.components.anchorViewport
import ru.stenfredd.movies.ui.components.anchoredRow import ru.stenfredd.sleepyowl.ui.components.anchoredRow
import ru.stenfredd.movies.ui.components.ContentRow import ru.stenfredd.sleepyowl.ui.components.ContentRow
import ru.stenfredd.movies.ui.components.FeaturedCard import ru.stenfredd.sleepyowl.ui.components.FeaturedCard
import ru.stenfredd.movies.ui.components.PosterCard import ru.stenfredd.sleepyowl.ui.components.PosterCard
import ru.stenfredd.movies.ui.components.SectionTitle import ru.stenfredd.sleepyowl.ui.components.SectionTitle
import ru.stenfredd.movies.ui.components.WideCard import ru.stenfredd.sleepyowl.ui.components.WideCard
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
@Composable @Composable
fun HomeScreen(onOpen: (Screen) -> Unit, vm: HomeViewModel = hiltViewModel()) { fun HomeScreen(onOpen: (Screen) -> Unit, vm: HomeViewModel = hiltViewModel()) {
@@ -84,7 +84,7 @@ fun HomeScreen(onOpen: (Screen) -> Unit, vm: HomeViewModel = hiltViewModel()) {
} }
@Composable @Composable
private fun ContinueGrid(state: HomeState, focus: ru.stenfredd.movies.ui.focus.ScreenFocus, open: (String) -> Unit) { private fun ContinueGrid(state: HomeState, focus: ru.stenfredd.sleepyowl.ui.focus.ScreenFocus, open: (String) -> Unit) {
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) { Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
state.continueItems.chunked(2).forEach { pair -> state.continueItems.chunked(2).forEach { pair ->
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) { Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.home package ru.stenfredd.sleepyowl.ui.home
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -12,14 +12,14 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.stenfredd.movies.core.data.HomeContent import ru.stenfredd.sleepyowl.core.data.HomeContent
import ru.stenfredd.movies.core.data.HomeRepository import ru.stenfredd.sleepyowl.core.data.HomeRepository
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.FeaturedModel import ru.stenfredd.sleepyowl.ui.components.FeaturedModel
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.components.WideModel import ru.stenfredd.sleepyowl.ui.components.WideModel
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,6 +1,6 @@
package ru.stenfredd.movies.ui.library package ru.stenfredd.sleepyowl.ui.library
import ru.stenfredd.movies.core.data.model.ItemSort import ru.stenfredd.sleepyowl.core.data.model.ItemSort
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.library package ru.stenfredd.sleepyowl.ui.library
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -46,27 +46,27 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AnchoredScroll import ru.stenfredd.sleepyowl.ui.components.AnchoredScroll
import ru.stenfredd.movies.ui.components.AnchoredScrolling import ru.stenfredd.sleepyowl.ui.components.AnchoredScrolling
import ru.stenfredd.movies.ui.components.Chip import ru.stenfredd.sleepyowl.ui.components.Chip
import ru.stenfredd.movies.ui.components.ContentRow import ru.stenfredd.sleepyowl.ui.components.ContentRow
import ru.stenfredd.movies.ui.components.DefaultScrolling import ru.stenfredd.sleepyowl.ui.components.DefaultScrolling
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.PosterCard import ru.stenfredd.sleepyowl.ui.components.PosterCard
import ru.stenfredd.movies.ui.components.WideCard import ru.stenfredd.sleepyowl.ui.components.WideCard
import ru.stenfredd.movies.ui.components.anchorViewport import ru.stenfredd.sleepyowl.ui.components.anchorViewport
import ru.stenfredd.movies.ui.components.anchoredRow import ru.stenfredd.sleepyowl.ui.components.anchoredRow
import ru.stenfredd.movies.ui.components.bleed import ru.stenfredd.sleepyowl.ui.components.bleed
import ru.stenfredd.movies.ui.components.fullItem import ru.stenfredd.sleepyowl.ui.components.fullItem
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** /**
* The library tab (mockup screen «Медиатека»): library tiles on top; under them, for the selected library, * The library tab (mockup screen «Медиатека»): library tiles on top; under them, for the selected library,

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.library package ru.stenfredd.sleepyowl.ui.library
import android.os.SystemClock import android.os.SystemClock
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@@ -18,24 +18,24 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.SessionCache import ru.stenfredd.sleepyowl.core.data.SessionCache
import ru.stenfredd.movies.core.data.WatchRepository import ru.stenfredd.sleepyowl.core.data.WatchRepository
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemQuery import ru.stenfredd.sleepyowl.core.data.model.ItemQuery
import ru.stenfredd.movies.core.data.model.ItemSort import ru.stenfredd.sleepyowl.core.data.model.ItemSort
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.LibraryType import ru.stenfredd.sleepyowl.core.data.model.LibraryType
import ru.stenfredd.movies.core.data.model.LibraryView import ru.stenfredd.sleepyowl.core.data.model.LibraryView
import ru.stenfredd.movies.core.data.model.itemKinds import ru.stenfredd.sleepyowl.core.data.model.itemKinds
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.components.WideModel import ru.stenfredd.sleepyowl.ui.components.WideModel
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import ru.stenfredd.movies.ui.model.daysAgo import ru.stenfredd.sleepyowl.ui.model.daysAgo
import ru.stenfredd.movies.ui.model.plural import ru.stenfredd.sleepyowl.ui.model.plural
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import timber.log.Timber import timber.log.Timber
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.library package ru.stenfredd.sleepyowl.ui.library
import android.content.Context import android.content.Context
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -31,7 +31,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
/** A tile's background in its two looks: the selected library's mosaic is brighter. */ /** A tile's background in its two looks: the selected library's mosaic is brighter. */
@Immutable @Immutable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.login package ru.stenfredd.sleepyowl.ui.login
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
@@ -31,7 +31,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.withFrameNanos import androidx.compose.runtime.withFrameNanos
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.focus.focusProperties import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -48,23 +47,25 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.components.KeyboardLift import ru.stenfredd.sleepyowl.ui.components.KeyboardLift
import ru.stenfredd.movies.ui.components.LocalKeyboardLift import ru.stenfredd.sleepyowl.ui.components.LocalKeyboardLift
import ru.stenfredd.movies.ui.components.liftForKeyboard import ru.stenfredd.sleepyowl.ui.components.OwlMark
import ru.stenfredd.movies.ui.components.StatusDot import ru.stenfredd.sleepyowl.ui.components.liftForKeyboard
import ru.stenfredd.movies.ui.components.TextInput import ru.stenfredd.sleepyowl.ui.components.StatusDot
import ru.stenfredd.movies.ui.components.dashedBorder import ru.stenfredd.sleepyowl.ui.components.TextInput
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.Wordmark
import ru.stenfredd.movies.ui.components.rememberTextInputState import ru.stenfredd.sleepyowl.ui.components.dashedBorder
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.components.rememberTextInputState
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.sleepyowl.ui.theme.AppType
/** Login flow: server → profile → login, see [LoginViewModel]. Sizes are the mockup's px / 2. */ /** Login flow: server → profile → login, see [LoginViewModel]. Sizes are the mockup's px / 2. */
@Composable @Composable
@@ -77,7 +78,7 @@ fun LoginScreen(onDone: () -> Unit, vm: LoginViewModel = hiltViewModel()) {
val lift = remember { KeyboardLift() } val lift = remember { KeyboardLift() }
Box(Modifier.fillMaxSize().liftForKeyboard(lift)) { Box(Modifier.fillMaxSize().liftForKeyboard(lift)) {
CompositionLocalProvider(LocalKeyboardLift provides lift) { CompositionLocalProvider(LocalKeyboardLift provides lift) {
Logo(Modifier.padding(start = 60.dp, top = 32.dp)) Logo(Modifier.padding(start = 60.dp, top = 29.dp))
StepChain(state.step, Modifier.align(Alignment.TopEnd).padding(end = 60.dp, top = 35.dp)) StepChain(state.step, Modifier.align(Alignment.TopEnd).padding(end = 60.dp, top = 35.dp))
val focus = vm.focus.getValue(state.step) val focus = vm.focus.getValue(state.step)
key(state.step) { key(state.step) {
@@ -105,17 +106,12 @@ private fun hint(state: LoginState) = when (state.step) {
// ---- Header ---- // ---- Header ----
/** Neutral placeholder logo until the app has a name (same as the side rail's). */ /** Same as the open side rail's. */
@Composable @Composable
private fun Logo(modifier: Modifier = Modifier) { private fun Logo(modifier: Modifier = Modifier) {
Row(modifier, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) { Row(modifier, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Spacer( OwlMark()
Modifier.size(9.dp).drawBehind { Wordmark()
drawCircle(AppColors.AccentStrong.copy(alpha = 0.35f), radius = size.minDimension)
drawCircle(AppColors.AccentStrong)
},
)
BasicText("movies", style = AppType.Display.copy(fontSize = 18.sp, fontWeight = FontWeight.Bold, letterSpacing = 0.em))
} }
} }

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.login package ru.stenfredd.sleepyowl.ui.login
import android.os.SystemClock import android.os.SystemClock
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@@ -19,14 +19,14 @@ import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.jellyfin.sdk.api.client.exception.InvalidStatusException import org.jellyfin.sdk.api.client.exception.InvalidStatusException
import ru.stenfredd.movies.core.jellyfin.Account import ru.stenfredd.sleepyowl.core.jellyfin.Account
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import ru.stenfredd.movies.core.jellyfin.PublicUser import ru.stenfredd.sleepyowl.core.jellyfin.PublicUser
import ru.stenfredd.movies.core.jellyfin.QuickConnectExpiredException import ru.stenfredd.sleepyowl.core.jellyfin.QuickConnectExpiredException
import ru.stenfredd.movies.core.jellyfin.Server import ru.stenfredd.sleepyowl.core.jellyfin.Server
import ru.stenfredd.movies.core.jellyfin.ServerLogin import ru.stenfredd.sleepyowl.core.jellyfin.ServerLogin
import ru.stenfredd.movies.core.jellyfin.ServerNotFoundException import ru.stenfredd.sleepyowl.core.jellyfin.ServerNotFoundException
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import timber.log.Timber import timber.log.Timber
import java.time.LocalDate import java.time.LocalDate
import java.time.ZoneId import java.time.ZoneId

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.login package ru.stenfredd.sleepyowl.ui.login
import android.graphics.Bitmap import android.graphics.Bitmap
import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.graphics.ImageBitmap

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.menu package ru.stenfredd.sleepyowl.ui.menu
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -49,16 +49,16 @@ import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.stenfredd.movies.core.data.WatchRepository import ru.stenfredd.sleepyowl.core.data.WatchRepository
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.model.plural import ru.stenfredd.sleepyowl.ui.model.plural
import ru.stenfredd.movies.ui.player.SidePanel import ru.stenfredd.sleepyowl.ui.player.SidePanel
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import timber.log.Timber import timber.log.Timber
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,18 +1,18 @@
package ru.stenfredd.movies.ui.model package ru.stenfredd.sleepyowl.ui.model
import android.content.Context import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import ru.stenfredd.movies.core.data.ImageUrls import ru.stenfredd.sleepyowl.core.data.ImageUrls
import ru.stenfredd.movies.core.data.model.ImageRef import ru.stenfredd.sleepyowl.core.data.model.ImageRef
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.FeaturedModel import ru.stenfredd.sleepyowl.ui.components.FeaturedModel
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.components.RemoteImageSpec import ru.stenfredd.sleepyowl.ui.components.RemoteImageSpec
import ru.stenfredd.movies.ui.components.WideModel import ru.stenfredd.sleepyowl.ui.components.WideModel
import ru.stenfredd.movies.ui.menu.WatchTarget import ru.stenfredd.sleepyowl.ui.menu.WatchTarget
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt import kotlin.math.roundToInt

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.model package ru.stenfredd.sleepyowl.ui.model
import java.time.Instant import java.time.Instant
import java.time.LocalDate import java.time.LocalDate

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.person package ru.stenfredd.sleepyowl.ui.person
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -22,20 +22,20 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AnchoredScrolling import ru.stenfredd.sleepyowl.ui.components.AnchoredScrolling
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.PosterCard import ru.stenfredd.sleepyowl.ui.components.PosterCard
import ru.stenfredd.movies.ui.components.RemoteImage import ru.stenfredd.sleepyowl.ui.components.RemoteImage
import ru.stenfredd.movies.ui.components.anchorViewport import ru.stenfredd.sleepyowl.ui.components.anchorViewport
import ru.stenfredd.movies.ui.components.anchoredRow import ru.stenfredd.sleepyowl.ui.components.anchoredRow
import ru.stenfredd.movies.ui.components.fullItem import ru.stenfredd.sleepyowl.ui.components.fullItem
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** /**
* A person (not in the mockup, built in its style like the favourites screen): photo, name, "12 фильмов · 3 сериала", * A person (not in the mockup, built in its style like the favourites screen): photo, name, "12 фильмов · 3 сериала",

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.person package ru.stenfredd.sleepyowl.ui.person
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -16,14 +16,14 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.SessionCache import ru.stenfredd.sleepyowl.core.data.SessionCache
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.components.RemoteImageSpec import ru.stenfredd.sleepyowl.ui.components.RemoteImageSpec
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import ru.stenfredd.movies.ui.model.plural import ru.stenfredd.sleepyowl.ui.model.plural
import timber.log.Timber import timber.log.Timber
import java.util.UUID import java.util.UUID
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@@ -21,15 +21,15 @@ import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text import androidx.tv.material3.Text
import org.jellyfin.sdk.model.api.MediaStreamType import org.jellyfin.sdk.model.api.MediaStreamType
import org.jellyfin.sdk.model.api.PlayMethod import org.jellyfin.sdk.model.api.PlayMethod
import ru.stenfredd.movies.playback.api.Codecs import ru.stenfredd.sleepyowl.playback.api.Codecs
import ru.stenfredd.movies.playback.api.DolbyVisionSwitchable import ru.stenfredd.sleepyowl.playback.api.DolbyVisionSwitchable
import ru.stenfredd.movies.playback.api.EngineId import ru.stenfredd.sleepyowl.playback.api.EngineId
import ru.stenfredd.movies.playback.api.VideoPathSwitchable import ru.stenfredd.sleepyowl.playback.api.VideoPathSwitchable
import ru.stenfredd.movies.playback.core.PlaybackSession import ru.stenfredd.sleepyowl.playback.core.PlaybackSession
import ru.stenfredd.movies.playback.core.PlaybackUiState import ru.stenfredd.sleepyowl.playback.core.PlaybackUiState
import ru.stenfredd.movies.playback.core.describe import ru.stenfredd.sleepyowl.playback.core.describe
import ru.stenfredd.movies.playback.exo.ExoEngineProvider import ru.stenfredd.sleepyowl.playback.exo.ExoEngineProvider
import ru.stenfredd.movies.playback.vlc.VlcEngineProvider import ru.stenfredd.sleepyowl.playback.vlc.VlcEngineProvider
/* /*
* Debug builds only: the prototype's numbered playback variants (badge in the corner, digit keys 0–9, MENU opens the * Debug builds only: the prototype's numbered playback variants (badge in the corner, digit keys 0–9, MENU opens the

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -48,16 +48,16 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.components.ImageShade import ru.stenfredd.sleepyowl.ui.components.ImageShade
import ru.stenfredd.movies.ui.components.ProgressLine import ru.stenfredd.sleepyowl.ui.components.ProgressLine
import ru.stenfredd.movies.ui.components.RemoteImage import ru.stenfredd.sleepyowl.ui.components.RemoteImage
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import java.util.UUID import java.util.UUID
/** Height of the drawer; the controls move up by this much while it is open. */ /** Height of the drawer; the controls move up by this much while it is open. */

View File

@@ -1,17 +1,17 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import org.jellyfin.sdk.model.api.PlayMethod import org.jellyfin.sdk.model.api.PlayMethod
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.core.data.model.VideoRange import ru.stenfredd.sleepyowl.core.data.model.VideoRange
import ru.stenfredd.movies.playback.api.DolbyVisionSwitchable import ru.stenfredd.sleepyowl.playback.api.DolbyVisionSwitchable
import ru.stenfredd.movies.playback.api.PlaybackEngine import ru.stenfredd.sleepyowl.playback.api.PlaybackEngine
import ru.stenfredd.movies.playback.api.VideoPathSwitchable import ru.stenfredd.sleepyowl.playback.api.VideoPathSwitchable
import ru.stenfredd.movies.playback.core.PlaybackUiState import ru.stenfredd.sleepyowl.playback.core.PlaybackUiState
import ru.stenfredd.movies.ui.details.MediaLabels import ru.stenfredd.sleepyowl.ui.details.MediaLabels
import ru.stenfredd.movies.ui.details.TrackOption import ru.stenfredd.sleepyowl.ui.details.TrackOption
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import java.util.Locale import java.util.Locale
/** Audio and subtitle choices of the file being played. Subtitles start with "Выкл" (index null). */ /** Audio and subtitle choices of the file being played. Subtitles start with "Выкл" (index null). */

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -33,13 +33,13 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.components.RemoteImage import ru.stenfredd.sleepyowl.ui.components.RemoteImage
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** Without known credits the card shows this long before the end of an episode that has a next one. */ /** Without known credits the card shows this long before the end of an episode that has a next one. */
internal const val NEXT_PROMPT_MS = 30_000L internal const val NEXT_PROMPT_MS = 30_000L

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -39,16 +39,16 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ru.stenfredd.movies.core.data.model.MediaSegment import ru.stenfredd.sleepyowl.core.data.model.MediaSegment
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import kotlin.math.roundToInt import kotlin.math.roundToInt
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.components.StatusDot import ru.stenfredd.sleepyowl.ui.components.StatusDot
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.shell.Clock import ru.stenfredd.sleepyowl.ui.shell.Clock
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/* /*
* The player's controls ("OSD") as drawn in the mockup's player screen; sizes are the mockup's px / 2. * The player's controls ("OSD") as drawn in the mockup's player screen; sizes are the mockup's px / 2.

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -46,14 +46,14 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.MinimalScrolling import ru.stenfredd.sleepyowl.ui.components.MinimalScrolling
import ru.stenfredd.movies.ui.components.SecondaryButton import ru.stenfredd.sleepyowl.ui.components.SecondaryButton
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.details.TrackOption import ru.stenfredd.sleepyowl.ui.details.TrackOption
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
enum class PlayerPanel { Audio, Subtitles, Quality, Info } enum class PlayerPanel { Audio, Subtitles, Quality, Info }

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
import android.widget.FrameLayout import android.widget.FrameLayout
@@ -49,24 +49,24 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.LifecycleEventEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import ru.stenfredd.movies.BuildConfig import ru.stenfredd.sleepyowl.BuildConfig
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.core.data.model.MediaSegment import ru.stenfredd.sleepyowl.core.data.model.MediaSegment
import ru.stenfredd.movies.core.data.model.VideoRange import ru.stenfredd.sleepyowl.core.data.model.VideoRange
import ru.stenfredd.movies.core.data.toMediaInfo import ru.stenfredd.sleepyowl.core.data.toMediaInfo
import ru.stenfredd.movies.playback.api.DolbyVisionSwitchable import ru.stenfredd.sleepyowl.playback.api.DolbyVisionSwitchable
import ru.stenfredd.movies.playback.api.EngineId import ru.stenfredd.sleepyowl.playback.api.EngineId
import ru.stenfredd.movies.playback.api.EngineState import ru.stenfredd.sleepyowl.playback.api.EngineState
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.playback.api.VideoPathSwitchable import ru.stenfredd.sleepyowl.playback.api.VideoPathSwitchable
import ru.stenfredd.movies.playback.core.PlaybackSession import ru.stenfredd.sleepyowl.playback.core.PlaybackSession
import ru.stenfredd.movies.playback.core.PlaybackUiState import ru.stenfredd.sleepyowl.playback.core.PlaybackUiState
import ru.stenfredd.movies.playback.exo.ExoEngineProvider import ru.stenfredd.sleepyowl.playback.exo.ExoEngineProvider
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.SecondaryButton import ru.stenfredd.sleepyowl.ui.components.SecondaryButton
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import java.time.LocalTime import java.time.LocalTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.UUID import java.util.UUID

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -24,14 +24,14 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ru.stenfredd.movies.core.data.model.MediaSegment import ru.stenfredd.sleepyowl.core.data.model.MediaSegment
import ru.stenfredd.movies.core.data.model.SegmentKind import ru.stenfredd.sleepyowl.core.data.model.SegmentKind
import ru.stenfredd.movies.playback.core.PlaybackDefaults import ru.stenfredd.sleepyowl.playback.core.PlaybackDefaults
import ru.stenfredd.movies.playback.core.SkipMode import ru.stenfredd.sleepyowl.playback.core.SkipMode
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import java.util.UUID import java.util.UUID
/** The server's segments of one item (they arrive after the item starts playing). */ /** The server's segments of one item (they arrive after the item starts playing). */

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.player package ru.stenfredd.sleepyowl.ui.player
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -14,26 +14,26 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.model.ItemDetails import ru.stenfredd.sleepyowl.core.data.model.ItemDetails
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.PersonKind import ru.stenfredd.sleepyowl.core.data.model.PersonKind
import ru.stenfredd.movies.playback.api.EngineId import ru.stenfredd.sleepyowl.playback.api.EngineId
import ru.stenfredd.movies.playback.api.StreamSelection import ru.stenfredd.sleepyowl.playback.api.StreamSelection
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.playback.core.DeviceCapabilitiesProbe import ru.stenfredd.sleepyowl.playback.core.DeviceCapabilitiesProbe
import ru.stenfredd.movies.playback.core.EngineSelector import ru.stenfredd.sleepyowl.playback.core.EngineSelector
import ru.stenfredd.movies.playback.core.PlaybackDefaults import ru.stenfredd.sleepyowl.playback.core.PlaybackDefaults
import ru.stenfredd.movies.playback.core.PlaybackPreferences import ru.stenfredd.sleepyowl.playback.core.PlaybackPreferences
import ru.stenfredd.movies.playback.core.PlaybackSession import ru.stenfredd.sleepyowl.playback.core.PlaybackSession
import ru.stenfredd.movies.playback.core.PlaybackSessionFactory import ru.stenfredd.sleepyowl.playback.core.PlaybackSessionFactory
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.RemoteImageSpec import ru.stenfredd.sleepyowl.ui.components.RemoteImageSpec
import ru.stenfredd.movies.ui.model.plural import ru.stenfredd.sleepyowl.ui.model.plural
import ru.stenfredd.movies.ui.details.CastModel import ru.stenfredd.sleepyowl.ui.details.CastModel
import ru.stenfredd.movies.ui.details.MediaLabels import ru.stenfredd.sleepyowl.ui.details.MediaLabels
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import timber.log.Timber import timber.log.Timber
import java.util.Locale import java.util.Locale
import java.util.UUID import java.util.UUID

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.search package ru.stenfredd.sleepyowl.ui.search
import android.view.KeyEvent as NativeKeyEvent import android.view.KeyEvent as NativeKeyEvent
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -48,26 +48,26 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AnchoredScrolling import ru.stenfredd.sleepyowl.ui.components.AnchoredScrolling
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.Chip import ru.stenfredd.sleepyowl.ui.components.Chip
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.components.PosterCard import ru.stenfredd.sleepyowl.ui.components.PosterCard
import ru.stenfredd.movies.ui.components.RemoteImage import ru.stenfredd.sleepyowl.ui.components.RemoteImage
import ru.stenfredd.movies.ui.components.anchorViewport import ru.stenfredd.sleepyowl.ui.components.anchorViewport
import ru.stenfredd.movies.ui.components.anchoredRow import ru.stenfredd.sleepyowl.ui.components.anchoredRow
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.components.fullItem import ru.stenfredd.sleepyowl.ui.components.fullItem
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** /**
* Search tab (mockup screen «Поиск»): on the left the query and an on-screen keyboard (Russian; one key switches * Search tab (mockup screen «Поиск»): on the left the query and an on-screen keyboard (Russian; one key switches
@@ -269,10 +269,10 @@ private fun Results(state: SearchState, focus: ScreenFocus, vm: SearchViewModel,
} }
private fun androidx.compose.foundation.lazy.grid.LazyGridScope.posters( private fun androidx.compose.foundation.lazy.grid.LazyGridScope.posters(
list: List<ru.stenfredd.movies.ui.components.PosterModel>, list: List<ru.stenfredd.sleepyowl.ui.components.PosterModel>,
focus: ScreenFocus, focus: ScreenFocus,
open: (String) -> Unit, open: (String) -> Unit,
anchored: ru.stenfredd.movies.ui.components.AnchoredScroll<*>, anchored: ru.stenfredd.sleepyowl.ui.components.AnchoredScroll<*>,
) { ) {
items(list, key = { it.key }, contentType = { "poster" }) { p -> items(list, key = { it.key }, contentType = { "poster" }) { p ->
PosterCard(p, { open(p.key) }, Modifier.padding(bottom = 18.dp).anchoredRow(anchored).remembered(focus, p.key)) PosterCard(p, { open(p.key) }, Modifier.padding(bottom = 18.dp).anchoredRow(anchored).remembered(focus, p.key))

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.search package ru.stenfredd.sleepyowl.ui.search
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -17,13 +17,13 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.SearchHistory import ru.stenfredd.sleepyowl.core.data.SearchHistory
import ru.stenfredd.movies.core.data.model.Person import ru.stenfredd.sleepyowl.core.data.model.Person
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.PosterModel import ru.stenfredd.sleepyowl.ui.components.PosterModel
import ru.stenfredd.movies.ui.components.RemoteImageSpec import ru.stenfredd.sleepyowl.ui.components.RemoteImageSpec
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.series package ru.stenfredd.sleepyowl.ui.series
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
@@ -69,26 +69,26 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.CircleButton import ru.stenfredd.sleepyowl.ui.components.CircleButton
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.FormatBadge import ru.stenfredd.sleepyowl.ui.components.FormatBadge
import ru.stenfredd.movies.ui.components.MinimalScrolling import ru.stenfredd.sleepyowl.ui.components.MinimalScrolling
import ru.stenfredd.movies.ui.components.PrimaryButton import ru.stenfredd.sleepyowl.ui.components.PrimaryButton
import ru.stenfredd.movies.ui.components.ProgressLine import ru.stenfredd.sleepyowl.ui.components.ProgressLine
import ru.stenfredd.movies.ui.components.RemoteImage import ru.stenfredd.sleepyowl.ui.components.RemoteImage
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.details.Backdrop import ru.stenfredd.sleepyowl.ui.details.Backdrop
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.menu.LocalWatchMenu import ru.stenfredd.sleepyowl.ui.menu.LocalWatchMenu
import ru.stenfredd.movies.ui.menu.clickableWithMenu import ru.stenfredd.sleepyowl.ui.menu.clickableWithMenu
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
import kotlin.math.floor import kotlin.math.floor
import kotlin.math.roundToInt import kotlin.math.roundToInt

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.series package ru.stenfredd.sleepyowl.ui.series
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -40,15 +40,15 @@ import androidx.compose.ui.input.key.type
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.ui.components.MinimalScrolling import ru.stenfredd.sleepyowl.ui.components.MinimalScrolling
import ru.stenfredd.movies.ui.player.PanelChips import ru.stenfredd.sleepyowl.ui.player.PanelChips
import ru.stenfredd.movies.ui.player.PanelList import ru.stenfredd.sleepyowl.ui.player.PanelList
import ru.stenfredd.movies.ui.player.PanelSection import ru.stenfredd.sleepyowl.ui.player.PanelSection
import ru.stenfredd.movies.ui.player.SubtitleChoices import ru.stenfredd.sleepyowl.ui.player.SubtitleChoices
import ru.stenfredd.movies.ui.player.toChoices import ru.stenfredd.sleepyowl.ui.player.toChoices
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** /**
* "Аудио и субтитры" tray at the bottom of the series page: audio, subtitles and their look, applied at once and * "Аудио и субтитры" tray at the bottom of the series page: audio, subtitles and their look, applied at once and

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.series package ru.stenfredd.sleepyowl.ui.series
import android.os.SystemClock import android.os.SystemClock
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@@ -20,25 +20,25 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.data.ImageUrls import ru.stenfredd.sleepyowl.core.data.ImageUrls
import ru.stenfredd.movies.core.data.LibraryRepository import ru.stenfredd.sleepyowl.core.data.LibraryRepository
import ru.stenfredd.movies.core.data.SessionCache import ru.stenfredd.sleepyowl.core.data.SessionCache
import ru.stenfredd.movies.core.data.WatchRepository import ru.stenfredd.sleepyowl.core.data.WatchRepository
import ru.stenfredd.movies.core.data.model.ItemDetails import ru.stenfredd.sleepyowl.core.data.model.ItemDetails
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.playback.core.PlaybackPreferences import ru.stenfredd.sleepyowl.playback.core.PlaybackPreferences
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.RemoteImageSpec import ru.stenfredd.sleepyowl.ui.components.RemoteImageSpec
import ru.stenfredd.movies.ui.details.MediaLabels import ru.stenfredd.sleepyowl.ui.details.MediaLabels
import ru.stenfredd.movies.ui.details.TrackChoices import ru.stenfredd.sleepyowl.ui.details.TrackChoices
import ru.stenfredd.movies.ui.details.TrackOption import ru.stenfredd.sleepyowl.ui.details.TrackOption
import ru.stenfredd.movies.ui.menu.WatchTarget import ru.stenfredd.sleepyowl.ui.menu.WatchTarget
import ru.stenfredd.movies.ui.model.CardMapper import ru.stenfredd.sleepyowl.ui.model.CardMapper
import ru.stenfredd.movies.ui.player.PlayerLabels import ru.stenfredd.sleepyowl.ui.player.PlayerLabels
import ru.stenfredd.movies.ui.model.plural import ru.stenfredd.sleepyowl.ui.model.plural
import timber.log.Timber import timber.log.Timber
import java.time.Instant import java.time.Instant
import java.time.ZoneId import java.time.ZoneId

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.settings package ru.stenfredd.sleepyowl.ui.settings
import android.view.KeyEvent as AndroidKeyEvent import android.view.KeyEvent as AndroidKeyEvent
import androidx.compose.foundation.focusable import androidx.compose.foundation.focusable
@@ -34,10 +34,10 @@ import androidx.compose.ui.unit.sp
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppType
/** Text of a licence from `assets/licenses`; ↑/↓ scroll it (a page at a time with ←/→ or channel keys). */ /** Text of a licence from `assets/licenses`; ↑/↓ scroll it (a page at a time with ←/→ or channel keys). */
@Composable @Composable

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.settings package ru.stenfredd.sleepyowl.ui.settings
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
@@ -8,7 +8,7 @@ data class Component(val name: String, val note: String?, val license: String, v
/** "О приложении": the app itself first, then what it is built from (playback first: it carries the copyleft licences). */ /** "О приложении": the app itself first, then what it is built from (playback first: it carries the copyleft licences). */
internal object Licenses { internal object Licenses {
val app = Component("Movies", "это приложение", "GPL-3.0", "GPL-3.0.txt") val app = Component("SleepyOwl", "это приложение", "GPL-3.0", "GPL-3.0.txt")
val components = listOf( val components = listOf(
Component("libVLC", "VideoLAN, второй движок воспроизведения", "LGPL-2.1", "LGPL-2.1.txt"), Component("libVLC", "VideoLAN, второй движок воспроизведения", "LGPL-2.1", "LGPL-2.1.txt"),

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.settings package ru.stenfredd.sleepyowl.ui.settings
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@@ -54,31 +54,33 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import ru.stenfredd.movies.core.data.LanguageSettings import ru.stenfredd.sleepyowl.core.data.LanguageSettings
import ru.stenfredd.movies.core.data.SubtitleMode import ru.stenfredd.sleepyowl.core.data.SubtitleMode
import ru.stenfredd.movies.core.jellyfin.Account import ru.stenfredd.sleepyowl.core.jellyfin.Account
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.playback.api.VideoPathSwitchable import ru.stenfredd.sleepyowl.playback.api.VideoPathSwitchable
import ru.stenfredd.movies.playback.core.PlaybackDefaults import ru.stenfredd.sleepyowl.playback.core.PlaybackDefaults
import ru.stenfredd.movies.playback.core.SkipMode import ru.stenfredd.sleepyowl.playback.core.SkipMode
import ru.stenfredd.movies.ui.Screen import ru.stenfredd.sleepyowl.ui.Screen
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.Chip import ru.stenfredd.sleepyowl.ui.components.Chip
import ru.stenfredd.movies.ui.components.FocusStyle import ru.stenfredd.sleepyowl.ui.components.FocusStyle
import ru.stenfredd.movies.ui.components.MinimalScrolling import ru.stenfredd.sleepyowl.ui.components.MinimalScrolling
import ru.stenfredd.movies.ui.components.SecondaryButton import ru.stenfredd.sleepyowl.ui.components.OwlMark
import ru.stenfredd.movies.ui.components.focusCard import ru.stenfredd.sleepyowl.ui.components.SecondaryButton
import ru.stenfredd.movies.ui.focus.Restore import ru.stenfredd.sleepyowl.ui.components.Wordmark
import ru.stenfredd.movies.ui.focus.ScreenFocus import ru.stenfredd.sleepyowl.ui.components.focusCard
import ru.stenfredd.movies.ui.focus.rememberScreenFocus import ru.stenfredd.sleepyowl.ui.focus.Restore
import ru.stenfredd.movies.ui.focus.remembered import ru.stenfredd.sleepyowl.ui.focus.ScreenFocus
import ru.stenfredd.movies.ui.player.PlayerLabels import ru.stenfredd.sleepyowl.ui.focus.rememberScreenFocus
import ru.stenfredd.movies.ui.player.QualityCaps import ru.stenfredd.sleepyowl.ui.focus.remembered
import ru.stenfredd.movies.ui.player.SubtitleChoices import ru.stenfredd.sleepyowl.ui.player.PlayerLabels
import ru.stenfredd.movies.ui.player.SubtitlePreview import ru.stenfredd.sleepyowl.ui.player.QualityCaps
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.player.SubtitleChoices
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.player.SubtitlePreview
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.sleepyowl.ui.theme.AppType
/** Sections on the left; the focused one is shown on the right. */ /** Sections on the left; the focused one is shown on the right. */
private enum class Section(val title: String, val dot: Color) { private enum class Section(val title: String, val dot: Color) {
@@ -530,7 +532,10 @@ private fun InfoLine(key: String, value: String) {
@Composable @Composable
private fun AboutSection(vm: SettingsViewModel, focus: ScreenFocus, onOpen: (Screen) -> Unit) { private fun AboutSection(vm: SettingsViewModel, focus: ScreenFocus, onOpen: (Screen) -> Unit) {
Column(verticalArrangement = Arrangement.spacedBy(5.dp)) { Column(verticalArrangement = Arrangement.spacedBy(5.dp)) {
BasicText("Movies", style = AppType.Section.copy(fontSize = 18.sp, fontWeight = FontWeight.Bold)) Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
OwlMark()
Wordmark()
}
BasicText("Версия ${vm.about.version}", style = AppType.MonoMeta) BasicText("Версия ${vm.about.version}", style = AppType.MonoMeta)
BasicText(vm.about.device, style = AppType.MonoMeta.copy(color = AppColors.TextDim)) BasicText(vm.about.device, style = AppType.MonoMeta.copy(color = AppColors.TextDim))
} }

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.settings package ru.stenfredd.sleepyowl.ui.settings
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
@@ -21,17 +21,17 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.BuildConfig import ru.stenfredd.sleepyowl.BuildConfig
import ru.stenfredd.movies.core.data.LanguageSettings import ru.stenfredd.sleepyowl.core.data.LanguageSettings
import ru.stenfredd.movies.core.data.ServerInfo import ru.stenfredd.sleepyowl.core.data.ServerInfo
import ru.stenfredd.movies.core.data.UserSettingsRepository import ru.stenfredd.sleepyowl.core.data.UserSettingsRepository
import ru.stenfredd.movies.core.jellyfin.Account import ru.stenfredd.sleepyowl.core.jellyfin.Account
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import ru.stenfredd.movies.playback.api.SubtitleStyle import ru.stenfredd.sleepyowl.playback.api.SubtitleStyle
import ru.stenfredd.movies.playback.core.DeviceCapabilitiesProbe import ru.stenfredd.sleepyowl.playback.core.DeviceCapabilitiesProbe
import ru.stenfredd.movies.playback.core.PlaybackDefaults import ru.stenfredd.sleepyowl.playback.core.PlaybackDefaults
import ru.stenfredd.movies.playback.core.PlaybackPreferences import ru.stenfredd.sleepyowl.playback.core.PlaybackPreferences
import ru.stenfredd.movies.ui.TourEntry import ru.stenfredd.sleepyowl.ui.TourEntry
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.shell package ru.stenfredd.sleepyowl.ui.shell
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
@@ -43,7 +43,6 @@ import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.lerp import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.util.lerp import androidx.compose.ui.util.lerp
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@@ -51,12 +50,14 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import ru.stenfredd.movies.ui.components.AppIcon import ru.stenfredd.sleepyowl.ui.components.AppIcon
import ru.stenfredd.movies.ui.components.Avatar import ru.stenfredd.sleepyowl.ui.components.Avatar
import ru.stenfredd.movies.ui.components.Icon import ru.stenfredd.sleepyowl.ui.components.Icon
import ru.stenfredd.movies.ui.theme.AppColors import ru.stenfredd.sleepyowl.ui.components.OwlMark
import ru.stenfredd.movies.ui.theme.AppDimens import ru.stenfredd.sleepyowl.ui.components.Wordmark
import ru.stenfredd.movies.ui.theme.AppType import ru.stenfredd.sleepyowl.ui.theme.AppColors
import ru.stenfredd.sleepyowl.ui.theme.AppDimens
import ru.stenfredd.sleepyowl.ui.theme.AppType
import java.time.LocalTime import java.time.LocalTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.UUID import java.util.UUID
@@ -161,7 +162,7 @@ private fun Rail(
.padding(horizontal = 9.dp, vertical = 28.dp), .padding(horizontal = 9.dp, vertical = 28.dp),
verticalArrangement = Arrangement.spacedBy(5.dp), verticalArrangement = Arrangement.spacedBy(5.dp),
) { ) {
Logo(progress, Modifier.padding(start = 13.dp, bottom = 20.dp)) Logo(progress, Modifier.padding(start = 1.dp, bottom = 16.dp))
@Composable @Composable
fun item(tab: Tab) = RailItem( fun item(tab: Tab) = RailItem(
label = tab.label, label = tab.label,
@@ -198,25 +199,12 @@ private fun Rail(
} }
} }
/** Neutral placeholder logo until the app has a name: a glowing dot and the working title. */ /** The owl, centred over the items' icons; the wordmark shows with the open rail. */
@Composable @Composable
private fun Logo(progress: State<Float>, modifier: Modifier = Modifier) { private fun Logo(progress: State<Float>, modifier: Modifier = Modifier) {
Row(modifier.height(32.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) { Row(modifier, verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Box( OwlMark()
Modifier Wordmark(Modifier.graphicsLayer { alpha = progress.value })
.size(11.dp)
.drawBehind {
drawCircle(AppColors.AccentStrong.copy(alpha = 0.35f), radius = size.minDimension)
drawCircle(AppColors.AccentStrong)
},
)
BasicText(
"movies",
Modifier.graphicsLayer { alpha = progress.value },
style = AppType.Rail.copy(fontSize = AppType.Section.fontSize, fontWeight = FontWeight.Bold),
maxLines = 1,
softWrap = false,
)
} }
} }

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.theme package ru.stenfredd.sleepyowl.ui.theme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.tv.material3.MaterialTheme import androidx.tv.material3.MaterialTheme

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.ui.theme package ru.stenfredd.sleepyowl.ui.theme
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
@@ -10,7 +10,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ru.stenfredd.movies.R import ru.stenfredd.sleepyowl.R
/** /**
* Design tokens from `design/…/Jellyfin TV.dc.html`. The mockup is drawn at 1920×1080 px, * Design tokens from `design/…/Jellyfin TV.dc.html`. The mockup is drawn at 1920×1080 px,

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Нейтральный баннер Android TV (320×180), пока нет названия и логотипа: фиолетовый круг с «play». -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="320dp"
android:height="180dp"
android:viewportWidth="320"
android:viewportHeight="180">
<path android:fillColor="#0A0B10" android:pathData="M0,0h320v180h-320z" />
<path android:fillColor="#408F6BFF" android:pathData="M160,90m-62,0a62,62 0,1 1,124 0a62,62 0,1 1,-124 0" />
<path android:fillColor="#8F6BFF" android:pathData="M160,90m-40,0a40,40 0,1 1,80 0a40,40 0,1 1,-80 0" />
<path android:fillColor="#FFFFFF" android:pathData="M148,68 L148,112 L184,90 Z" />
</vector>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Иконка приложения (настройки ТВ, список приложений): сова из логотипа на его тёмно-синем фоне.
Картинки делает tools/logo/make_assets.py. -->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_owl" />
</adaptive-icon>

View File

@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="background">#0A0B10</color> <color name="background">#0A0B10</color>
<!-- Фон логотипа: под совой в иконке приложения. -->
<color name="ic_launcher_background">#050927</color>
</resources> </resources>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Рабочее название, пока нет настоящего. Меняется здесь и в логотипе (drawable/banner.xml, Shell.Logo). --> <!-- Название приложения. Логотип — design/logo/sleepyowl.png, картинки из него делает tools/logo/make_assets.py. -->
<string name="app_name">Movies</string> <string name="app_name">SleepyOwl</string>
</resources> </resources>

View File

@@ -3,7 +3,7 @@
<!-- Фон приложения — фон окна: без белой вспышки до первого кадра Compose, и экраны не рисуют свой фон. <!-- Фон приложения — фон окна: без белой вспышки до первого кадра Compose, и экраны не рисуют свой фон.
Сплошной цвет: GPU заливает его почти бесплатно. Сетка точек из макета стоила ~5 мс каждого кадра Сплошной цвет: GPU заливает его почти бесплатно. Сетка точек из макета стоила ~5 мс каждого кадра
на тестовом ТВ (он перерисовывает весь экран на каждом кадре) — убрана. --> на тестовом ТВ (он перерисовывает весь экран на каждом кадре) — убрана. -->
<style name="Theme.Movies" parent="@android:style/Theme.DeviceDefault.NoActionBar"> <style name="Theme.SleepyOwl" parent="@android:style/Theme.DeviceDefault.NoActionBar">
<item name="android:windowBackground">@color/background</item> <item name="android:windowBackground">@color/background</item>
<item name="android:colorBackground">@color/background</item> <item name="android:colorBackground">@color/background</item>
</style> </style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ plugins {
// Generates the app's baseline profile on a connected device (the test TV, logged in): // Generates the app's baseline profile on a connected device (the test TV, logged in):
// ./gradlew :app:generateReleaseBaselineProfile // ./gradlew :app:generateReleaseBaselineProfile
android { android {
namespace = "ru.stenfredd.movies.baselineprofile" namespace = "ru.stenfredd.sleepyowl.baselineprofile"
compileSdk = 37 compileSdk = 37
defaultConfig { defaultConfig {
minSdk = 28 minSdk = 28

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.baselineprofile package ru.stenfredd.sleepyowl.baselineprofile
import androidx.benchmark.macro.junit4.BaselineProfileRule import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -147,7 +147,7 @@ class BaselineProfileGenerator {
} }
private companion object { private companion object {
const val PACKAGE = "ru.stenfredd.movies" const val PACKAGE = "ru.stenfredd.sleepyowl"
const val ROWS = 6 const val ROWS = 6
const val LIBRARY_ROWS = 14 const val LIBRARY_ROWS = 14
} }

View File

@@ -6,7 +6,7 @@ plugins {
} }
android { android {
namespace = "ru.stenfredd.movies.core.data" namespace = "ru.stenfredd.sleepyowl.core.data"
compileSdk = 37 compileSdk = 37
defaultConfig { minSdk = 26 } defaultConfig { minSdk = 26 }
compileOptions { compileOptions {

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import android.content.Context import android.content.Context
import android.os.SystemClock import android.os.SystemClock
@@ -18,11 +18,11 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import ru.stenfredd.movies.core.data.model.ItemQuery import ru.stenfredd.sleepyowl.core.data.model.ItemQuery
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.LibraryView import ru.stenfredd.sleepyowl.core.data.model.LibraryView
import ru.stenfredd.movies.core.data.model.itemKinds import ru.stenfredd.sleepyowl.core.data.model.itemKinds
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap

View File

@@ -1,10 +1,10 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import org.jellyfin.sdk.api.client.extensions.imageApi import org.jellyfin.sdk.api.client.extensions.imageApi
import org.jellyfin.sdk.model.api.ImageType import org.jellyfin.sdk.model.api.ImageType
import ru.stenfredd.movies.core.data.model.ImageKind import ru.stenfredd.sleepyowl.core.data.model.ImageKind
import ru.stenfredd.movies.core.data.model.ImageRef import ru.stenfredd.sleepyowl.core.data.model.ImageRef
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
@@ -11,19 +11,19 @@ import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.ItemFilter import org.jellyfin.sdk.model.api.ItemFilter
import org.jellyfin.sdk.model.api.ItemSortBy import org.jellyfin.sdk.model.api.ItemSortBy
import org.jellyfin.sdk.model.api.SortOrder import org.jellyfin.sdk.model.api.SortOrder
import ru.stenfredd.movies.core.data.SessionCache.Kind import ru.stenfredd.sleepyowl.core.data.SessionCache.Kind
import ru.stenfredd.movies.core.data.model.ItemDetails import ru.stenfredd.sleepyowl.core.data.model.ItemDetails
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemQuery import ru.stenfredd.sleepyowl.core.data.model.ItemQuery
import ru.stenfredd.movies.core.data.model.ItemSort import ru.stenfredd.sleepyowl.core.data.model.ItemSort
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.LibraryType import ru.stenfredd.sleepyowl.core.data.model.LibraryType
import ru.stenfredd.movies.core.data.model.LibraryView import ru.stenfredd.sleepyowl.core.data.model.LibraryView
import ru.stenfredd.movies.core.data.model.MediaSegment import ru.stenfredd.sleepyowl.core.data.model.MediaSegment
import ru.stenfredd.movies.core.data.model.Page import ru.stenfredd.sleepyowl.core.data.model.Page
import ru.stenfredd.movies.core.data.model.Person import ru.stenfredd.sleepyowl.core.data.model.Person
import ru.stenfredd.movies.core.data.model.itemKinds import ru.stenfredd.sleepyowl.core.data.model.itemKinds
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import org.jellyfin.sdk.model.api.AudioSpatialFormat import org.jellyfin.sdk.model.api.AudioSpatialFormat
import org.jellyfin.sdk.model.api.BaseItemDto import org.jellyfin.sdk.model.api.BaseItemDto
@@ -13,24 +13,24 @@ import org.jellyfin.sdk.model.api.MediaSourceInfo
import org.jellyfin.sdk.model.api.MediaStream import org.jellyfin.sdk.model.api.MediaStream
import org.jellyfin.sdk.model.api.MediaStreamType import org.jellyfin.sdk.model.api.MediaStreamType
import org.jellyfin.sdk.model.api.VideoRangeType import org.jellyfin.sdk.model.api.VideoRangeType
import ru.stenfredd.movies.core.data.model.AudioTrack import ru.stenfredd.sleepyowl.core.data.model.AudioTrack
import ru.stenfredd.movies.core.data.model.Chapter import ru.stenfredd.sleepyowl.core.data.model.Chapter
import ru.stenfredd.movies.core.data.model.ImageKind import ru.stenfredd.sleepyowl.core.data.model.ImageKind
import ru.stenfredd.movies.core.data.model.ImageRef import ru.stenfredd.sleepyowl.core.data.model.ImageRef
import ru.stenfredd.movies.core.data.model.ItemDetails import ru.stenfredd.sleepyowl.core.data.model.ItemDetails
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.LibraryType import ru.stenfredd.sleepyowl.core.data.model.LibraryType
import ru.stenfredd.movies.core.data.model.LibraryView import ru.stenfredd.sleepyowl.core.data.model.LibraryView
import ru.stenfredd.movies.core.data.model.MediaInfo import ru.stenfredd.sleepyowl.core.data.model.MediaInfo
import ru.stenfredd.movies.core.data.model.MediaSegment import ru.stenfredd.sleepyowl.core.data.model.MediaSegment
import ru.stenfredd.movies.core.data.model.Person import ru.stenfredd.sleepyowl.core.data.model.Person
import ru.stenfredd.movies.core.data.model.PersonKind import ru.stenfredd.sleepyowl.core.data.model.PersonKind
import ru.stenfredd.movies.core.data.model.SegmentKind import ru.stenfredd.sleepyowl.core.data.model.SegmentKind
import ru.stenfredd.movies.core.data.model.SubtitleTrack import ru.stenfredd.sleepyowl.core.data.model.SubtitleTrack
import ru.stenfredd.movies.core.data.model.UserState import ru.stenfredd.sleepyowl.core.data.model.UserState
import ru.stenfredd.movies.core.data.model.VideoRange import ru.stenfredd.sleepyowl.core.data.model.VideoRange
import ru.stenfredd.movies.core.data.model.VideoTrack import ru.stenfredd.sleepyowl.core.data.model.VideoTrack
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneId import java.time.ZoneId
import java.util.UUID import java.util.UUID

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import android.content.Context import android.content.Context
import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.edit
@@ -8,7 +8,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import org.json.JSONArray import org.json.JSONArray
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import android.os.SystemClock import android.os.SystemClock
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
@@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject import javax.inject.Inject

View File

@@ -1,10 +1,10 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import org.jellyfin.sdk.api.client.extensions.systemApi import org.jellyfin.sdk.api.client.extensions.systemApi
import org.jellyfin.sdk.api.client.extensions.userApi import org.jellyfin.sdk.api.client.extensions.userApi
import org.jellyfin.sdk.model.api.SubtitlePlaybackMode import org.jellyfin.sdk.model.api.SubtitlePlaybackMode
import org.jellyfin.sdk.model.api.UserConfiguration import org.jellyfin.sdk.model.api.UserConfiguration
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.data package ru.stenfredd.sleepyowl.core.data
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
@@ -6,15 +6,15 @@ import org.jellyfin.sdk.api.client.extensions.libraryApi
import org.jellyfin.sdk.api.client.extensions.showApi import org.jellyfin.sdk.api.client.extensions.showApi
import org.jellyfin.sdk.api.client.extensions.userDataApi import org.jellyfin.sdk.api.client.extensions.userDataApi
import org.jellyfin.sdk.model.api.MediaType import org.jellyfin.sdk.model.api.MediaType
import ru.stenfredd.movies.core.data.SessionCache.Kind import ru.stenfredd.sleepyowl.core.data.SessionCache.Kind
import ru.stenfredd.movies.core.data.model.ItemKind import ru.stenfredd.sleepyowl.core.data.model.ItemKind
import ru.stenfredd.movies.core.data.model.ItemQuery import ru.stenfredd.sleepyowl.core.data.model.ItemQuery
import ru.stenfredd.movies.core.data.model.ItemSort import ru.stenfredd.sleepyowl.core.data.model.ItemSort
import ru.stenfredd.movies.core.data.model.ItemSummary import ru.stenfredd.sleepyowl.core.data.model.ItemSummary
import ru.stenfredd.movies.core.data.model.LibraryView import ru.stenfredd.sleepyowl.core.data.model.LibraryView
import ru.stenfredd.movies.core.data.model.Page import ru.stenfredd.sleepyowl.core.data.model.Page
import ru.stenfredd.movies.core.data.model.itemKinds import ru.stenfredd.sleepyowl.core.data.model.itemKinds
import ru.stenfredd.movies.core.jellyfin.JellyfinSession import ru.stenfredd.sleepyowl.core.jellyfin.JellyfinSession
import java.util.UUID import java.util.UUID
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton

View File

@@ -1,6 +1,6 @@
@file:UseSerializers(UUIDSerializer::class) @file:UseSerializers(UUIDSerializer::class)
package ru.stenfredd.movies.core.data.model package ru.stenfredd.sleepyowl.core.data.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers

View File

@@ -5,7 +5,7 @@ plugins {
} }
android { android {
namespace = "ru.stenfredd.movies.core.jellyfin" namespace = "ru.stenfredd.sleepyowl.core.jellyfin"
compileSdk = 37 compileSdk = 37
defaultConfig { minSdk = 26 } defaultConfig { minSdk = 26 }
compileOptions { compileOptions {

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.jellyfin package ru.stenfredd.sleepyowl.core.jellyfin
import android.content.Context import android.content.Context
import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.Preferences

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.jellyfin package ru.stenfredd.sleepyowl.core.jellyfin
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.jellyfin package ru.stenfredd.sleepyowl.core.jellyfin
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
@@ -253,7 +253,7 @@ class JellyfinSession @Inject constructor(
private fun deviceInfo(id: String) = DeviceInfo(id = id, name = "${Build.MANUFACTURER} ${Build.MODEL}") private fun deviceInfo(id: String) = DeviceInfo(id = id, name = "${Build.MANUFACTURER} ${Build.MODEL}")
private companion object { private companion object {
const val CLIENT_NAME = "Movies" const val CLIENT_NAME = "SleepyOwl"
const val CLIENT_VERSION = "0.1.0" const val CLIENT_VERSION = "0.1.0"
const val LOCAL_RECHECK_MS = 10 * 60_000L const val LOCAL_RECHECK_MS = 10 * 60_000L
const val REVOKE_TIMEOUT_MS = 3_000L const val REVOKE_TIMEOUT_MS = 3_000L

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.jellyfin package ru.stenfredd.sleepyowl.core.jellyfin
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.jellyfin package ru.stenfredd.sleepyowl.core.jellyfin
import android.os.SystemClock import android.os.SystemClock
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.core.jellyfin package ru.stenfredd.sleepyowl.core.jellyfin
import okhttp3.HttpUrl import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull

BIN
design/logo/sleepyowl.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -3,7 +3,7 @@ plugins {
} }
android { android {
namespace = "ru.stenfredd.movies.playback.api" namespace = "ru.stenfredd.sleepyowl.playback.api"
compileSdk = 37 compileSdk = 37
defaultConfig { minSdk = 26 } defaultConfig { minSdk = 26 }
compileOptions { compileOptions {

View File

@@ -1,4 +1,4 @@
package ru.stenfredd.movies.playback.api package ru.stenfredd.sleepyowl.playback.api
import android.media.AudioFormat import android.media.AudioFormat

Some files were not shown because too many files have changed in this diff Show More