Compare commits
96 commits
transcodin
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
e009b86153 | ||
|
d669dcb618 | ||
|
ff5bce074e | ||
|
d85684317b | ||
|
3cc52938f2 | ||
|
3ff71ae489 | ||
|
b511b26aa1 | ||
|
059b17af9a | ||
|
c293c906d4 | ||
|
b5d31a6c72 | ||
|
89d5a332d1 | ||
|
4e8ee15d0a | ||
|
36dd8480e1 | ||
|
a6c1ef15b7 | ||
|
75ea1dc43a | ||
|
2b2e6ce58b | ||
|
09427e1de0 | ||
|
fbf4c185f0 | ||
|
c84ec082be | ||
|
5a8403f6a9 | ||
|
362201eddf | ||
|
afbf68937d | ||
|
8139119c35 | ||
|
ab090a01d7 | ||
|
2253780903 | ||
|
3340ce4e58 | ||
|
ce66bbc0b2 | ||
|
e122ef303e | ||
|
dedb99b73d | ||
|
4bf8e6b697 | ||
|
89fb969d67 | ||
|
eac3eaa3f3 | ||
|
e6c49ea660 | ||
|
44c1b51553 | ||
|
e18e73cca8 | ||
|
5156333a95 | ||
|
eface29638 | ||
|
44b6e915ba | ||
|
a1cbea0b92 | ||
|
e987ac477d | ||
|
9baa84e1e7 | ||
|
ed69473e26 | ||
|
73d1b7c099 | ||
|
f269bea184 | ||
|
5c283982bb | ||
|
cb4518c86e | ||
|
2d141b6f0f | ||
|
ab19866899 | ||
|
168cfcd19f | ||
|
288c96709e | ||
|
8b5c19b957 | ||
|
be1da2eb7b | ||
|
61af530c89 | ||
|
7b508fa456 | ||
|
fcb58ef8ad | ||
|
09f3d218c1 | ||
|
350afaa8a9 | ||
|
ba2f9d9708 | ||
|
e74a86da24 | ||
|
5ab65062e6 | ||
|
6095c97704 | ||
|
91cccc55a7 | ||
|
df984fb24b | ||
|
9f3be43eac | ||
|
0999823d6d | ||
|
e10ae9c487 | ||
|
ce9eed6344 | ||
|
d4e6351a2d | ||
|
f75079f720 | ||
|
4a3afe62ef | ||
|
50b39d6658 | ||
|
3c6e03db89 | ||
|
05730a513c | ||
|
674699aeab | ||
|
f9454029f7 | ||
|
2b9831af56 | ||
|
6402a6a0c4 | ||
|
a740d3fc71 | ||
|
9711f4c4fb | ||
|
916d71a085 | ||
|
bdef58d433 | ||
|
4a3a22de37 | ||
|
6a917be93f | ||
|
7f02f3de0a | ||
|
14eb313b1e | ||
|
85ff16d843 | ||
|
92eaefe6e1 | ||
|
216092888a | ||
|
a972832aae | ||
|
722267ced2 | ||
|
da64c968bc | ||
|
b5f5a6eaed | ||
|
49d52f9713 | ||
|
5b38bdb1c1 | ||
|
689c5cff3f | ||
|
3db0f57437 |
350 changed files with 6692 additions and 2996 deletions
113
.github/workflows/build.yaml
vendored
113
.github/workflows/build.yaml
vendored
|
@ -5,26 +5,27 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
# lint:
|
||||||
name: Lint
|
# name: Lint
|
||||||
runs-on: ubuntu-22.04
|
# runs-on: ubuntu-22.04
|
||||||
steps:
|
# steps:
|
||||||
- name: Checkout repository
|
# - name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
# uses: actions/checkout@v4
|
||||||
- name: Validate Gradle Wrapper
|
# - name: Validate Gradle Wrapper
|
||||||
uses: gradle/actions/wrapper-validation@v3
|
# uses: gradle/actions/wrapper-validation@v3
|
||||||
- name: Set up JDK 17
|
# - name: Set up JDK 17
|
||||||
uses: actions/setup-java@v4
|
# uses: actions/setup-java@v4
|
||||||
with:
|
# with:
|
||||||
java-version: 17
|
# java-version: 17
|
||||||
distribution: temurin
|
# distribution: temurin
|
||||||
- name: Setup Gradle
|
# - name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v3
|
# uses: gradle/actions/setup-gradle@v3
|
||||||
- name: Build with Gradle
|
# - name: Build with Gradle
|
||||||
run: ./gradlew lintDebug ktlintCheck
|
# run: ./gradlew lintDebug ktlintCheck
|
||||||
assemble:
|
assemble:
|
||||||
name: Assemble
|
name: Assemble
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
if: startsWith(github.event.head_commit.message, 'build:')
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
@ -38,45 +39,45 @@ jobs:
|
||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v3
|
uses: gradle/actions/setup-gradle@v3
|
||||||
- name: Build with Gradle
|
- name: Build with Gradle
|
||||||
run: ./gradlew assembleDebug
|
run: ./gradlew assemble
|
||||||
# Upload all build artifacts in separate steps. This can be shortened once https://github.com/actions/upload-artifact/pull/354 is merged.
|
# Upload all build artifacts in separate steps. This can be shortened once https://github.com/actions/upload-artifact/pull/354 is merged.
|
||||||
- name: Upload artifact phone-libre-arm64-v8a-debug.apk
|
- name: Upload artifact ananas-v0.10.3-0.14.2-libre-arm64-v8a.apk
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: phone-libre-arm64-v8a-debug.apk
|
name: phone-libre-arm64-v8a.apk
|
||||||
path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-arm64-v8a-debug.apk
|
path: ./app/phone/build/outputs/apk/libre/release/ananas-v0.10.3-0.14.2-libre-arm64-v8a.apk
|
||||||
- name: Upload artifact phone-libre-armeabi-v7a-debug.apk
|
# - name: Upload artifact phone-libre-armeabi-v7a-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: phone-libre-armeabi-v7a-debug.apk
|
# name: phone-libre-armeabi-v7a-debug.apk
|
||||||
path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-armeabi-v7a-debug.apk
|
# path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-armeabi-v7a-debug.apk
|
||||||
- name: Upload artifact phone-libre-x86_64-debug.apk
|
# - name: Upload artifact phone-libre-x86_64-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: phone-libre-x86_64-debug.apk
|
# name: phone-libre-x86_64-debug.apk
|
||||||
path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-x86_64-debug.apk
|
# path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-x86_64-debug.apk
|
||||||
- name: Upload artifact phone-libre-x86-debug.apk
|
# - name: Upload artifact phone-libre-x86-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: phone-libre-x86-debug.apk
|
# name: phone-libre-x86-debug.apk
|
||||||
path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-x86-debug.apk
|
# path: ./app/phone/build/outputs/apk/libre/debug/phone-libre-x86-debug.apk
|
||||||
- name: Upload artifact tv-libre-arm64-v8a-debug.apk
|
# - name: Upload artifact tv-libre-arm64-v8a-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: tv-libre-arm64-v8a-debug.apk
|
# name: tv-libre-arm64-v8a-debug.apk
|
||||||
path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-arm64-v8a-debug.apk
|
# path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-arm64-v8a-debug.apk
|
||||||
- name: Upload artifact tv-libre-armeabi-v7a-debug.apk
|
# - name: Upload artifact tv-libre-armeabi-v7a-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: tv-libre-armeabi-v7a-debug.apk
|
# name: tv-libre-armeabi-v7a-debug.apk
|
||||||
path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-armeabi-v7a-debug.apk
|
# path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-armeabi-v7a-debug.apk
|
||||||
- name: Upload artifact tv-libre-x86_64-debug.apk
|
# - name: Upload artifact tv-libre-x86_64-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: tv-libre-x86_64-debug.apk
|
# name: tv-libre-x86_64-debug.apk
|
||||||
path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-x86_64-debug.apk
|
# path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-x86_64-debug.apk
|
||||||
- name: Upload artifact tv-libre-x86-debug.apk
|
# - name: Upload artifact tv-libre-x86-debug.apk
|
||||||
uses: actions/upload-artifact@v4
|
# uses: actions/upload-artifact@v4
|
||||||
with:
|
# with:
|
||||||
name: tv-libre-x86-debug.apk
|
# name: tv-libre-x86-debug.apk
|
||||||
path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-x86-debug.apk
|
# path: ./app/tv/build/outputs/apk/libre/debug/tv-libre-x86-debug.apk
|
||||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -10,10 +10,14 @@ local.properties
|
||||||
|
|
||||||
# Android Studio generated files and folders
|
# Android Studio generated files and folders
|
||||||
captures/
|
captures/
|
||||||
|
app/phone/libre/release/
|
||||||
|
.kotlin
|
||||||
.externalNativeBuild/
|
.externalNativeBuild/
|
||||||
.cxx/
|
.cxx/
|
||||||
*.apk
|
*.apk
|
||||||
|
*.dm
|
||||||
output.json
|
output.json
|
||||||
|
app/phone/libre/release/output-metadata.json
|
||||||
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
*.iml
|
*.iml
|
||||||
|
@ -37,3 +41,4 @@ fastlane/report.xml
|
||||||
fastlane/Preview.html
|
fastlane/Preview.html
|
||||||
fastlane/screenshots
|
fastlane/screenshots
|
||||||
fastlane/test_output
|
fastlane/test_output
|
||||||
|
push.sh
|
||||||
|
|
7
PRIVACY
7
PRIVACY
|
@ -1,7 +1,6 @@
|
||||||
This privacy policy pertains the Findroid app.
|
This privacy policy pertains the Ananas app.
|
||||||
|
|
||||||
Findroid does not collect or access any personal information. No identifying information or user data of any kind is made available to third-parties.
|
Ananas does not collect or access any personal information. No identifying information or user data of any kind is made available to third-parties.
|
||||||
|
|
||||||
This Privacy Policy is effective as of Feb 8th, 2023 and will remain in effect except with respect to any changes in its provisions in the future, which will be in effect immediately after being posted on this page. We reserve the right to update or change our Privacy Policy at any time and you should check this Privacy Policy periodically. Your continued use of the Service after we post any modifications to the Privacy Policy on this page will constitute your acknowledgment of the modifications and your consent to abide and be bound by the modified Privacy Policy.
|
This Privacy Policy is effective as of Jun 24th, 2024 and will remain in effect except with respect to any changes in its provisions in the future, which will be in effect immediately after being posted on this page. We reserve the right to update or change our Privacy Policy at any time and you should check this Privacy Policy periodically. Your continued use of the Service after we post any modifications to the Privacy Policy on this page will constitute your acknowledgment of the modifications and your consent to abide and be bound by the modified Privacy Policy.
|
||||||
|
|
||||||
Findroid is published by Jarne Demeulemeester. Inquiries can be submitted to jarnedemeulemeester@gmail.com.
|
|
||||||
|
|
36
README.md
36
README.md
|
@ -1,21 +1,6 @@
|
||||||

|
|
||||||
|
|
||||||
# Findroid
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
Findroid is third-party Android application for Jellyfin that provides a native user interface to browse and play movies and series.
|
|
||||||
|
|
||||||
I am developing this application in my spare time.
|
|
||||||
|
|
||||||
**This project is in its early stages so expect bugs.**
|
|
||||||
|
|
||||||
<a href='https://play.google.com/store/apps/details?id=dev.jdtech.jellyfin'><img alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png' height="80"/></a><a href='http://www.amazon.com/gp/product/B0BTWC8DNZ'><img alt='Available at Amazon Appstore' src='https://user-images.githubusercontent.com/32322857/219019331-027a6775-7362-44bb-a026-281f71e9b37b.png' height="80"/></a><a href='https://apt.izzysoft.de/fdroid/index/apk/dev.jdtech.jellyfin'><img alt='Get it on IzzyOnDroid' src='https://gitlab.com/IzzyOnDroid/repo/-/raw/master/assets/IzzyOnDroid.png' height="80"/></a>
|
|
||||||
|
|
||||||
|
# Ananas
|
||||||
|
Personal fork
|
||||||
## Screenshots
|
## Screenshots
|
||||||
| Home | Library | Movie | Season | Episode |
|
| Home | Library | Movie | Season | Episode |
|
||||||
|-------------------------------------|-------------------------------------|---------------------------------|-----------------------------------|-------------------------------------|
|
|-------------------------------------|-------------------------------------|---------------------------------|-----------------------------------|-------------------------------------|
|
||||||
|
@ -24,8 +9,9 @@ I am developing this application in my spare time.
|
||||||
## Features
|
## Features
|
||||||
- Completely native interface
|
- Completely native interface
|
||||||
- Supported media items: movies, series, seasons, episodes
|
- Supported media items: movies, series, seasons, episodes
|
||||||
- Direct play only, (no transcoding)
|
- Direct play and Transcoding
|
||||||
- Offline playback / downloads
|
- Offline playback / downloads
|
||||||
|
- Transcoding Downloads (Original - 720p - 480p - 360p)
|
||||||
- ExoPlayer
|
- ExoPlayer
|
||||||
- Video codecs: H.263, H.264, H.265, VP8, VP9, AV1
|
- Video codecs: H.263, H.264, H.265, VP8, VP9, AV1
|
||||||
- Support depends on Android device
|
- Support depends on Android device
|
||||||
|
@ -49,20 +35,8 @@ I am developing this application in my spare time.
|
||||||
- Websocket connection (Syncplay)
|
- Websocket connection (Syncplay)
|
||||||
- Chromecast support
|
- Chromecast support
|
||||||
|
|
||||||
## Translating
|
|
||||||
[JDTech Weblate](https://weblate.jdtech.dev) is a selfhosted instance of Weblate where you can translate this project and future projects of mine.
|
|
||||||
|
|
||||||
## Questions?
|
|
||||||
[](https://discord.gg/tg5VvTFwTV)\
|
|
||||||
We have a Discord server to discuss future development or ask general questions.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
This project is licensed under [GPLv3](LICENSE).
|
This project is licensed under [GPLv3](LICENSE).
|
||||||
|
|
||||||
The logo is a combination of the Jellyfin logo and the Android robot.
|
|
||||||
|
|
||||||
The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License.
|
|
||||||
|
|
||||||
Android is a trademark of Google LLC.
|
|
||||||
|
|
||||||
Google Play and the Google Play logo are trademarks of Google LLC.
|
|
||||||
|
|
87
app/phone/Ananas/release/output-metadata.json
Normal file
87
app/phone/Ananas/release/output-metadata.json
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "com.nomadics9.ananas",
|
||||||
|
"variantName": "AnanasRelease",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "armeabi-v7a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 16,
|
||||||
|
"versionName": "0.10.6-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.6-0.14.2-Ananas-armeabi-v7a.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "arm64-v8a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 16,
|
||||||
|
"versionName": "0.10.6-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.6-0.14.2-Ananas-arm64-v8a.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86_64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 16,
|
||||||
|
"versionName": "0.10.6-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.6-0.14.2-Ananas-x86_64.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 16,
|
||||||
|
"versionName": "0.10.6-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.6-0.14.2-Ananas-x86.apk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elementType": "File",
|
||||||
|
"baselineProfiles": [
|
||||||
|
{
|
||||||
|
"minApi": 28,
|
||||||
|
"maxApi": 30,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/1/ananas-v0.10.6-0.14.2-Ananas-armeabi-v7a.dm",
|
||||||
|
"baselineProfiles/1/ananas-v0.10.6-0.14.2-Ananas-arm64-v8a.dm",
|
||||||
|
"baselineProfiles/1/ananas-v0.10.6-0.14.2-Ananas-x86_64.dm",
|
||||||
|
"baselineProfiles/1/ananas-v0.10.6-0.14.2-Ananas-x86.dm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minApi": 31,
|
||||||
|
"maxApi": 2147483647,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/0/ananas-v0.10.6-0.14.2-Ananas-armeabi-v7a.dm",
|
||||||
|
"baselineProfiles/0/ananas-v0.10.6-0.14.2-Ananas-arm64-v8a.dm",
|
||||||
|
"baselineProfiles/0/ananas-v0.10.6-0.14.2-Ananas-x86_64.dm",
|
||||||
|
"baselineProfiles/0/ananas-v0.10.6-0.14.2-Ananas-x86.dm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minSdkVersionForDexing": 28
|
||||||
|
}
|
|
@ -10,19 +10,23 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "dev.jdtech.jellyfin"
|
namespace = "com.nomadics9.ananas"
|
||||||
compileSdk = Versions.compileSdk
|
compileSdk = Versions.compileSdk
|
||||||
buildToolsVersion = Versions.buildTools
|
buildToolsVersion = Versions.buildTools
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "dev.jdtech.jellyfin"
|
applicationId = "com.nomadics9.ananas"
|
||||||
minSdk = Versions.minSdk
|
minSdk = Versions.minSdk
|
||||||
targetSdk = Versions.targetSdk
|
targetSdk = Versions.targetSdk
|
||||||
|
|
||||||
versionCode = Versions.appCode
|
versionCode = Versions.appCode
|
||||||
versionName = Versions.appName
|
versionName = Versions.appName
|
||||||
|
|
||||||
testInstrumentationRunner = "dev.jdtech.jellyfin.HiltTestRunner"
|
testInstrumentationRunner = "com.nomadics9.ananas.HiltTestRunner"
|
||||||
|
buildConfigField( "String", "DEFAULT_SERVER_ADDRESS", "\" \"")
|
||||||
|
buildConfigField( "String", "REQUEST_SERVER_ADDRESS", "\" \"")
|
||||||
|
buildConfigField("String", "FORGET_PASSWORD_ADDRESS", "\" \"")
|
||||||
|
buildConfigField("String", "UPDATE_ADDRESS", "\" \"")
|
||||||
}
|
}
|
||||||
|
|
||||||
applicationVariants.all {
|
applicationVariants.all {
|
||||||
|
@ -31,7 +35,7 @@ android {
|
||||||
.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
|
.map { it as com.android.build.gradle.internal.api.BaseVariantOutputImpl }
|
||||||
.forEach { output ->
|
.forEach { output ->
|
||||||
if (variant.buildType.name == "release") {
|
if (variant.buildType.name == "release") {
|
||||||
val outputFileName = "findroid-v${variant.versionName}-${variant.flavorName}-${output.getFilter("ABI")}.apk"
|
val outputFileName = "ananas-v${variant.versionName}-${variant.flavorName}-${output.getFilter("ABI")}.apk"
|
||||||
output.outputFileName = outputFileName
|
output.outputFileName = outputFileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,10 +61,18 @@ android {
|
||||||
|
|
||||||
flavorDimensions += "variant"
|
flavorDimensions += "variant"
|
||||||
productFlavors {
|
productFlavors {
|
||||||
register("libre") {
|
create("libre") {
|
||||||
dimension = "variant"
|
dimension = "variant"
|
||||||
isDefault = true
|
isDefault = true
|
||||||
}
|
}
|
||||||
|
create("Ananas") {
|
||||||
|
dimension = "variant"
|
||||||
|
isDefault = false
|
||||||
|
buildConfigField( "String", "DEFAULT_SERVER_ADDRESS", "\"https://askar.tv\"")
|
||||||
|
buildConfigField( "String", "REQUEST_SERVER_ADDRESS", "\"https://r.askar.tv\"")
|
||||||
|
buildConfigField("String", "FORGET_PASSWORD_ADDRESS", "\"https://user.askar.tv/my/account\"")
|
||||||
|
buildConfigField("String", "UPDATE_ADDRESS", "\"https://fs.nmd.mov/p/ananas.apk\"")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
splits {
|
splits {
|
||||||
|
@ -122,6 +134,7 @@ dependencies {
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.media3.ffmpeg.decoder)
|
implementation(libs.media3.ffmpeg.decoder)
|
||||||
implementation(libs.timber)
|
implementation(libs.timber)
|
||||||
|
implementation(libs.markwon)
|
||||||
|
|
||||||
coreLibraryDesugaring(libs.android.desugar.jdk)
|
coreLibraryDesugaring(libs.android.desugar.jdk)
|
||||||
|
|
||||||
|
|
87
app/phone/libre/release/output-metadata.json
Normal file
87
app/phone/libre/release/output-metadata.json
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "com.nomadics9.ananas",
|
||||||
|
"variantName": "libreRelease",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "armeabi-v7a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 11,
|
||||||
|
"versionName": "0.10.1-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.1-0.14.2-libre-armeabi-v7a.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86_64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 11,
|
||||||
|
"versionName": "0.10.1-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.1-0.14.2-libre-x86_64.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "arm64-v8a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 11,
|
||||||
|
"versionName": "0.10.1-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.1-0.14.2-libre-arm64-v8a.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 11,
|
||||||
|
"versionName": "0.10.1-0.14.2",
|
||||||
|
"outputFile": "ananas-v0.10.1-0.14.2-libre-x86.apk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elementType": "File",
|
||||||
|
"baselineProfiles": [
|
||||||
|
{
|
||||||
|
"minApi": 28,
|
||||||
|
"maxApi": 30,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/1/ananas-v0.10.1-0.14.2-libre-armeabi-v7a.dm",
|
||||||
|
"baselineProfiles/1/ananas-v0.10.1-0.14.2-libre-x86_64.dm",
|
||||||
|
"baselineProfiles/1/ananas-v0.10.1-0.14.2-libre-arm64-v8a.dm",
|
||||||
|
"baselineProfiles/1/ananas-v0.10.1-0.14.2-libre-x86.dm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minApi": 31,
|
||||||
|
"maxApi": 2147483647,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/0/ananas-v0.10.1-0.14.2-libre-armeabi-v7a.dm",
|
||||||
|
"baselineProfiles/0/ananas-v0.10.1-0.14.2-libre-x86_64.dm",
|
||||||
|
"baselineProfiles/0/ananas-v0.10.1-0.14.2-libre-arm64-v8a.dm",
|
||||||
|
"baselineProfiles/0/ananas-v0.10.1-0.14.2-libre-x86.dm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minSdkVersionForDexing": 28
|
||||||
|
}
|
16
app/phone/proguard-rules.pro
vendored
16
app/phone/proguard-rules.pro
vendored
|
@ -20,16 +20,16 @@
|
||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
-keepnames class dev.jdtech.jellyfin.models.PlayerItem
|
-keepnames class com.nomadics9.ananas.models.PlayerItem
|
||||||
|
|
||||||
# ProGuard thinks all SettingsFragments are unused
|
# ProGuard thinks all SettingsFragments are unused
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsLanguageFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsLanguageFragment
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsAppearanceFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsAppearanceFragment
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsDownloadsFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsDownloadsFragment
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsPlayerFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsPlayerFragment
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsDeviceFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsDeviceFragment
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsCacheFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsCacheFragment
|
||||||
-keep class dev.jdtech.jellyfin.fragments.SettingsNetworkFragment
|
-keep class com.nomadics9.ananas.fragments.SettingsNetworkFragment
|
||||||
|
|
||||||
# These classes are from okhttp and are not used in Android
|
# These classes are from okhttp and are not used in Android
|
||||||
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
-dontwarn org.bouncycastle.jsse.BCSSLSocket
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.hilt.work.HiltWorkerFactory
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
|
@ -19,7 +19,7 @@ import androidx.work.testing.WorkManagerTestInitHelper
|
||||||
import dagger.hilt.android.testing.HiltAndroidRule
|
import dagger.hilt.android.testing.HiltAndroidRule
|
||||||
import dagger.hilt.android.testing.HiltAndroidTest
|
import dagger.hilt.android.testing.HiltAndroidTest
|
||||||
import dagger.hilt.android.testing.UninstallModules
|
import dagger.hilt.android.testing.UninstallModules
|
||||||
import dev.jdtech.jellyfin.di.DatabaseModule
|
import com.nomadics9.ananas.di.DatabaseModule
|
||||||
import org.hamcrest.CoreMatchers.allOf
|
import org.hamcrest.CoreMatchers.allOf
|
||||||
import org.hamcrest.CoreMatchers.not
|
import org.hamcrest.CoreMatchers.not
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
@ -76,9 +76,9 @@ class MainActivityTest {
|
||||||
waitForElement(allOf(withText("Movies"), isDisplayed()))
|
waitForElement(allOf(withText("Movies"), isDisplayed()))
|
||||||
onView(withText("Movies")).perform(click())
|
onView(withText("Movies")).perform(click())
|
||||||
|
|
||||||
// Navigate to The Boy in the Plastic Bubble
|
// Navigate to Battle of the Stars
|
||||||
waitForElement(allOf(withText("The Boy in the Plastic Bubble"), isDisplayed()))
|
waitForElement(allOf(withText("Battle of the Stars"), isDisplayed()))
|
||||||
onView(withText("The Boy in the Plastic Bubble")).perform(click())
|
onView(withText("Battle of the Stars")).perform(click())
|
||||||
|
|
||||||
// Play the movie
|
// Play the movie
|
||||||
waitForElement(allOf(withId(R.id.play_button), isEnabled()))
|
waitForElement(allOf(withId(R.id.play_button), isEnabled()))
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.di
|
package com.nomadics9.ananas.di
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
|
@ -7,8 +7,8 @@ import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import dev.jdtech.jellyfin.database.ServerDatabase
|
import com.nomadics9.ananas.database.ServerDatabase
|
||||||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
import com.nomadics9.ananas.database.ServerDatabaseDao
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
@ -14,7 +14,7 @@ import com.google.android.material.color.DynamicColorsOptions
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class BaseApplication : Application(), Configuration.Provider, ImageLoaderFactory {
|
class BaseApplication : Application(), Configuration.Provider, ImageLoaderFactory {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -9,7 +9,7 @@ import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.media3.session.MediaSession
|
import androidx.media3.session.MediaSession
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
import com.nomadics9.ananas.viewmodels.PlayerActivityViewModel
|
||||||
|
|
||||||
abstract class BasePlayerActivity : AppCompatActivity() {
|
abstract class BasePlayerActivity : AppCompatActivity() {
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import coil.load
|
import coil.load
|
||||||
import dev.jdtech.jellyfin.api.JellyfinApi
|
import com.nomadics9.ananas.api.JellyfinApi
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.User
|
import com.nomadics9.ananas.models.User
|
||||||
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 org.jellyfin.sdk.model.api.BaseItemPerson
|
import org.jellyfin.sdk.model.api.BaseItemPerson
|
||||||
import org.jellyfin.sdk.model.api.ImageType
|
import org.jellyfin.sdk.model.api.ImageType
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
fun bindItemImage(imageView: ImageView, item: BaseItemDto) {
|
fun bindItemImage(imageView: ImageView, item: BaseItemDto) {
|
||||||
val itemId =
|
val itemId =
|
|
@ -1,12 +1,10 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.core.view.WindowInsetsCompat
|
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.NavGraph
|
import androidx.navigation.NavGraph
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
@ -21,12 +19,16 @@ import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.google.android.material.navigation.NavigationBarView
|
import com.google.android.material.navigation.NavigationBarView
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
import com.nomadics9.ananas.database.ServerDatabaseDao
|
||||||
import dev.jdtech.jellyfin.databinding.ActivityMainBinding
|
import com.nomadics9.ananas.databinding.ActivityMainBinding
|
||||||
import dev.jdtech.jellyfin.viewmodels.MainViewModel
|
import com.nomadics9.ananas.viewmodels.MainViewModel
|
||||||
import dev.jdtech.jellyfin.work.SyncWorker
|
import com.nomadics9.ananas.work.SyncWorker
|
||||||
|
import com.nomadics9.ananas.repository.JellyfinRepository
|
||||||
|
import com.nomadics9.ananas.utils.restart
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
@ -38,6 +40,9 @@ class MainActivity : AppCompatActivity() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var database: ServerDatabaseDao
|
lateinit var database: ServerDatabaseDao
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var jellyfinRepository: JellyfinRepository
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appPreferences: AppPreferences
|
lateinit var appPreferences: AppPreferences
|
||||||
|
|
||||||
|
@ -48,21 +53,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
scheduleUserDataSync()
|
scheduleUserDataSync()
|
||||||
applyTheme()
|
applyTheme()
|
||||||
setupActivity()
|
setupActivity()
|
||||||
|
|
||||||
// Temp fix insets because SDK 35 enables edge to edge by default. This will probably be removed once we move to compose
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
|
|
||||||
val bars = insets.getInsets(
|
|
||||||
WindowInsetsCompat.Type.systemBars()
|
|
||||||
or WindowInsetsCompat.Type.displayCutout(),
|
|
||||||
)
|
|
||||||
v.updatePadding(
|
|
||||||
left = bars.left,
|
|
||||||
top = bars.top,
|
|
||||||
right = bars.right,
|
|
||||||
bottom = bars.bottom,
|
|
||||||
)
|
|
||||||
WindowInsetsCompat.CONSUMED
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(NavigationUiSaveStateControl::class)
|
@OptIn(NavigationUiSaveStateControl::class)
|
||||||
|
@ -86,10 +76,18 @@ class MainActivity : AppCompatActivity() {
|
||||||
val navView: NavigationBarView = binding.navView as NavigationBarView
|
val navView: NavigationBarView = binding.navView as NavigationBarView
|
||||||
|
|
||||||
if (appPreferences.offlineMode) {
|
if (appPreferences.offlineMode) {
|
||||||
|
appPreferences.isOffline = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appPreferences.isOffline) {
|
||||||
navView.menu.clear()
|
navView.menu.clear()
|
||||||
navView.inflateMenu(CoreR.menu.bottom_nav_menu_offline)
|
navView.inflateMenu(CoreR.menu.bottom_nav_menu_offline)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!appPreferences.isOffline && appPreferences.autoOffline) {
|
||||||
|
testServerConnection()
|
||||||
|
}
|
||||||
|
|
||||||
setSupportActionBar(binding.mainToolbar)
|
setSupportActionBar(binding.mainToolbar)
|
||||||
|
|
||||||
// Passing each menu ID as a set of Ids because each
|
// Passing each menu ID as a set of Ids because each
|
||||||
|
@ -110,7 +108,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
navController.addOnDestinationChangedListener { _, destination, _ ->
|
navController.addOnDestinationChangedListener { _, destination, _ ->
|
||||||
binding.navView.visibility = when (destination.id) {
|
binding.navView.visibility = when (destination.id) {
|
||||||
R.id.twoPaneSettingsFragment, R.id.serverSelectFragment, R.id.addServerFragment, R.id.loginFragment, com.mikepenz.aboutlibraries.R.id.about_libraries_dest, R.id.usersFragment, R.id.serverAddressesFragment -> View.GONE
|
R.id.twoPaneSettingsFragment, R.id.serverSelectFragment, R.id.addServerFragment, R.id.loginFragment, com.mikepenz.aboutlibraries.R.id.about_libraries_dest, R.id.usersFragment, R.id.serverAddressesFragment, R.id.requestsWebFragment -> View.GONE
|
||||||
else -> View.VISIBLE
|
else -> View.VISIBLE
|
||||||
}
|
}
|
||||||
if (destination.id == com.mikepenz.aboutlibraries.R.id.about_libraries_dest) {
|
if (destination.id == com.mikepenz.aboutlibraries.R.id.about_libraries_dest) {
|
||||||
|
@ -170,4 +168,18 @@ class MainActivity : AppCompatActivity() {
|
||||||
setTheme(CoreR.style.ThemeOverlay_Findroid_Amoled)
|
setTheme(CoreR.style.ThemeOverlay_Findroid_Amoled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun testServerConnection() {
|
||||||
|
val activity = this
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
jellyfinRepository.getPublicSystemInfo()
|
||||||
|
// Give the UI a chance to load
|
||||||
|
delay(100)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
appPreferences.isOffline = true
|
||||||
|
activity.restart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.AppOpsManager
|
import android.app.AppOpsManager
|
||||||
import android.app.PictureInPictureParams
|
import android.app.PictureInPictureParams
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
@ -35,25 +34,25 @@ import androidx.media3.ui.PlayerControlView
|
||||||
import androidx.media3.ui.PlayerView
|
import androidx.media3.ui.PlayerView
|
||||||
import androidx.navigation.navArgs
|
import androidx.navigation.navArgs
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.nomadics9.ananas.databinding.ActivityPlayerBinding
|
||||||
|
import com.nomadics9.ananas.dialogs.SpeedSelectionDialogFragment
|
||||||
|
import com.nomadics9.ananas.dialogs.TrackSelectionDialogFragment
|
||||||
|
import com.nomadics9.ananas.models.FindroidSegment
|
||||||
|
import com.nomadics9.ananas.utils.PlayerGestureHelper
|
||||||
|
import com.nomadics9.ananas.utils.PreviewScrubListener
|
||||||
|
import com.nomadics9.ananas.viewmodels.PlayerActivityViewModel
|
||||||
|
import com.nomadics9.ananas.viewmodels.PlayerEvents
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.databinding.ActivityPlayerBinding
|
|
||||||
import dev.jdtech.jellyfin.dialogs.SpeedSelectionDialogFragment
|
|
||||||
import dev.jdtech.jellyfin.dialogs.TrackSelectionDialogFragment
|
|
||||||
import dev.jdtech.jellyfin.models.VideoQuality
|
|
||||||
import dev.jdtech.jellyfin.utils.PlayerGestureHelper
|
|
||||||
import dev.jdtech.jellyfin.utils.PreviewScrubListener
|
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerActivityViewModel
|
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerEvents
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
import com.nomadics9.ananas.models.VideoQuality
|
||||||
|
|
||||||
var isControlsLocked: Boolean = false
|
var isControlsLocked: Boolean = false
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class PlayerActivity : BasePlayerActivity() {
|
class PlayerActivity : BasePlayerActivity() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appPreferences: AppPreferences
|
lateinit var appPreferences: AppPreferences
|
||||||
|
|
||||||
|
@ -62,6 +61,8 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
override val viewModel: PlayerActivityViewModel by viewModels()
|
override val viewModel: PlayerActivityViewModel by viewModels()
|
||||||
private var previewScrubListener: PreviewScrubListener? = null
|
private var previewScrubListener: PreviewScrubListener? = null
|
||||||
private var wasZoom: Boolean = false
|
private var wasZoom: Boolean = false
|
||||||
|
private var oldSegment: FindroidSegment? = null
|
||||||
|
private var buttonPressed: Boolean = false
|
||||||
|
|
||||||
private val isPipSupported by lazy {
|
private val isPipSupported by lazy {
|
||||||
// Check if device has PiP feature
|
// Check if device has PiP feature
|
||||||
|
@ -110,12 +111,13 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
configureInsets(lockedControls)
|
configureInsets(lockedControls)
|
||||||
|
|
||||||
if (appPreferences.playerGestures) {
|
if (appPreferences.playerGestures) {
|
||||||
playerGestureHelper = PlayerGestureHelper(
|
playerGestureHelper =
|
||||||
appPreferences,
|
PlayerGestureHelper(
|
||||||
this,
|
appPreferences,
|
||||||
binding.playerView,
|
this,
|
||||||
getSystemService(Context.AUDIO_SERVICE) as AudioManager,
|
binding.playerView,
|
||||||
)
|
getSystemService(AUDIO_SERVICE) as AudioManager,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.playerView.findViewById<View>(R.id.back_button).setOnClickListener {
|
binding.playerView.findViewById<View>(R.id.back_button).setOnClickListener {
|
||||||
|
@ -127,7 +129,8 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
val audioButton = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track)
|
val audioButton = binding.playerView.findViewById<ImageButton>(R.id.btn_audio_track)
|
||||||
val subtitleButton = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle)
|
val subtitleButton = binding.playerView.findViewById<ImageButton>(R.id.btn_subtitle)
|
||||||
val speedButton = binding.playerView.findViewById<ImageButton>(R.id.btn_speed)
|
val speedButton = binding.playerView.findViewById<ImageButton>(R.id.btn_speed)
|
||||||
val skipIntroButton = binding.playerView.findViewById<Button>(R.id.btn_skip_intro)
|
val skipButton = binding.playerView.findViewById<Button>(R.id.btn_skip_intro)
|
||||||
|
val watchCreditsButton = binding.playerView.findViewById<Button>(R.id.btn_watch_credits)
|
||||||
val pipButton = binding.playerView.findViewById<ImageButton>(R.id.btn_pip)
|
val pipButton = binding.playerView.findViewById<ImageButton>(R.id.btn_pip)
|
||||||
val lockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_lockview)
|
val lockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_lockview)
|
||||||
val unlockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_unlock)
|
val unlockButton = binding.playerView.findViewById<ImageButton>(R.id.btn_unlock)
|
||||||
|
@ -141,19 +144,101 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
// Title
|
// Title
|
||||||
videoNameTextView.text = currentItemTitle
|
videoNameTextView.text = currentItemTitle
|
||||||
|
|
||||||
// Skip Intro button
|
// Skip Button
|
||||||
skipIntroButton.isVisible = !isInPictureInPictureMode && currentIntro != null
|
if (currentSegment != oldSegment) buttonPressed = false
|
||||||
skipIntroButton.setOnClickListener {
|
// Button Visibility and Text
|
||||||
currentIntro?.let {
|
when (currentSegment?.type) {
|
||||||
binding.playerView.player?.seekTo((it.introEnd * 1000).toLong())
|
"intro" -> {
|
||||||
|
skipButton.text =
|
||||||
|
getString(CoreR.string.skip_intro_button)
|
||||||
|
skipButton.isVisible =
|
||||||
|
!isInPictureInPictureMode &&
|
||||||
|
!buttonPressed &&
|
||||||
|
(
|
||||||
|
showSkip == true ||
|
||||||
|
(binding.playerView.isControllerFullyVisible && currentSegment?.skip == true)
|
||||||
|
)
|
||||||
|
watchCreditsButton.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
"credit" -> {
|
||||||
|
skipButton.text =
|
||||||
|
if (binding.playerView.player?.hasNextMediaItem() == true) {
|
||||||
|
getString(CoreR.string.skip_credit_button)
|
||||||
|
} else {
|
||||||
|
getString(CoreR.string.skip_credit_button_last)
|
||||||
|
}
|
||||||
|
skipButton.isVisible =
|
||||||
|
!isInPictureInPictureMode &&
|
||||||
|
!buttonPressed &&
|
||||||
|
currentSegment?.skip == true &&
|
||||||
|
!binding.playerView.isControllerFullyVisible
|
||||||
|
watchCreditsButton.isVisible = skipButton.isVisible
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
skipButton.isVisible = false
|
||||||
|
watchCreditsButton.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.playerView.setControllerVisibilityListener(
|
||||||
|
PlayerView.ControllerVisibilityListener { visibility ->
|
||||||
|
when (currentSegment?.type) {
|
||||||
|
"intro" -> {
|
||||||
|
skipButton.isVisible =
|
||||||
|
!buttonPressed &&
|
||||||
|
(showSkip == true || (visibility == View.VISIBLE && currentSegment?.skip == true))
|
||||||
|
}
|
||||||
|
|
||||||
|
"credit" -> {
|
||||||
|
skipButton.isVisible =
|
||||||
|
!buttonPressed &&
|
||||||
|
currentSegment?.skip == true &&
|
||||||
|
visibility == View.GONE
|
||||||
|
watchCreditsButton.isVisible = skipButton.isVisible
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// onClick
|
||||||
|
if (currentSegment?.type == "credit") {
|
||||||
|
watchCreditsButton.setOnClickListener {
|
||||||
|
buttonPressed = true
|
||||||
|
skipButton.isVisible = false
|
||||||
|
watchCreditsButton.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skipButton.setOnClickListener {
|
||||||
|
when (currentSegment?.type) {
|
||||||
|
"intro" -> {
|
||||||
|
currentSegment?.let {
|
||||||
|
binding.playerView.player?.seekTo((it.endTime * 1000).toLong())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"credit" -> {
|
||||||
|
if (binding.playerView.player?.hasNextMediaItem() == true) {
|
||||||
|
binding.playerView.player?.seekToNext()
|
||||||
|
} else {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buttonPressed = true
|
||||||
|
skipButton.isVisible = false
|
||||||
|
watchCreditsButton.isVisible = false
|
||||||
|
}
|
||||||
|
oldSegment = currentSegment
|
||||||
|
|
||||||
// Trickplay
|
// Trickplay
|
||||||
previewScrubListener?.let {
|
previewScrubListener?.let {
|
||||||
it.currentTrickplay = currentTrickplay
|
it.currentTrickplay = currentTrickplay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
playerGestureHelper?.let {
|
||||||
|
it.currentTrickplay = currentTrickplay
|
||||||
|
}
|
||||||
|
|
||||||
// Chapters
|
// Chapters
|
||||||
if (appPreferences.showChapterMarkers && currentChapters != null) {
|
if (appPreferences.showChapterMarkers && currentChapters != null) {
|
||||||
currentChapters?.let { chapters ->
|
currentChapters?.let { chapters ->
|
||||||
|
@ -191,7 +276,8 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
if (appPreferences.playerPipGesture) {
|
if (appPreferences.playerPipGesture) {
|
||||||
try {
|
try {
|
||||||
setPictureInPictureParams(pipParams(event.isPlaying))
|
setPictureInPictureParams(pipParams(event.isPlaying))
|
||||||
} catch (_: IllegalArgumentException) { }
|
} catch (_: IllegalArgumentException) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,7 +376,6 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
viewModel.initializePlayer(args.items)
|
viewModel.initializePlayer(args.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingSuperCall")
|
|
||||||
override fun onUserLeaveHint() {
|
override fun onUserLeaveHint() {
|
||||||
super.onUserLeaveHint()
|
super.onUserLeaveHint()
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S &&
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S &&
|
||||||
|
@ -305,34 +390,38 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
private fun pipParams(enableAutoEnter: Boolean = viewModel.player.isPlaying): PictureInPictureParams {
|
private fun pipParams(enableAutoEnter: Boolean = viewModel.player.isPlaying): PictureInPictureParams {
|
||||||
val displayAspectRatio = Rational(binding.playerView.width, binding.playerView.height)
|
val displayAspectRatio = Rational(binding.playerView.width, binding.playerView.height)
|
||||||
|
|
||||||
val aspectRatio = binding.playerView.player?.videoSize?.let {
|
val aspectRatio =
|
||||||
Rational(
|
binding.playerView.player?.videoSize?.let {
|
||||||
it.width.coerceAtMost((it.height * 2.39f).toInt()),
|
Rational(
|
||||||
it.height.coerceAtMost((it.width * 2.39f).toInt()),
|
it.width.coerceAtMost((it.height * 2.39f).toInt()),
|
||||||
)
|
it.height.coerceAtMost((it.width * 2.39f).toInt()),
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val sourceRectHint = if (displayAspectRatio < aspectRatio!!) {
|
val sourceRectHint =
|
||||||
val space = ((binding.playerView.height - (binding.playerView.width.toFloat() / aspectRatio.toFloat())) / 2).toInt()
|
if (displayAspectRatio < aspectRatio!!) {
|
||||||
Rect(
|
val space = ((binding.playerView.height - (binding.playerView.width.toFloat() / aspectRatio.toFloat())) / 2).toInt()
|
||||||
0,
|
Rect(
|
||||||
space,
|
0,
|
||||||
binding.playerView.width,
|
space,
|
||||||
(binding.playerView.width.toFloat() / aspectRatio.toFloat()).toInt() + space,
|
binding.playerView.width,
|
||||||
)
|
(binding.playerView.width.toFloat() / aspectRatio.toFloat()).toInt() + space,
|
||||||
} else {
|
)
|
||||||
val space = ((binding.playerView.width - (binding.playerView.height.toFloat() * aspectRatio.toFloat())) / 2).toInt()
|
} else {
|
||||||
Rect(
|
val space = ((binding.playerView.width - (binding.playerView.height.toFloat() * aspectRatio.toFloat())) / 2).toInt()
|
||||||
space,
|
Rect(
|
||||||
0,
|
space,
|
||||||
(binding.playerView.height.toFloat() * aspectRatio.toFloat()).toInt() + space,
|
0,
|
||||||
binding.playerView.height,
|
(binding.playerView.height.toFloat() * aspectRatio.toFloat()).toInt() + space,
|
||||||
)
|
binding.playerView.height,
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val builder = PictureInPictureParams.Builder()
|
val builder =
|
||||||
.setAspectRatio(aspectRatio)
|
PictureInPictureParams
|
||||||
.setSourceRectHint(sourceRectHint)
|
.Builder()
|
||||||
|
.setAspectRatio(aspectRatio)
|
||||||
|
.setSourceRectHint(sourceRectHint)
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
builder.setAutoEnterEnabled(enableAutoEnter)
|
builder.setAutoEnterEnabled(enableAutoEnter)
|
||||||
|
@ -390,25 +479,29 @@ class PlayerActivity : BasePlayerActivity() {
|
||||||
playerGestureHelper?.updateZoomMode(false)
|
playerGestureHelper?.updateZoomMode(false)
|
||||||
|
|
||||||
// Brightness mode Auto
|
// Brightness mode Auto
|
||||||
window.attributes = window.attributes.apply {
|
window.attributes =
|
||||||
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
|
window.attributes.apply {
|
||||||
}
|
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
false -> {
|
false -> {
|
||||||
binding.playerView.useController = true
|
binding.playerView.useController = true
|
||||||
playerGestureHelper?.updateZoomMode(wasZoom)
|
playerGestureHelper?.updateZoomMode(wasZoom)
|
||||||
|
|
||||||
// Override auto brightness
|
// Override auto brightness
|
||||||
window.attributes = window.attributes.apply {
|
window.attributes =
|
||||||
screenBrightness = if (appPreferences.playerBrightnessRemember) {
|
window.attributes.apply {
|
||||||
appPreferences.playerBrightness
|
screenBrightness =
|
||||||
} else {
|
if (appPreferences.playerBrightnessRemember) {
|
||||||
Settings.System.getInt(
|
appPreferences.playerBrightness
|
||||||
contentResolver,
|
} else {
|
||||||
Settings.System.SCREEN_BRIGHTNESS,
|
Settings.System
|
||||||
).toFloat() / 255
|
.getInt(
|
||||||
|
contentResolver,
|
||||||
|
Settings.System.SCREEN_BRIGHTNESS,
|
||||||
|
).toFloat() / 255
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindCardItemImage
|
import com.nomadics9.ananas.bindCardItemImage
|
||||||
import dev.jdtech.jellyfin.databinding.CollectionItemBinding
|
import com.nomadics9.ananas.databinding.CollectionItemBinding
|
||||||
import dev.jdtech.jellyfin.models.FindroidCollection
|
import com.nomadics9.ananas.models.FindroidCollection
|
||||||
|
|
||||||
class CollectionListAdapter(
|
class CollectionListAdapter(
|
||||||
private val onClickListener: (collection: FindroidCollection) -> Unit,
|
private val onClickListener: (collection: FindroidCollection) -> Unit,
|
||||||
|
@ -47,4 +47,4 @@ class CollectionListAdapter(
|
||||||
}
|
}
|
||||||
holder.bind(collection)
|
holder.bind(collection)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.databinding.DiscoveredServerItemBinding
|
import com.nomadics9.ananas.databinding.DiscoveredServerItemBinding
|
||||||
import dev.jdtech.jellyfin.models.DiscoveredServer
|
import com.nomadics9.ananas.models.DiscoveredServer
|
||||||
|
|
||||||
class DiscoveredServerListAdapter(
|
class DiscoveredServerListAdapter(
|
||||||
private val clickListener: (server: DiscoveredServer) -> Unit,
|
private val clickListener: (server: DiscoveredServer) -> Unit,
|
||||||
|
@ -55,4 +55,4 @@ class DiscoveredServerListAdapter(
|
||||||
holder.itemView.setOnClickListener { clickListener(server) }
|
holder.itemView.setOnClickListener { clickListener(server) }
|
||||||
holder.bind(server)
|
holder.bind(server)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.text.Html.fromHtml
|
import android.text.Html.fromHtml
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
@ -9,15 +9,15 @@ import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindCardItemImage
|
import com.nomadics9.ananas.bindCardItemImage
|
||||||
import dev.jdtech.jellyfin.bindItemBackdropById
|
import com.nomadics9.ananas.bindItemBackdropById
|
||||||
import dev.jdtech.jellyfin.bindSeasonPoster
|
import com.nomadics9.ananas.bindSeasonPoster
|
||||||
import dev.jdtech.jellyfin.databinding.EpisodeItemBinding
|
import com.nomadics9.ananas.databinding.EpisodeItemBinding
|
||||||
import dev.jdtech.jellyfin.databinding.SeasonHeaderBinding
|
import com.nomadics9.ananas.databinding.SeasonHeaderBinding
|
||||||
import dev.jdtech.jellyfin.models.EpisodeItem
|
import com.nomadics9.ananas.models.EpisodeItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
private const val ITEM_VIEW_TYPE_HEADER = 0
|
private const val ITEM_VIEW_TYPE_HEADER = 0
|
||||||
private const val ITEM_VIEW_TYPE_EPISODE = 1
|
private const val ITEM_VIEW_TYPE_EPISODE = 1
|
||||||
|
@ -123,4 +123,4 @@ class EpisodeListAdapter(
|
||||||
is EpisodeItem.Episode -> ITEM_VIEW_TYPE_EPISODE
|
is EpisodeItem.Episode -> ITEM_VIEW_TYPE_EPISODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.Constants
|
import com.nomadics9.ananas.Constants
|
||||||
import dev.jdtech.jellyfin.databinding.FavoriteSectionBinding
|
import com.nomadics9.ananas.databinding.FavoriteSectionBinding
|
||||||
import dev.jdtech.jellyfin.models.FavoriteSection
|
import com.nomadics9.ananas.models.FavoriteSection
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
|
|
||||||
class FavoritesListAdapter(
|
class FavoritesListAdapter(
|
||||||
private val onItemClickListener: (item: FindroidItem) -> Unit,
|
private val onItemClickListener: (item: FindroidItem) -> Unit,
|
||||||
|
@ -59,4 +59,4 @@ class FavoritesListAdapter(
|
||||||
val collection = getItem(position)
|
val collection = getItem(position)
|
||||||
holder.bind(collection, onItemClickListener)
|
holder.bind(collection, onItemClickListener)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -8,13 +8,13 @@ import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindCardItemImage
|
import com.nomadics9.ananas.bindCardItemImage
|
||||||
import dev.jdtech.jellyfin.databinding.HomeEpisodeItemBinding
|
import com.nomadics9.ananas.databinding.HomeEpisodeItemBinding
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class HomeEpisodeListAdapter(private val onClickListener: (item: FindroidItem) -> Unit) : ListAdapter<FindroidItem, HomeEpisodeListAdapter.EpisodeViewHolder>(DiffCallback) {
|
class HomeEpisodeListAdapter(private val onClickListener: (item: FindroidItem) -> Unit) : ListAdapter<FindroidItem, HomeEpisodeListAdapter.EpisodeViewHolder>(DiffCallback) {
|
||||||
class EpisodeViewHolder(
|
class EpisodeViewHolder(
|
||||||
|
@ -81,4 +81,4 @@ class HomeEpisodeListAdapter(private val onClickListener: (item: FindroidItem) -
|
||||||
}
|
}
|
||||||
holder.bind(item)
|
holder.bind(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindPersonImage
|
import com.nomadics9.ananas.bindPersonImage
|
||||||
import dev.jdtech.jellyfin.databinding.PersonItemBinding
|
import com.nomadics9.ananas.databinding.PersonItemBinding
|
||||||
import org.jellyfin.sdk.model.api.BaseItemPerson
|
import org.jellyfin.sdk.model.api.BaseItemPerson
|
||||||
|
|
||||||
class PersonListAdapter(private val clickListener: (item: BaseItemPerson) -> Unit) : ListAdapter<BaseItemPerson, PersonListAdapter.PersonViewHolder>(DiffCallback) {
|
class PersonListAdapter(private val clickListener: (item: BaseItemPerson) -> Unit) : ListAdapter<BaseItemPerson, PersonListAdapter.PersonViewHolder>(DiffCallback) {
|
||||||
|
@ -45,4 +45,4 @@ class PersonListAdapter(private val clickListener: (item: BaseItemPerson) -> Uni
|
||||||
holder.bind(item)
|
holder.bind(item)
|
||||||
holder.itemView.setOnClickListener { clickListener(item) }
|
holder.itemView.setOnClickListener { clickListener(item) }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.databinding.ServerAddressListItemBinding
|
import com.nomadics9.ananas.databinding.ServerAddressListItemBinding
|
||||||
import dev.jdtech.jellyfin.models.ServerAddress
|
import com.nomadics9.ananas.models.ServerAddress
|
||||||
|
|
||||||
class ServerAddressAdapter(
|
class ServerAddressAdapter(
|
||||||
private val clickListener: (address: ServerAddress) -> Unit,
|
private val clickListener: (address: ServerAddress) -> Unit,
|
||||||
|
@ -48,4 +48,4 @@ class ServerAddressAdapter(
|
||||||
holder.itemView.setOnLongClickListener { longClickListener(address) }
|
holder.itemView.setOnLongClickListener { longClickListener(address) }
|
||||||
holder.bind(address)
|
holder.bind(address)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.databinding.ServerItemBinding
|
import com.nomadics9.ananas.databinding.ServerItemBinding
|
||||||
import dev.jdtech.jellyfin.models.Server
|
import com.nomadics9.ananas.models.Server
|
||||||
|
|
||||||
class ServerGridAdapter(
|
class ServerGridAdapter(
|
||||||
private val onClickListener: (server: Server) -> Unit,
|
private val onClickListener: (server: Server) -> Unit,
|
||||||
|
@ -46,4 +46,4 @@ class ServerGridAdapter(
|
||||||
}
|
}
|
||||||
holder.bind(server)
|
holder.bind(server)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindUserImage
|
import com.nomadics9.ananas.bindUserImage
|
||||||
import dev.jdtech.jellyfin.databinding.UserListItemBinding
|
import com.nomadics9.ananas.databinding.UserListItemBinding
|
||||||
import dev.jdtech.jellyfin.models.User
|
import com.nomadics9.ananas.models.User
|
||||||
|
|
||||||
class UserListAdapter(
|
class UserListAdapter(
|
||||||
private val clickListener: (user: User) -> Unit,
|
private val clickListener: (user: User) -> Unit,
|
||||||
|
@ -50,4 +50,4 @@ class UserListAdapter(
|
||||||
holder.itemView.setOnLongClickListener { longClickListener(user) }
|
holder.itemView.setOnLongClickListener { longClickListener(user) }
|
||||||
holder.bind(user)
|
holder.bind(user)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindUserImage
|
import com.nomadics9.ananas.bindUserImage
|
||||||
import dev.jdtech.jellyfin.databinding.UserItemBinding
|
import com.nomadics9.ananas.databinding.UserItemBinding
|
||||||
import dev.jdtech.jellyfin.models.User
|
import com.nomadics9.ananas.models.User
|
||||||
|
|
||||||
class UserLoginListAdapter(
|
class UserLoginListAdapter(
|
||||||
private val clickListener: (user: User) -> Unit,
|
private val clickListener: (user: User) -> Unit,
|
||||||
|
@ -48,4 +48,4 @@ class UserLoginListAdapter(
|
||||||
holder.itemView.setOnClickListener { clickListener(user) }
|
holder.itemView.setOnClickListener { clickListener(user) }
|
||||||
holder.bind(user)
|
holder.bind(user)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -7,12 +7,12 @@ import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindItemImage
|
import com.nomadics9.ananas.bindItemImage
|
||||||
import dev.jdtech.jellyfin.databinding.BaseItemBinding
|
import com.nomadics9.ananas.databinding.BaseItemBinding
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class ViewItemListAdapter(
|
class ViewItemListAdapter(
|
||||||
private val onClickListener: (item: FindroidItem) -> Unit,
|
private val onClickListener: (item: FindroidItem) -> Unit,
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -7,12 +7,12 @@ import androidx.core.view.isVisible
|
||||||
import androidx.paging.PagingDataAdapter
|
import androidx.paging.PagingDataAdapter
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.bindItemImage
|
import com.nomadics9.ananas.bindItemImage
|
||||||
import dev.jdtech.jellyfin.databinding.BaseItemBinding
|
import com.nomadics9.ananas.databinding.BaseItemBinding
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class ViewItemPagingAdapter(
|
class ViewItemPagingAdapter(
|
||||||
private val onClickListener: (item: FindroidItem) -> Unit,
|
private val onClickListener: (item: FindroidItem) -> Unit,
|
||||||
|
@ -70,4 +70,4 @@ class ViewItemPagingAdapter(
|
||||||
holder.bind(item, fixedWidth)
|
holder.bind(item, fixedWidth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,17 +1,17 @@
|
||||||
package dev.jdtech.jellyfin.adapters
|
package com.nomadics9.ananas.adapters
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dev.jdtech.jellyfin.databinding.CardOfflineBinding
|
import com.nomadics9.ananas.databinding.CardOfflineBinding
|
||||||
import dev.jdtech.jellyfin.databinding.NextUpSectionBinding
|
import com.nomadics9.ananas.databinding.NextUpSectionBinding
|
||||||
import dev.jdtech.jellyfin.databinding.ViewItemBinding
|
import com.nomadics9.ananas.databinding.ViewItemBinding
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.HomeItem
|
import com.nomadics9.ananas.models.HomeItem
|
||||||
import dev.jdtech.jellyfin.models.View
|
import com.nomadics9.ananas.models.View
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
private const val ITEM_VIEW_TYPE_NEXT_UP = 0
|
private const val ITEM_VIEW_TYPE_NEXT_UP = 0
|
||||||
private const val ITEM_VIEW_TYPE_VIEW = 1
|
private const val ITEM_VIEW_TYPE_VIEW = 1
|
||||||
|
@ -125,4 +125,4 @@ class ViewListAdapter(
|
||||||
is HomeItem.ViewItem -> ITEM_VIEW_TYPE_VIEW
|
is HomeItem.ViewItem -> ITEM_VIEW_TYPE_VIEW
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.di
|
package com.nomadics9.ananas.di
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
@ -6,7 +6,7 @@ import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import dev.jdtech.jellyfin.BaseApplication
|
import com.nomadics9.ananas.BaseApplication
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.jdtech.jellyfin.dialogs
|
package com.nomadics9.ananas.dialogs
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.StatFs
|
import android.os.StatFs
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
fun getStorageSelectionDialog(
|
fun getStorageSelectionDialog(
|
||||||
context: Context,
|
context: Context,
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
|
@ -14,11 +14,12 @@ import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import com.nomadics9.ananas.BuildConfig
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.DiscoveredServerListAdapter
|
import com.nomadics9.ananas.adapters.DiscoveredServerListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentAddServerBinding
|
import com.nomadics9.ananas.databinding.FragmentAddServerBinding
|
||||||
import dev.jdtech.jellyfin.viewmodels.AddServerEvent
|
import com.nomadics9.ananas.viewmodels.AddServerEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.AddServerViewModel
|
import com.nomadics9.ananas.viewmodels.AddServerViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
@ -89,7 +90,12 @@ class AddServerFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (BuildConfig.FLAVOR == "Ananas") {
|
||||||
|
fun connectToServerDirectly(serverAddress: String = BuildConfig.DEFAULT_SERVER_ADDRESS) {
|
||||||
|
viewModel.checkServer(serverAddress.removeSuffix("/"))
|
||||||
|
}
|
||||||
|
connectToServerDirectly()
|
||||||
|
}
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,6 +140,16 @@ class AddServerFragment : Fragment() {
|
||||||
viewModel.checkServer(serverAddress.removeSuffix("/"))
|
viewModel.checkServer(serverAddress.removeSuffix("/"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// private fun connectToServer() {
|
||||||
|
// val serverAddress = (binding.editTextServerAddress as AppCompatEditText).text.toString()
|
||||||
|
// if (serverAddress.isNotBlank()) {
|
||||||
|
// viewModel.checkServer(serverAddress.removeSuffix("/"))
|
||||||
|
// } else {
|
||||||
|
// viewModel.checkServer(BuildConfig.DEFAULT_SERVER_ADDRESS.removeSuffix("/"))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
private fun navigateToLoginFragment() {
|
private fun navigateToLoginFragment() {
|
||||||
findNavController().navigate(AddServerFragmentDirections.actionAddServerFragmentToLoginFragment())
|
findNavController().navigate(AddServerFragmentDirections.actionAddServerFragmentToLoginFragment())
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -13,18 +13,18 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.FavoritesListAdapter
|
import com.nomadics9.ananas.adapters.FavoritesListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentFavoriteBinding
|
import com.nomadics9.ananas.databinding.FragmentFavoriteBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.viewmodels.CollectionViewModel
|
import com.nomadics9.ananas.viewmodels.CollectionViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class CollectionFragment : Fragment() {
|
class CollectionFragment : Fragment() {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -13,19 +13,19 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.adapters.FavoritesListAdapter
|
import com.nomadics9.ananas.adapters.FavoritesListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentDownloadsBinding
|
import com.nomadics9.ananas.databinding.FragmentDownloadsBinding
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.utils.restart
|
import com.nomadics9.ananas.utils.restart
|
||||||
import dev.jdtech.jellyfin.viewmodels.DownloadsEvent
|
import com.nomadics9.ananas.viewmodels.DownloadsEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.DownloadsViewModel
|
import com.nomadics9.ananas.viewmodels.DownloadsViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class DownloadsFragment : Fragment() {
|
class DownloadsFragment : Fragment() {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.app.DownloadManager
|
import android.app.DownloadManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -21,23 +21,23 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.R
|
import com.nomadics9.ananas.R
|
||||||
import dev.jdtech.jellyfin.bindCardItemImage
|
import com.nomadics9.ananas.bindCardItemImage
|
||||||
import dev.jdtech.jellyfin.databinding.EpisodeBottomSheetBinding
|
import com.nomadics9.ananas.databinding.EpisodeBottomSheetBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.dialogs.getStorageSelectionDialog
|
import com.nomadics9.ananas.dialogs.getStorageSelectionDialog
|
||||||
import dev.jdtech.jellyfin.dialogs.getVideoVersionDialog
|
import com.nomadics9.ananas.dialogs.getVideoVersionDialog
|
||||||
import dev.jdtech.jellyfin.models.FindroidSourceType
|
import com.nomadics9.ananas.models.FindroidSourceType
|
||||||
import dev.jdtech.jellyfin.models.PlayerItem
|
import com.nomadics9.ananas.models.PlayerItem
|
||||||
import dev.jdtech.jellyfin.models.UiText
|
import com.nomadics9.ananas.models.UiText
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.models.isDownloading
|
import com.nomadics9.ananas.models.isDownloading
|
||||||
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
|
import com.nomadics9.ananas.utils.setIconTintColorAttribute
|
||||||
import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetEvent
|
import com.nomadics9.ananas.viewmodels.EpisodeBottomSheetEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.EpisodeBottomSheetViewModel
|
import com.nomadics9.ananas.viewmodels.EpisodeBottomSheetViewModel
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerItemsEvent
|
import com.nomadics9.ananas.viewmodels.PlayerItemsEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
import com.nomadics9.ananas.viewmodels.PlayerViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jellyfin.sdk.model.DateTime
|
import org.jellyfin.sdk.model.DateTime
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
@ -48,7 +48,7 @@ import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import android.R as AndroidR
|
import android.R as AndroidR
|
||||||
import com.google.android.material.R as MaterialR
|
import com.google.android.material.R as MaterialR
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
|
class EpisodeBottomSheetFragment : BottomSheetDialogFragment() {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -12,15 +12,15 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.FavoritesListAdapter
|
import com.nomadics9.ananas.adapters.FavoritesListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentFavoriteBinding
|
import com.nomadics9.ananas.databinding.FragmentFavoriteBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.viewmodels.FavoriteViewModel
|
import com.nomadics9.ananas.viewmodels.FavoriteViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -19,21 +19,21 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.adapters.ViewListAdapter
|
import com.nomadics9.ananas.adapters.ViewListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentHomeBinding
|
import com.nomadics9.ananas.databinding.FragmentHomeBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.utils.restart
|
import com.nomadics9.ananas.utils.restart
|
||||||
import dev.jdtech.jellyfin.viewmodels.HomeViewModel
|
import com.nomadics9.ananas.viewmodels.HomeViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class HomeFragment : Fragment() {
|
class HomeFragment : Fragment() {
|
||||||
|
@ -74,6 +74,12 @@ class HomeFragment : Fragment() {
|
||||||
val searchView = search.actionView as SearchView
|
val searchView = search.actionView as SearchView
|
||||||
searchView.queryHint = getString(CoreR.string.search_hint)
|
searchView.queryHint = getString(CoreR.string.search_hint)
|
||||||
|
|
||||||
|
val requests = menu.findItem(CoreR.id.action_requests)
|
||||||
|
requests.setOnMenuItemClickListener{
|
||||||
|
navigateToRequestsWebViewFragment()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
search.setOnActionExpandListener(
|
search.setOnActionExpandListener(
|
||||||
object : MenuItem.OnActionExpandListener {
|
object : MenuItem.OnActionExpandListener {
|
||||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
||||||
|
@ -202,7 +208,7 @@ class HomeFragment : Fragment() {
|
||||||
checkIfLoginRequired(uiState.error.message)
|
checkIfLoginRequired(uiState.error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateToLibraryFragment(view: dev.jdtech.jellyfin.models.View) {
|
private fun navigateToLibraryFragment(view: com.nomadics9.ananas.models.View) {
|
||||||
findNavController().navigate(
|
findNavController().navigate(
|
||||||
HomeFragmentDirections.actionNavigationHomeToLibraryFragment(
|
HomeFragmentDirections.actionNavigationHomeToLibraryFragment(
|
||||||
libraryId = view.id,
|
libraryId = view.id,
|
||||||
|
@ -251,4 +257,10 @@ class HomeFragment : Fragment() {
|
||||||
HomeFragmentDirections.actionHomeFragmentToSearchResultFragment(query),
|
HomeFragmentDirections.actionHomeFragmentToSearchResultFragment(query),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun navigateToRequestsWebViewFragment() {
|
||||||
|
findNavController().navigate(
|
||||||
|
HomeFragmentDirections.actionHomeFragmentToRequestsWebFragment()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -19,24 +19,25 @@ import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import androidx.paging.LoadState
|
import androidx.paging.LoadState
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.adapters.ViewItemPagingAdapter
|
import com.nomadics9.ananas.adapters.ViewItemPagingAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentLibraryBinding
|
import com.nomadics9.ananas.databinding.FragmentLibraryBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.dialogs.SortDialogFragment
|
import com.nomadics9.ananas.dialogs.SortDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidBoxSet
|
import com.nomadics9.ananas.models.FindroidBoxSet
|
||||||
import dev.jdtech.jellyfin.models.FindroidFolder
|
import com.nomadics9.ananas.models.FindroidFolder
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.models.SortBy
|
import com.nomadics9.ananas.models.SortBy
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.viewmodels.LibraryViewModel
|
import com.nomadics9.ananas.viewmodels.LibraryViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jellyfin.sdk.model.api.SortOrder
|
import org.jellyfin.sdk.model.api.SortOrder
|
||||||
import java.lang.IllegalArgumentException
|
import java.lang.IllegalArgumentException
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class LibraryFragment : Fragment() {
|
class LibraryFragment : Fragment() {
|
||||||
|
@ -62,6 +63,11 @@ class LibraryFragment : Fragment() {
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
binding.itemsRecyclerView.layoutManager =
|
||||||
|
GridLayoutManager(context, preferences.spanCount)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val menuHost: MenuHost = requireActivity()
|
val menuHost: MenuHost = requireActivity()
|
||||||
menuHost.addMenuProvider(
|
menuHost.addMenuProvider(
|
||||||
object : MenuProvider {
|
object : MenuProvider {
|
|
@ -1,5 +1,7 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Html.fromHtml
|
import android.text.Html.fromHtml
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -16,16 +18,18 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.adapters.UserLoginListAdapter
|
import com.nomadics9.ananas.BuildConfig
|
||||||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
import com.nomadics9.ananas.adapters.UserLoginListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentLoginBinding
|
import com.nomadics9.ananas.database.ServerDatabaseDao
|
||||||
import dev.jdtech.jellyfin.viewmodels.LoginEvent
|
import com.nomadics9.ananas.databinding.FragmentLoginBinding
|
||||||
import dev.jdtech.jellyfin.viewmodels.LoginViewModel
|
import com.nomadics9.ananas.viewmodels.LoginEvent
|
||||||
|
import com.nomadics9.ananas.viewmodels.LoginViewModel
|
||||||
|
import io.noties.markwon.Markwon
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class LoginFragment : Fragment() {
|
class LoginFragment : Fragment() {
|
||||||
|
@ -78,6 +82,17 @@ class LoginFragment : Fragment() {
|
||||||
(binding.editTextPassword as AppCompatEditText).requestFocus()
|
(binding.editTextPassword as AppCompatEditText).requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (BuildConfig.FLAVOR == "Ananas") {
|
||||||
|
binding.buttonForgetPassword.setOnClickListener {
|
||||||
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.FORGET_PASSWORD_ADDRESS))
|
||||||
|
startActivity(browserIntent)
|
||||||
|
}
|
||||||
|
binding.buttonForgetPassword.isVisible = true
|
||||||
|
} else {
|
||||||
|
binding.buttonForgetPassword.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
viewModel.uiState.collect { uiState ->
|
viewModel.uiState.collect { uiState ->
|
||||||
|
@ -143,7 +158,21 @@ class LoginFragment : Fragment() {
|
||||||
binding.editTextPasswordLayout.isEnabled = true
|
binding.editTextPasswordLayout.isEnabled = true
|
||||||
|
|
||||||
uiState.disclaimer?.let { disclaimer ->
|
uiState.disclaimer?.let { disclaimer ->
|
||||||
binding.loginDisclaimer.text = fromHtml(disclaimer, 0)
|
if (BuildConfig.FLAVOR == "Ananas") {
|
||||||
|
val lines = disclaimer.lines()
|
||||||
|
val lineToRemoveIndex = 3
|
||||||
|
val filteredLines = lines.toMutableList().apply {
|
||||||
|
if (size > lineToRemoveIndex) {
|
||||||
|
removeAt(lineToRemoveIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val filteredDisclaimer = filteredLines.joinToString("\n")
|
||||||
|
val markwon = Markwon.create(requireContext())
|
||||||
|
markwon.setMarkdown(binding.loginDisclaimer, filteredDisclaimer)
|
||||||
|
} else {
|
||||||
|
val markwon = Markwon.create(requireContext())
|
||||||
|
markwon.setMarkdown(binding.loginDisclaimer, disclaimer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -19,15 +19,15 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.CollectionListAdapter
|
import com.nomadics9.ananas.adapters.CollectionListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentMediaBinding
|
import com.nomadics9.ananas.databinding.FragmentMediaBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidCollection
|
import com.nomadics9.ananas.models.FindroidCollection
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.viewmodels.MediaViewModel
|
import com.nomadics9.ananas.viewmodels.MediaViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MediaFragment : Fragment() {
|
class MediaFragment : Fragment() {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.app.DownloadManager
|
import android.app.DownloadManager
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
@ -21,32 +21,32 @@ import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.R
|
import com.nomadics9.ananas.R
|
||||||
import dev.jdtech.jellyfin.adapters.PersonListAdapter
|
import com.nomadics9.ananas.adapters.PersonListAdapter
|
||||||
import dev.jdtech.jellyfin.bindItemBackdropImage
|
import com.nomadics9.ananas.bindItemBackdropImage
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentMovieBinding
|
import com.nomadics9.ananas.databinding.FragmentMovieBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.dialogs.getStorageSelectionDialog
|
import com.nomadics9.ananas.dialogs.getStorageSelectionDialog
|
||||||
import dev.jdtech.jellyfin.dialogs.getVideoVersionDialog
|
import com.nomadics9.ananas.dialogs.getVideoVersionDialog
|
||||||
import dev.jdtech.jellyfin.models.AudioCodec
|
import com.nomadics9.ananas.models.AudioCodec
|
||||||
import dev.jdtech.jellyfin.models.DisplayProfile
|
import com.nomadics9.ananas.models.DisplayProfile
|
||||||
import dev.jdtech.jellyfin.models.FindroidSourceType
|
import com.nomadics9.ananas.models.FindroidSourceType
|
||||||
import dev.jdtech.jellyfin.models.PlayerItem
|
import com.nomadics9.ananas.models.PlayerItem
|
||||||
import dev.jdtech.jellyfin.models.UiText
|
import com.nomadics9.ananas.models.UiText
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.models.isDownloading
|
import com.nomadics9.ananas.models.isDownloading
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
|
import com.nomadics9.ananas.utils.setIconTintColorAttribute
|
||||||
import dev.jdtech.jellyfin.viewmodels.MovieEvent
|
import com.nomadics9.ananas.viewmodels.MovieEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.MovieViewModel
|
import com.nomadics9.ananas.viewmodels.MovieViewModel
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerItemsEvent
|
import com.nomadics9.ananas.viewmodels.PlayerItemsEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
import com.nomadics9.ananas.viewmodels.PlayerViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MovieFragment : Fragment() {
|
class MovieFragment : Fragment() {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -15,18 +15,18 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
|
import com.nomadics9.ananas.adapters.ViewItemListAdapter
|
||||||
import dev.jdtech.jellyfin.bindItemImage
|
import com.nomadics9.ananas.bindItemImage
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentPersonDetailBinding
|
import com.nomadics9.ananas.databinding.FragmentPersonDetailBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.viewmodels.PersonDetailViewModel
|
import com.nomadics9.ananas.viewmodels.PersonDetailViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
internal class PersonDetailFragment : Fragment() {
|
internal class PersonDetailFragment : Fragment() {
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.webkit.WebSettings
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.nomadics9.ananas.BuildConfig
|
||||||
|
import com.nomadics9.ananas.R
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class RequestsWebViewFragment : Fragment() {
|
||||||
|
private lateinit var webView: WebView
|
||||||
|
private lateinit var progressBar: ProgressBar
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
val rootView = inflater.inflate(R.layout.fragment_webview, container, false)
|
||||||
|
|
||||||
|
webView = rootView.findViewById(R.id.webview)
|
||||||
|
progressBar = rootView.findViewById(R.id.progressBar)
|
||||||
|
|
||||||
|
val webSettings: WebSettings = webView.settings
|
||||||
|
webSettings.javaScriptEnabled = true // Enable JavaScript if required
|
||||||
|
|
||||||
|
// Set WebViewClient to handle loading URLs within the WebView
|
||||||
|
webView.webViewClient = object : WebViewClient() {
|
||||||
|
override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
|
||||||
|
// Return false to indicate that the WebView should load the URL
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up WebView client to handle page loading events
|
||||||
|
webView.webViewClient = object : WebViewClient() {
|
||||||
|
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||||
|
super.onPageStarted(view, url, favicon)
|
||||||
|
progressBar.visibility = View.VISIBLE // Show progress bar when page starts loading
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
|
super.onPageFinished(view, url)
|
||||||
|
progressBar.visibility = View.GONE // Hide progress bar when page finishes loading
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load your URL here
|
||||||
|
webView.loadUrl(BuildConfig.REQUEST_SERVER_ADDRESS)
|
||||||
|
|
||||||
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
if (webView.canGoBack()) {
|
||||||
|
webView.goBack()
|
||||||
|
} else {
|
||||||
|
isEnabled = false
|
||||||
|
requireActivity().onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rootView
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -13,15 +13,15 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.FavoritesListAdapter
|
import com.nomadics9.ananas.adapters.FavoritesListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentSearchResultBinding
|
import com.nomadics9.ananas.databinding.FragmentSearchResultBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.viewmodels.SearchResultViewModel
|
import com.nomadics9.ananas.viewmodels.SearchResultViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -0,0 +1,266 @@
|
||||||
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.MenuHost
|
||||||
|
import androidx.core.view.MenuProvider
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.navigation.fragment.navArgs
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import com.nomadics9.ananas.adapters.EpisodeListAdapter
|
||||||
|
import com.nomadics9.ananas.databinding.FragmentSeasonBinding
|
||||||
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
|
import com.nomadics9.ananas.dialogs.getStorageSelectionDialog
|
||||||
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
|
import com.nomadics9.ananas.viewmodels.SeasonEvent
|
||||||
|
import com.nomadics9.ananas.viewmodels.SeasonViewModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.nomadics9.ananas.AppPreferences
|
||||||
|
import com.nomadics9.ananas.models.UiText
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class SeasonFragment : Fragment() {
|
||||||
|
|
||||||
|
private lateinit var binding: FragmentSeasonBinding
|
||||||
|
private val viewModel: SeasonViewModel by viewModels()
|
||||||
|
private val args: SeasonFragmentArgs by navArgs()
|
||||||
|
|
||||||
|
private lateinit var errorDialog: ErrorDialogFragment
|
||||||
|
private lateinit var downloadPreparingDialog: AlertDialog
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var appPreferences: AppPreferences
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?,
|
||||||
|
): View {
|
||||||
|
binding = FragmentSeasonBinding.inflate(inflater, container, false)
|
||||||
|
val menuHost: MenuHost = requireActivity()
|
||||||
|
menuHost.addMenuProvider(
|
||||||
|
object : MenuProvider {
|
||||||
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
menuInflater.inflate(com.nomadics9.ananas.core.R.menu.season_menu, menu)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||||
|
return when (menuItem.itemId) {
|
||||||
|
com.nomadics9.ananas.core.R.id.action_download_season -> {
|
||||||
|
if (requireContext().getExternalFilesDirs(null).filterNotNull().size > 1) {
|
||||||
|
val storageDialog = getStorageSelectionDialog(
|
||||||
|
requireContext(),
|
||||||
|
onItemSelected = { storageIndex ->
|
||||||
|
createEpisodesToDownloadDialog(storageIndex)
|
||||||
|
},
|
||||||
|
onCancel = {
|
||||||
|
},
|
||||||
|
)
|
||||||
|
viewModel.download()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
createEpisodesToDownloadDialog()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
viewLifecycleOwner,
|
||||||
|
Lifecycle.State.RESUMED,
|
||||||
|
)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
launch {
|
||||||
|
viewModel.uiState.collect { uiState ->
|
||||||
|
Timber.d("$uiState")
|
||||||
|
when (uiState) {
|
||||||
|
is SeasonViewModel.UiState.Normal -> bindUiStateNormal(uiState)
|
||||||
|
is SeasonViewModel.UiState.Loading -> bindUiStateLoading()
|
||||||
|
is SeasonViewModel.UiState.Error -> bindUiStateError(uiState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
|
||||||
|
viewModel.downloadStatus.collect { (status, progress) ->
|
||||||
|
when (status) {
|
||||||
|
10 -> {
|
||||||
|
downloadPreparingDialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.downloadError.collect { uiText ->
|
||||||
|
createErrorDialog(uiText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
launch {
|
||||||
|
viewModel.eventsChannelFlow.collect { event ->
|
||||||
|
when (event) {
|
||||||
|
is SeasonEvent.NavigateBack -> findNavController().navigateUp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.errorLayout.errorRetryButton.setOnClickListener {
|
||||||
|
viewModel.loadEpisodes(args.seriesId, args.seasonId, args.offline)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.errorLayout.errorDetailsButton.setOnClickListener {
|
||||||
|
errorDialog.show(parentFragmentManager, ErrorDialogFragment.TAG)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.episodesRecyclerView.adapter =
|
||||||
|
EpisodeListAdapter { episode ->
|
||||||
|
navigateToEpisodeBottomSheetFragment(episode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
viewModel.loadEpisodes(args.seriesId, args.seasonId, args.offline)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindUiStateNormal(uiState: SeasonViewModel.UiState.Normal) {
|
||||||
|
uiState.apply {
|
||||||
|
val adapter = binding.episodesRecyclerView.adapter as EpisodeListAdapter
|
||||||
|
adapter.submitList(uiState.episodes)
|
||||||
|
}
|
||||||
|
binding.loadingIndicator.isVisible = false
|
||||||
|
binding.episodesRecyclerView.isVisible = true
|
||||||
|
binding.errorLayout.errorPanel.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindUiStateLoading() {
|
||||||
|
binding.loadingIndicator.isVisible = true
|
||||||
|
binding.errorLayout.errorPanel.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bindUiStateError(uiState: SeasonViewModel.UiState.Error) {
|
||||||
|
errorDialog = ErrorDialogFragment.newInstance(uiState.error)
|
||||||
|
binding.loadingIndicator.isVisible = false
|
||||||
|
binding.episodesRecyclerView.isVisible = false
|
||||||
|
binding.errorLayout.errorPanel.isVisible = true
|
||||||
|
checkIfLoginRequired(uiState.error.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDownloadPreparingDialog() {
|
||||||
|
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||||
|
downloadPreparingDialog = builder
|
||||||
|
.setTitle(com.nomadics9.ananas.core.R.string.preparing_download)
|
||||||
|
.setView(com.nomadics9.ananas.R.layout.preparing_download_dialog)
|
||||||
|
.setCancelable(false)
|
||||||
|
.create()
|
||||||
|
downloadPreparingDialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createErrorDialog(uiText: UiText) {
|
||||||
|
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||||
|
builder
|
||||||
|
.setTitle(com.nomadics9.ananas.core.R.string.downloading_error)
|
||||||
|
.setMessage(uiText.asString(requireContext().resources))
|
||||||
|
.setPositiveButton(getString(com.nomadics9.ananas.core.R.string.close)) { _, _ ->
|
||||||
|
}
|
||||||
|
builder.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEpisodesToDownloadDialog(storageIndex: Int = 0) {
|
||||||
|
if (!appPreferences.downloadQualityDefault)
|
||||||
|
createPickQualityDialog {
|
||||||
|
showDownloadDialog(storageIndex)
|
||||||
|
} else {
|
||||||
|
showDownloadDialog(storageIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDownloadDialog(storageIndex: Int = 0) {
|
||||||
|
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||||
|
val dialog = builder
|
||||||
|
.setTitle(com.nomadics9.ananas.core.R.string.download_season_dialog_title)
|
||||||
|
.setMessage(com.nomadics9.ananas.core.R.string.download_season_dialog_question)
|
||||||
|
.setPositiveButton(com.nomadics9.ananas.core.R.string.download_season_dialog_download_all) { _, _ ->
|
||||||
|
createDownloadPreparingDialog()
|
||||||
|
viewModel.download(storageIndex = storageIndex, downloadWatched = true)
|
||||||
|
}
|
||||||
|
.setNegativeButton(com.nomadics9.ananas.core.R.string.download_season_dialog_download_unwatched) { _, _ ->
|
||||||
|
createDownloadPreparingDialog()
|
||||||
|
viewModel.download(storageIndex = storageIndex, downloadWatched = false)
|
||||||
|
}
|
||||||
|
.create()
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPickQualityDialog(onQualitySelected: () -> Unit) {
|
||||||
|
val qualityEntries = resources.getStringArray(com.nomadics9.ananas.core.R.array.download_quality_entries)
|
||||||
|
val qualityValues = resources.getStringArray(com.nomadics9.ananas.core.R.array.download_quality_values)
|
||||||
|
val quality = appPreferences.downloadQuality
|
||||||
|
val currentQualityIndex = qualityValues.indexOf(quality)
|
||||||
|
|
||||||
|
var selectedQuality = quality
|
||||||
|
|
||||||
|
val builder = MaterialAlertDialogBuilder(requireContext())
|
||||||
|
builder.setTitle("Download Quality")
|
||||||
|
builder.setSingleChoiceItems(qualityEntries, currentQualityIndex) { _, which ->
|
||||||
|
selectedQuality = qualityValues[which]
|
||||||
|
}
|
||||||
|
builder.setPositiveButton("Download") { dialog, _ ->
|
||||||
|
appPreferences.downloadQuality = selectedQuality
|
||||||
|
onQualitySelected()
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
builder.setNegativeButton("Cancel") { dialog, _ ->
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
val dialog = builder.create()
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private fun navigateToEpisodeBottomSheetFragment(episode: FindroidEpisode) {
|
||||||
|
findNavController().navigate(
|
||||||
|
SeasonFragmentDirections.actionSeasonFragmentToEpisodeBottomSheetFragment(
|
||||||
|
episode.id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -12,12 +12,12 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.ServerAddressAdapter
|
import com.nomadics9.ananas.adapters.ServerAddressAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentServerAddressesBinding
|
import com.nomadics9.ananas.databinding.FragmentServerAddressesBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.AddServerAddressDialog
|
import com.nomadics9.ananas.dialogs.AddServerAddressDialog
|
||||||
import dev.jdtech.jellyfin.dialogs.DeleteServerAddressDialog
|
import com.nomadics9.ananas.dialogs.DeleteServerAddressDialog
|
||||||
import dev.jdtech.jellyfin.viewmodels.ServerAddressesEvent
|
import com.nomadics9.ananas.viewmodels.ServerAddressesEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.ServerAddressesViewModel
|
import com.nomadics9.ananas.viewmodels.ServerAddressesViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -11,11 +11,11 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.adapters.ServerGridAdapter
|
import com.nomadics9.ananas.adapters.ServerGridAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentServerSelectBinding
|
import com.nomadics9.ananas.databinding.FragmentServerSelectBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.DeleteServerDialogFragment
|
import com.nomadics9.ananas.dialogs.DeleteServerDialogFragment
|
||||||
import dev.jdtech.jellyfin.viewmodels.ServerSelectEvent
|
import com.nomadics9.ananas.viewmodels.ServerSelectEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.ServerSelectViewModel
|
import com.nomadics9.ananas.viewmodels.ServerSelectViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreferenceCompat
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class SettingsAppearanceFragment : PreferenceFragmentCompat() {
|
class SettingsAppearanceFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
@ -1,10 +1,10 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class SettingsCacheFragment : PreferenceFragmentCompat() {
|
class SettingsCacheFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
@ -1,12 +1,12 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.viewmodels.SettingsDeviceViewModel
|
import com.nomadics9.ananas.viewmodels.SettingsDeviceViewModel
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class SettingsDeviceFragment : PreferenceFragmentCompat() {
|
class SettingsDeviceFragment : PreferenceFragmentCompat() {
|
|
@ -1,8 +1,8 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class SettingsDownloadsFragment : PreferenceFragmentCompat() {
|
class SettingsDownloadsFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
@ -0,0 +1,175 @@
|
||||||
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import com.nomadics9.ananas.AppPreferences
|
||||||
|
import com.nomadics9.ananas.BuildConfig
|
||||||
|
import com.nomadics9.ananas.utils.restart
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.net.HttpURLConnection
|
||||||
|
import java.net.URL
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
|
@Inject
|
||||||
|
lateinit var appPreferences: AppPreferences
|
||||||
|
|
||||||
|
private val updateUrl = BuildConfig.UPDATE_ADDRESS
|
||||||
|
private var isUpdateAvailable: Boolean = false
|
||||||
|
private var newLastModifiedDate: Date? = null
|
||||||
|
|
||||||
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
setPreferencesFromResource(CoreR.xml.fragment_settings, rootKey)
|
||||||
|
|
||||||
|
findPreference<Preference>("switchServer")?.setOnPreferenceClickListener {
|
||||||
|
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionNavigationSettingsToServerSelectFragment())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("switchUser")?.setOnPreferenceClickListener {
|
||||||
|
val serverId = appPreferences.currentServer!!
|
||||||
|
findNavController().navigate(
|
||||||
|
TwoPaneSettingsFragmentDirections.actionNavigationSettingsToUsersFragment(
|
||||||
|
serverId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("switchAddress")?.setOnPreferenceClickListener {
|
||||||
|
val serverId = appPreferences.currentServer!!
|
||||||
|
findNavController().navigate(
|
||||||
|
TwoPaneSettingsFragmentDirections.actionNavigationSettingsToServerAddressesFragment(
|
||||||
|
serverId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("pref_offline_mode")?.setOnPreferenceClickListener {
|
||||||
|
activity?.restart()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("privacyPolicy")?.setOnPreferenceClickListener {
|
||||||
|
val intent = Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse("https://github.com/nomadics9/ananas/blob/main/PRIVACY"),
|
||||||
|
)
|
||||||
|
startActivity(intent)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
findPreference<Preference>("appInfo")?.setOnPreferenceClickListener {
|
||||||
|
if (isUpdateAvailable && newLastModifiedDate != null) {
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(updateUrl))
|
||||||
|
startActivity(intent)
|
||||||
|
storeDate(newLastModifiedDate!!)
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionSettingsFragmentToAboutLibraries())
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findPreference<Preference>("requests")?.setOnPreferenceClickListener {
|
||||||
|
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionNavigationSettingsToRequestsWebFragment())
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for updates when the settings screen is opened
|
||||||
|
checkForUpdates()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkForUpdates() {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val lastModifiedDate = fetchLastModifiedDate(updateUrl)
|
||||||
|
if (lastModifiedDate != null) {
|
||||||
|
Timber.d("Fetched Last-Modified date: $lastModifiedDate")
|
||||||
|
val storedDate = getStoredDate()
|
||||||
|
Timber.d("Stored date: $storedDate")
|
||||||
|
if (storedDate == Date(0L) || lastModifiedDate.after(storedDate)) {
|
||||||
|
Timber.d("Update available")
|
||||||
|
isUpdateAvailable = true
|
||||||
|
newLastModifiedDate = lastModifiedDate
|
||||||
|
showUpdateAvailable()
|
||||||
|
} else {
|
||||||
|
Timber.d("No update available")
|
||||||
|
isUpdateAvailable = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Timber.d("Failed to fetch Last-Modified date")
|
||||||
|
isUpdateAvailable = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchLastModifiedDate(urlString: String): Date? {
|
||||||
|
return withContext(Dispatchers.IO) {
|
||||||
|
var urlConnection: HttpURLConnection? = null
|
||||||
|
try {
|
||||||
|
val url = URL(urlString)
|
||||||
|
urlConnection = url.openConnection() as HttpURLConnection
|
||||||
|
urlConnection.requestMethod = "HEAD"
|
||||||
|
val lastModified = urlConnection.getHeaderField("Last-Modified")
|
||||||
|
if (lastModified != null) {
|
||||||
|
val dateFormat = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US)
|
||||||
|
dateFormat.parse(lastModified)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "Error fetching Last-Modified date")
|
||||||
|
null
|
||||||
|
} finally {
|
||||||
|
urlConnection?.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getStoredDate(): Date {
|
||||||
|
val sharedPreferences = preferenceManager.sharedPreferences
|
||||||
|
val storedDateString = sharedPreferences?.getString("stored_date", null)
|
||||||
|
Timber.d("Retrieved stored date string: $storedDateString")
|
||||||
|
return if (storedDateString != null) {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).parse(storedDateString) ?: Date(0)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "Error parsing stored date string")
|
||||||
|
Date(0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Date(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun storeDate(date: Date) {
|
||||||
|
val dateString = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).format(date)
|
||||||
|
preferenceManager.sharedPreferences?.edit()?.putString("stored_date", dateString)?.apply()
|
||||||
|
Timber.d("Stored new date: $dateString")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUpdateAvailable() {
|
||||||
|
val appInfoPreference = findPreference<Preference>("appInfo")
|
||||||
|
appInfoPreference?.let {
|
||||||
|
it.summary = "Update available!"
|
||||||
|
it.icon = ResourcesCompat.getDrawable(resources, CoreR.drawable.ic_download, null) // Ensure this drawable exists
|
||||||
|
Timber.d("Update available UI shown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -7,7 +7,7 @@ import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class SettingsLanguageFragment : PreferenceFragmentCompat() {
|
class SettingsLanguageFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import dev.jdtech.jellyfin.Constants
|
import com.nomadics9.ananas.Constants
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class SettingsNetworkFragment : PreferenceFragmentCompat() {
|
class SettingsNetworkFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -7,7 +7,7 @@ import android.text.InputType
|
||||||
import androidx.preference.EditTextPreference
|
import androidx.preference.EditTextPreference
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
class SettingsPlayerFragment : PreferenceFragmentCompat() {
|
class SettingsPlayerFragment : PreferenceFragmentCompat() {
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
@ -18,29 +18,29 @@ import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import com.google.android.material.R
|
import com.google.android.material.R
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.adapters.PersonListAdapter
|
import com.nomadics9.ananas.adapters.PersonListAdapter
|
||||||
import dev.jdtech.jellyfin.adapters.ViewItemListAdapter
|
import com.nomadics9.ananas.adapters.ViewItemListAdapter
|
||||||
import dev.jdtech.jellyfin.bindCardItemImage
|
import com.nomadics9.ananas.bindCardItemImage
|
||||||
import dev.jdtech.jellyfin.bindItemBackdropImage
|
import com.nomadics9.ananas.bindItemBackdropImage
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentShowBinding
|
import com.nomadics9.ananas.databinding.FragmentShowBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
import com.nomadics9.ananas.dialogs.ErrorDialogFragment
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidSeason
|
import com.nomadics9.ananas.models.FindroidSeason
|
||||||
import dev.jdtech.jellyfin.models.FindroidSourceType
|
import com.nomadics9.ananas.models.FindroidSourceType
|
||||||
import dev.jdtech.jellyfin.models.PlayerItem
|
import com.nomadics9.ananas.models.PlayerItem
|
||||||
import dev.jdtech.jellyfin.models.isDownloaded
|
import com.nomadics9.ananas.models.isDownloaded
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
import com.nomadics9.ananas.utils.checkIfLoginRequired
|
||||||
import dev.jdtech.jellyfin.utils.setIconTintColorAttribute
|
import com.nomadics9.ananas.utils.setIconTintColorAttribute
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerItemsEvent
|
import com.nomadics9.ananas.viewmodels.PlayerItemsEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
import com.nomadics9.ananas.viewmodels.PlayerViewModel
|
||||||
import dev.jdtech.jellyfin.viewmodels.ShowEvent
|
import com.nomadics9.ananas.viewmodels.ShowEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.ShowViewModel
|
import com.nomadics9.ananas.viewmodels.ShowViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ShowFragment : Fragment() {
|
class ShowFragment : Fragment() {
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.PreferenceHeaderFragmentCompat
|
import androidx.preference.PreferenceHeaderFragmentCompat
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
package com.nomadics9.ananas.fragments
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
@ -12,12 +12,12 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import androidx.navigation.fragment.navArgs
|
import androidx.navigation.fragment.navArgs
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.AppNavigationDirections
|
import com.nomadics9.ananas.AppNavigationDirections
|
||||||
import dev.jdtech.jellyfin.adapters.UserListAdapter
|
import com.nomadics9.ananas.adapters.UserListAdapter
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentUsersBinding
|
import com.nomadics9.ananas.databinding.FragmentUsersBinding
|
||||||
import dev.jdtech.jellyfin.dialogs.DeleteUserDialogFragment
|
import com.nomadics9.ananas.dialogs.DeleteUserDialogFragment
|
||||||
import dev.jdtech.jellyfin.viewmodels.UsersEvent
|
import com.nomadics9.ananas.viewmodels.UsersEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.UsersViewModel
|
import com.nomadics9.ananas.viewmodels.UsersViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package dev.jdtech.jellyfin.utils
|
package com.nomadics9.ananas.utils
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import dev.jdtech.jellyfin.AppNavigationDirections
|
import com.nomadics9.ananas.AppNavigationDirections
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
fun Fragment.checkIfLoginRequired(error: String?) {
|
fun Fragment.checkIfLoginRequired(error: String?) {
|
|
@ -1,7 +1,8 @@
|
||||||
package dev.jdtech.jellyfin.utils
|
package com.nomadics9.ananas.utils
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
@ -19,15 +20,20 @@ import android.view.animation.DecelerateInterpolator
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.media3.ui.AspectRatioFrameLayout
|
import androidx.media3.ui.AspectRatioFrameLayout
|
||||||
import androidx.media3.ui.PlayerView
|
import androidx.media3.ui.PlayerView
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
import coil.transform.RoundedCornersTransformation
|
||||||
import dev.jdtech.jellyfin.Constants
|
import com.nomadics9.ananas.AppPreferences
|
||||||
import dev.jdtech.jellyfin.PlayerActivity
|
import com.nomadics9.ananas.Constants
|
||||||
import dev.jdtech.jellyfin.isControlsLocked
|
import com.nomadics9.ananas.PlayerActivity
|
||||||
import dev.jdtech.jellyfin.models.PlayerChapter
|
import com.nomadics9.ananas.isControlsLocked
|
||||||
import dev.jdtech.jellyfin.mpv.MPVPlayer
|
import com.nomadics9.ananas.models.PlayerChapter
|
||||||
|
import com.nomadics9.ananas.models.Trickplay
|
||||||
|
import com.nomadics9.ananas.mpv.MPVPlayer
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import coil.load
|
||||||
|
|
||||||
class PlayerGestureHelper(
|
class PlayerGestureHelper(
|
||||||
private val appPreferences: AppPreferences,
|
private val appPreferences: AppPreferences,
|
||||||
private val activity: PlayerActivity,
|
private val activity: PlayerActivity,
|
||||||
|
@ -62,6 +68,10 @@ class PlayerGestureHelper(
|
||||||
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
|
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
|
||||||
private val screenHeight = Resources.getSystem().displayMetrics.heightPixels
|
private val screenHeight = Resources.getSystem().displayMetrics.heightPixels
|
||||||
|
|
||||||
|
var currentTrickplay: Trickplay? = null
|
||||||
|
private val roundedCorners = RoundedCornersTransformation(10f)
|
||||||
|
private var currentBitMap: Bitmap? = null
|
||||||
|
|
||||||
private var currentNumberOfPointers: Int = 0
|
private var currentNumberOfPointers: Int = 0
|
||||||
|
|
||||||
private val tapGestureDetector = GestureDetector(
|
private val tapGestureDetector = GestureDetector(
|
||||||
|
@ -265,6 +275,13 @@ class PlayerGestureHelper(
|
||||||
activity.binding.progressScrubberLayout.visibility = View.VISIBLE
|
activity.binding.progressScrubberLayout.visibility = View.VISIBLE
|
||||||
activity.binding.progressScrubberText.text = "${longToTimestamp(difference)} [${longToTimestamp(newPos, true)}]"
|
activity.binding.progressScrubberText.text = "${longToTimestamp(difference)} [${longToTimestamp(newPos, true)}]"
|
||||||
swipeGestureValueTrackerProgress = newPos
|
swipeGestureValueTrackerProgress = newPos
|
||||||
|
|
||||||
|
if (currentTrickplay != null) {
|
||||||
|
onMove(newPos)
|
||||||
|
} else {
|
||||||
|
activity.binding.imagePreviewGesture.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
swipeGestureProgressOpen = true
|
swipeGestureProgressOpen = true
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
@ -471,11 +488,28 @@ class PlayerGestureHelper(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onMove(position: Long) {
|
||||||
|
val trickplay = currentTrickplay ?: return
|
||||||
|
val image = trickplay.images[position.div(trickplay.interval).toInt()]
|
||||||
|
|
||||||
|
if (currentBitMap != image) {
|
||||||
|
activity.binding.imagePreviewGesture.load(image) {
|
||||||
|
dispatcher(Dispatchers.Main.immediate)
|
||||||
|
transformations(roundedCorners)
|
||||||
|
}
|
||||||
|
currentBitMap = image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if (appPreferences.playerBrightnessRemember) {
|
if (appPreferences.playerBrightnessRemember) {
|
||||||
activity.window.attributes.screenBrightness = appPreferences.playerBrightness
|
activity.window.attributes.screenBrightness = appPreferences.playerBrightness
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!appPreferences.playerTrickPlayGesture) {
|
||||||
|
activity.binding.imagePreviewGesture.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
updateZoomMode(appPreferences.playerStartMaximized)
|
updateZoomMode(appPreferences.playerStartMaximized)
|
||||||
|
|
||||||
@Suppress("ClickableViewAccessibility")
|
@Suppress("ClickableViewAccessibility")
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.utils
|
package com.nomadics9.ananas.utils
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -8,7 +8,7 @@ import androidx.media3.common.Player
|
||||||
import androidx.media3.ui.TimeBar
|
import androidx.media3.ui.TimeBar
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.RoundedCornersTransformation
|
import coil.transform.RoundedCornersTransformation
|
||||||
import dev.jdtech.jellyfin.models.Trickplay
|
import com.nomadics9.ananas.models.Trickplay
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.fragment.app.viewModels
|
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import androidx.navigation.fragment.navArgs
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import dev.jdtech.jellyfin.adapters.EpisodeListAdapter
|
|
||||||
import dev.jdtech.jellyfin.databinding.FragmentSeasonBinding
|
|
||||||
import dev.jdtech.jellyfin.dialogs.ErrorDialogFragment
|
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
|
||||||
import dev.jdtech.jellyfin.utils.checkIfLoginRequired
|
|
||||||
import dev.jdtech.jellyfin.viewmodels.SeasonEvent
|
|
||||||
import dev.jdtech.jellyfin.viewmodels.SeasonViewModel
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class SeasonFragment : Fragment() {
|
|
||||||
|
|
||||||
private lateinit var binding: FragmentSeasonBinding
|
|
||||||
private val viewModel: SeasonViewModel by viewModels()
|
|
||||||
private val args: SeasonFragmentArgs by navArgs()
|
|
||||||
|
|
||||||
private lateinit var errorDialog: ErrorDialogFragment
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater,
|
|
||||||
container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?,
|
|
||||||
): View {
|
|
||||||
binding = FragmentSeasonBinding.inflate(inflater, container, false)
|
|
||||||
return binding.root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
||||||
launch {
|
|
||||||
viewModel.uiState.collect { uiState ->
|
|
||||||
Timber.d("$uiState")
|
|
||||||
when (uiState) {
|
|
||||||
is SeasonViewModel.UiState.Normal -> bindUiStateNormal(uiState)
|
|
||||||
is SeasonViewModel.UiState.Loading -> bindUiStateLoading()
|
|
||||||
is SeasonViewModel.UiState.Error -> bindUiStateError(uiState)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch {
|
|
||||||
viewModel.eventsChannelFlow.collect { event ->
|
|
||||||
when (event) {
|
|
||||||
is SeasonEvent.NavigateBack -> findNavController().navigateUp()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.errorLayout.errorRetryButton.setOnClickListener {
|
|
||||||
viewModel.loadEpisodes(args.seriesId, args.seasonId, args.offline)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.errorLayout.errorDetailsButton.setOnClickListener {
|
|
||||||
errorDialog.show(parentFragmentManager, ErrorDialogFragment.TAG)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.episodesRecyclerView.adapter =
|
|
||||||
EpisodeListAdapter { episode ->
|
|
||||||
navigateToEpisodeBottomSheetFragment(episode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
|
|
||||||
viewModel.loadEpisodes(args.seriesId, args.seasonId, args.offline)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bindUiStateNormal(uiState: SeasonViewModel.UiState.Normal) {
|
|
||||||
uiState.apply {
|
|
||||||
val adapter = binding.episodesRecyclerView.adapter as EpisodeListAdapter
|
|
||||||
adapter.submitList(uiState.episodes)
|
|
||||||
}
|
|
||||||
binding.loadingIndicator.isVisible = false
|
|
||||||
binding.episodesRecyclerView.isVisible = true
|
|
||||||
binding.errorLayout.errorPanel.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bindUiStateLoading() {
|
|
||||||
binding.loadingIndicator.isVisible = true
|
|
||||||
binding.errorLayout.errorPanel.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bindUiStateError(uiState: SeasonViewModel.UiState.Error) {
|
|
||||||
errorDialog = ErrorDialogFragment.newInstance(uiState.error)
|
|
||||||
binding.loadingIndicator.isVisible = false
|
|
||||||
binding.episodesRecyclerView.isVisible = false
|
|
||||||
binding.errorLayout.errorPanel.isVisible = true
|
|
||||||
checkIfLoginRequired(uiState.error.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun navigateToEpisodeBottomSheetFragment(episode: FindroidEpisode) {
|
|
||||||
findNavController().navigate(
|
|
||||||
SeasonFragmentDirections.actionSeasonFragmentToEpisodeBottomSheetFragment(
|
|
||||||
episode.id,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
package dev.jdtech.jellyfin.fragments
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import androidx.preference.Preference
|
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import dev.jdtech.jellyfin.AppPreferences
|
|
||||||
import dev.jdtech.jellyfin.utils.restart
|
|
||||||
import javax.inject.Inject
|
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class SettingsFragment : PreferenceFragmentCompat() {
|
|
||||||
@Inject
|
|
||||||
lateinit var appPreferences: AppPreferences
|
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
|
||||||
setPreferencesFromResource(CoreR.xml.fragment_settings, rootKey)
|
|
||||||
|
|
||||||
findPreference<Preference>("switchServer")?.setOnPreferenceClickListener {
|
|
||||||
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionNavigationSettingsToServerSelectFragment())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>("switchUser")?.setOnPreferenceClickListener {
|
|
||||||
val serverId = appPreferences.currentServer!!
|
|
||||||
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionNavigationSettingsToUsersFragment(serverId))
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>("switchAddress")?.setOnPreferenceClickListener {
|
|
||||||
val serverId = appPreferences.currentServer!!
|
|
||||||
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionNavigationSettingsToServerAddressesFragment(serverId))
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>("pref_offline_mode")?.setOnPreferenceClickListener {
|
|
||||||
activity?.restart()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>("privacyPolicy")?.setOnPreferenceClickListener {
|
|
||||||
val intent = Intent(
|
|
||||||
Intent.ACTION_VIEW,
|
|
||||||
Uri.parse("https://github.com/jarnedemeulemeester/findroid/blob/main/PRIVACY"),
|
|
||||||
)
|
|
||||||
startActivity(intent)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
findPreference<Preference>("appInfo")?.setOnPreferenceClickListener {
|
|
||||||
findNavController().navigate(TwoPaneSettingsFragmentDirections.actionSettingsFragmentToAboutLibraries())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -37,7 +37,16 @@
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/main_toolbar"
|
android:id="@+id/main_toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize" />
|
android:layout_height="?attr/actionBarSize">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="65dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:contentDescription="@string/app_name"
|
||||||
|
android:src="@drawable/ic_launcher_foreground" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
@ -39,8 +40,17 @@
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/main_toolbar"
|
android:id="@+id/main_toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize" />
|
android:layout_height="?attr/actionBarSize">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="65dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:contentDescription="@string/app_name"
|
||||||
|
android:src="@drawable/ic_launcher_foreground" />
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/progress_scrubber_layout"
|
android:id="@+id/progress_scrubber_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="64dp"
|
||||||
|
android:padding="10dp"
|
||||||
android:background="@drawable/overlay_background"
|
android:background="@drawable/overlay_background"
|
||||||
android:clickable="false"
|
android:clickable="false"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
@ -25,10 +28,20 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/image_preview_gesture"
|
||||||
|
android:layout_width="272dp"
|
||||||
|
android:layout_height="153dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
|
||||||
|
android:contentDescription="@string/player_trickplay" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/progress_scrubber_text"
|
android:id="@+id/progress_scrubber_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
|
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
tools:text="+00:00:10 [00:00:20]" />
|
tools:text="+00:00:10 [00:00:20]" />
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center">
|
android:layout_gravity="center">
|
||||||
|
|
||||||
|
|
||||||
<!-- Video surface will be inserted as the first child of the content frame. -->
|
<!-- Video surface will be inserted as the first child of the content frame. -->
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -48,24 +49,6 @@
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="14sp" />
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_skip_intro"
|
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end|bottom"
|
|
||||||
android:layout_marginEnd="24dp"
|
|
||||||
android:layout_marginBottom="64dp"
|
|
||||||
android:text="@string/player_controls_skip_intro"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:backgroundTint="@color/player_background"
|
|
||||||
app:icon="@drawable/ic_skip_forward"
|
|
||||||
app:iconGravity="end"
|
|
||||||
app:iconTint="@android:color/white"
|
|
||||||
app:strokeColor="@android:color/white"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
</androidx.media3.ui.AspectRatioFrameLayout>
|
</androidx.media3.ui.AspectRatioFrameLayout>
|
||||||
|
|
||||||
<androidx.media3.ui.SubtitleView
|
<androidx.media3.ui.SubtitleView
|
||||||
|
@ -89,4 +72,33 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:animation_enabled="false"/>
|
app:animation_enabled="false"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_gravity="end|bottom"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:layout_marginBottom="64dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_watch_credits"
|
||||||
|
style="@style/Widget.Material3.Button.TonalButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="24dp"
|
||||||
|
android:text="@string/watch_credits"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_skip_intro"
|
||||||
|
style="@style/Widget.Material3.Button.Icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:icon="@drawable/ic_skip_forward"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</merge>
|
</merge>
|
|
@ -141,10 +141,24 @@
|
||||||
android:visibility="invisible" />
|
android:visibility="invisible" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="24dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/button_forget_password"
|
||||||
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/forget_password" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/login_disclaimer"
|
android:id="@+id/login_disclaimer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
android:layout_marginHorizontal="24dp"
|
android:layout_marginHorizontal="24dp"
|
||||||
android:layout_margin="24dp"
|
android:layout_margin="24dp"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
|
|
16
app/phone/src/main/res/layout/fragment_webview.xml
Normal file
16
app/phone/src/main/res/layout/fragment_webview.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<WebView
|
||||||
|
android:id="@+id/webview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true" />
|
||||||
|
</RelativeLayout>
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/homeFragment"
|
android:id="@+id/homeFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.HomeFragment"
|
android:name="com.nomadics9.ananas.fragments.HomeFragment"
|
||||||
android:label="@string/title_home"
|
android:label="@string/title_home"
|
||||||
tools:layout="@layout/fragment_home">
|
tools:layout="@layout/fragment_home">
|
||||||
<action
|
<action
|
||||||
|
@ -49,11 +49,14 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_homeFragment_to_searchResultFragment"
|
android:id="@+id/action_homeFragment_to_searchResultFragment"
|
||||||
app:destination="@id/searchResultFragment" />
|
app:destination="@id/searchResultFragment" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_homeFragment_to_requestsWebFragment"
|
||||||
|
app:destination="@id/requestsWebFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/mediaFragment"
|
android:id="@+id/mediaFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.MediaFragment"
|
android:name="com.nomadics9.ananas.fragments.MediaFragment"
|
||||||
android:label="@string/title_media"
|
android:label="@string/title_media"
|
||||||
tools:layout="@layout/fragment_media">
|
tools:layout="@layout/fragment_media">
|
||||||
<action
|
<action
|
||||||
|
@ -70,7 +73,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/twoPaneSettingsFragment"
|
android:id="@+id/twoPaneSettingsFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.TwoPaneSettingsFragment"
|
android:name="com.nomadics9.ananas.fragments.TwoPaneSettingsFragment"
|
||||||
android:label="@string/title_settings">
|
android:label="@string/title_settings">
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_navigation_settings_to_serverSelectFragment"
|
android:id="@+id/action_navigation_settings_to_serverSelectFragment"
|
||||||
|
@ -84,13 +87,23 @@
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_settingsFragment_to_about_libraries"
|
android:id="@+id/action_settingsFragment_to_about_libraries"
|
||||||
app:destination="@id/about_libraries" />
|
app:destination="@id/about_libraries" />
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_navigation_settings_to_requestsWebFragment"
|
||||||
|
app:destination="@id/requestsWebFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/settingsFragment"
|
android:id="@+id/settingsFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.SettingsFragment" />
|
android:name="com.nomadics9.ananas.fragments.SettingsFragment">
|
||||||
|
</fragment>
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/requestsWebFragment"
|
||||||
|
android:name="com.nomadics9.ananas.fragments.RequestsWebViewFragment"
|
||||||
|
android:label="Requests"
|
||||||
|
tools:layout="@layout/fragment_webview">
|
||||||
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/libraryFragment"
|
android:id="@+id/libraryFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.LibraryFragment"
|
android:name="com.nomadics9.ananas.fragments.LibraryFragment"
|
||||||
android:label="{libraryName}"
|
android:label="{libraryName}"
|
||||||
tools:layout="@layout/fragment_library">
|
tools:layout="@layout/fragment_library">
|
||||||
<argument
|
<argument
|
||||||
|
@ -122,14 +135,14 @@
|
||||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
<argument
|
<argument
|
||||||
android:name="libraryType"
|
android:name="libraryType"
|
||||||
app:argType="dev.jdtech.jellyfin.models.CollectionType" />
|
app:argType="com.nomadics9.ananas.models.CollectionType" />
|
||||||
<action
|
<action
|
||||||
android:id="@+id/action_libraryFragment_self"
|
android:id="@+id/action_libraryFragment_self"
|
||||||
app:destination="@id/libraryFragment" />
|
app:destination="@id/libraryFragment" />
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/showFragment"
|
android:id="@+id/showFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.ShowFragment"
|
android:name="com.nomadics9.ananas.fragments.ShowFragment"
|
||||||
android:label="{itemName}"
|
android:label="{itemName}"
|
||||||
tools:layout="@layout/fragment_show">
|
tools:layout="@layout/fragment_show">
|
||||||
<argument
|
<argument
|
||||||
|
@ -158,7 +171,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/movieFragment"
|
android:id="@+id/movieFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.MovieFragment"
|
android:name="com.nomadics9.ananas.fragments.MovieFragment"
|
||||||
android:label="{itemName}"
|
android:label="{itemName}"
|
||||||
tools:layout="@layout/fragment_movie">
|
tools:layout="@layout/fragment_movie">
|
||||||
<argument
|
<argument
|
||||||
|
@ -179,7 +192,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/seasonFragment"
|
android:id="@+id/seasonFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.SeasonFragment"
|
android:name="com.nomadics9.ananas.fragments.SeasonFragment"
|
||||||
android:label="{seasonName}"
|
android:label="{seasonName}"
|
||||||
tools:layout="@layout/fragment_season">
|
tools:layout="@layout/fragment_season">
|
||||||
<argument
|
<argument
|
||||||
|
@ -211,7 +224,7 @@
|
||||||
</fragment>
|
</fragment>
|
||||||
<dialog
|
<dialog
|
||||||
android:id="@+id/episodeBottomSheetFragment"
|
android:id="@+id/episodeBottomSheetFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.EpisodeBottomSheetFragment"
|
android:name="com.nomadics9.ananas.fragments.EpisodeBottomSheetFragment"
|
||||||
android:label="EpisodeBottomSheetFragment"
|
android:label="EpisodeBottomSheetFragment"
|
||||||
tools:layout="@layout/episode_bottom_sheet">
|
tools:layout="@layout/episode_bottom_sheet">
|
||||||
<argument
|
<argument
|
||||||
|
@ -226,7 +239,7 @@
|
||||||
</dialog>
|
</dialog>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/favoriteFragment"
|
android:id="@+id/favoriteFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.FavoriteFragment"
|
android:name="com.nomadics9.ananas.fragments.FavoriteFragment"
|
||||||
android:label="@string/title_favorite"
|
android:label="@string/title_favorite"
|
||||||
tools:layout="@layout/fragment_favorite">
|
tools:layout="@layout/fragment_favorite">
|
||||||
<action
|
<action
|
||||||
|
@ -241,7 +254,7 @@
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/collectionFragment"
|
android:id="@+id/collectionFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.CollectionFragment"
|
android:name="com.nomadics9.ananas.fragments.CollectionFragment"
|
||||||
android:label="{collectionName}"
|
android:label="{collectionName}"
|
||||||
tools:layout="@layout/fragment_favorite">
|
tools:layout="@layout/fragment_favorite">
|
||||||
<argument
|
<argument
|
||||||
|
@ -264,7 +277,7 @@
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/searchResultFragment"
|
android:id="@+id/searchResultFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.SearchResultFragment"
|
android:name="com.nomadics9.ananas.fragments.SearchResultFragment"
|
||||||
android:label="{query}"
|
android:label="{query}"
|
||||||
tools:layout="@layout/fragment_search_result">
|
tools:layout="@layout/fragment_search_result">
|
||||||
<action
|
<action
|
||||||
|
@ -282,7 +295,7 @@
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/addServerFragment"
|
android:id="@+id/addServerFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.AddServerFragment"
|
android:name="com.nomadics9.ananas.fragments.AddServerFragment"
|
||||||
android:label="@string/add_server"
|
android:label="@string/add_server"
|
||||||
tools:layout="@layout/fragment_add_server">
|
tools:layout="@layout/fragment_add_server">
|
||||||
<action
|
<action
|
||||||
|
@ -291,7 +304,7 @@
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/serverSelectFragment"
|
android:id="@+id/serverSelectFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.ServerSelectFragment"
|
android:name="com.nomadics9.ananas.fragments.ServerSelectFragment"
|
||||||
android:label="@string/select_server"
|
android:label="@string/select_server"
|
||||||
tools:layout="@layout/fragment_server_select">
|
tools:layout="@layout/fragment_server_select">
|
||||||
<action
|
<action
|
||||||
|
@ -308,7 +321,7 @@
|
||||||
</fragment>
|
</fragment>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/loginFragment"
|
android:id="@+id/loginFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.LoginFragment"
|
android:name="com.nomadics9.ananas.fragments.LoginFragment"
|
||||||
android:label="@string/login"
|
android:label="@string/login"
|
||||||
tools:layout="@layout/fragment_login">
|
tools:layout="@layout/fragment_login">
|
||||||
<action
|
<action
|
||||||
|
@ -324,7 +337,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/personDetailFragment"
|
android:id="@+id/personDetailFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.PersonDetailFragment"
|
android:name="com.nomadics9.ananas.fragments.PersonDetailFragment"
|
||||||
android:label="@string/person_detail_title"
|
android:label="@string/person_detail_title"
|
||||||
tools:layout="@layout/fragment_person_detail">
|
tools:layout="@layout/fragment_person_detail">
|
||||||
|
|
||||||
|
@ -342,12 +355,12 @@
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:id="@+id/playerActivity"
|
android:id="@+id/playerActivity"
|
||||||
android:name="dev.jdtech.jellyfin.PlayerActivity"
|
android:name="com.nomadics9.ananas.PlayerActivity"
|
||||||
android:label="activity_player"
|
android:label="activity_player"
|
||||||
tools:layout="@layout/activity_player">
|
tools:layout="@layout/activity_player">
|
||||||
<argument
|
<argument
|
||||||
android:name="items"
|
android:name="items"
|
||||||
app:argType="dev.jdtech.jellyfin.models.PlayerItem[]" />
|
app:argType="com.nomadics9.ananas.models.PlayerItem[]" />
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<include app:graph="@navigation/aboutlibs_navigation" />
|
<include app:graph="@navigation/aboutlibs_navigation" />
|
||||||
|
@ -357,7 +370,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/usersFragment"
|
android:id="@+id/usersFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.UsersFragment"
|
android:name="com.nomadics9.ananas.fragments.UsersFragment"
|
||||||
android:label="@string/users"
|
android:label="@string/users"
|
||||||
tools:layout="@layout/fragment_users">
|
tools:layout="@layout/fragment_users">
|
||||||
<action
|
<action
|
||||||
|
@ -375,7 +388,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/serverAddressesFragment"
|
android:id="@+id/serverAddressesFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.ServerAddressesFragment"
|
android:name="com.nomadics9.ananas.fragments.ServerAddressesFragment"
|
||||||
android:label="@string/addresses"
|
android:label="@string/addresses"
|
||||||
tools:layout="@layout/fragment_server_addresses">
|
tools:layout="@layout/fragment_server_addresses">
|
||||||
<action
|
<action
|
||||||
|
@ -390,7 +403,7 @@
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/downloadsFragment"
|
android:id="@+id/downloadsFragment"
|
||||||
android:name="dev.jdtech.jellyfin.fragments.DownloadsFragment"
|
android:name="com.nomadics9.ananas.fragments.DownloadsFragment"
|
||||||
android:label="@string/title_download"
|
android:label="@string/title_download"
|
||||||
tools:layout="@layout/fragment_favorite">
|
tools:layout="@layout/fragment_favorite">
|
||||||
<action
|
<action
|
||||||
|
@ -409,4 +422,4 @@
|
||||||
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
</navigation>
|
</navigation>
|
||||||
|
|
4
app/phone/src/main/res/values/strings.xml
Normal file
4
app/phone/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="watch_credits">Watch credits</string>
|
||||||
|
</resources>
|
|
@ -9,12 +9,12 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "dev.jdtech.jellyfin"
|
namespace = "com.nomadics9.ananas"
|
||||||
compileSdk = Versions.compileSdk
|
compileSdk = Versions.compileSdk
|
||||||
buildToolsVersion = Versions.buildTools
|
buildToolsVersion = Versions.buildTools
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "dev.jdtech.jellyfin"
|
applicationId = "com.nomadics9.ananas"
|
||||||
minSdk = Versions.minSdk
|
minSdk = Versions.minSdk
|
||||||
targetSdk = Versions.targetSdk
|
targetSdk = Versions.targetSdk
|
||||||
|
|
||||||
|
@ -81,14 +81,15 @@ ktlint {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
val composeBom = platform(libs.androidx.compose.bom)
|
||||||
|
|
||||||
implementation(projects.core)
|
implementation(projects.core)
|
||||||
implementation(projects.data)
|
implementation(projects.data)
|
||||||
implementation(projects.preferences)
|
implementation(projects.preferences)
|
||||||
implementation(projects.player.core)
|
implementation(projects.player.core)
|
||||||
implementation(projects.player.video)
|
implementation(projects.player.video)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(libs.androidx.compose.foundation)
|
implementation(composeBom)
|
||||||
implementation(libs.androidx.compose.runtime)
|
|
||||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||||
implementation(libs.androidx.compose.material3)
|
implementation(libs.androidx.compose.material3)
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
|
@ -98,6 +99,7 @@ dependencies {
|
||||||
implementation(libs.androidx.media3.ui)
|
implementation(libs.androidx.media3.ui)
|
||||||
implementation(libs.androidx.media3.session)
|
implementation(libs.androidx.media3.session)
|
||||||
implementation(libs.androidx.paging.compose)
|
implementation(libs.androidx.paging.compose)
|
||||||
|
implementation(libs.androidx.tv.foundation)
|
||||||
implementation(libs.androidx.tv.material)
|
implementation(libs.androidx.tv.material)
|
||||||
implementation(libs.coil.compose)
|
implementation(libs.coil.compose)
|
||||||
implementation(libs.coil.svg)
|
implementation(libs.coil.svg)
|
||||||
|
|
65
app/tv/libre/debug/output-metadata.json
Normal file
65
app/tv/libre/debug/output-metadata.json
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "com.nomadics9.ananas.debug",
|
||||||
|
"variantName": "libreDebug",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "armeabi-v7a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-armeabi-v7a-debug.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86_64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-x86_64-debug.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "arm64-v8a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-arm64-v8a-debug.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-x86-debug.apk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elementType": "File",
|
||||||
|
"minSdkVersionForDexing": 28
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
BIN
app/tv/libre/release/baselineProfiles/0/tv-libre-x86-release.dm
Normal file
BIN
app/tv/libre/release/baselineProfiles/0/tv-libre-x86-release.dm
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app/tv/libre/release/baselineProfiles/1/tv-libre-x86-release.dm
Normal file
BIN
app/tv/libre/release/baselineProfiles/1/tv-libre-x86-release.dm
Normal file
Binary file not shown.
Binary file not shown.
87
app/tv/libre/release/output-metadata.json
Normal file
87
app/tv/libre/release/output-metadata.json
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "com.nomadics9.ananas",
|
||||||
|
"variantName": "libreRelease",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "armeabi-v7a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-armeabi-v7a-release.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-x86-release.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "arm64-v8a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-arm64-v8a-release.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86_64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 6,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-x86_64-release.apk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elementType": "File",
|
||||||
|
"baselineProfiles": [
|
||||||
|
{
|
||||||
|
"minApi": 28,
|
||||||
|
"maxApi": 30,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/1/tv-libre-armeabi-v7a-release.dm",
|
||||||
|
"baselineProfiles/1/tv-libre-x86-release.dm",
|
||||||
|
"baselineProfiles/1/tv-libre-arm64-v8a-release.dm",
|
||||||
|
"baselineProfiles/1/tv-libre-x86_64-release.dm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minApi": 31,
|
||||||
|
"maxApi": 2147483647,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/0/tv-libre-armeabi-v7a-release.dm",
|
||||||
|
"baselineProfiles/0/tv-libre-x86-release.dm",
|
||||||
|
"baselineProfiles/0/tv-libre-arm64-v8a-release.dm",
|
||||||
|
"baselineProfiles/0/tv-libre-x86_64-release.dm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minSdkVersionForDexing": 28
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
BIN
app/tv/libre/staging/baselineProfiles/0/tv-libre-x86-staging.dm
Normal file
BIN
app/tv/libre/staging/baselineProfiles/0/tv-libre-x86-staging.dm
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
app/tv/libre/staging/baselineProfiles/1/tv-libre-x86-staging.dm
Normal file
BIN
app/tv/libre/staging/baselineProfiles/1/tv-libre-x86-staging.dm
Normal file
Binary file not shown.
Binary file not shown.
87
app/tv/libre/staging/output-metadata.json
Normal file
87
app/tv/libre/staging/output-metadata.json
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"artifactType": {
|
||||||
|
"type": "APK",
|
||||||
|
"kind": "Directory"
|
||||||
|
},
|
||||||
|
"applicationId": "com.nomadics9.ananas.staging",
|
||||||
|
"variantName": "libreStaging",
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "armeabi-v7a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 1,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-armeabi-v7a-staging.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86_64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 1,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-x86_64-staging.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "x86"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 1,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-x86-staging.apk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ONE_OF_MANY",
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"filterType": "ABI",
|
||||||
|
"value": "arm64-v8a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": [],
|
||||||
|
"versionCode": 1,
|
||||||
|
"versionName": "0.14.2",
|
||||||
|
"outputFile": "tv-libre-arm64-v8a-staging.apk"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"elementType": "File",
|
||||||
|
"baselineProfiles": [
|
||||||
|
{
|
||||||
|
"minApi": 28,
|
||||||
|
"maxApi": 30,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/1/tv-libre-armeabi-v7a-staging.dm",
|
||||||
|
"baselineProfiles/1/tv-libre-x86_64-staging.dm",
|
||||||
|
"baselineProfiles/1/tv-libre-x86-staging.dm",
|
||||||
|
"baselineProfiles/1/tv-libre-arm64-v8a-staging.dm"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"minApi": 31,
|
||||||
|
"maxApi": 2147483647,
|
||||||
|
"baselineProfiles": [
|
||||||
|
"baselineProfiles/0/tv-libre-armeabi-v7a-staging.dm",
|
||||||
|
"baselineProfiles/0/tv-libre-x86_64-staging.dm",
|
||||||
|
"baselineProfiles/0/tv-libre-x86-staging.dm",
|
||||||
|
"baselineProfiles/0/tv-libre-arm64-v8a-staging.dm"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minSdkVersionForDexing": 28
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
@ -6,11 +6,11 @@ import androidx.activity.compose.setContent
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import com.ramcosta.composedestinations.DestinationsNavHost
|
import com.ramcosta.composedestinations.DestinationsNavHost
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.database.ServerDatabaseDao
|
import com.nomadics9.ananas.database.ServerDatabaseDao
|
||||||
import dev.jdtech.jellyfin.destinations.AddServerScreenDestination
|
import com.nomadics9.ananas.destinations.AddServerScreenDestination
|
||||||
import dev.jdtech.jellyfin.destinations.LoginScreenDestination
|
import com.nomadics9.ananas.destinations.LoginScreenDestination
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
import dev.jdtech.jellyfin.viewmodels.MainViewModel
|
import com.nomadics9.ananas.viewmodels.MainViewModel
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin
|
package com.nomadics9.ananas
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
@ -9,11 +9,11 @@ import com.ramcosta.composedestinations.annotation.ActivityDestination
|
||||||
import com.ramcosta.composedestinations.manualcomposablecalls.composable
|
import com.ramcosta.composedestinations.manualcomposablecalls.composable
|
||||||
import com.ramcosta.composedestinations.scope.resultRecipient
|
import com.ramcosta.composedestinations.scope.resultRecipient
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dev.jdtech.jellyfin.destinations.PlayerActivityDestination
|
import com.nomadics9.ananas.destinations.PlayerActivityDestination
|
||||||
import dev.jdtech.jellyfin.destinations.PlayerScreenDestination
|
import com.nomadics9.ananas.destinations.PlayerScreenDestination
|
||||||
import dev.jdtech.jellyfin.models.PlayerItem
|
import com.nomadics9.ananas.models.PlayerItem
|
||||||
import dev.jdtech.jellyfin.ui.PlayerScreen
|
import com.nomadics9.ananas.ui.PlayerScreen
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
|
|
||||||
data class PlayerActivityNavArgs(
|
data class PlayerActivityNavArgs(
|
||||||
val items: ArrayList<PlayerItem>,
|
val items: ArrayList<PlayerItem>,
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.ui
|
package com.nomadics9.ananas.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
@ -38,13 +38,13 @@ import androidx.tv.material3.MaterialTheme
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import dev.jdtech.jellyfin.destinations.LoginScreenDestination
|
import com.nomadics9.ananas.destinations.LoginScreenDestination
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
import com.nomadics9.ananas.ui.theme.spacings
|
||||||
import dev.jdtech.jellyfin.utils.ObserveAsEvents
|
import com.nomadics9.ananas.utils.ObserveAsEvents
|
||||||
import dev.jdtech.jellyfin.viewmodels.AddServerEvent
|
import com.nomadics9.ananas.viewmodels.AddServerEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.AddServerViewModel
|
import com.nomadics9.ananas.viewmodels.AddServerViewModel
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@Destination
|
@Destination
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -115,7 +115,7 @@ private fun AddServerScreenLayout(
|
||||||
},
|
},
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
autoCorrectEnabled = false,
|
autoCorrect = false,
|
||||||
keyboardType = KeyboardType.Uri,
|
keyboardType = KeyboardType.Uri,
|
||||||
imeAction = ImeAction.Go,
|
imeAction = ImeAction.Go,
|
||||||
),
|
),
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.ui
|
package com.nomadics9.ananas.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
@ -6,9 +6,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
@ -22,28 +19,31 @@ import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.tv.foundation.lazy.list.TvLazyColumn
|
||||||
|
import androidx.tv.foundation.lazy.list.TvLazyRow
|
||||||
|
import androidx.tv.foundation.lazy.list.items
|
||||||
import androidx.tv.material3.MaterialTheme
|
import androidx.tv.material3.MaterialTheme
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import dev.jdtech.jellyfin.destinations.MovieScreenDestination
|
import com.nomadics9.ananas.destinations.MovieScreenDestination
|
||||||
import dev.jdtech.jellyfin.destinations.PlayerActivityDestination
|
import com.nomadics9.ananas.destinations.PlayerActivityDestination
|
||||||
import dev.jdtech.jellyfin.destinations.ShowScreenDestination
|
import com.nomadics9.ananas.destinations.ShowScreenDestination
|
||||||
import dev.jdtech.jellyfin.models.FindroidEpisode
|
import com.nomadics9.ananas.models.FindroidEpisode
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.models.HomeItem
|
import com.nomadics9.ananas.models.HomeItem
|
||||||
import dev.jdtech.jellyfin.ui.components.Direction
|
import com.nomadics9.ananas.ui.components.Direction
|
||||||
import dev.jdtech.jellyfin.ui.components.ItemCard
|
import com.nomadics9.ananas.ui.components.ItemCard
|
||||||
import dev.jdtech.jellyfin.ui.dummy.dummyHomeItems
|
import com.nomadics9.ananas.ui.dummy.dummyHomeItems
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
import com.nomadics9.ananas.ui.theme.spacings
|
||||||
import dev.jdtech.jellyfin.utils.ObserveAsEvents
|
import com.nomadics9.ananas.utils.ObserveAsEvents
|
||||||
import dev.jdtech.jellyfin.viewmodels.HomeViewModel
|
import com.nomadics9.ananas.viewmodels.HomeViewModel
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerItemsEvent
|
import com.nomadics9.ananas.viewmodels.PlayerItemsEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.PlayerViewModel
|
import com.nomadics9.ananas.viewmodels.PlayerViewModel
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@Destination
|
@Destination
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -107,7 +107,7 @@ private fun HomeScreenLayout(
|
||||||
}
|
}
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
LazyColumn(
|
TvLazyColumn(
|
||||||
contentPadding = PaddingValues(bottom = MaterialTheme.spacings.large),
|
contentPadding = PaddingValues(bottom = MaterialTheme.spacings.large),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
|
@ -122,7 +122,7 @@ private fun HomeScreenLayout(
|
||||||
modifier = Modifier.padding(start = MaterialTheme.spacings.large),
|
modifier = Modifier.padding(start = MaterialTheme.spacings.large),
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(MaterialTheme.spacings.medium))
|
Spacer(modifier = Modifier.height(MaterialTheme.spacings.medium))
|
||||||
LazyRow(
|
TvLazyRow(
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
||||||
contentPadding = PaddingValues(horizontal = MaterialTheme.spacings.large),
|
contentPadding = PaddingValues(horizontal = MaterialTheme.spacings.large),
|
||||||
) {
|
) {
|
||||||
|
@ -145,7 +145,7 @@ private fun HomeScreenLayout(
|
||||||
modifier = Modifier.padding(start = MaterialTheme.spacings.large),
|
modifier = Modifier.padding(start = MaterialTheme.spacings.large),
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(MaterialTheme.spacings.medium))
|
Spacer(modifier = Modifier.height(MaterialTheme.spacings.medium))
|
||||||
LazyRow(
|
TvLazyRow(
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
||||||
contentPadding = PaddingValues(horizontal = MaterialTheme.spacings.large),
|
contentPadding = PaddingValues(horizontal = MaterialTheme.spacings.large),
|
||||||
) {
|
) {
|
|
@ -1,10 +1,7 @@
|
||||||
package dev.jdtech.jellyfin.ui
|
package com.nomadics9.ananas.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|
||||||
import androidx.compose.foundation.lazy.grid.items
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
@ -17,18 +14,21 @@ import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.tv.foundation.lazy.grid.TvGridCells
|
||||||
|
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
|
||||||
|
import androidx.tv.foundation.lazy.grid.items
|
||||||
import androidx.tv.material3.MaterialTheme
|
import androidx.tv.material3.MaterialTheme
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import dev.jdtech.jellyfin.destinations.LibraryScreenDestination
|
import com.nomadics9.ananas.destinations.LibraryScreenDestination
|
||||||
import dev.jdtech.jellyfin.models.CollectionType
|
import com.nomadics9.ananas.models.CollectionType
|
||||||
import dev.jdtech.jellyfin.models.FindroidCollection
|
import com.nomadics9.ananas.models.FindroidCollection
|
||||||
import dev.jdtech.jellyfin.ui.components.Direction
|
import com.nomadics9.ananas.ui.components.Direction
|
||||||
import dev.jdtech.jellyfin.ui.components.ItemCard
|
import com.nomadics9.ananas.ui.components.ItemCard
|
||||||
import dev.jdtech.jellyfin.ui.dummy.dummyCollections
|
import com.nomadics9.ananas.ui.dummy.dummyCollections
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
import com.nomadics9.ananas.ui.theme.spacings
|
||||||
import dev.jdtech.jellyfin.viewmodels.MediaViewModel
|
import com.nomadics9.ananas.viewmodels.MediaViewModel
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@Destination
|
@Destination
|
||||||
|
@ -72,8 +72,8 @@ private fun LibrariesScreenLayout(
|
||||||
|
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
LazyVerticalGrid(
|
TvLazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = TvGridCells.Fixed(3),
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.large),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.large),
|
||||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.large),
|
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.large),
|
||||||
contentPadding = PaddingValues(
|
contentPadding = PaddingValues(
|
|
@ -1,11 +1,8 @@
|
||||||
package dev.jdtech.jellyfin.ui
|
package com.nomadics9.ananas.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
|
||||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
|
||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
@ -18,24 +15,27 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.paging.PagingData
|
import androidx.paging.PagingData
|
||||||
import androidx.paging.compose.collectAsLazyPagingItems
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import androidx.tv.foundation.lazy.grid.TvGridCells
|
||||||
|
import androidx.tv.foundation.lazy.grid.TvGridItemSpan
|
||||||
|
import androidx.tv.foundation.lazy.grid.TvLazyVerticalGrid
|
||||||
import androidx.tv.material3.MaterialTheme
|
import androidx.tv.material3.MaterialTheme
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import dev.jdtech.jellyfin.destinations.LibraryScreenDestination
|
import com.nomadics9.ananas.destinations.LibraryScreenDestination
|
||||||
import dev.jdtech.jellyfin.destinations.MovieScreenDestination
|
import com.nomadics9.ananas.destinations.MovieScreenDestination
|
||||||
import dev.jdtech.jellyfin.destinations.ShowScreenDestination
|
import com.nomadics9.ananas.destinations.ShowScreenDestination
|
||||||
import dev.jdtech.jellyfin.models.CollectionType
|
import com.nomadics9.ananas.models.CollectionType
|
||||||
import dev.jdtech.jellyfin.models.FindroidFolder
|
import com.nomadics9.ananas.models.FindroidFolder
|
||||||
import dev.jdtech.jellyfin.models.FindroidItem
|
import com.nomadics9.ananas.models.FindroidItem
|
||||||
import dev.jdtech.jellyfin.models.FindroidMovie
|
import com.nomadics9.ananas.models.FindroidMovie
|
||||||
import dev.jdtech.jellyfin.models.FindroidShow
|
import com.nomadics9.ananas.models.FindroidShow
|
||||||
import dev.jdtech.jellyfin.ui.components.Direction
|
import com.nomadics9.ananas.ui.components.Direction
|
||||||
import dev.jdtech.jellyfin.ui.components.ItemCard
|
import com.nomadics9.ananas.ui.components.ItemCard
|
||||||
import dev.jdtech.jellyfin.ui.dummy.dummyMovies
|
import com.nomadics9.ananas.ui.dummy.dummyMovies
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
import com.nomadics9.ananas.ui.theme.spacings
|
||||||
import dev.jdtech.jellyfin.viewmodels.LibraryViewModel
|
import com.nomadics9.ananas.viewmodels.LibraryViewModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
@ -86,8 +86,8 @@ private fun LibraryScreenLayout(
|
||||||
is LibraryViewModel.UiState.Loading -> Text(text = "LOADING")
|
is LibraryViewModel.UiState.Loading -> Text(text = "LOADING")
|
||||||
is LibraryViewModel.UiState.Normal -> {
|
is LibraryViewModel.UiState.Normal -> {
|
||||||
val items = uiState.items.collectAsLazyPagingItems()
|
val items = uiState.items.collectAsLazyPagingItems()
|
||||||
LazyVerticalGrid(
|
TvLazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(5),
|
columns = TvGridCells.Fixed(5),
|
||||||
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
||||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
|
||||||
contentPadding = PaddingValues(horizontal = MaterialTheme.spacings.default * 2, vertical = MaterialTheme.spacings.large),
|
contentPadding = PaddingValues(horizontal = MaterialTheme.spacings.default * 2, vertical = MaterialTheme.spacings.large),
|
||||||
|
@ -95,7 +95,7 @@ private fun LibraryScreenLayout(
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.focusRequester(focusRequester),
|
.focusRequester(focusRequester),
|
||||||
) {
|
) {
|
||||||
item(span = { GridItemSpan(this.maxLineSpan) }) {
|
item(span = { TvGridItemSpan(this.maxLineSpan) }) {
|
||||||
Text(
|
Text(
|
||||||
text = libraryName,
|
text = libraryName,
|
||||||
style = MaterialTheme.typography.displayMedium,
|
style = MaterialTheme.typography.displayMedium,
|
|
@ -1,4 +1,4 @@
|
||||||
package dev.jdtech.jellyfin.ui
|
package com.nomadics9.ananas.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
@ -41,15 +41,15 @@ import androidx.tv.material3.Text
|
||||||
import com.ramcosta.composedestinations.annotation.Destination
|
import com.ramcosta.composedestinations.annotation.Destination
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.ramcosta.composedestinations.navigation.popUpTo
|
import com.ramcosta.composedestinations.navigation.popUpTo
|
||||||
import dev.jdtech.jellyfin.NavGraphs
|
import com.nomadics9.ananas.NavGraphs
|
||||||
import dev.jdtech.jellyfin.destinations.MainScreenDestination
|
import com.nomadics9.ananas.destinations.MainScreenDestination
|
||||||
import dev.jdtech.jellyfin.models.UiText
|
import com.nomadics9.ananas.models.UiText
|
||||||
import dev.jdtech.jellyfin.ui.theme.FindroidTheme
|
import com.nomadics9.ananas.ui.theme.FindroidTheme
|
||||||
import dev.jdtech.jellyfin.ui.theme.spacings
|
import com.nomadics9.ananas.ui.theme.spacings
|
||||||
import dev.jdtech.jellyfin.utils.ObserveAsEvents
|
import com.nomadics9.ananas.utils.ObserveAsEvents
|
||||||
import dev.jdtech.jellyfin.viewmodels.LoginEvent
|
import com.nomadics9.ananas.viewmodels.LoginEvent
|
||||||
import dev.jdtech.jellyfin.viewmodels.LoginViewModel
|
import com.nomadics9.ananas.viewmodels.LoginViewModel
|
||||||
import dev.jdtech.jellyfin.core.R as CoreR
|
import com.nomadics9.ananas.core.R as CoreR
|
||||||
|
|
||||||
@Destination
|
@Destination
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -152,7 +152,7 @@ private fun LoginScreenLayout(
|
||||||
label = { Text(text = stringResource(id = CoreR.string.edit_text_username_hint)) },
|
label = { Text(text = stringResource(id = CoreR.string.edit_text_username_hint)) },
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
autoCorrectEnabled = false,
|
autoCorrect = false,
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Text,
|
||||||
imeAction = ImeAction.Next,
|
imeAction = ImeAction.Next,
|
||||||
),
|
),
|
||||||
|
@ -175,7 +175,7 @@ private fun LoginScreenLayout(
|
||||||
label = { Text(text = stringResource(id = CoreR.string.edit_text_password_hint)) },
|
label = { Text(text = stringResource(id = CoreR.string.edit_text_password_hint)) },
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
autoCorrectEnabled = false,
|
autoCorrect = false,
|
||||||
keyboardType = KeyboardType.Password,
|
keyboardType = KeyboardType.Password,
|
||||||
imeAction = ImeAction.Go,
|
imeAction = ImeAction.Go,
|
||||||
),
|
),
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue