Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
3ed50d6
feat: keep the session and reconnect while the server is down
Priveetee Oct 21, 2026
fa69ca2
feat: retry screens on their own when the server is silent
Priveetee Oct 21, 2026
315300d
style: show the session check as plain text
Priveetee Oct 21, 2026
9a6e4cd
perf: find the key frame that starts a resumed window
Priveetee Oct 21, 2026
b3e114b
perf: open playback from the loaded stream at the key frame
Priveetee Oct 21, 2026
566ee7f
perf: load sideloaded subtitles only when they are shown
Priveetee Oct 21, 2026
c6824ad
fix: declare the experimental subtitle decoding opt-in
Priveetee Oct 21, 2026
a8135da
perf: keep shelf rows in their own layer
Priveetee Oct 21, 2026
f314611
perf: draw the ink background as one opaque image
Priveetee Oct 21, 2026
d1fbcea
perf: blink the search caret instead of fading it
Priveetee Oct 21, 2026
a349308
perf: stop the comments panel from redrawing every frame
Priveetee Oct 21, 2026
dfed297
fix: close responses when the caller is cancelled
Priveetee Oct 22, 2026
4ef3b67
perf: show a steady caret in search
Priveetee Oct 22, 2026
66da6ea
perf: pause the featured rotation while browsing rows
Priveetee Oct 22, 2026
4697b61
perf: draw the background glow only over its corner
Priveetee Oct 22, 2026
85c509f
fix: keep the window loader alive when playback restarts after an error
Priveetee Oct 22, 2026
3264971
fix: hide missing metadata parts and unknown durations
Priveetee Oct 23, 2026
25dea4a
feat: open the detail page at once from the card
Priveetee Oct 23, 2026
03d13ad
feat: show the video poster while the player opens
Priveetee Oct 23, 2026
1103fb5
fix: move down from the seek bar to play and pause
Priveetee Oct 23, 2026
f96f7fd
feat: return to the top of home before leaving on back
Priveetee Oct 23, 2026
fd3446c
perf: warm the stream of the focused video on the server
Priveetee Oct 23, 2026
544bee3
feat: load more search results while scrolling
Priveetee Oct 23, 2026
2cf09f0
feat: add a startup splash with a short chime
Priveetee Oct 23, 2026
6dc2f8d
perf: keep library membership for the detail page
Priveetee Oct 23, 2026
0d12eda
style: hide rows that scroll under the top bar
Priveetee Oct 23, 2026
3f37808
fix: change the hero backdrop together with its title
Priveetee Oct 23, 2026
da8c096
style: show icons in the settings sections
Priveetee Oct 23, 2026
16b9ab4
fix: open a channel on its first video
Priveetee Oct 23, 2026
c144e8f
feat: load more playlist and channel search results
Priveetee Oct 23, 2026
7be1dd2
feat: type search queries from a keyboard
Priveetee Oct 23, 2026
4399a9c
feat: choose video codecs from the decoders of the device
Priveetee Oct 23, 2026
b0710b0
feat: mark live videos on the detail page
Priveetee Oct 23, 2026
9848291
fix: show the delay behind live in the seek bubble
Priveetee Oct 23, 2026
edb0d12
refactor: move shared message and video id types to their layers
Priveetee Oct 23, 2026
5e3661f
build: add convention plugins for library modules
Priveetee Oct 23, 2026
9969c5e
refactor: split the app into core and feature modules
Priveetee Oct 23, 2026
9058f0e
feat: show live audience as viewers watching
Priveetee Oct 23, 2026
ae961a9
feat: choose the quality of a live stream in place
Priveetee Oct 23, 2026
891e486
feat: say when a live stream has ended
Priveetee Oct 23, 2026
d9053f6
fix: remove object placeholders from video titles
Priveetee Oct 23, 2026
6f62ee6
feat: read the live chat stream of a video
Priveetee Oct 23, 2026
c4fd29f
feat: show the live chat beside a live stream
Priveetee Oct 23, 2026
b239072
fix: stack the live chat under the statistics and hide it at the end
Priveetee Oct 23, 2026
8202389
refactor: move the player preference row to its own file
Priveetee Oct 23, 2026
75a7d42
fix: handle Back in the player through the back dispatcher
Priveetee Oct 23, 2026
3ee742f
feat: put the live chat beside the picture
Priveetee Oct 23, 2026
4bf2bec
feat: show related videos under the player controls
Priveetee Oct 23, 2026
8b422e9
perf: open previews with a small silent player
Priveetee Oct 23, 2026
35a1f5e
feat: play a muted preview after two seconds on a video
Priveetee Oct 23, 2026
659de97
fix: paint the player background around a letterboxed picture
Priveetee Oct 23, 2026
83a0ded
docs: refresh the README features and screenshots
Priveetee Oct 23, 2026
be77f90
refactor: move the player control timing to its own file
Priveetee Oct 23, 2026
58f7f33
feat: name the focused icon buttons of the player
Priveetee Oct 23, 2026
6fbe402
feat: reach description, comments and chapters from the player
Priveetee Oct 23, 2026
83d3fd7
feat: answer the dedicated keys of TV remotes in the player
Priveetee Oct 23, 2026
3a20604
feat: trace the startup mark hop by hop on a shared timeline
Priveetee Oct 23, 2026
b267686
feat: write the wordmark and land the chord in the new startup intro
Priveetee Oct 23, 2026
8073ec9
fix: size the TV banner and pad the launcher icon
Priveetee Oct 23, 2026
23a9e04
fix: keep the keyboard closed while the startup intro plays
Priveetee Oct 23, 2026
5e59871
feat: type recent searches as a ghost in the search field
Priveetee Oct 23, 2026
e63e373
feat: draw the lettered wordmark in every TypeType logo
Priveetee Oct 23, 2026
312bbe4
feat: search by voice with the words typed as they are heard
Priveetee Oct 23, 2026
0dc9e42
feat: show the service marks of the web app on TV
Priveetee Oct 23, 2026
34e8553
feat: block and unblock videos through the server
Priveetee Oct 23, 2026
5f432e3
feat: open the video options with a long press on any card
Priveetee Oct 23, 2026
eeab18c
feat: add the content settings and 4K quality to the TV settings
Priveetee Oct 23, 2026
e22b076
feat: pick settings from a list and give every row an icon
Priveetee Oct 23, 2026
4cc6da8
test: check that a setting choice opens its picker
Priveetee Oct 23, 2026
03c1f76
feat: answer the remote's play, menu, search, page and digit keys
Priveetee Oct 23, 2026
d56d857
fix: let Back cancel a server change and keep the session
Priveetee Oct 23, 2026
e12c73c
fix: keep the focus on the right row and group in the settings
Priveetee Oct 23, 2026
1872343
fix: stop cutting the bottom of letters in titles and the search field
Priveetee Oct 23, 2026
14ee398
fix: return to the open section when leaving the library videos
Priveetee Oct 23, 2026
bf0802a
fix: open pickers and confirmations above the top bar
Priveetee Oct 23, 2026
4b8b511
fix: start the tab content below the shade of the top bar
Priveetee Oct 23, 2026
2646573
feat: remove a video from the open playlist with its menu
Priveetee Oct 23, 2026
7c734df
feat: pick the search kind on a wheel
Priveetee Oct 23, 2026
0d2c5bc
feat: load channel tabs, sorts and playlists from the server
Priveetee Oct 23, 2026
b29d55e
feat: add the channel tabs, sort wheel and playlist cards
Priveetee Oct 23, 2026
6751809
feat: rebuild the channel page around its banner and tabs
Priveetee Oct 23, 2026
04cd852
feat: show a playlist's picture behind its page
Priveetee Oct 23, 2026
d0485b1
perf: ask streams and SABR sessions without the account first
Priveetee Oct 23, 2026
17102a6
perf: warm the next autoplay video near the end
Priveetee Oct 23, 2026
96281c6
refactor: share the search keyboard and typing rules
Priveetee Oct 23, 2026
2dc6301
feat: search the videos of a channel
Priveetee Oct 23, 2026
5d599fa
feat: add a performance section to turn off heavy effects
Priveetee Oct 23, 2026
6ae038c
fix: enter a settings section on its first row
Priveetee Oct 23, 2026
a6f8632
perf: prepare the player's session while a video page is open
Priveetee Oct 23, 2026
9451a46
perf: prepare the next autoplay video's session too
Priveetee Oct 23, 2026
cc650e6
feat: let slow boxes turn off animations, backdrops and the intro
Priveetee Oct 24, 2026
318ffe7
feat: hold the picture still while scrubbing
Priveetee Oct 24, 2026
6b2dee4
feat: tighten the player sheets and keep the read comment on top
Priveetee Oct 24, 2026
7962552
feat: add a channel card for the player
Priveetee Oct 24, 2026
5c15557
feat: put comments, channel and description beside the player options
Priveetee Oct 24, 2026
25fd272
feat: fill an empty related row with the channel's latest videos
Priveetee Oct 24, 2026
d1a1ee4
perf: prepare playback as soon as a video page opens
Priveetee Oct 24, 2026
7e4adf2
fix: show the channel picture on the video page
Priveetee Oct 24, 2026
993c957
fix: switch codec or step down when a decoder fails while playing
Priveetee Oct 24, 2026
bf83c3e
feat: step Auto down when frames drop and show the decoder in stats
Priveetee Oct 24, 2026
0267f31
feat: let a box check its video decoders again
Priveetee Oct 24, 2026
19c5a12
perf: pause the animated avatar while the remote is in use
Priveetee Oct 24, 2026
d5677db
fix: close panels with one press of Back on older Android
Priveetee Oct 24, 2026
219b11d
fix: name the decoder in stats opened during playback
Priveetee Oct 24, 2026
20dedc2
fix: let the decoder settle before judging dropped frames
Priveetee Oct 24, 2026
7685981
feat: shrink the picture beside every player panel
Priveetee Oct 24, 2026
5bf74c6
feat: give the focus back to what opened a player panel
Priveetee Oct 24, 2026
5044c08
feat: show the chapters as a row under the player controls
Priveetee Oct 24, 2026
72c13fe
fix: keep the player options on screen with many long labels
Priveetee Oct 24, 2026
dce0d69
fix: let a seek go back before the playing window
Priveetee Oct 24, 2026
d764e2b
fix: stop reloading a video when seeks drop frames
Priveetee Oct 24, 2026
6d2a565
fix: send Back to the dispatcher only before Android 13
Priveetee Oct 24, 2026
854bf2b
feat: grow the scrub step with each press and the video length
Priveetee Oct 24, 2026
7a4abe4
docs: tighten code comments and use one comment style
Priveetee Oct 24, 2026
ea7c692
build: derive the version code from the version name
Priveetee Oct 24, 2026
4b4b6c9
ci: verify every push to dev and every pull request
Priveetee Oct 24, 2026
10c18bd
ci: publish signed releases from the beta and main branches
Priveetee Oct 24, 2026
19b9aba
chore: release 0.1.0
Priveetee Oct 24, 2026
dfd41d7
chore: release 0.1.1-beta.1
Priveetee Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
71 changes: 71 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: CI

on:
push:
branches:
- dev
paths-ignore:
- '**.md'
- 'assets/**'
pull_request:
branches:
- dev
- beta
- main
paths-ignore:
- '**.md'
- 'assets/**'
workflow_call:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CI: true
ANDROID_PLATFORM: platforms;android-37.0
ANDROID_BUILD_TOOLS: build-tools;36.0.0

jobs:
verify:
# Hosted runners: pull requests from forks run here, never on a machine of the project.
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Checkout
uses: actions/checkout@v7.0.1

- name: Set up Java
uses: actions/setup-java@v6.0.1
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6.4.0

- name: Install Android SDK packages
run: yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --install "$ANDROID_PLATFORM" "$ANDROID_BUILD_TOOLS" > /dev/null

- name: Test, lint and build
run: |
./gradlew --stacktrace \
testDebugUnitTest \
:app:compileDebugAndroidTestKotlin \
lintDebug \
:app:assembleRelease

- name: Upload reports
if: ${{ failure() }}
uses: actions/upload-artifact@v7.0.1
with:
name: reports
path: |
**/build/reports/
**/build/test-results/
if-no-files-found: ignore
retention-days: 14
161 changes: 161 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
name: Release

# A push to beta publishes a prerelease, a push to main a stable release. The version comes from app/build.gradle.kts
# and the text from release-notes/v<version>.md, which must be in the pushed commit.
on:
push:
branches:
- beta
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: release-${{ github.ref_name }}
cancel-in-progress: false

env:
CI: true
APPLICATION_ID: video.typetype.tv
ANDROID_PLATFORM: platforms;android-37.0
ANDROID_BUILD_TOOLS: build-tools;36.0.0
BUILD_TOOLS_VERSION: 36.0.0

jobs:
verify:
uses: ./.github/workflows/ci.yml

publish:
needs: verify
if: ${{ github.ref_name == 'beta' || github.ref_name == 'main' }}
runs-on: ubuntu-latest
timeout-minutes: 45
# The signing key lives in this environment, which only the beta and main branches can use.
environment: release
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v7.0.1

- name: Set up Java
uses: actions/setup-java@v6.0.1
with:
distribution: temurin
java-version: 21

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6.4.0

- name: Install Android SDK packages
run: yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --install "$ANDROID_PLATFORM" "$ANDROID_BUILD_TOOLS" > /dev/null

- name: Check the version
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
version="$(sed -nE 's/^val appVersion = "([^"]+)"$/\1/p' app/build.gradle.kts)"
case "$GITHUB_REF_NAME" in
beta) pattern='^[0-9]+\.[0-9]+\.[0-9]+-beta\.[1-9][0-9]?$'; channel=beta ;;
main) pattern='^[0-9]+\.[0-9]+\.[0-9]+$'; channel=stable ;;
esac
if [[ ! "$version" =~ $pattern ]]; then
echo "::error::Version '$version' does not fit the $GITHUB_REF_NAME branch"
exit 1
fi
tag="v$version"
if [ ! -f "release-notes/$tag.md" ]; then
echo "::error::release-notes/$tag.md is missing"
exit 1
fi
if gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$tag" > /dev/null 2>&1; then
echo "::error::Tag $tag already exists: raise the version before publishing"
exit 1
fi
{
echo "RELEASE_VERSION=$version"
echo "RELEASE_TAG=$tag"
echo "RELEASE_CHANNEL=$channel"
} >> "$GITHUB_ENV"

- name: Build
run: ./gradlew --stacktrace :app:assembleRelease

- name: Sign
env:
KEYSTORE_BASE64: ${{ secrets.TV_KEYSTORE_BASE64 }}
KEYSTORE_PASSWORD: ${{ secrets.TV_KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.TV_KEY_ALIAS }}
run: |
set -euo pipefail
test -n "$KEYSTORE_BASE64" && test -n "$KEYSTORE_PASSWORD" && test -n "$KEY_ALIAS"
tools="$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION"
keystore="$RUNNER_TEMP/release.jks"
trap 'rm -f "$keystore"' EXIT
printf '%s' "$KEYSTORE_BASE64" | base64 --decode > "$keystore"
mkdir -p artifacts
"$tools/zipalign" -f -P 16 4 app/build/outputs/apk/release/app-release-unsigned.apk "$RUNNER_TEMP/aligned.apk"
"$tools/apksigner" sign --ks "$keystore" --ks-key-alias "$KEY_ALIAS" --v4-signing-enabled false \
--ks-pass env:KEYSTORE_PASSWORD --key-pass env:KEYSTORE_PASSWORD \
--out "artifacts/TypeType-TV-$RELEASE_TAG.apk" "$RUNNER_TEMP/aligned.apk"

- name: Check the APK
run: |
set -euo pipefail
tools="$ANDROID_HOME/build-tools/$BUILD_TOOLS_VERSION"
apk="artifacts/TypeType-TV-$RELEASE_TAG.apk"
"$tools/zipalign" -c -P 16 4 "$apk"
"$tools/apksigner" verify --print-certs "$apk" | grep -E 'Signer #1 certificate (DN|SHA-256)'
badging="$("$tools/aapt2" dump badging "$apk" | head -n 1)"
echo "$badging"
package="$(sed -nE "s/^package: name='([^']+)'.*/\1/p" <<< "$badging")"
code="$(sed -nE "s/.*versionCode='([0-9]+)'.*/\1/p" <<< "$badging")"
name="$(sed -nE "s/.*versionName='([^']+)'.*/\1/p" <<< "$badging")"
test "$package" = "$APPLICATION_ID"
test "$name" = "$RELEASE_VERSION"
echo "RELEASE_CODE=$code" >> "$GITHUB_ENV"

- name: Write checksum and update manifest
run: |
set -euo pipefail
cd artifacts
apk="TypeType-TV-$RELEASE_TAG.apk"
sha256sum "$apk" > "$apk.sha256"
jq -n \
--arg channel "$RELEASE_CHANNEL" \
--arg packageName "$APPLICATION_ID" \
--arg versionName "$RELEASE_VERSION" \
--argjson versionCode "$RELEASE_CODE" \
--arg apkAsset "$apk" \
--arg sha256 "$(cut -d ' ' -f 1 "$apk.sha256")" \
'{schemaVersion: 1, channel: $channel, packageName: $packageName, versionName: $versionName,
versionCode: $versionCode, apkAsset: $apkAsset, sha256: $sha256}' > typetype-update.json
cat typetype-update.json

- name: Keep the files with the run
uses: actions/upload-artifact@v7.0.1
with:
name: typetype-tv-${{ env.RELEASE_TAG }}
path: artifacts/
if-no-files-found: error
compression-level: 0
retention-days: 30

- name: Publish the release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
if [ "$RELEASE_CHANNEL" = beta ]; then
flags=(--prerelease --latest=false)
else
flags=(--latest)
fi
gh release create "$RELEASE_TAG" artifacts/* \
--target "$GITHUB_SHA" \
--title "TypeType TV $RELEASE_VERSION" \
--notes-file "release-notes/$RELEASE_TAG.md" \
"${flags[@]}"
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,38 @@ synchronization. It supports YouTube, Bilibili, and NicoNico.

| Home | Video details | Player |
| --- | --- | --- |
| ![TypeType TV home screen](assets/screenshots/tv-home.png) | ![TypeType TV video details](assets/screenshots/tv-detail.png) | ![TypeType TV player](assets/screenshots/tv-player.png) |
| ![TypeType TV home with a muted preview](assets/screenshots/tv-home.png) | ![TypeType TV video details](assets/screenshots/tv-detail.png) | ![TypeType TV player](assets/screenshots/tv-player.png) |

| Comments | Search | Settings |
| Live chat | More videos | Search |
| --- | --- | --- |
| ![TypeType TV comments panel](assets/screenshots/tv-comments.png) | ![TypeType TV search with the on-screen keyboard](assets/screenshots/tv-search.png) | ![TypeType TV playback settings](assets/screenshots/tv-settings.png) |
| ![TypeType TV live stream with its chat](assets/screenshots/tv-live-chat.png) | ![TypeType TV related videos under the player](assets/screenshots/tv-related.png) | ![TypeType TV search with the on-screen keyboard](assets/screenshots/tv-search.png) |

## Features

- Browse the home feed, search videos and channels, and open channels and playlists.
- Browse the home feed, search videos, playlists and channels, and open channels and playlists.
- Rest on a video for two seconds to see a muted preview behind the home screen and the video details.
- Resume videos and find your history, favorites, and Watch Later in the library.
- Play up to 4K with AVC, VP9, AV1 or HEVC, chosen from the decoders of your device; HDR on HDR screens.
- Choose the quality, audio language, captions and their style, and the playback speed.
- Use chapters, SponsorBlock, the description, comments and their replies, and the Up next queue.
- Show scrolling comments on Bilibili and NicoNico videos.
- Watch live streams, or keep only the audio.
- Press Down twice in the player to browse more videos without leaving playback.
- Watch YouTube live streams with their chat beside the picture, the live audience, and the quality of your choice.
- Show scrolling comments on Bilibili and NicoNico videos, or keep only the audio.
- Subscribe to channels and add videos to your playlists from the player.

## Build

Requirements: JDK 17 and the Android SDK (`ANDROID_HOME` set).

```sh
./gradlew :app:testDebugUnitTest :app:assembleDebug
./gradlew testDebugUnitTest :app:assembleDebug
```

The project has two modules:
The project is split into modules:

- `app`: the TV interface, built with Compose for remote-control focus, and the client for the TypeType Server API.
- `app`: the TV application, its navigation and startup.
- `core:*`: shared resources, the TypeType Server client, playback, the design system, and test fakes.
- `feature:*`: one module per screen family (home, search, library, settings, collections, details, player, sign-in).
- `player`: the Media3 source for TypeType SABR playback.

## Acknowledgements
Expand Down
38 changes: 31 additions & 7 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ plugins {
alias(libs.plugins.kotlin.serialization)
}

// The release workflow reads this line: "x.y.z-beta.n" is published from the beta branch, "x.y.z" from main.
val appVersion = "0.1.1-beta.1"

// The version code follows from the name, so each release installs over the one before, and a beta sits under the
// stable release that ends it: 0.3.0-beta.2 is 30002 and 0.3.0 is 30099.
fun versionCodeOf(name: String): Int {
val match = requireNotNull(Regex("""(\d+)\.(\d+)\.(\d+)(?:-beta\.(\d+))?""").matchEntire(name)) {
"Version $name is neither x.y.z nor x.y.z-beta.n"
}
val (major, minor, patch, beta) = match.destructured
require(minor.toInt() < 100 && patch.toInt() < 100) { "Minor and patch of $name stay under 100" }
val step = if (beta.isEmpty()) 99 else beta.toInt()
require(beta.isEmpty() || step in 1..98) { "The beta number of $name is 1 to 98" }
return major.toInt() * 1_000_000 + minor.toInt() * 10_000 + patch.toInt() * 100 + step
}

android {
namespace = "video.typetype.tv"
compileSdk = 37
Expand All @@ -12,8 +28,8 @@ android {
applicationId = "video.typetype.tv"
minSdk = 23
targetSdk = 37
versionCode = 1
versionName = "0.2.0"
versionCode = versionCodeOf(appVersion)
versionName = appVersion
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

Expand Down Expand Up @@ -41,10 +57,6 @@ android {
unitTests.isReturnDefaultValues = true
}

sourceSets {
getByName("test").kotlin.srcDir("src/sharedTest/java")
getByName("androidTest").kotlin.srcDir("src/sharedTest/java")
}
}

dependencies {
Expand All @@ -57,7 +69,18 @@ dependencies {
implementation(libs.androidx.concurrent.futures)
implementation(libs.androidx.lifecycle.runtime.compose)

implementation(project(":player"))
implementation(project(":core:resources"))
implementation(project(":core:data"))
implementation(project(":core:playback"))
implementation(project(":core:ui"))
implementation(project(":feature:auth"))
implementation(project(":feature:home"))
implementation(project(":feature:search"))
implementation(project(":feature:library"))
implementation(project(":feature:settings"))
implementation(project(":feature:collections"))
implementation(project(":feature:detail"))
implementation(project(":feature:player"))
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.media3.exoplayer.hls)
implementation(libs.androidx.media3.datasource.okhttp)
Expand All @@ -77,6 +100,7 @@ dependencies {
testImplementation(libs.okhttp.mockwebserver)
testImplementation(libs.okhttp.tls)

androidTestImplementation(project(":core:testing"))
androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
androidTestImplementation(libs.androidx.compose.ui.test.accessibility)
Expand Down
Loading
Loading