Replace deprecated bundleOf() usages

This commit is contained in:
Niels van Velzen authored and Niels van Velzen committed 2026-06-04 22:45:29 +02:00
1 parent 2939d64e59
commit 82284c9d6c
9 files changed
+119 -109

No files matched your search

@@ -9,19 +9,19 @@ import android.util.AttributeSet
import android.widget.FrameLayout
import androidx.core.os.BundleCompat
import androidx.core.os.ParcelCompat
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import org.jellyfin.androidtv.R
import org.jellyfin.androidtv.ui.navigation.NavigationAction
import org.jellyfin.androidtv.util.createBundle
import timber.log.Timber
import java.util.Stack
private class HistoryEntry(
val name: Class<out Fragment>,
val arguments: Bundle = bundleOf(),
val arguments: Bundle = createBundle(),
var fragment: Fragment? = null,
var savedState: Fragment.SavedState? = null,
@@ -169,10 +169,10 @@ class DestinationFragmentView @JvmOverloads constructor(
saveCurrentFragmentState()
// Save state
return bundleOf(
BUNDLE_SUPER to super.onSaveInstanceState(),
BUNDLE_HISTORY to ArrayList(history),
)
return createBundle {
putParcelable(BUNDLE_SUPER, super.onSaveInstanceState())
putParcelableArrayList(BUNDLE_HISTORY, ArrayList(history))
}
}
override fun onRestoreInstanceState(state: Parcelable?) {
@@ -2,17 +2,17 @@ package org.jellyfin.androidtv.ui.navigation
import android.content.Context
import android.content.Intent
import androidx.core.os.bundleOf
import org.jellyfin.androidtv.ui.playback.ExternalPlayerActivity
import org.jellyfin.androidtv.ui.startup.StartupActivity
import org.jellyfin.androidtv.util.createBundle
import kotlin.time.Duration
object ActivityDestinations {
fun externalPlayer(context: Context, position: Duration = Duration.ZERO) = Intent(context, ExternalPlayerActivity::class.java).apply {
putExtras(
bundleOf(
ExternalPlayerActivity.EXTRA_POSITION to position.inWholeMilliseconds
)
createBundle {
putLong(ExternalPlayerActivity.EXTRA_POSITION, position.inWholeMilliseconds)
}
)
}
@@ -1,20 +1,20 @@
package org.jellyfin.androidtv.ui.navigation
import android.os.Bundle
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import org.jellyfin.androidtv.util.createBundle
import kotlin.reflect.KClass
sealed interface Destination {
data class Fragment(
val fragment: KClass<out androidx.fragment.app.Fragment>,
val arguments: Bundle = bundleOf(),
val arguments: Bundle = createBundle(),
) : Destination
}
inline fun <reified T : Fragment> fragmentDestination(
vararg arguments: Pair<String, Any?>,
noinline arguments: (Bundle.() -> Unit)? = null,
) = Destination.Fragment(
fragment = T::class,
arguments = bundleOf(*arguments),
arguments = createBundle(arguments),
)
@@ -33,86 +33,88 @@ import java.util.UUID
object Destinations {
// General
val home = fragmentDestination<HomeFragment>()
fun search(query: String? = null) = fragmentDestination<SearchFragment>(
SearchFragment.EXTRA_QUERY to query,
)
fun search(query: String? = null) = fragmentDestination<SearchFragment> {
putString(SearchFragment.EXTRA_QUERY, query)
}
// Browsing
// TODO only pass item id instead of complete JSON to browsing destinations
fun libraryBrowser(item: BaseItemDto, includeType: String? = null) =
fragmentDestination<BrowseGridFragment>(
Extras.Folder to Json.encodeToString(item),
Extras.IncludeType to includeType,
)
fragmentDestination<BrowseGridFragment> {
putString(Extras.Folder, Json.encodeToString(item))
putString(Extras.IncludeType, includeType)
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun librarySmartScreen(item: BaseItemDto) = fragmentDestination<BrowseViewFragment>(
Extras.Folder to Json.encodeToString(item),
)
fun librarySmartScreen(item: BaseItemDto) = fragmentDestination<BrowseViewFragment> {
putString(Extras.Folder, Json.encodeToString(item))
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun collectionBrowser(item: BaseItemDto) = fragmentDestination<CollectionFragment>(
Extras.Folder to Json.encodeToString(item),
)
fun collectionBrowser(item: BaseItemDto) = fragmentDestination<CollectionFragment> {
putString(Extras.Folder, Json.encodeToString(item))
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun folderBrowser(item: BaseItemDto) = fragmentDestination<GenericFolderFragment>(
Extras.Folder to Json.encodeToString(item),
)
fun folderBrowser(item: BaseItemDto) = fragmentDestination<GenericFolderFragment> {
putString(Extras.Folder, Json.encodeToString(item))
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun libraryByGenres(item: BaseItemDto, includeType: String) =
fragmentDestination<ByGenreFragment>(
Extras.Folder to Json.encodeToString(item),
Extras.IncludeType to includeType,
)
fragmentDestination<ByGenreFragment> {
putString(Extras.Folder, Json.encodeToString(item))
putString(Extras.IncludeType, includeType)
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun libraryByLetter(item: BaseItemDto, includeType: String) =
fragmentDestination<ByLetterFragment>(
Extras.Folder to Json.encodeToString(item),
Extras.IncludeType to includeType,
)
fragmentDestination<ByLetterFragment> {
putString(Extras.Folder, Json.encodeToString(item))
putString(Extras.IncludeType, includeType)
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun librarySuggestions(item: BaseItemDto) =
fragmentDestination<SuggestedMoviesFragment>(
Extras.Folder to Json.encodeToString(item),
)
fragmentDestination<SuggestedMoviesFragment> {
putString(Extras.Folder, Json.encodeToString(item))
}
// Item details
fun itemDetails(item: UUID) = fragmentDestination<FullDetailsFragment>(
"ItemId" to item.toString(),
)
fun itemDetails(item: UUID) = fragmentDestination<FullDetailsFragment> {
putString("ItemId", item.toString())
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun channelDetails(item: UUID, channel: UUID, programInfo: BaseItemDto) =
fragmentDestination<FullDetailsFragment>(
"ItemId" to item.toString(),
"ChannelId" to channel.toString(),
"ProgramInfo" to Json.encodeToString(programInfo),
)
fragmentDestination<FullDetailsFragment> {
putString("ItemId", item.toString())
putString("ChannelId", channel.toString())
putString("ProgramInfo", Json.encodeToString(programInfo))
}
// TODO only pass item id instead of complete JSON to browsing destinations
fun seriesTimerDetails(item: UUID, seriesTimer: SeriesTimerInfoDto) =
fragmentDestination<FullDetailsFragment>(
"ItemId" to item.toString(),
"SeriesTimer" to Json.encodeToString(seriesTimer),
)
fragmentDestination<FullDetailsFragment> {
putString("ItemId", item.toString())
putString("SeriesTimer", Json.encodeToString(seriesTimer))
}
fun itemList(item: UUID) = fragmentDestination<ItemListFragment>(
"ItemId" to item.toString(),
)
fun itemList(item: UUID) = fragmentDestination<ItemListFragment> {
putString("ItemId", item.toString())
}
fun musicFavorites(parent: UUID) = fragmentDestination<MusicFavoritesListFragment>(
"ParentId" to parent.toString(),
)
fun musicFavorites(parent: UUID) = fragmentDestination<MusicFavoritesListFragment> {
putString("ParentId", parent.toString())
}
// Live TV
val liveTvGuide = fragmentDestination<LiveTvGuideFragment>()
val liveTvSchedule = fragmentDestination<BrowseScheduleFragment>()
val liveTvRecordings = fragmentDestination<BrowseRecordingsFragment>()
val liveTvSeriesRecordings = fragmentDestination<BrowseViewFragment>(Extras.IsLiveTvSeriesRecordings to true)
val liveTvSeriesRecordings = fragmentDestination<BrowseViewFragment> {
putBoolean(Extras.IsLiveTvSeriesRecordings, true)
}
// Playback
val nowPlaying = fragmentDestination<AudioNowPlayingFragment>()
@@ -122,26 +124,26 @@ object Destinations {
autoPlay: Boolean,
albumSortBy: ItemSortBy?,
albumSortOrder: SortOrder?,
) = fragmentDestination<PhotoPlayerFragment>(
PhotoPlayerFragment.ARGUMENT_ITEM_ID to item.toString(),
PhotoPlayerFragment.ARGUMENT_ALBUM_SORT_BY to albumSortBy?.serialName,
PhotoPlayerFragment.ARGUMENT_ALBUM_SORT_ORDER to albumSortOrder?.serialName,
PhotoPlayerFragment.ARGUMENT_AUTO_PLAY to autoPlay,
)
) = fragmentDestination<PhotoPlayerFragment> {
putString(PhotoPlayerFragment.ARGUMENT_ITEM_ID, item.toString())
putString(PhotoPlayerFragment.ARGUMENT_ALBUM_SORT_BY, albumSortBy?.serialName)
putString(PhotoPlayerFragment.ARGUMENT_ALBUM_SORT_ORDER, albumSortOrder?.serialName)
putBoolean(PhotoPlayerFragment.ARGUMENT_AUTO_PLAY, autoPlay)
}
fun videoPlayer(position: Int?) = fragmentDestination<CustomPlaybackOverlayFragment>(
"Position" to (position ?: 0)
)
fun videoPlayer(position: Int?) = fragmentDestination<CustomPlaybackOverlayFragment> {
putInt("Position", position ?: 0)
}
fun videoPlayerNew(position: Int?) = fragmentDestination<VideoPlayerFragment>(
VideoPlayerFragment.EXTRA_POSITION to position
)
fun videoPlayerNew(position: Int?) = fragmentDestination<VideoPlayerFragment> {
putInt(VideoPlayerFragment.EXTRA_POSITION, position ?: 0)
}
fun nextUp(item: UUID) = fragmentDestination<NextUpFragment>(
NextUpFragment.ARGUMENT_ITEM_ID to item.toString()
)
fun nextUp(item: UUID) = fragmentDestination<NextUpFragment> {
putString(NextUpFragment.ARGUMENT_ITEM_ID, item.toString())
}
fun stillWatching(item: UUID) = fragmentDestination<StillWatchingFragment>(
NextUpFragment.ARGUMENT_ITEM_ID to item.toString()
)
fun stillWatching(item: UUID) = fragmentDestination<StillWatchingFragment> {
putString(NextUpFragment.ARGUMENT_ITEM_ID, item.toString())
}
}
@@ -6,7 +6,6 @@ import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.add
@@ -41,6 +40,7 @@ import org.jellyfin.androidtv.ui.startup.fragment.ServerFragment
import org.jellyfin.androidtv.ui.startup.fragment.SplashFragment
import org.jellyfin.androidtv.ui.startup.fragment.StartupToolbarFragment
import org.jellyfin.androidtv.util.applyTheme
import org.jellyfin.androidtv.util.createBundle
import org.jellyfin.sdk.api.client.ApiClient
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
@@ -185,9 +185,9 @@ class StartupActivity : FragmentActivity() {
private fun showServer(id: UUID) = supportFragmentManager.commit {
replace<StartupToolbarFragment>(R.id.content_view)
add<ServerFragment>(
R.id.content_view, null, bundleOf(
ServerFragment.ARG_SERVER_ID to id.toString()
)
R.id.content_view, null, createBundle {
putString(ServerFragment.ARG_SERVER_ID, id.toString())
}
)
}
@@ -17,7 +17,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.unit.dp
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.add
@@ -46,6 +45,7 @@ import org.jellyfin.androidtv.ui.base.Text
import org.jellyfin.androidtv.ui.startup.StartupViewModel
import org.jellyfin.androidtv.util.ListAdapter
import org.jellyfin.androidtv.util.MenuBuilder
import org.jellyfin.androidtv.util.createBundle
import org.jellyfin.androidtv.util.getSummary
import org.koin.androidx.viewmodel.ext.android.activityViewModel
import org.koin.compose.koinInject
@@ -73,9 +73,9 @@ class SelectServerFragment : Fragment() {
add<ServerFragment>(
R.id.content_view,
null,
bundleOf(
ServerFragment.ARG_SERVER_ID to server.id.toString()
)
createBundle {
putString(ServerFragment.ARG_SERVER_ID, server.id.toString())
}
)
addToBackStack(null)
}
@@ -102,9 +102,9 @@ class SelectServerFragment : Fragment() {
add<ServerFragment>(
R.id.content_view,
null,
bundleOf(
ServerFragment.ARG_SERVER_ID to state.id.toString()
)
createBundle {
putString(ServerFragment.ARG_SERVER_ID, state.id.toString())
}
)
}
} else {
@@ -115,12 +115,16 @@ class SelectServerFragment : Fragment() {
// Show error as toast
if (state is UnableToConnectState) {
Toast.makeText(requireContext(), getString(
R.string.server_connection_failed_candidates,
state.addressCandidates
.map { "${it.key} ${it.value.getSummary(requireContext())}" }
.joinToString(prefix = "\n", separator = "\n")
), Toast.LENGTH_LONG).show()
Toast.makeText(
requireContext(),
getString(
R.string.server_connection_failed_candidates,
state.addressCandidates
.map { "${it.key} ${it.value.getSummary(requireContext())}" }
.joinToString(prefix = "\n", separator = "\n")
),
Toast.LENGTH_LONG,
).show()
}
}
}.launchIn(lifecycleScope)
@@ -5,7 +5,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import androidx.fragment.app.add
import androidx.fragment.app.commit
@@ -19,6 +18,7 @@ import org.jellyfin.androidtv.auth.model.ConnectingState
import org.jellyfin.androidtv.auth.model.UnableToConnectState
import org.jellyfin.androidtv.databinding.FragmentServerAddBinding
import org.jellyfin.androidtv.ui.startup.ServerAddViewModel
import org.jellyfin.androidtv.util.createBundle
import org.jellyfin.androidtv.util.getSummary
import org.koin.androidx.viewmodel.ext.android.viewModel
@@ -96,9 +96,9 @@ class ServerAddFragment : Fragment() {
add<ServerFragment>(
R.id.content_view,
null,
bundleOf(
ServerFragment.ARG_SERVER_ID to state.id.toString()
)
createBundle {
putString(ServerFragment.ARG_SERVER_ID, state.id.toString())
}
)
}
@@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
@@ -41,6 +40,7 @@ import org.jellyfin.androidtv.ui.card.UserCardView
import org.jellyfin.androidtv.ui.startup.StartupViewModel
import org.jellyfin.androidtv.util.ListAdapter
import org.jellyfin.androidtv.util.MarkdownRenderer
import org.jellyfin.androidtv.util.createBundle
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.activityViewModel
@@ -78,10 +78,10 @@ class ServerFragment : Fragment() {
AuthenticatingState -> Unit
AuthenticatedState -> Unit
// Actions
RequireSignInState -> navigateFragment<UserLoginFragment>(bundleOf(
UserLoginFragment.ARG_SERVER_ID to server.id.toString(),
UserLoginFragment.ARG_USERNAME to user.name,
))
RequireSignInState -> navigateFragment<UserLoginFragment>(createBundle {
putString(UserLoginFragment.ARG_SERVER_ID, server.id.toString())
putString(UserLoginFragment.ARG_USERNAME, user.name)
})
// Errors
ServerUnavailableState,
is ApiClientErrorLoginState -> Toast.makeText(context, R.string.server_connection_failed, Toast.LENGTH_LONG).show()
@@ -142,10 +142,10 @@ class ServerFragment : Fragment() {
binding.addUserButton.setOnClickListener {
navigateFragment<UserLoginFragment>(
args = bundleOf(
UserLoginFragment.ARG_SERVER_ID to server.id.toString(),
UserLoginFragment.ARG_USERNAME to null
)
args = createBundle {
putString(UserLoginFragment.ARG_SERVER_ID, server.id.toString())
putString(UserLoginFragment.ARG_USERNAME, null)
}
)
}
@@ -169,7 +169,7 @@ class ServerFragment : Fragment() {
}
private inline fun <reified F : Fragment> navigateFragment(
args: Bundle = bundleOf(),
args: Bundle = createBundle(),
keepToolbar: Boolean = false,
keepHistory: Boolean = true,
) {
@@ -8,3 +8,7 @@ inline fun <reified T> Bundle.getValue(key: String): T? = when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelable(key, T::class.java)
else -> get(key) as T?
}
fun createBundle(init: (Bundle.() -> Unit)? = null) = Bundle().also { bundle ->
if (init != null) bundle.init()
}