refactor: decouple and abstract auth from media service logic

This commit is contained in:
Bnyro 2025-03-01 17:49:49 +01:00
parent 0aa8ebb413
commit 1dabd07de4
No known key found for this signature in database
29 changed files with 320 additions and 207 deletions

View File

@ -1,6 +1,7 @@
package com.github.libretube.api
import com.github.libretube.api.obj.DeArrowBody
import com.github.libretube.api.obj.PipedConfig
import com.github.libretube.api.obj.PipedInstance
import com.github.libretube.api.obj.SubmitSegmentResponse
import com.github.libretube.api.obj.VoteInfo
@ -20,6 +21,9 @@ interface ExternalApi {
@GET
suspend fun getInstances(@Url url: String): List<PipedInstance>
@GET("config")
suspend fun getInstanceConfig(@Url url: String): PipedConfig
// fetch latest version info
@GET(GITHUB_API_URL)
suspend fun getLatestRelease(): UpdateInfo

View File

@ -0,0 +1,35 @@
package com.github.libretube.api
import com.github.libretube.api.obj.Channel
import com.github.libretube.api.obj.ChannelTabResponse
import com.github.libretube.api.obj.CommentsPage
import com.github.libretube.api.obj.DeArrowContent
import com.github.libretube.api.obj.Playlist
import com.github.libretube.api.obj.SearchResult
import com.github.libretube.api.obj.SegmentData
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.api.obj.Streams
interface MediaServiceRepository {
suspend fun getTrending(region: String): List<StreamItem>
suspend fun getStreams(videoId: String): Streams
suspend fun getComments(videoId: String): CommentsPage
suspend fun getSegments(videoId: String, category: String, actionType: String? = null): SegmentData
suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent>
suspend fun getCommentsNextPage(videoId: String, nextPage: String): CommentsPage
suspend fun getSearchResults(searchQuery: String, filter: String): SearchResult
suspend fun getSearchResultsNextPage(searchQuery: String, filter: String, nextPage: String): SearchResult
suspend fun getSuggestions(query: String): List<String>
suspend fun getChannel(channelId: String): Channel
suspend fun getChannelTab(data: String, nextPage: String? = null): ChannelTabResponse
suspend fun getChannelByName(channelName: String): Channel
suspend fun getChannelNextPage(channelId: String, nextPage: String): Channel
suspend fun getPlaylist(playlistId: String): Playlist
suspend fun getPlaylistNextPage(playlistId: String, nextPage: String): Playlist
companion object {
val instance by lazy {
PipedMediaServiceRepository()
}
}
}

View File

@ -4,33 +4,16 @@ import com.github.libretube.api.obj.Channel
import com.github.libretube.api.obj.ChannelTabResponse
import com.github.libretube.api.obj.CommentsPage
import com.github.libretube.api.obj.DeArrowContent
import com.github.libretube.api.obj.DeleteUserRequest
import com.github.libretube.api.obj.EditPlaylistBody
import com.github.libretube.api.obj.Login
import com.github.libretube.api.obj.Message
import com.github.libretube.api.obj.PipedConfig
import com.github.libretube.api.obj.Playlist
import com.github.libretube.api.obj.Playlists
import com.github.libretube.api.obj.SearchResult
import com.github.libretube.api.obj.SegmentData
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.api.obj.Streams
import com.github.libretube.api.obj.Subscribe
import com.github.libretube.api.obj.Subscribed
import com.github.libretube.api.obj.Subscription
import com.github.libretube.api.obj.Token
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
interface PipedApi {
@GET("config")
suspend fun getConfig(): PipedConfig
@GET("trending")
suspend fun getTrending(@Query("region") region: String): List<StreamItem>
@ -98,106 +81,4 @@ interface PipedApi {
@Path("playlistId") playlistId: String,
@Query("nextpage") nextPage: String
): Playlist
@POST("login")
suspend fun login(@Body login: Login): Token
@POST("register")
suspend fun register(@Body login: Login): Token
@POST("user/delete")
suspend fun deleteAccount(
@Header("Authorization") token: String,
@Body password: DeleteUserRequest
)
@GET("feed")
suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem>
@GET("feed/unauthenticated")
suspend fun getUnauthenticatedFeed(@Query("channels") channels: String): List<StreamItem>
@POST("feed/unauthenticated")
suspend fun getUnauthenticatedFeed(@Body channels: List<String>): List<StreamItem>
@GET("subscribed")
suspend fun isSubscribed(
@Query("channelId") channelId: String,
@Header("Authorization") token: String
): Subscribed
@GET("subscriptions")
suspend fun subscriptions(@Header("Authorization") token: String): List<Subscription>
@GET("subscriptions/unauthenticated")
suspend fun unauthenticatedSubscriptions(
@Query("channels") channels: String
): List<Subscription>
@POST("subscriptions/unauthenticated")
suspend fun unauthenticatedSubscriptions(@Body channels: List<String>): List<Subscription>
@POST("subscribe")
suspend fun subscribe(
@Header("Authorization") token: String,
@Body subscribe: Subscribe
): Message
@POST("unsubscribe")
suspend fun unsubscribe(
@Header("Authorization") token: String,
@Body subscribe: Subscribe
): Message
@POST("import")
suspend fun importSubscriptions(
@Query("override") override: Boolean,
@Header("Authorization") token: String,
@Body channels: List<String>
): Message
@POST("import/playlist")
suspend fun clonePlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): EditPlaylistBody
@GET("user/playlists")
suspend fun getUserPlaylists(@Header("Authorization") token: String): List<Playlists>
@POST("user/playlists/rename")
suspend fun renamePlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@PATCH("user/playlists/description")
suspend fun changePlaylistDescription(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@POST("user/playlists/delete")
suspend fun deletePlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@POST("user/playlists/create")
suspend fun createPlaylist(
@Header("Authorization") token: String,
@Body name: Playlists
): EditPlaylistBody
@POST("user/playlists/add")
suspend fun addToPlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@POST("user/playlists/remove")
suspend fun removeFromPlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
}

View File

@ -0,0 +1,128 @@
package com.github.libretube.api
import com.github.libretube.api.obj.DeleteUserRequest
import com.github.libretube.api.obj.EditPlaylistBody
import com.github.libretube.api.obj.Login
import com.github.libretube.api.obj.Message
import com.github.libretube.api.obj.Playlist
import com.github.libretube.api.obj.Playlists
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.api.obj.Subscribe
import com.github.libretube.api.obj.Subscribed
import com.github.libretube.api.obj.Subscription
import com.github.libretube.api.obj.Token
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
interface PipedAuthApi {
@POST("login")
suspend fun login(@Body login: Login): Token
@POST("register")
suspend fun register(@Body login: Login): Token
@POST("user/delete")
suspend fun deleteAccount(
@Header("Authorization") token: String,
@Body password: DeleteUserRequest
)
@GET("feed")
suspend fun getFeed(@Query("authToken") token: String?): List<StreamItem>
@GET("feed/unauthenticated")
suspend fun getUnauthenticatedFeed(@Query("channels") channels: String): List<StreamItem>
@POST("feed/unauthenticated")
suspend fun getUnauthenticatedFeed(@Body channels: List<String>): List<StreamItem>
@GET("subscribed")
suspend fun isSubscribed(
@Query("channelId") channelId: String,
@Header("Authorization") token: String
): Subscribed
@GET("subscriptions")
suspend fun subscriptions(@Header("Authorization") token: String): List<Subscription>
@GET("subscriptions/unauthenticated")
suspend fun unauthenticatedSubscriptions(
@Query("channels") channels: String
): List<Subscription>
@POST("subscriptions/unauthenticated")
suspend fun unauthenticatedSubscriptions(@Body channels: List<String>): List<Subscription>
@POST("subscribe")
suspend fun subscribe(
@Header("Authorization") token: String,
@Body subscribe: Subscribe
): Message
@POST("unsubscribe")
suspend fun unsubscribe(
@Header("Authorization") token: String,
@Body subscribe: Subscribe
): Message
@POST("import")
suspend fun importSubscriptions(
@Query("override") override: Boolean,
@Header("Authorization") token: String,
@Body channels: List<String>
): Message
@POST("import/playlist")
suspend fun clonePlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): EditPlaylistBody
@GET("user/playlists")
suspend fun getUserPlaylists(@Header("Authorization") token: String): List<Playlists>
@POST("user/playlists/rename")
suspend fun renamePlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@PATCH("user/playlists/description")
suspend fun changePlaylistDescription(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@POST("user/playlists/delete")
suspend fun deletePlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@POST("user/playlists/create")
suspend fun createPlaylist(
@Header("Authorization") token: String,
@Body name: Playlists
): EditPlaylistBody
@POST("user/playlists/add")
suspend fun addToPlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@POST("user/playlists/remove")
suspend fun removeFromPlaylist(
@Header("Authorization") token: String,
@Body editPlaylistBody: EditPlaylistBody
): Message
@GET("playlists/{playlistId}")
suspend fun getPlaylist(@Path("playlistId") playlistId: String): Playlist
}

View File

@ -0,0 +1,75 @@
package com.github.libretube.api
import com.github.libretube.api.RetrofitInstance.PIPED_API_URL
import com.github.libretube.api.obj.Channel
import com.github.libretube.api.obj.ChannelTabResponse
import com.github.libretube.api.obj.CommentsPage
import com.github.libretube.api.obj.DeArrowContent
import com.github.libretube.api.obj.Playlist
import com.github.libretube.api.obj.SearchResult
import com.github.libretube.api.obj.SegmentData
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.api.obj.Streams
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.helpers.PreferenceHelper
class PipedMediaServiceRepository : MediaServiceRepository {
override suspend fun getTrending(region: String): List<StreamItem> =
api.getTrending(region)
override suspend fun getStreams(videoId: String): Streams =
api.getStreams(videoId)
override suspend fun getComments(videoId: String): CommentsPage =
api.getComments(videoId)
override suspend fun getSegments(
videoId: String,
category: String,
actionType: String?
): SegmentData = api.getSegments(videoId, category, actionType)
override suspend fun getDeArrowContent(videoIds: String): Map<String, DeArrowContent> =
api.getDeArrowContent(videoIds)
override suspend fun getCommentsNextPage(videoId: String, nextPage: String): CommentsPage =
api.getCommentsNextPage(videoId, nextPage)
override suspend fun getSearchResults(searchQuery: String, filter: String): SearchResult =
api.getSearchResults(searchQuery, filter)
override suspend fun getSearchResultsNextPage(
searchQuery: String,
filter: String,
nextPage: String
): SearchResult = api.getSearchResultsNextPage(searchQuery, filter, nextPage)
override suspend fun getSuggestions(query: String): List<String> =
api.getSuggestions(query)
override suspend fun getChannel(channelId: String): Channel =
api.getChannel(channelId)
override suspend fun getChannelTab(data: String, nextPage: String?): ChannelTabResponse =
api.getChannelTab(data, nextPage)
override suspend fun getChannelByName(channelName: String): Channel =
api.getChannelByName(channelName)
override suspend fun getChannelNextPage(channelId: String, nextPage: String): Channel =
api.getChannelNextPage(channelId, nextPage)
override suspend fun getPlaylist(playlistId: String): Playlist =
api.getPlaylist(playlistId)
override suspend fun getPlaylistNextPage(playlistId: String, nextPage: String): Playlist =
api.getPlaylistNextPage(playlistId, nextPage)
companion object {
val apiUrl get() = PreferenceHelper.getString(PreferenceKeys.FETCH_INSTANCE, PIPED_API_URL)
private val api by resettableLazy(RetrofitInstance.apiLazyMgr) {
RetrofitInstance.buildRetrofitInstance<PipedApi>(apiUrl)
}
}
}

View File

@ -52,7 +52,7 @@ object PlaylistsHelper {
suspend fun getPlaylist(playlistId: String): Playlist {
// load locally stored playlists with the auth api
return when (getPrivatePlaylistType(playlistId)) {
PlaylistType.PUBLIC -> RetrofitInstance.api.getPlaylist(playlistId)
PlaylistType.PUBLIC -> MediaServiceRepository.instance.getPlaylist(playlistId)
else -> playlistsRepository.getPlaylist(playlistId)
}.apply {
relatedStreams = relatedStreams.deArrow()

View File

@ -11,55 +11,33 @@ import retrofit2.converter.kotlinx.serialization.asConverterFactory
import retrofit2.create
object RetrofitInstance {
private const val PIPED_API_URL = "https://pipedapi.kavin.rocks"
val apiUrl get() = PreferenceHelper.getString(PreferenceKeys.FETCH_INSTANCE, PIPED_API_URL)
const val PIPED_API_URL = "https://pipedapi.kavin.rocks"
val authUrl
get() = when (
get() = if (
PreferenceHelper.getBoolean(
PreferenceKeys.AUTH_INSTANCE_TOGGLE,
false
)
) {
true -> PreferenceHelper.getString(
PreferenceHelper.getString(
PreferenceKeys.AUTH_INSTANCE,
PIPED_API_URL
)
false -> apiUrl
} else {
PipedMediaServiceRepository.apiUrl
}
val lazyMgr = resettableManager()
private val kotlinxConverterFactory = JsonHelper.json
val apiLazyMgr = resettableManager()
val kotlinxConverterFactory = JsonHelper.json
.asConverterFactory("application/json".toMediaType())
private val httpClient by lazy { buildClient() }
val httpClient by lazy { buildClient() }
val api by resettableLazy(lazyMgr) {
Retrofit.Builder()
.baseUrl(apiUrl)
.client(httpClient)
.addConverterFactory(kotlinxConverterFactory)
.build()
.create<PipedApi>()
}
val authApi = buildRetrofitInstance<PipedAuthApi>(authUrl)
val authApi by resettableLazy(lazyMgr) {
Retrofit.Builder()
.baseUrl(authUrl)
.client(httpClient)
.addConverterFactory(kotlinxConverterFactory)
.build()
.create<PipedApi>()
}
val externalApi by resettableLazy(lazyMgr) {
Retrofit.Builder()
.baseUrl(apiUrl)
.client(httpClient)
.addConverterFactory(kotlinxConverterFactory)
.build()
.create<ExternalApi>()
}
// the url provided here isn't actually used anywhere in the external api
val externalApi = buildRetrofitInstance<ExternalApi>(PIPED_API_URL)
private fun buildClient(): OkHttpClient {
val httpClient = OkHttpClient().newBuilder()
@ -74,4 +52,11 @@ object RetrofitInstance {
return httpClient.build()
}
inline fun <reified T: Any> buildRetrofitInstance(apiUrl: String): T = Retrofit.Builder()
.baseUrl(apiUrl)
.client(httpClient)
.addConverterFactory(kotlinxConverterFactory)
.build()
.create<T>()
}

View File

@ -85,7 +85,7 @@ fun StreamInfoItem.toStreamItem(
object StreamsExtractor {
suspend fun extractStreams(videoId: String): Streams = withContext(Dispatchers.IO) {
if (!PlayerHelper.disablePipedProxy || !PlayerHelper.localStreamExtraction) {
return@withContext RetrofitInstance.api.getStreams(videoId).deArrow(videoId)
return@withContext MediaServiceRepository.instance.getStreams(videoId).deArrow(videoId)
}
val respAsync = async {

View File

@ -1,5 +1,6 @@
package com.github.libretube.helpers
import com.github.libretube.api.PipedMediaServiceRepository
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.constants.PreferenceKeys
import kotlinx.coroutines.CoroutineScope
@ -11,9 +12,10 @@ object ProxyHelper {
fun fetchProxyUrl() {
CoroutineScope(Dispatchers.IO).launch {
runCatching {
RetrofitInstance.api.getConfig().imageProxyUrl?.let {
PreferenceHelper.putString(PreferenceKeys.IMAGE_PROXY_URL, it)
}
RetrofitInstance.externalApi.getInstanceConfig(PipedMediaServiceRepository.apiUrl)
.imageProxyUrl?.let {
PreferenceHelper.putString(PreferenceKeys.IMAGE_PROXY_URL, it)
}
}
}
}

View File

@ -1,8 +1,8 @@
package com.github.libretube.repo
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.PlaylistsHelper.MAX_CONCURRENT_IMPORT_CALLS
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.StreamsExtractor
import com.github.libretube.api.obj.Playlist
import com.github.libretube.api.obj.Playlists
@ -84,7 +84,7 @@ class LocalPlaylistsRepository: PlaylistRepository {
}
override suspend fun clonePlaylist(playlistId: String): String {
val playlist = RetrofitInstance.api.getPlaylist(playlistId)
val playlist = MediaServiceRepository.instance.getPlaylist(playlistId)
val newPlaylist = createPlaylist(playlist.name ?: "Unknown name")
PlaylistsHelper.addToPlaylist(newPlaylist, *playlist.relatedStreams.toTypedArray())
@ -92,7 +92,7 @@ class LocalPlaylistsRepository: PlaylistRepository {
var nextPage = playlist.nextpage
while (nextPage != null) {
nextPage = runCatching {
RetrofitInstance.api.getPlaylistNextPage(playlistId, nextPage!!).apply {
MediaServiceRepository.instance.getPlaylistNextPage(playlistId, nextPage!!).apply {
PlaylistsHelper.addToPlaylist(newPlaylist, *relatedStreams.toTypedArray())
}.nextpage
}.getOrNull()

View File

@ -12,7 +12,7 @@ import androidx.media3.datasource.DefaultDataSource
import androidx.media3.exoplayer.hls.HlsMediaSource
import com.github.libretube.R
import com.github.libretube.api.JsonHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.StreamsExtractor
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.api.obj.Segment
@ -20,7 +20,6 @@ import com.github.libretube.api.obj.Streams
import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.db.DatabaseHelper
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.enums.PlayerCommand
import com.github.libretube.extensions.parcelable
import com.github.libretube.extensions.setMetadata
@ -206,7 +205,7 @@ open class OnlinePlayerService : AbstractPlayerService() {
private fun fetchSponsorBlockSegments() = scope.launch(Dispatchers.IO) {
runCatching {
if (sponsorBlockConfig.isEmpty()) return@runCatching
sponsorBlockSegments = RetrofitInstance.api.getSegments(
sponsorBlockSegments = MediaServiceRepository.instance.getSegments(
videoId,
JsonHelper.json.encodeToString(sponsorBlockConfig.keys),
"""["skip","mute","full","poi","chapter"]"""

View File

@ -10,8 +10,8 @@ import androidx.lifecycle.LifecycleService
import androidx.lifecycle.lifecycleScope
import com.github.libretube.LibreTubeApp.Companion.PLAYLIST_DOWNLOAD_ENQUEUE_CHANNEL_NAME
import com.github.libretube.R
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.StreamsExtractor
import com.github.libretube.api.obj.PipedStream
import com.github.libretube.api.obj.StreamItem
@ -95,7 +95,7 @@ class PlaylistDownloadEnqueueService : LifecycleService() {
private suspend fun enqueuePublicPlaylist() {
val playlist = try {
RetrofitInstance.api.getPlaylist(playlistId)
MediaServiceRepository.instance.getPlaylist(playlistId)
} catch (e: Exception) {
toastFromMainDispatcher(e.localizedMessage.orEmpty())
stopSelf()
@ -111,7 +111,7 @@ class PlaylistDownloadEnqueueService : LifecycleService() {
while (nextPage != null) {
val playlistPage = runCatching {
RetrofitInstance.api.getPlaylistNextPage(playlistId, nextPage!!)
MediaServiceRepository.instance.getPlaylistNextPage(playlistId, nextPage!!)
}.getOrNull()
if (playlistPage == null && alreadyRetriedOnce) {

View File

@ -6,6 +6,7 @@ import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.github.libretube.R
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.obj.DeArrowBody
import com.github.libretube.api.obj.DeArrowSubmitThumbnail
@ -71,7 +72,7 @@ class SubmitDeArrowDialog: DialogFragment() {
private suspend fun fetchDeArrowData() {
val data = try {
withContext(Dispatchers.IO) {
RetrofitInstance.api.getDeArrowContent(videoId)
MediaServiceRepository.instance.getDeArrowContent(videoId)
}.getOrElse(videoId) { return }
} catch (e: Exception) {
return

View File

@ -10,6 +10,7 @@ import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import com.github.libretube.R
import com.github.libretube.api.JsonHelper
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.obj.Segment
import com.github.libretube.constants.IntentData
@ -146,7 +147,7 @@ class SubmitSegmentDialog : DialogFragment() {
private suspend fun fetchSegments() {
val categories = resources.getStringArray(R.array.sponsorBlockSegments).toList()
segments = try {
RetrofitInstance.api.getSegments(videoId, JsonHelper.json.encodeToString(categories)).segments
MediaServiceRepository.instance.getSegments(videoId, JsonHelper.json.encodeToString(categories)).segments
} catch (e: Exception) {
Log.e(TAG(), e.toString())
return

View File

@ -11,7 +11,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.ChannelTab
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.constants.IntentData
@ -47,7 +47,7 @@ class ChannelContentFragment : DynamicLayoutManagerFragment(R.layout.fragment_ch
private suspend fun fetchChannelNextPage(nextPage: String): String? {
val response = withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannelNextPage(channelId!!, nextPage).apply {
MediaServiceRepository.instance.getChannelNextPage(channelId!!, nextPage).apply {
relatedStreams = relatedStreams.deArrow()
}
}
@ -57,7 +57,7 @@ class ChannelContentFragment : DynamicLayoutManagerFragment(R.layout.fragment_ch
private suspend fun fetchTabNextPage(nextPage: String, tab: ChannelTab): String? {
val newContent = withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannelTab(tab.data, nextPage)
MediaServiceRepository.instance.getChannelTab(tab.data, nextPage)
}.apply {
content = content.deArrow()
}
@ -77,7 +77,7 @@ class ChannelContentFragment : DynamicLayoutManagerFragment(R.layout.fragment_ch
private fun loadChannelTab(tab: ChannelTab) = lifecycleScope.launch {
val response = try {
withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannelTab(tab.data)
MediaServiceRepository.instance.getChannelTab(tab.data)
}.apply {
content = content.deArrow()
}

View File

@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.ChannelTab
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.constants.IntentData
@ -122,9 +122,9 @@ class ChannelFragment : DynamicLayoutManagerFragment(R.layout.fragment_channel)
val response = try {
withContext(Dispatchers.IO) {
if (channelId != null) {
RetrofitInstance.api.getChannel(channelId!!)
MediaServiceRepository.instance.getChannel(channelId!!)
} else {
RetrofitInstance.api.getChannelByName(channelName!!)
MediaServiceRepository.instance.getChannelByName(channelName!!)
}.apply {
relatedStreams = relatedStreams.deArrow()
}

View File

@ -18,8 +18,8 @@ import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.obj.Playlist
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.constants.IntentData
@ -382,7 +382,7 @@ class PlaylistFragment : DynamicLayoutManagerFragment(R.layout.fragment_playlist
val response = try {
withContext(Dispatchers.IO) {
// load locally stored playlists with the auth api
RetrofitInstance.api.getPlaylistNextPage(playlistId, nextPage!!)
MediaServiceRepository.instance.getPlaylistNextPage(playlistId, nextPage!!)
}
} catch (e: Exception) {
context?.toastFromMainDispatcher(e.localizedMessage.orEmpty())

View File

@ -12,7 +12,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.map
import androidx.navigation.fragment.findNavController
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.constants.IntentData
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.databinding.FragmentSearchSuggestionsBinding
@ -102,7 +102,7 @@ class SearchSuggestionsFragment : Fragment(R.layout.fragment_search_suggestions)
lifecycleScope.launch {
val response = try {
withContext(Dispatchers.IO) {
RetrofitInstance.api.getSuggestions(query)
MediaServiceRepository.instance.getSuggestions(query)
}
} catch (e: Exception) {
Log.e(TAG(), e.toString())

View File

@ -4,8 +4,8 @@ import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.api.obj.Playlists
import com.github.libretube.api.obj.StreamItem
@ -78,7 +78,7 @@ class HomeViewModel : ViewModel() {
runSafely(
onSuccess = { videos -> trending.updateIfChanged(videos) },
ioBlock = { RetrofitInstance.api.getTrending(region).deArrow().take(10) }
ioBlock = { MediaServiceRepository.instance.getTrending(region).deArrow().take(10) }
)
}

View File

@ -8,7 +8,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.StreamItem
import com.github.libretube.extensions.TAG
import com.github.libretube.helpers.LocaleHelper
@ -28,7 +28,7 @@ class TrendsViewModel : ViewModel() {
try {
val region = LocaleHelper.getTrendingRegion(context)
val response = withContext(Dispatchers.IO) {
RetrofitInstance.api.getTrending(region).deArrow()
MediaServiceRepository.instance.getTrending(region).deArrow()
}
trendingVideos.postValue(response)
} catch (e: IOException) {

View File

@ -77,7 +77,7 @@ class WelcomeViewModel(
private fun refreshAndNavigate() {
// refresh the api urls since they have changed likely
RetrofitInstance.lazyMgr.reset()
RetrofitInstance.apiLazyMgr.reset()
savedStateHandle[UI_STATE] = _uiState.value.copy(navigateToMain = Unit)
}

View File

@ -2,7 +2,7 @@ package com.github.libretube.ui.models.sources
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.Comment
class CommentPagingSource(
@ -14,8 +14,8 @@ class CommentPagingSource(
override suspend fun load(params: LoadParams<String>): LoadResult<String, Comment> {
return try {
val result = params.key?.let {
RetrofitInstance.api.getCommentsNextPage(videoId, it)
} ?: RetrofitInstance.api.getComments(videoId)
MediaServiceRepository.instance.getCommentsNextPage(videoId, it)
} ?: MediaServiceRepository.instance.getComments(videoId)
if (result.commentCount > 0) onCommentCount(result.commentCount)

View File

@ -2,7 +2,7 @@ package com.github.libretube.ui.models.sources
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.Comment
class CommentRepliesPagingSource(
@ -14,7 +14,7 @@ class CommentRepliesPagingSource(
override suspend fun load(params: LoadParams<String>): LoadResult<String, Comment> {
return try {
val key = params.key.orEmpty().ifEmpty { originalComment.repliesPage.orEmpty() }
val result = RetrofitInstance.api.getCommentsNextPage(videoId, key)
val result = MediaServiceRepository.instance.getCommentsNextPage(videoId, key)
val replies = result.comments.toMutableList()
if (params.key.isNullOrEmpty()) {

View File

@ -2,7 +2,7 @@ package com.github.libretube.ui.models.sources
import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.ContentItem
import com.github.libretube.util.deArrow
@ -15,8 +15,8 @@ class SearchPagingSource(
override suspend fun load(params: LoadParams<String>): LoadResult<String, ContentItem> {
return try {
val result = params.key?.let {
RetrofitInstance.api.getSearchResultsNextPage(searchQuery, searchFilter, it)
} ?: RetrofitInstance.api.getSearchResults(searchQuery, searchFilter)
MediaServiceRepository.instance.getSearchResultsNextPage(searchQuery, searchFilter, it)
} ?: MediaServiceRepository.instance.getSearchResults(searchQuery, searchFilter)
LoadResult.Page(result.items.deArrow(), null, result.nextpage)
} catch (e: Exception) {
LoadResult.Error(e)

View File

@ -11,6 +11,7 @@ import androidx.preference.SwitchPreferenceCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R
import com.github.libretube.api.InstanceRepository
import com.github.libretube.api.PipedMediaServiceRepository
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.obj.PipedInstance
import com.github.libretube.constants.IntentData
@ -68,13 +69,13 @@ class InstanceSettings : BasePreferenceFragment() {
}
authInstance.setOnPreferenceChangeListener { _, _ ->
RetrofitInstance.lazyMgr.reset()
RetrofitInstance.apiLazyMgr.reset()
logoutAndUpdateUI()
true
}
authInstanceToggle.setOnPreferenceChangeListener { _, _ ->
RetrofitInstance.lazyMgr.reset()
RetrofitInstance.apiLazyMgr.reset()
logoutAndUpdateUI()
true
}
@ -147,7 +148,7 @@ class InstanceSettings : BasePreferenceFragment() {
// add the currently used instances to the list if they're currently down / not part
// of the public instances list
for (apiUrl in listOf(RetrofitInstance.apiUrl, RetrofitInstance.authUrl)) {
for (apiUrl in listOf(PipedMediaServiceRepository.apiUrl, RetrofitInstance.authUrl)) {
if (instances.none { it.apiUrl == apiUrl }) {
val origin = apiUrl.toHttpUrl().host
instances.add(PipedInstance(origin, apiUrl, isCurrentlyDown = true))
@ -215,7 +216,7 @@ class InstanceSettings : BasePreferenceFragment() {
if (!authInstanceToggle.isChecked) {
logoutAndUpdateUI()
}
RetrofitInstance.lazyMgr.reset()
RetrofitInstance.apiLazyMgr.reset()
ActivityCompat.recreate(requireActivity())
}

View File

@ -4,7 +4,7 @@ import android.os.Bundle
import android.util.Log
import androidx.core.os.bundleOf
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.constants.IntentData
import com.github.libretube.enums.ShareObjectType
import com.github.libretube.extensions.TAG
@ -66,7 +66,7 @@ class ChannelOptionsBottomSheet : BaseBottomSheet() {
R.string.play_latest_videos -> {
try {
val channel = withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannel(channelId)
MediaServiceRepository.instance.getChannel(channelId)
}
channel.relatedStreams.firstOrNull()?.url?.toID()?.let {
NavigationHelper.navigateVideo(
@ -83,7 +83,7 @@ class ChannelOptionsBottomSheet : BaseBottomSheet() {
R.string.playOnBackground -> {
try {
val channel = withContext(Dispatchers.IO) {
RetrofitInstance.api.getChannel(channelId)
MediaServiceRepository.instance.getChannel(channelId)
}
channel.relatedStreams.firstOrNull()?.url?.toID()?.let {
BackgroundHelper.playOnBackground(

View File

@ -3,8 +3,8 @@ package com.github.libretube.ui.sheets
import android.os.Bundle
import androidx.core.os.bundleOf
import com.github.libretube.R
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.constants.IntentData
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.enums.ImportFormat
@ -176,7 +176,7 @@ class PlaylistOptionsBottomSheet : BaseBottomSheet() {
DatabaseHolder.Database.playlistBookmarkDao().deleteById(playlistId)
} else {
val bookmark = try {
RetrofitInstance.api.getPlaylist(playlistId)
MediaServiceRepository.instance.getPlaylist(playlistId)
} catch (e: Exception) {
return@withContext
}.toPlaylistBookmark(playlistId)

View File

@ -1,7 +1,7 @@
package com.github.libretube.util
import android.util.Log
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.obj.ContentItem
import com.github.libretube.api.obj.DeArrowContent
import com.github.libretube.api.obj.StreamItem
@ -26,7 +26,7 @@ object DeArrowUtil {
val videoIdsString = videoIds.mapTo(TreeSet()) { it }.joinToString(",")
return try {
RetrofitInstance.api.getDeArrowContent(videoIdsString)
MediaServiceRepository.instance.getDeArrowContent(videoIdsString)
} catch (e: Exception) {
Log.e(this::class.java.name, "Failed to fetch DeArrow content: ${e.message}")
null

View File

@ -1,6 +1,7 @@
package com.github.libretube.util
import androidx.media3.common.Player
import com.github.libretube.api.MediaServiceRepository
import com.github.libretube.api.PlaylistsHelper
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.StreamsExtractor
@ -158,7 +159,7 @@ object PlayingQueue {
) {
var playlistNextPage = nextPage
while (playlistNextPage != null) {
RetrofitInstance.api.getPlaylistNextPage(playlistId, playlistNextPage).run {
MediaServiceRepository.instance.getPlaylistNextPage(playlistId, playlistNextPage).run {
addToQueueAsync(relatedStreams, isMainList = isMainList)
playlistNextPage = this.nextpage
}
@ -177,7 +178,7 @@ object PlayingQueue {
var channelNextPage = nextPage
var pageIndex = 1
while (channelNextPage != null && pageIndex < 10) {
RetrofitInstance.api.getChannelNextPage(channelId, channelNextPage).run {
MediaServiceRepository.instance.getChannelNextPage(channelId, channelNextPage).run {
addToQueueAsync(relatedStreams)
channelNextPage = this.nextpage
pageIndex++
@ -186,7 +187,7 @@ object PlayingQueue {
}
private fun insertChannel(channelId: String, newCurrentStream: StreamItem) = runCatchingIO {
val channel = RetrofitInstance.api.getChannel(channelId)
val channel = MediaServiceRepository.instance.getChannel(channelId)
addToQueueAsync(channel.relatedStreams, newCurrentStream)
if (channel.nextpage == null) return@runCatchingIO
fetchMoreFromChannel(channelId, channel.nextpage)