Refactor application packages

This commit is contained in:
Maxr1998 2022-01-24 19:10:12 +01:00 committed by Niels van Velzen
parent ade07dbb62
commit 33a2d85595
64 changed files with 224 additions and 203 deletions

View File

@ -15,7 +15,7 @@
}
# Keep Chromecast methods
-keepclassmembers class org.jellyfin.mobile.cast.Chromecast {
-keepclassmembers class org.jellyfin.mobile.player.cast.Chromecast {
public *;
}

View File

@ -1,7 +1,7 @@
package org.jellyfin.mobile.cast
package org.jellyfin.mobile.player.cast
import com.google.android.exoplayer2.Player
import org.jellyfin.mobile.media.MediaService
import org.jellyfin.mobile.player.audio.MediaService
class CastPlayerProvider(@Suppress("UNUSED_PARAMETER") mediaService: MediaService) : ICastPlayerProvider {
override val isCastSessionAvailable: Boolean = false

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast
package org.jellyfin.mobile.player.cast
import android.app.Activity
import org.jellyfin.mobile.bridge.JavascriptCallback

View File

@ -59,7 +59,7 @@
<service android:name=".webapp.RemotePlayerService" />
<service
android:name="org.jellyfin.mobile.media.MediaService"
android:name="org.jellyfin.mobile.player.audio.MediaService"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>

View File

@ -3,8 +3,9 @@ package org.jellyfin.mobile
import android.app.Application
import android.webkit.WebView
import com.melegy.redscreenofdeath.RedScreenOfDeath
import org.jellyfin.mobile.api.apiModule
import org.jellyfin.mobile.model.databaseModule
import org.jellyfin.mobile.app.apiModule
import org.jellyfin.mobile.app.applicationModule
import org.jellyfin.mobile.data.databaseModule
import org.jellyfin.mobile.utils.JellyTree
import org.jellyfin.mobile.utils.isWebViewSupported
import org.koin.android.ext.koin.androidContext

View File

@ -13,18 +13,16 @@ import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import org.jellyfin.mobile.cast.Chromecast
import org.jellyfin.mobile.cast.IChromecast
import org.jellyfin.mobile.fragment.ConnectFragment
import org.jellyfin.mobile.fragment.WebViewFragment
import org.jellyfin.mobile.player.PlayerFragment
import org.jellyfin.mobile.player.cast.Chromecast
import org.jellyfin.mobile.player.cast.IChromecast
import org.jellyfin.mobile.setup.ConnectFragment
import org.jellyfin.mobile.webapp.WebViewFragment
import org.jellyfin.mobile.player.ui.PlayerFragment
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.PermissionRequestHelper
import org.jellyfin.mobile.utils.SmartOrientationListener
import org.jellyfin.mobile.utils.isWebViewSupported
import org.jellyfin.mobile.utils.replaceFragment
import org.jellyfin.mobile.viewmodel.MainViewModel
import org.jellyfin.mobile.viewmodel.ServerState
import org.jellyfin.mobile.utils.extensions.replaceFragment
import org.jellyfin.mobile.webapp.RemotePlayerService
import org.koin.android.ext.android.inject
import org.koin.androidx.fragment.android.setupKoinFragmentFactory

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.viewmodel
package org.jellyfin.mobile
import android.app.Application
import androidx.lifecycle.AndroidViewModel
@ -6,25 +6,25 @@ import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import org.jellyfin.mobile.controller.ApiController
import org.jellyfin.mobile.model.sql.entity.ServerEntity
import org.jellyfin.mobile.app.ApiClientController
import org.jellyfin.mobile.data.entity.ServerEntity
class MainViewModel(
app: Application,
private val apiController: ApiController,
private val apiClientController: ApiClientController,
) : AndroidViewModel(app) {
private val _serverState: MutableStateFlow<ServerState> = MutableStateFlow(ServerState.Pending)
val serverState: StateFlow<ServerState> get() = _serverState
init {
viewModelScope.launch {
apiController.migrateFromPreferences()
apiClientController.migrateFromPreferences()
refreshServer()
}
}
suspend fun refreshServer() {
val server = apiController.loadSavedServer()
val server = apiClientController.loadSavedServer()
_serverState.value = server?.let { ServerState.Available(it) } ?: ServerState.Unset
}
}

View File

@ -1,18 +1,17 @@
package org.jellyfin.mobile.controller
package org.jellyfin.mobile.app
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.model.sql.dao.ServerDao
import org.jellyfin.mobile.model.sql.dao.UserDao
import org.jellyfin.mobile.model.sql.entity.ServerEntity
import org.jellyfin.mobile.data.dao.ServerDao
import org.jellyfin.mobile.data.dao.UserDao
import org.jellyfin.mobile.data.entity.ServerEntity
import org.jellyfin.sdk.Jellyfin
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.model.DeviceInfo
import org.jellyfin.sdk.model.serializer.toUUID
import java.util.*
class ApiController(
class ApiClientController(
private val appPreferences: AppPreferences,
private val jellyfin: Jellyfin,
private val apiClient: ApiClient,

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.api
package org.jellyfin.mobile.app
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.sdk.Jellyfin

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile
package org.jellyfin.mobile.app
import android.content.Context
import coil.ImageLoader
@ -15,19 +15,18 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
import com.google.android.exoplayer2.util.Util
import kotlinx.coroutines.channels.Channel
import okhttp3.OkHttpClient
import org.jellyfin.mobile.api.DeviceProfileBuilder
import org.jellyfin.mobile.MainViewModel
import org.jellyfin.mobile.player.deviceprofile.DeviceProfileBuilder
import org.jellyfin.mobile.bridge.ExternalPlayer
import org.jellyfin.mobile.controller.ApiController
import org.jellyfin.mobile.fragment.ConnectFragment
import org.jellyfin.mobile.fragment.WebViewFragment
import org.jellyfin.mobile.media.car.LibraryBrowser
import org.jellyfin.mobile.player.PlayerEvent
import org.jellyfin.mobile.player.PlayerFragment
import org.jellyfin.mobile.setup.ConnectFragment
import org.jellyfin.mobile.webapp.WebViewFragment
import org.jellyfin.mobile.player.audio.car.LibraryBrowser
import org.jellyfin.mobile.player.interaction.PlayerEvent
import org.jellyfin.mobile.player.ui.PlayerFragment
import org.jellyfin.mobile.player.source.MediaSourceResolver
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.PermissionRequestHelper
import org.jellyfin.mobile.utils.isLowRamDevice
import org.jellyfin.mobile.viewmodel.MainViewModel
import org.jellyfin.mobile.webapp.RemoteVolumeProvider
import org.jellyfin.mobile.webapp.WebappFunctionChannel
import org.koin.android.ext.koin.androidApplication
@ -49,7 +48,7 @@ val applicationModule = module {
single(named(PLAYER_EVENT_CHANNEL)) { Channel<PlayerEvent>() }
// Controllers
single { ApiController(get(), get(), get(), get(), get()) }
single { ApiClientController(get(), get(), get(), get(), get()) }
// ViewModels
viewModel { MainViewModel(get(), get()) }

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile
package org.jellyfin.mobile.app
import android.content.Context
import android.content.SharedPreferences

View File

@ -12,9 +12,10 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.LifecycleOwner
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.R
import org.jellyfin.mobile.player.PlayerException
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.player.source.ExternalSubtitleStream
import org.jellyfin.mobile.player.source.JellyfinMediaSource
import org.jellyfin.mobile.player.source.MediaSourceResolver

View File

@ -11,7 +11,7 @@ import android.webkit.JavascriptInterface
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.jellyfin.mobile.R
import org.jellyfin.mobile.fragment.WebViewFragment
import org.jellyfin.mobile.webapp.WebViewFragment
import org.jellyfin.mobile.settings.SettingsFragment
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.EXTRA_ALBUM
@ -25,11 +25,11 @@ import org.jellyfin.mobile.utils.Constants.EXTRA_ITEM_ID
import org.jellyfin.mobile.utils.Constants.EXTRA_PLAYER_ACTION
import org.jellyfin.mobile.utils.Constants.EXTRA_POSITION
import org.jellyfin.mobile.utils.Constants.EXTRA_TITLE
import org.jellyfin.mobile.utils.addFragment
import org.jellyfin.mobile.utils.disableFullscreen
import org.jellyfin.mobile.utils.enableFullscreen
import org.jellyfin.mobile.utils.extensions.addFragment
import org.jellyfin.mobile.utils.extensions.disableFullscreen
import org.jellyfin.mobile.utils.extensions.enableFullscreen
import org.jellyfin.mobile.utils.requestDownload
import org.jellyfin.mobile.utils.requireMainActivity
import org.jellyfin.mobile.utils.extensions.requireMainActivity
import org.jellyfin.mobile.utils.runOnUiThread
import org.jellyfin.mobile.webapp.RemotePlayerService
import org.jellyfin.mobile.webapp.RemoteVolumeProvider

View File

@ -2,9 +2,10 @@ package org.jellyfin.mobile.bridge
import android.webkit.JavascriptInterface
import kotlinx.coroutines.channels.Channel
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.PLAYER_EVENT_CHANNEL
import org.jellyfin.mobile.player.PlayerEvent
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.app.PLAYER_EVENT_CHANNEL
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.player.interaction.PlayerEvent
import org.jellyfin.mobile.settings.VideoPlayerType
import org.jellyfin.mobile.utils.Constants
import org.json.JSONObject

View File

@ -1,5 +1,7 @@
package org.jellyfin.mobile.bridge
import org.jellyfin.mobile.player.interaction.PlayOptions
interface NativePlayerHost {
fun loadNativePlayer(playOptions: PlayOptions)
}

View File

@ -1,7 +1,6 @@
package org.jellyfin.mobile.model
package org.jellyfin.mobile.data
import androidx.room.Room
import org.jellyfin.mobile.model.sql.JellyfinDatabase
import org.koin.android.ext.koin.androidApplication
import org.koin.dsl.module

View File

@ -1,11 +1,11 @@
package org.jellyfin.mobile.model.sql
package org.jellyfin.mobile.data
import androidx.room.Database
import androidx.room.RoomDatabase
import org.jellyfin.mobile.model.sql.dao.ServerDao
import org.jellyfin.mobile.model.sql.dao.UserDao
import org.jellyfin.mobile.model.sql.entity.ServerEntity
import org.jellyfin.mobile.model.sql.entity.UserEntity
import org.jellyfin.mobile.data.dao.ServerDao
import org.jellyfin.mobile.data.dao.UserDao
import org.jellyfin.mobile.data.entity.ServerEntity
import org.jellyfin.mobile.data.entity.UserEntity
@Database(entities = [ServerEntity::class, UserEntity::class], version = 2)
abstract class JellyfinDatabase : RoomDatabase() {

View File

@ -1,11 +1,11 @@
package org.jellyfin.mobile.model.sql.dao
package org.jellyfin.mobile.data.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import org.jellyfin.mobile.model.sql.entity.ServerEntity
import org.jellyfin.mobile.model.sql.entity.ServerEntity.Key.TABLE_NAME
import org.jellyfin.mobile.data.entity.ServerEntity
import org.jellyfin.mobile.data.entity.ServerEntity.Key.TABLE_NAME
@Dao
interface ServerDao {

View File

@ -1,17 +1,17 @@
package org.jellyfin.mobile.model.sql.dao
package org.jellyfin.mobile.data.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import org.jellyfin.mobile.model.sql.entity.ServerUser
import org.jellyfin.mobile.model.sql.entity.UserEntity
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.ACCESS_TOKEN
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.ID
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.SERVER_ID
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.TABLE_NAME
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.USER_ID
import org.jellyfin.mobile.data.entity.ServerUser
import org.jellyfin.mobile.data.entity.UserEntity
import org.jellyfin.mobile.data.entity.UserEntity.Key.ACCESS_TOKEN
import org.jellyfin.mobile.data.entity.UserEntity.Key.ID
import org.jellyfin.mobile.data.entity.UserEntity.Key.SERVER_ID
import org.jellyfin.mobile.data.entity.UserEntity.Key.TABLE_NAME
import org.jellyfin.mobile.data.entity.UserEntity.Key.USER_ID
@Dao
@Suppress("TooManyFunctions")

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.model.sql.entity
package org.jellyfin.mobile.data.entity
import android.os.Parcelable
import androidx.room.ColumnInfo
@ -6,8 +6,8 @@ import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
import kotlinx.parcelize.Parcelize
import org.jellyfin.mobile.model.sql.entity.ServerEntity.Key.HOSTNAME
import org.jellyfin.mobile.model.sql.entity.ServerEntity.Key.TABLE_NAME
import org.jellyfin.mobile.data.entity.ServerEntity.Key.HOSTNAME
import org.jellyfin.mobile.data.entity.ServerEntity.Key.TABLE_NAME
@Parcelize
@Entity(tableName = TABLE_NAME, indices = [Index(value = arrayOf(HOSTNAME), unique = true)])

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.model.sql.entity
package org.jellyfin.mobile.data.entity
import androidx.room.Embedded
import androidx.room.Relation

View File

@ -1,13 +1,13 @@
package org.jellyfin.mobile.model.sql.entity
package org.jellyfin.mobile.data.entity
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.SERVER_ID
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.TABLE_NAME
import org.jellyfin.mobile.model.sql.entity.UserEntity.Key.USER_ID
import org.jellyfin.mobile.data.entity.UserEntity.Key.SERVER_ID
import org.jellyfin.mobile.data.entity.UserEntity.Key.TABLE_NAME
import org.jellyfin.mobile.data.entity.UserEntity.Key.USER_ID
@Entity(
tableName = TABLE_NAME,

View File

@ -28,10 +28,14 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.jellyfin.mobile.BuildConfig
import org.jellyfin.mobile.PLAYER_EVENT_CHANNEL
import org.jellyfin.mobile.model.DisplayPreferences
import org.jellyfin.mobile.app.PLAYER_EVENT_CHANNEL
import org.jellyfin.mobile.player.ui.DisplayPreferences
import org.jellyfin.mobile.player.interaction.PlayerEvent
import org.jellyfin.mobile.player.interaction.PlayerLifecycleObserver
import org.jellyfin.mobile.player.interaction.PlayerMediaSessionCallback
import org.jellyfin.mobile.player.interaction.PlayerNotificationHelper
import org.jellyfin.mobile.player.source.JellyfinMediaSource
import org.jellyfin.mobile.player.source.MediaQueueManager
import org.jellyfin.mobile.player.queue.QueueManager
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.SUPPORTED_VIDEO_PLAYER_PLAYBACK_ACTIONS
import org.jellyfin.mobile.utils.applyDefaultAudioAttributes
@ -39,11 +43,11 @@ import org.jellyfin.mobile.utils.applyDefaultLocalAudioAttributes
import org.jellyfin.mobile.utils.getVolumeLevelPercent
import org.jellyfin.mobile.utils.getVolumeRange
import org.jellyfin.mobile.utils.logTracks
import org.jellyfin.mobile.utils.scaleInRange
import org.jellyfin.mobile.utils.extensions.scaleInRange
import org.jellyfin.mobile.utils.seekToOffset
import org.jellyfin.mobile.utils.setPlaybackState
import org.jellyfin.mobile.utils.toMediaMetadata
import org.jellyfin.mobile.utils.width
import org.jellyfin.mobile.utils.extensions.width
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.api.client.extensions.displayPreferencesApi
@ -75,7 +79,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application),
val notificationHelper: PlayerNotificationHelper by lazy { PlayerNotificationHelper(this) }
// Media source handling
val mediaQueueManager = MediaQueueManager(this)
val mediaQueueManager = QueueManager(this)
val mediaSourceOrNull: JellyfinMediaSource?
get() = mediaQueueManager.mediaQueue.value?.jellyfinMediaSource
@ -188,7 +192,7 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application),
_player.value = null
}
fun play(queueItem: MediaQueueManager.QueueItem.Loaded) {
fun play(queueItem: QueueManager.QueueItem.Loaded) {
val player = playerOrNull ?: return
player.setMediaSource(queueItem.exoMediaSource)
@ -353,14 +357,14 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application),
}
/**
* @see MediaQueueManager.selectAudioTrack
* @see QueueManager.selectAudioTrack
*/
fun selectAudioTrack(streamIndex: Int): Boolean = mediaQueueManager.selectAudioTrack(streamIndex).also { success ->
if (success) playerOrNull?.logTracks(analyticsCollector)
}
/**
* @see MediaQueueManager.selectSubtitle
* @see QueueManager.selectSubtitle
*/
fun selectSubtitle(streamIndex: Int): Boolean = mediaQueueManager.selectSubtitle(streamIndex).also { success ->
if (success) playerOrNull?.logTracks(analyticsCollector)

View File

@ -16,7 +16,7 @@
* limitations under the License.
*/
package org.jellyfin.mobile.media
package org.jellyfin.mobile.player.audio
import android.app.PendingIntent
import android.content.Context
@ -45,7 +45,7 @@ import org.koin.core.component.inject
* A wrapper class for ExoPlayer's PlayerNotificationManager. It sets up the notification shown to
* the user during audio playback and provides track metadata, such as track title and icon image.
*/
class MediaNotificationManager(
class AudioNotificationManager(
private val context: Context,
sessionToken: MediaSessionCompat.Token,
notificationListener: PlayerNotificationManager.NotificationListener

View File

@ -1,6 +1,6 @@
// Contains code adapted from https://github.com/android/uamp/blob/main/common/src/main/java/com/example/android/uamp/media/MediaService.kt
package org.jellyfin.mobile.media
package org.jellyfin.mobile.player.audio
import android.app.Notification
import android.app.PendingIntent
@ -36,11 +36,12 @@ import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import org.jellyfin.mobile.R
import org.jellyfin.mobile.cast.CastPlayerProvider
import org.jellyfin.mobile.cast.ICastPlayerProvider
import org.jellyfin.mobile.controller.ApiController
import org.jellyfin.mobile.media.car.LibraryBrowser
import org.jellyfin.mobile.media.car.LibraryPage
import org.jellyfin.mobile.player.cast.CastPlayerProvider
import org.jellyfin.mobile.player.cast.ICastPlayerProvider
import org.jellyfin.mobile.app.ApiClientController
import org.jellyfin.mobile.player.audio.car.LibraryBrowser
import org.jellyfin.mobile.player.audio.car.LibraryPage
import org.jellyfin.mobile.utils.extensions.mediaUri
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.toast
import org.jellyfin.sdk.api.client.ApiClient
@ -51,7 +52,7 @@ import timber.log.Timber
import com.google.android.exoplayer2.MediaItem as ExoPlayerMediaItem
class MediaService : MediaBrowserServiceCompat() {
private val apiController: ApiController by inject()
private val apiClientController: ApiClientController by inject()
private val apiClient: ApiClient by inject()
private val libraryBrowser: LibraryBrowser by inject()
@ -64,7 +65,7 @@ class MediaService : MediaBrowserServiceCompat() {
// remote playback through a Cast device).
private lateinit var currentPlayer: Player
private lateinit var notificationManager: MediaNotificationManager
private lateinit var notificationManager: AudioNotificationManager
private lateinit var mediaController: MediaControllerCompat
private lateinit var mediaSession: MediaSessionCompat
private lateinit var mediaSessionConnector: MediaSessionConnector
@ -98,7 +99,7 @@ class MediaService : MediaBrowserServiceCompat() {
super.onCreate()
loadingJob = serviceScope.launch {
apiController.loadSavedServerUser()
apiClientController.loadSavedServerUser()
}
val sessionActivityPendingIntent = packageManager?.getLaunchIntentForPackage(packageName)?.let { sessionIntent ->
@ -112,7 +113,7 @@ class MediaService : MediaBrowserServiceCompat() {
sessionToken = mediaSession.sessionToken
notificationManager = MediaNotificationManager(
notificationManager = AudioNotificationManager(
this,
mediaSession.sessionToken,
PlayerNotificationListener()

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.media.car
package org.jellyfin.mobile.player.audio.car
import android.content.Context
import android.net.Uri
@ -12,17 +12,17 @@ import android.support.v4.media.MediaMetadataCompat
import androidx.media.MediaBrowserServiceCompat
import androidx.media.utils.MediaConstants
import org.jellyfin.mobile.R
import org.jellyfin.mobile.media.MediaService
import org.jellyfin.mobile.media.mediaId
import org.jellyfin.mobile.media.setAlbum
import org.jellyfin.mobile.media.setAlbumArtUri
import org.jellyfin.mobile.media.setAlbumArtist
import org.jellyfin.mobile.media.setArtist
import org.jellyfin.mobile.media.setDisplayIconUri
import org.jellyfin.mobile.media.setMediaId
import org.jellyfin.mobile.media.setMediaUri
import org.jellyfin.mobile.media.setTitle
import org.jellyfin.mobile.media.setTrackNumber
import org.jellyfin.mobile.player.audio.MediaService
import org.jellyfin.mobile.utils.extensions.mediaId
import org.jellyfin.mobile.utils.extensions.setAlbum
import org.jellyfin.mobile.utils.extensions.setAlbumArtUri
import org.jellyfin.mobile.utils.extensions.setAlbumArtist
import org.jellyfin.mobile.utils.extensions.setArtist
import org.jellyfin.mobile.utils.extensions.setDisplayIconUri
import org.jellyfin.mobile.utils.extensions.setMediaId
import org.jellyfin.mobile.utils.extensions.setMediaUri
import org.jellyfin.mobile.utils.extensions.setTitle
import org.jellyfin.mobile.utils.extensions.setTrackNumber
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.exception.ApiClientException
import org.jellyfin.sdk.api.client.extensions.genresApi

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.media.car
package org.jellyfin.mobile.player.audio.car
object LibraryPage {
/**

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast
package org.jellyfin.mobile.player.cast
import com.google.android.exoplayer2.Player

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast
package org.jellyfin.mobile.player.cast
import android.app.Activity
import org.jellyfin.mobile.bridge.JavascriptCallback

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.deviceprofile
import android.media.MediaCodecInfo.CodecProfileLevel
import android.media.MediaFormat

View File

@ -1,12 +1,12 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.deviceprofile
import android.media.MediaCodecInfo.CodecCapabilities
import android.util.Range
import org.jellyfin.mobile.player.CodecHelpers.getAudioCodec
import org.jellyfin.mobile.player.CodecHelpers.getAudioProfile
import org.jellyfin.mobile.player.CodecHelpers.getVideoCodec
import org.jellyfin.mobile.player.CodecHelpers.getVideoLevel
import org.jellyfin.mobile.player.CodecHelpers.getVideoProfile
import org.jellyfin.mobile.player.deviceprofile.CodecHelpers.getAudioCodec
import org.jellyfin.mobile.player.deviceprofile.CodecHelpers.getAudioProfile
import org.jellyfin.mobile.player.deviceprofile.CodecHelpers.getVideoCodec
import org.jellyfin.mobile.player.deviceprofile.CodecHelpers.getVideoLevel
import org.jellyfin.mobile.player.deviceprofile.CodecHelpers.getVideoProfile
import java.util.*
import kotlin.collections.HashSet
import kotlin.math.max

View File

@ -1,8 +1,7 @@
package org.jellyfin.mobile.api
package org.jellyfin.mobile.player.deviceprofile
import android.media.MediaCodecList
import org.jellyfin.mobile.bridge.ExternalPlayer
import org.jellyfin.mobile.player.DeviceCodec
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.sdk.model.api.CodecProfile
import org.jellyfin.sdk.model.api.ContainerProfile

View File

@ -1,8 +1,8 @@
package org.jellyfin.mobile.bridge
package org.jellyfin.mobile.player.interaction
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import org.jellyfin.mobile.utils.size
import org.jellyfin.mobile.utils.extensions.size
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import org.json.JSONException
import org.json.JSONObject

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.interaction
sealed class PlayerEvent {
object Pause : PlayerEvent()

View File

@ -1,7 +1,8 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.interaction
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import org.jellyfin.mobile.player.PlayerViewModel
class PlayerLifecycleObserver(private val viewModel: PlayerViewModel) : DefaultLifecycleObserver {

View File

@ -1,6 +1,7 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.interaction
import android.media.session.MediaSession
import org.jellyfin.mobile.player.PlayerViewModel
class PlayerMediaSessionCallback(private val viewModel: PlayerViewModel) : MediaSession.Callback() {
override fun onPlay() {

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.interaction
import android.app.Application
import android.app.Notification
@ -20,10 +20,11 @@ import com.google.android.exoplayer2.Player
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.BuildConfig
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
import org.jellyfin.mobile.player.PlayerViewModel
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.VIDEO_PLAYER_NOTIFICATION_ID
import org.jellyfin.mobile.utils.createMediaNotificationChannel

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player.source
package org.jellyfin.mobile.player.queue
import android.app.Application
import android.net.Uri
@ -13,9 +13,11 @@ import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.source.SingleSampleMediaSource
import com.google.android.exoplayer2.source.hls.HlsMediaSource
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import org.jellyfin.mobile.bridge.PlayOptions
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.player.PlayerException
import org.jellyfin.mobile.player.PlayerViewModel
import org.jellyfin.mobile.player.source.JellyfinMediaSource
import org.jellyfin.mobile.player.source.MediaSourceResolver
import org.jellyfin.mobile.utils.clearSelectionAndDisableRendererByType
import org.jellyfin.mobile.utils.selectTrackByTypeAndGroup
import org.jellyfin.sdk.api.client.ApiClient
@ -30,7 +32,7 @@ import org.koin.core.component.get
import org.koin.core.component.inject
import java.util.UUID
class MediaQueueManager(
class QueueManager(
private val viewModel: PlayerViewModel,
) : KoinComponent {
private val apiClient: ApiClient = get()

View File

@ -1,6 +1,6 @@
package org.jellyfin.mobile.player.source
import org.jellyfin.mobile.player.CodecHelpers
import org.jellyfin.mobile.player.deviceprofile.CodecHelpers
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.sdk.model.api.BaseItemDto
import org.jellyfin.sdk.model.api.MediaSourceInfo

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.model
package org.jellyfin.mobile.player.ui
import org.jellyfin.mobile.utils.Constants

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.ui
import android.app.Activity
import android.app.PictureInPictureParams
@ -28,20 +28,22 @@ import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ui.PlayerView
import kotlinx.coroutines.launch
import org.jellyfin.mobile.R
import org.jellyfin.mobile.api.aspectRational
import org.jellyfin.mobile.api.isLandscape
import org.jellyfin.mobile.bridge.PlayOptions
import org.jellyfin.mobile.utils.extensions.aspectRational
import org.jellyfin.mobile.utils.extensions.isLandscape
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.databinding.ExoPlayerControlViewBinding
import org.jellyfin.mobile.databinding.FragmentPlayerBinding
import org.jellyfin.mobile.player.PlayerException
import org.jellyfin.mobile.player.PlayerViewModel
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.DEFAULT_CONTROLS_TIMEOUT_MS
import org.jellyfin.mobile.utils.Constants.PIP_MAX_RATIONAL
import org.jellyfin.mobile.utils.Constants.PIP_MIN_RATIONAL
import org.jellyfin.mobile.utils.SmartOrientationListener
import org.jellyfin.mobile.utils.brightness
import org.jellyfin.mobile.utils.disableFullscreen
import org.jellyfin.mobile.utils.enableFullscreen
import org.jellyfin.mobile.utils.isFullscreen
import org.jellyfin.mobile.utils.extensions.disableFullscreen
import org.jellyfin.mobile.utils.extensions.enableFullscreen
import org.jellyfin.mobile.utils.extensions.isFullscreen
import org.jellyfin.mobile.utils.toast
import org.jellyfin.sdk.model.api.MediaStream
@ -57,7 +59,7 @@ class PlayerFragment : Fragment() {
private val playerControlsView: View get() = playerControlsBinding.root
private val titleTextView: TextView get() = playerControlsBinding.trackTitle
private val fullscreenSwitcher: ImageButton get() = playerControlsBinding.fullscreenSwitcher
private var playbackMenus: PlaybackMenus? = null
private var playerMenus: PlayerMenus? = null
lateinit var playerLockScreenHelper: PlayerLockScreenHelper
lateinit var playerGestureHelper: PlayerGestureHelper
@ -108,7 +110,7 @@ class PlayerFragment : Fragment() {
// Update title and player menus
titleTextView.text = jellyfinMediaSource.name
playbackMenus?.onQueueItemChanged(queueItem)
playerMenus?.onQueueItemChanged(queueItem)
}
// Handle fragment arguments, extract playback options and start playback
@ -156,7 +158,7 @@ class PlayerFragment : Fragment() {
}
// Create playback menus
playbackMenus = PlaybackMenus(this, playerBinding, playerControlsBinding)
playerMenus = PlayerMenus(this, playerBinding, playerControlsBinding)
// Set controller timeout
suppressControllerAutoHide(false)
@ -318,7 +320,7 @@ class PlayerFragment : Fragment() {
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) {
playerView.useController = !isInPictureInPictureMode
if (isInPictureInPictureMode) {
playbackMenus?.dismissPlaybackInfo()
playerMenus?.dismissPlaybackInfo()
playerLockScreenHelper.hideUnlockButton()
}
}
@ -344,7 +346,7 @@ class PlayerFragment : Fragment() {
// Set binding references to null
_playerBinding = null
_playerControlsBinding = null
playbackMenus = null
playerMenus = null
}
override fun onDestroy() {

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.ui
import android.content.res.Configuration
import android.media.AudioManager
@ -16,7 +16,7 @@ import androidx.core.view.isVisible
import androidx.core.view.postDelayed
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
import com.google.android.exoplayer2.ui.PlayerView
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.databinding.FragmentPlayerBinding
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.brightness

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.ui
import android.content.pm.ActivityInfo
import android.os.Build
@ -9,7 +9,7 @@ import com.google.android.exoplayer2.ui.PlayerView
import org.jellyfin.mobile.databinding.FragmentPlayerBinding
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.isAutoRotateOn
import org.jellyfin.mobile.utils.lockOrientation
import org.jellyfin.mobile.utils.extensions.lockOrientation
class PlayerLockScreenHelper(
private val playerFragment: PlayerFragment,

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.player
package org.jellyfin.mobile.player.ui
import android.view.Menu
import android.view.MenuItem
@ -12,14 +12,14 @@ import androidx.core.view.isVisible
import org.jellyfin.mobile.R
import org.jellyfin.mobile.databinding.ExoPlayerControlViewBinding
import org.jellyfin.mobile.databinding.FragmentPlayerBinding
import org.jellyfin.mobile.player.source.MediaQueueManager
import org.jellyfin.mobile.player.queue.QueueManager
import org.jellyfin.sdk.model.api.MediaStream
import java.util.Locale
/**
* Provides a menu UI for audio, subtitle and video stream selection
*/
class PlaybackMenus(
class PlayerMenus(
private val fragment: PlayerFragment,
private val playerBinding: FragmentPlayerBinding,
private val playerControlsBinding: ExoPlayerControlViewBinding
@ -79,7 +79,7 @@ class PlaybackMenus(
}
}
fun onQueueItemChanged(queueItem: MediaQueueManager.QueueItem.Loaded) {
fun onQueueItemChanged(queueItem: QueueManager.QueueItem.Loaded) {
nextButton.isEnabled = queueItem.hasNext()
val mediaSource = queueItem.jellyfinMediaSource
@ -152,7 +152,7 @@ class PlaybackMenus(
}
}
}
setOnDismissListener(this@PlaybackMenus)
setOnDismissListener(this@PlayerMenus)
}
private fun createAudioStreamsMenu() = PopupMenu(context, audioStreamsButton).apply {
@ -167,7 +167,7 @@ class PlaybackMenus(
}
}
}
setOnDismissListener(this@PlaybackMenus)
setOnDismissListener(this@PlayerMenus)
}
private fun createSpeedMenu() = PopupMenu(context, speedButton).apply {
@ -186,7 +186,7 @@ class PlaybackMenus(
}
}
}
setOnDismissListener(this@PlaybackMenus)
setOnDismissListener(this@PlayerMenus)
}
private fun buildMenuItems(menu: Menu, groupId: Int, mediaStreams: List<MediaStream>, selectedStream: MediaStream?, showNone: Boolean = false) {

View File

@ -16,14 +16,14 @@ import de.Maxr1998.modernpreferences.helpers.screen
import de.Maxr1998.modernpreferences.helpers.singleChoice
import de.Maxr1998.modernpreferences.preferences.CheckBoxPreference
import de.Maxr1998.modernpreferences.preferences.choice.SelectionItem
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.R
import org.jellyfin.mobile.databinding.FragmentSettingsBinding
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.applyWindowInsetsAsMargins
import org.jellyfin.mobile.utils.getDownloadsPaths
import org.jellyfin.mobile.utils.isPackageInstalled
import org.jellyfin.mobile.utils.requireMainActivity
import org.jellyfin.mobile.utils.extensions.requireMainActivity
import org.jellyfin.mobile.utils.withThemedContext
import org.koin.android.ext.android.inject

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.fragment
package org.jellyfin.mobile.setup
import android.app.AlertDialog
import android.os.Bundle
@ -23,11 +23,11 @@ import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import org.jellyfin.mobile.R
import org.jellyfin.mobile.controller.ApiController
import org.jellyfin.mobile.app.ApiClientController
import org.jellyfin.mobile.databinding.FragmentConnectBinding
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.applyWindowInsetsAsMargins
import org.jellyfin.mobile.viewmodel.MainViewModel
import org.jellyfin.mobile.MainViewModel
import org.jellyfin.sdk.Jellyfin
import org.jellyfin.sdk.discovery.LocalServerDiscovery
import org.jellyfin.sdk.discovery.RecommendedServerInfo
@ -40,7 +40,7 @@ import timber.log.Timber
class ConnectFragment : Fragment() {
private val mainViewModel: MainViewModel by sharedViewModel()
private val jellyfin: Jellyfin by inject()
private val apiController: ApiController by inject()
private val apiClientController: ApiClientController by inject()
// UI
private var _connectServerBinding: FragmentConnectBinding? = null
@ -118,7 +118,7 @@ class ConnectFragment : Fragment() {
val httpUrl = checkServerUrlAndConnection(enteredUrl)
if (httpUrl != null) {
serverList.clear()
apiController.setupServer(httpUrl)
apiClientController.setupServer(httpUrl)
mainViewModel.refreshServer()
}
hostInput.isEnabled = true

View File

@ -13,6 +13,7 @@ import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.analytics.AnalyticsCollector
import org.jellyfin.mobile.player.source.JellyfinMediaSource
import org.jellyfin.mobile.utils.extensions.width
import com.google.android.exoplayer2.audio.AudioAttributes as ExoPlayerAudioAttributes
inline fun MediaSession.applyDefaultLocalAudioAttributes(contentType: Int) {

View File

@ -24,10 +24,10 @@ import androidx.core.content.getSystemService
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.BuildConfig
import org.jellyfin.mobile.R
import org.jellyfin.mobile.fragment.WebViewFragment
import org.jellyfin.mobile.webapp.WebViewFragment
import org.jellyfin.mobile.settings.ExternalPlayerPackage
import org.koin.android.ext.android.get
import timber.log.Timber

View File

@ -1,6 +1,6 @@
@file:Suppress("DEPRECATION")
package org.jellyfin.mobile.utils
package org.jellyfin.mobile.utils.extensions
import android.app.Activity
import android.content.pm.ActivityInfo

View File

@ -0,0 +1,8 @@
@file:Suppress("NOTHING_TO_INLINE")
package org.jellyfin.mobile.utils.extensions
import androidx.fragment.app.Fragment
import org.jellyfin.mobile.MainActivity
inline fun Fragment.requireMainActivity(): MainActivity = requireActivity() as MainActivity

View File

@ -1,13 +1,12 @@
@file:Suppress("NOTHING_TO_INLINE")
package org.jellyfin.mobile.utils
package org.jellyfin.mobile.utils.extensions
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.add
import androidx.fragment.app.replace
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
inline fun <reified T : Fragment> FragmentManager.addFragment() {
@ -20,5 +19,3 @@ inline fun <reified T : Fragment> FragmentManager.addFragment() {
inline fun <reified T : Fragment> FragmentManager.replaceFragment(args: Bundle? = null) {
beginTransaction().replace<T>(R.id.fragment_container, args = args).commit()
}
inline fun Fragment.requireMainActivity(): MainActivity = requireActivity() as MainActivity

View File

@ -1,6 +1,6 @@
@file:Suppress("NOTHING_TO_INLINE")
package org.jellyfin.mobile.utils
package org.jellyfin.mobile.utils.extensions
import androidx.annotation.CheckResult
@ -12,12 +12,3 @@ inline fun Int.withFlag(flag: Int) = this or flag
@CheckResult
inline fun Int.withoutFlag(flag: Int) = this and flag.inv()
@get:CheckResult
val IntRange.width: Int
get() = endInclusive - start
@CheckResult
fun IntRange.scaleInRange(percent: Int): Int {
return start + width * percent / Constants.PERCENT_MAX
}

View File

@ -0,0 +1,15 @@
@file:Suppress("NOTHING_TO_INLINE")
package org.jellyfin.mobile.utils.extensions
import androidx.annotation.CheckResult
import org.jellyfin.mobile.utils.Constants
@get:CheckResult
val IntRange.width: Int
get() = endInclusive - start
@CheckResult
fun IntRange.scaleInRange(percent: Int): Int {
return start + width * percent / Constants.PERCENT_MAX
}

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.utils
package org.jellyfin.mobile.utils.extensions
import org.json.JSONArray

View File

@ -1,15 +1,12 @@
@file:Suppress("NOTHING_TO_INLINE")
package org.jellyfin.mobile.media
package org.jellyfin.mobile.utils.extensions
import android.graphics.Bitmap
import android.net.Uri
import android.support.v4.media.MediaMetadataCompat
import androidx.core.net.toUri
/**
* Useful extensions for [MediaMetadataCompat].
*/
inline val MediaMetadataCompat.mediaId: String?
get() = getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.api
package org.jellyfin.mobile.utils.extensions
import android.util.Rational
import org.jellyfin.sdk.model.api.MediaStream

View File

@ -31,7 +31,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.MainActivity
import org.jellyfin.mobile.R
import org.jellyfin.mobile.utils.Constants

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.fragment
package org.jellyfin.mobile.webapp
import android.content.Intent
import android.graphics.Rect
@ -36,20 +36,21 @@ import androidx.webkit.WebViewCompat
import androidx.webkit.WebViewFeature
import io.ktor.http.HttpStatusCode
import kotlinx.coroutines.launch
import org.jellyfin.mobile.AppPreferences
import org.jellyfin.mobile.app.AppPreferences
import org.jellyfin.mobile.R
import org.jellyfin.mobile.bridge.ExternalPlayer
import org.jellyfin.mobile.bridge.NativeInterface
import org.jellyfin.mobile.bridge.NativePlayer
import org.jellyfin.mobile.bridge.NativePlayerHost
import org.jellyfin.mobile.bridge.PlayOptions
import org.jellyfin.mobile.controller.ApiController
import org.jellyfin.mobile.player.interaction.PlayOptions
import org.jellyfin.mobile.app.ApiClientController
import org.jellyfin.mobile.databinding.FragmentWebviewBinding
import org.jellyfin.mobile.model.sql.entity.ServerEntity
import org.jellyfin.mobile.player.PlayerFragment
import org.jellyfin.mobile.setup.ConnectFragment
import org.jellyfin.mobile.data.entity.ServerEntity
import org.jellyfin.mobile.player.ui.PlayerFragment
import org.jellyfin.mobile.utils.Constants
import org.jellyfin.mobile.utils.Constants.FRAGMENT_WEB_VIEW_EXTRA_SERVER
import org.jellyfin.mobile.utils.addFragment
import org.jellyfin.mobile.utils.extensions.addFragment
import org.jellyfin.mobile.utils.applyDefault
import org.jellyfin.mobile.utils.applyWindowInsetsAsMargins
import org.jellyfin.mobile.utils.dip
@ -57,10 +58,9 @@ import org.jellyfin.mobile.utils.fadeIn
import org.jellyfin.mobile.utils.initLocale
import org.jellyfin.mobile.utils.inject
import org.jellyfin.mobile.utils.isOutdated
import org.jellyfin.mobile.utils.replaceFragment
import org.jellyfin.mobile.utils.extensions.replaceFragment
import org.jellyfin.mobile.utils.requestNoBatteryOptimizations
import org.jellyfin.mobile.utils.runOnUiThread
import org.jellyfin.mobile.webapp.WebappFunctionChannel
import org.json.JSONException
import org.json.JSONObject
import org.koin.android.ext.android.inject
@ -73,7 +73,7 @@ import kotlin.coroutines.suspendCoroutine
class WebViewFragment : Fragment(), NativePlayerHost {
val appPreferences: AppPreferences by inject()
private val apiController: ApiController by inject()
private val apiClientController: ApiClientController by inject()
private val webappFunctionChannel: WebappFunctionChannel by inject()
private lateinit var assetsPathHandler: AssetsPathHandler
private lateinit var externalPlayer: ExternalPlayer
@ -194,7 +194,7 @@ class WebViewFragment : Fragment(), NativePlayerHost {
val storedServer = credentials.getJSONArray("Servers").getJSONObject(0)
val user = storedServer.getString("UserId")
val token = storedServer.getString("AccessToken")
apiController.setupUser(server.id, user, token)
apiClientController.setupUser(server.id, user, token)
webView.initLocale(user)
}
null

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast
package org.jellyfin.mobile.player.cast
import android.content.Context
import com.google.android.gms.cast.framework.CastOptions

View File

@ -1,10 +1,10 @@
package org.jellyfin.mobile.cast
package org.jellyfin.mobile.player.cast
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.ext.cast.CastPlayer
import com.google.android.exoplayer2.ext.cast.SessionAvailabilityListener
import com.google.android.gms.cast.framework.CastContext
import org.jellyfin.mobile.media.MediaService
import org.jellyfin.mobile.player.audio.MediaService
class CastPlayerProvider(private val mediaService: MediaService) : ICastPlayerProvider, SessionAvailabilityListener {
private val castPlayer: CastPlayer? = try {

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast;
package org.jellyfin.mobile.player.cast;
import android.app.Activity;

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast;
package org.jellyfin.mobile.player.cast;
import android.app.Activity;
import android.app.AlertDialog;
@ -24,6 +24,7 @@ import com.google.android.gms.cast.framework.SessionManagerListener;
import org.jellyfin.mobile.R;
import org.jellyfin.mobile.bridge.JavascriptCallback;
import org.jellyfin.mobile.player.cast.CastOptionsProvider;
import org.json.JSONObject;
import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast;
package org.jellyfin.mobile.player.cast;
import android.app.Activity;

View File

@ -1,4 +1,4 @@
package org.jellyfin.mobile.cast;
package org.jellyfin.mobile.player.cast;
import android.annotation.SuppressLint;
import android.graphics.Color;