diff --git a/app/src/main/java/com/pr0gramm/app/Services.kt b/app/src/main/java/com/pr0gramm/app/Services.kt index 3c1e23622..74533eb93 100644 --- a/app/src/main/java/com/pr0gramm/app/Services.kt +++ b/app/src/main/java/com/pr0gramm/app/Services.kt @@ -202,7 +202,7 @@ fun appInjector(app: Application) = Module.build { bind() with eagerSingleton { SyncSiteSettingsService(instance()) } bind() with singleton { AdminService(instance(), instance()) } - bind() with singleton { AdService(instance(), instance()) } + bind() with singleton { AdService(instance(), instance(), instance()) } bind() with singleton { ContactService(instance()) } bind() with singleton { DownloadService(instance(), instance(), instance()) } bind() with singleton { FeedServiceImpl(instance(), instance(), instance()) } diff --git a/app/src/main/java/com/pr0gramm/app/services/NavigationProvider.kt b/app/src/main/java/com/pr0gramm/app/services/NavigationProvider.kt index 3c46e2c92..a486c72f3 100644 --- a/app/src/main/java/com/pr0gramm/app/services/NavigationProvider.kt +++ b/app/src/main/java/com/pr0gramm/app/services/NavigationProvider.kt @@ -6,19 +6,35 @@ import android.graphics.drawable.Drawable import android.net.Uri import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources -import com.pr0gramm.app.* +import com.pr0gramm.app.Logger +import com.pr0gramm.app.R +import com.pr0gramm.app.Settings import com.pr0gramm.app.api.pr0gramm.Api +import com.pr0gramm.app.delay import com.pr0gramm.app.feed.FeedFilter import com.pr0gramm.app.feed.FeedType import com.pr0gramm.app.model.bookmark.Bookmark import com.pr0gramm.app.model.config.Config import com.pr0gramm.app.model.user.LoginState import com.pr0gramm.app.orm.asFeedFilter +import com.pr0gramm.app.seconds import com.pr0gramm.app.services.config.ConfigService +import com.pr0gramm.app.ui.AdService import com.pr0gramm.app.util.getColorCompat import com.squareup.picasso.Picasso import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.retry +import kotlinx.coroutines.flow.retryWhen import kotlinx.coroutines.runInterruptible const val BLACK: Int = 0x80000000.toInt() @@ -32,7 +48,9 @@ class NavigationProvider( private val bookmarkService: BookmarkService, private val configService: ConfigService, private val singleShotService: SingleShotService, - private val picasso: Picasso) { + private val adService: AdService, + private val picasso: Picasso +) { private val logger = Logger("NavigationProvider") @@ -73,26 +91,27 @@ class NavigationProvider( val items = loginStates.flatMapLatest { loginState -> val rawSources = listOf( - remoteConfigItems(loginState, upper = true), + remoteConfigItems(loginState, upper = true), - ageVerificationItem(loginState), + ageVerificationItem(loginState), - currentSelection.map { selection -> - categoryNavigationItems(selection, loginState.name) - }, + currentSelection.map { selection -> + categoryNavigationItems(selection, loginState.name) + }, - remoteConfigItems(loginState, upper = false), + remoteConfigItems(loginState, upper = false), - inboxService.unreadMessagesCount() - .map { listOf(inboxNavigationItem(it)) }, + inboxService.unreadMessagesCount() + .map { listOf(inboxNavigationItem(it)) }, - flowOf(listOf(uploadNavigationItem)), + flowOf(listOf(uploadNavigationItem)), - bookmarkService.observe().combine(currentSelection) { bookmarks, selection -> - bookmarksToNavItem(selection, bookmarks) - }, + bookmarkService.observe().combine(currentSelection) { bookmarks, selection -> + bookmarksToNavItem(selection, bookmarks) + }, - flowOf(footerItems(loginState))) + flowOf(footerItems(loginState)) + ) val sources = rawSources.map { source -> source.onStart { emit(listOf()) }.retryWhen { err, _ -> @@ -133,7 +152,9 @@ class NavigationProvider( items += staticItemFAQ if (!loginState.authorized || !loginState.premium) { - items += staticItemPremium + if (adService.isSideloaded()) { + items += staticItemPremium + } } if (loginState.authorized) { @@ -153,45 +174,53 @@ class NavigationProvider( * Adds the default "fixed" items to the menu */ private fun categoryNavigationItems(selection: FeedFilter?, username: String?): List { - fun makeItem(title: String, icon: Drawable, filter: FeedFilter, action: ActionType = ActionType.FILTER) = NavigationItem( - action = action, title = title, icon = icon, filter = filter, isSelected = filter == selection) + fun makeItem(title: String, icon: Drawable, filter: FeedFilter, action: ActionType = ActionType.FILTER) = + NavigationItem( + action = action, title = title, icon = icon, filter = filter, isSelected = filter == selection + ) val items = mutableListOf() items += makeItem( - title = getString(R.string.action_feed_type_promoted), - icon = iconFeedTypePromoted, - filter = FeedFilter().withFeedType(FeedType.PROMOTED)) + title = getString(R.string.action_feed_type_promoted), + icon = iconFeedTypePromoted, + filter = FeedFilter().withFeedType(FeedType.PROMOTED) + ) items += makeItem( - title = getString(R.string.action_feed_type_new), - icon = iconFeedTypeNew, - filter = FeedFilter().withFeedType(FeedType.NEW)) + title = getString(R.string.action_feed_type_new), + icon = iconFeedTypeNew, + filter = FeedFilter().withFeedType(FeedType.NEW) + ) items += makeItem( - title = getString(R.string.action_feed_type_bestof), - icon = iconFeedTypeBestOf, - filter = FeedFilter().withFeedType(FeedType.BESTOF)) + title = getString(R.string.action_feed_type_bestof), + icon = iconFeedTypeBestOf, + filter = FeedFilter().withFeedType(FeedType.BESTOF) + ) if (Settings.showCategoryControversial) { items += makeItem( - title = getString(R.string.action_feed_type_controversial), - icon = iconFeedTypeControversial, - filter = FeedFilter().withFeedType(FeedType.CONTROVERSIAL)) + title = getString(R.string.action_feed_type_controversial), + icon = iconFeedTypeControversial, + filter = FeedFilter().withFeedType(FeedType.CONTROVERSIAL) + ) } if (Settings.showCategoryRandom) { items += makeItem( - title = getString(R.string.action_feed_type_random), - icon = iconFeedTypeRandom, - filter = FeedFilter().withFeedType(FeedType.RANDOM)) + title = getString(R.string.action_feed_type_random), + icon = iconFeedTypeRandom, + filter = FeedFilter().withFeedType(FeedType.RANDOM) + ) } if (Settings.showCategoryStalk) { items += makeItem( - title = getString(R.string.action_feed_type_premium), - icon = iconFeedTypePremium, - filter = FeedFilter().withFeedType(FeedType.STALK)) + title = getString(R.string.action_feed_type_premium), + icon = iconFeedTypePremium, + filter = FeedFilter().withFeedType(FeedType.STALK) + ) } if (username != null) { @@ -213,11 +242,12 @@ class NavigationProvider( */ private fun inboxNavigationItem(unreadCounts: Api.InboxCounts): NavigationItem { return NavigationItem( - action = ActionType.MESSAGES, - title = getString(R.string.action_inbox), - icon = iconInbox, - layout = R.layout.left_drawer_nav_item_inbox, - unreadCount = unreadCounts) + action = ActionType.MESSAGES, + title = getString(R.string.action_inbox), + icon = iconInbox, + layout = R.layout.left_drawer_nav_item_inbox, + unreadCount = unreadCounts + ) } private fun bookmarksToNavItem(currentSelection: FeedFilter?, bookmarks: List): List { @@ -241,10 +271,11 @@ class NavigationProvider( val isSelected = filter == currentSelection || filterInverse == currentSelection NavigationItem( - action = ActionType.BOOKMARK, layout = layoutId, - title = title, icon = icon, bookmark = entry, - filter = filter, filterInverse = filterInverse, - isSelected = isSelected) + action = ActionType.BOOKMARK, layout = layoutId, + title = title, icon = icon, bookmark = entry, + filter = filter, filterInverse = filterInverse, + isSelected = isSelected + ) } val actionKey = "hint:bookmark-hold-to-delete:2" @@ -252,14 +283,14 @@ class NavigationProvider( val hintNotYetShown = singleShotService.isFirstTime(actionKey) if (items.isNotEmpty() && bookmarkService.canEdit && hintNotYetShown) { val hint = NavigationItem( - action = ActionType.HINT, - title = getString(R.string.bookmark_hint_delete), - icon = null, - layout = R.layout.left_drawer_nav_item_hint, - customAction = { - singleShotService.markAsDoneOnce(actionKey) - refreshAfterNavItemWasDeletedStateFlow.value = true - }) + action = ActionType.HINT, + title = getString(R.string.bookmark_hint_delete), + icon = null, + layout = R.layout.left_drawer_nav_item_hint, + customAction = { + singleShotService.markAsDoneOnce(actionKey) + refreshAfterNavItemWasDeletedStateFlow.value = true + }) items.add(0, hint) } @@ -276,9 +307,10 @@ class NavigationProvider( */ private val uploadNavigationItem: NavigationItem by lazy(LazyThreadSafetyMode.PUBLICATION) { NavigationItem( - action = ActionType.UPLOAD, - title = getString(R.string.action_upload), - icon = iconUpload) + action = ActionType.UPLOAD, + title = getString(R.string.action_upload), + icon = iconUpload + ) } /** @@ -338,9 +370,9 @@ class NavigationProvider( // we want some alarm color val color = context.getColorCompat(R.color.red_700) staticItem( - ActionType.AGE_VERIFICATION, iconAgeVerify, - getString(R.string.action_age_verification), - colorOverride = color, + ActionType.AGE_VERIFICATION, iconAgeVerify, + getString(R.string.action_age_verification), + colorOverride = color, ) } @@ -361,9 +393,9 @@ class NavigationProvider( private fun remoteConfigItems(loginState: LoginState, upper: Boolean): Flow> { return configService.observeConfig() - .map { config -> config.specialMenuItems } - .distinctUntilChanged() - .flatMapLatest { item -> resolveRemoteConfigItems(loginState, upper, item) } + .map { config -> config.specialMenuItems } + .distinctUntilChanged() + .flatMapLatest { item -> resolveRemoteConfigItems(loginState, upper, item) } } @@ -372,8 +404,9 @@ class NavigationProvider( * if there is one. */ private fun resolveRemoteConfigItems( - loginState: LoginState, upper: Boolean, - items: List): Flow> { + loginState: LoginState, upper: Boolean, + items: List + ): Flow> { val images = flow { val itemsToLoad = items.filterNot { item -> @@ -385,15 +418,16 @@ class NavigationProvider( logger.debug { "Loading item $item" } val bitmap = picasso.load(Uri.parse(item.icon)) - .noPlaceholder() - .resize(iconUpload.intrinsicWidth, iconUpload.intrinsicHeight) - .get() + .noPlaceholder() + .resize(iconUpload.intrinsicWidth, iconUpload.intrinsicHeight) + .get() logger.info { "Loaded image for $item" } val icon = BitmapDrawable(context.resources, bitmap) val uri = Uri.parse(item.link) - val layout = if (item.noHighlight) R.layout.left_drawer_nav_item else R.layout.left_drawer_nav_item_special + val layout = + if (item.noHighlight) R.layout.left_drawer_nav_item else R.layout.left_drawer_nav_item_special NavigationItem(ActionType.URI, item.name, icon, uri = uri, layout = layout) } } @@ -406,18 +440,20 @@ class NavigationProvider( } } - class NavigationItem(val action: ActionType, - val title: CharSequence? = null, - val icon: Drawable? = null, - val layout: Int = R.layout.left_drawer_nav_item, - val filter: FeedFilter? = null, - val filterInverse: FeedFilter? = null, - val bookmark: Bookmark? = null, - val unreadCount: Api.InboxCounts = Api.InboxCounts(), - val customAction: () -> Unit = {}, - val uri: Uri? = null, - val isSelected: Boolean = false, - val colorOverride: Int? = null) { + class NavigationItem( + val action: ActionType, + val title: CharSequence? = null, + val icon: Drawable? = null, + val layout: Int = R.layout.left_drawer_nav_item, + val filter: FeedFilter? = null, + val filterInverse: FeedFilter? = null, + val bookmark: Bookmark? = null, + val unreadCount: Api.InboxCounts = Api.InboxCounts(), + val customAction: () -> Unit = {}, + val uri: Uri? = null, + val isSelected: Boolean = false, + val colorOverride: Int? = null + ) { private val hashCode by lazy(LazyThreadSafetyMode.PUBLICATION) { listOf(action, title, layout, filter, bookmark, unreadCount, uri, isSelected).hashCode() diff --git a/app/src/main/java/com/pr0gramm/app/ui/AdService.kt b/app/src/main/java/com/pr0gramm/app/ui/AdService.kt index 9b6ddcb24..96b3b6a87 100644 --- a/app/src/main/java/com/pr0gramm/app/ui/AdService.kt +++ b/app/src/main/java/com/pr0gramm/app/ui/AdService.kt @@ -1,5 +1,6 @@ package com.pr0gramm.app.ui +import android.app.Application import android.content.Context import com.google.android.gms.ads.AdListener import com.google.android.gms.ads.AdRequest @@ -12,6 +13,7 @@ import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback import com.pr0gramm.app.BuildConfig import com.pr0gramm.app.Duration import com.pr0gramm.app.Instant +import com.pr0gramm.app.Logger import com.pr0gramm.app.Settings import com.pr0gramm.app.model.config.Config import com.pr0gramm.app.services.Track @@ -34,7 +36,13 @@ import java.util.concurrent.TimeUnit * Utility methods for ads. */ -class AdService(private val configService: ConfigService, private val userService: UserService) { +class AdService( + private val appContext: Application, + private val configService: ConfigService, + private val userService: UserService, +) { + + private val logger = Logger("AdService") private var lastInterstitialAdShown: Instant? = null /** @@ -70,7 +78,7 @@ class AdService(private val configService: ConfigService, private val userServic } } - fun enabledForTypeNow(type: Config.AdType): Boolean { + private fun enabledForTypeNow(type: Config.AdType): Boolean { if (Settings.alwaysShowAds) { // If the user opted in to ads, we always show the feed ad. return type == Config.AdType.FEED @@ -89,8 +97,8 @@ class AdService(private val configService: ConfigService, private val userServic fun enabledForType(type: Config.AdType): Flow { return userService.loginStates - .map { enabledForTypeNow(type) } - .distinctUntilChanged() + .map { enabledForTypeNow(type) } + .distinctUntilChanged() } fun shouldShowInterstitialAd(): Boolean { @@ -121,15 +129,19 @@ class AdService(private val configService: ConfigService, private val userServic return if (enabledForTypeNow(Config.AdType.FEED_TO_POST_INTERSTITIAL)) { val value = CompletableDeferred() - InterstitialAd.load(context, interstitialUnitId, AdRequest.Builder().build(), object : InterstitialAdLoadCallback() { - override fun onAdLoaded(p0: InterstitialAd) { - value.complete(p0) - } + InterstitialAd.load( + context, + interstitialUnitId, + AdRequest.Builder().build(), + object : InterstitialAdLoadCallback() { + override fun onAdLoaded(p0: InterstitialAd) { + value.complete(p0) + } - override fun onAdFailedToLoad(p0: LoadAdError) { - value.complete(null) - } - }) + override fun onAdFailedToLoad(p0: LoadAdError) { + value.complete(null) + } + }) Holder { value.await() } } else { @@ -137,6 +149,24 @@ class AdService(private val configService: ConfigService, private val userServic } } + fun isSideloaded(): Boolean { + try { + val name = appContext + .packageManager + .getInstallerPackageName(BuildConfig.APPLICATION_ID) + + logger.info { "Installer package is '$name'" } + + return name.isNullOrBlank() || name == "com.android.packageinstaller" + + } catch (err: Exception) { + logger.warn(err) { "Failed to query for installer package" } + + // hm. better be safe and assume not sideloaded + return false + } + } + companion object { private val interstitialUnitId: String = if (BuildConfig.DEBUG) { "ca-app-pub-3940256099942544/1033173712" diff --git a/app/src/main/java/com/pr0gramm/app/ui/fragments/AdViewHolder.kt b/app/src/main/java/com/pr0gramm/app/ui/fragments/AdViewHolder.kt index d7f017a24..6944a4c8c 100644 --- a/app/src/main/java/com/pr0gramm/app/ui/fragments/AdViewHolder.kt +++ b/app/src/main/java/com/pr0gramm/app/ui/fragments/AdViewHolder.kt @@ -24,7 +24,7 @@ import com.pr0gramm.app.util.trace import kotlin.math.roundToInt class AdViewHolder private constructor(val adView: AdView, itemView: View) : - RecyclerView.ViewHolder(itemView) { + RecyclerView.ViewHolder(itemView) { companion object { private val logger = Logger("AdViewHolder") @@ -34,20 +34,27 @@ class AdViewHolder private constructor(val adView: AdView, itemView: View) : val container = FrameLayout(context).apply { layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT) + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) } trace { "newPlaceholderView" } val placeholder = ImageView(context).apply { layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - context.dp(70f).roundToInt()) + ViewGroup.LayoutParams.MATCH_PARENT, + context.dp(70f).roundToInt() + ) scaleType = ImageView.ScaleType.CENTER_CROP - setImageDrawable(VectorDrawableCompat.create( - resources, R.drawable.pr0mium_ad, null)) + if (context.injector.instance().isSideloaded()) { + setImageDrawable( + VectorDrawableCompat.create( + resources, R.drawable.pr0mium_ad, null + ) + ) + } setOnClickListener { BrowserHelper.openCustomTab(context, Uri.parse("https://pr0gramm.com/pr0mium")) diff --git a/app/src/main/java/com/pr0gramm/app/ui/fragments/DrawerFragment.kt b/app/src/main/java/com/pr0gramm/app/ui/fragments/DrawerFragment.kt index 685f0edc4..be6bfec1a 100644 --- a/app/src/main/java/com/pr0gramm/app/ui/fragments/DrawerFragment.kt +++ b/app/src/main/java/com/pr0gramm/app/ui/fragments/DrawerFragment.kt @@ -86,18 +86,26 @@ class DrawerFragment : BaseFragment("DrawerFragment", R.layout.left_drawer) { val inboxService = instance() val configService = instance() val singleShotService = instance() + val adService = instance() logger.time("Create navigation provider") { - NavigationProvider(requireActivity(), userService, inboxService, - bookmarkService, configService, singleShotService, picasso) + NavigationProvider( + requireActivity(), userService, inboxService, + bookmarkService, configService, singleShotService, adService, + picasso, + ) } } val rxNavItems = provider.navigationItems(currentSelection) - .flowOn(Dispatchers.Default) - .onStart { emit(listOf()) } - - val elements = combine(userService.loginStateWithBenisGraph, rxNavItems, userClassesService.onChange) { state, navItems, _ -> + .flowOn(Dispatchers.Default) + .onStart { emit(listOf()) } + + val elements = combine( + userService.loginStateWithBenisGraph, + rxNavItems, + userClassesService.onChange + ) { state, navItems, _ -> buildList { val userClass = userClassesService.get(state.loginState.mark) add(TitleInfo(state.loginState.name, userClass)) @@ -159,12 +167,48 @@ class DrawerFragment : BaseFragment("DrawerFragment", R.layout.left_drawer) { init { val viewContext = requireView().context - delegates += NavigationDelegateAdapter(viewContext, requireActivity(), doIfAuthorizedHelper, callbacks, R.layout.left_drawer_nav_item) - delegates += NavigationDelegateAdapter(viewContext, requireActivity(), doIfAuthorizedHelper, callbacks, R.layout.left_drawer_nav_item_hint) - delegates += NavigationDelegateAdapter(viewContext, requireActivity(), doIfAuthorizedHelper, callbacks, R.layout.left_drawer_nav_item_inbox) - delegates += NavigationDelegateAdapter(viewContext, requireActivity(), doIfAuthorizedHelper, callbacks, R.layout.left_drawer_nav_item_trending) - delegates += NavigationDelegateAdapter(viewContext, requireActivity(), doIfAuthorizedHelper, callbacks, R.layout.left_drawer_nav_item_divider) - delegates += NavigationDelegateAdapter(viewContext, requireActivity(), doIfAuthorizedHelper, callbacks, R.layout.left_drawer_nav_item_special) + delegates += NavigationDelegateAdapter( + viewContext, + requireActivity(), + doIfAuthorizedHelper, + callbacks, + R.layout.left_drawer_nav_item + ) + delegates += NavigationDelegateAdapter( + viewContext, + requireActivity(), + doIfAuthorizedHelper, + callbacks, + R.layout.left_drawer_nav_item_hint + ) + delegates += NavigationDelegateAdapter( + viewContext, + requireActivity(), + doIfAuthorizedHelper, + callbacks, + R.layout.left_drawer_nav_item_inbox + ) + delegates += NavigationDelegateAdapter( + viewContext, + requireActivity(), + doIfAuthorizedHelper, + callbacks, + R.layout.left_drawer_nav_item_trending + ) + delegates += NavigationDelegateAdapter( + viewContext, + requireActivity(), + doIfAuthorizedHelper, + callbacks, + R.layout.left_drawer_nav_item_divider + ) + delegates += NavigationDelegateAdapter( + viewContext, + requireActivity(), + doIfAuthorizedHelper, + callbacks, + R.layout.left_drawer_nav_item_special + ) delegates += TitleDelegateAdapter(callbacks) delegates += BenisGraphDelegateAdapter(callbacks) @@ -182,12 +226,16 @@ class DrawerFragment : BaseFragment("DrawerFragment", R.layout.left_drawer) { return@postDelayed val lm = views.drawerNavList.layoutManager as? LinearLayoutManager - ?: return@postDelayed + ?: return@postDelayed - lm.startSmoothScroll(OverscrollLinearSmoothScroller(context, idx, + lm.startSmoothScroll( + OverscrollLinearSmoothScroller( + context, idx, dontScrollIfVisible = true, offsetTop = AndroidUtility.getActionBarContentOffset(context) + context.dp(32), - offsetBottom = context.dp(32))) + offsetBottom = context.dp(32) + ) + ) } } } @@ -202,11 +250,12 @@ private class NavigationItemViewHolder(itemView: View) : RecyclerView.ViewHolder } private class NavigationDelegateAdapter( - viewContext: Context, - private val activity: FragmentActivity, - private val doIfAuthorizedHelper: LoginActivity.DoIfAuthorizedHelper, - private val callback: DrawerFragment.Callbacks, - @LayoutRes private val layoutId: Int) + viewContext: Context, + private val activity: FragmentActivity, + private val doIfAuthorizedHelper: LoginActivity.DoIfAuthorizedHelper, + private val callback: DrawerFragment.Callbacks, + @LayoutRes private val layoutId: Int +) : ItemAdapterDelegate(), InjectorAware { @@ -218,10 +267,11 @@ private class NavigationDelegateAdapter( private val markedColor: ColorStateList init { - viewContext.obtainStyledAttributes(intArrayOf(R.attr.colorAccent, android.R.attr.textColorPrimary)).use { result -> - markedColor = ColorStateList.valueOf(result.getColor(result.getIndex(0), 0)) - defaultColor = ColorStateList.valueOf(result.getColor(result.getIndex(1), 0)) - } + viewContext.obtainStyledAttributes(intArrayOf(R.attr.colorAccent, android.R.attr.textColorPrimary)) + .use { result -> + markedColor = ColorStateList.valueOf(result.getColor(result.getIndex(0), 0)) + defaultColor = ColorStateList.valueOf(result.getColor(result.getIndex(1), 0)) + } } override fun isForViewType(value: Any): Boolean { @@ -455,8 +505,8 @@ private class NavigationDelegateAdapter( data class TitleInfo(val name: String?, val userClass: UserClassesService.UserClass) -private class TitleDelegateAdapter(private val callbacks: DrawerFragment.Callbacks) - : ListItemTypeAdapterDelegate(TitleInfo::class) { +private class TitleDelegateAdapter(private val callbacks: DrawerFragment.Callbacks) : + ListItemTypeAdapterDelegate(TitleInfo::class) { override fun onCreateViewHolder(parent: ViewGroup): TitleViewHolder { return TitleViewHolder(parent.inflateDetachedChild(R.layout.left_drawer_nav_title)) @@ -491,8 +541,8 @@ private class TitleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView data class BenisInfo(val score: Int, val graph: Graph?) -private class BenisGraphDelegateAdapter(private val callbacks: DrawerFragment.Callbacks) - : ListItemTypeAdapterDelegate(BenisInfo::class) { +private class BenisGraphDelegateAdapter(private val callbacks: DrawerFragment.Callbacks) : + ListItemTypeAdapterDelegate(BenisInfo::class) { override fun onCreateViewHolder(parent: ViewGroup): BenisGraphViewHolder { return BenisGraphViewHolder(parent.inflateDetachedChild(R.layout.left_drawer_nav_benis)) @@ -538,10 +588,12 @@ private class BenisGraphViewHolder(itemView: View) : RecyclerView.ViewHolder(ite private object Spacer -private object SpacerAdapterDelegate : ListItemTypeAdapterDelegate(Spacer::class) { +private object SpacerAdapterDelegate : + ListItemTypeAdapterDelegate(Spacer::class) { override fun onCreateViewHolder(parent: ViewGroup): RecyclerView.ViewHolder { return object : RecyclerView.ViewHolder( - parent.inflateDetachedChild(R.layout.left_drawer_nav_spacer)) {} + parent.inflateDetachedChild(R.layout.left_drawer_nav_spacer) + ) {} } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, value: Spacer) {