Skip to content

Instantly share code, notes, and snippets.

View diousk's full-sized avatar

David diousk

  • Taipei
View GitHub Profile
@diousk
diousk / Paginator.kt
Created August 20, 2025 05:00
compose paginator
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
Here’s a step-by-step plan to improve your in-app navigation result system for Jetpack Compose, focusing on robustness, type safety, and simplicity—without over-engineering.
1. Plan
1. Type Safety:
▫ Avoid unchecked casts by associating result types with result keys.
▫ Use a sealed class or inline class for result keys to prevent accidental collisions.
2. Result Delivery:
▫ Ensure results are delivered only once.
▫ Handle the case where a result is set but no callback is registered (e.g., after process death).
3. API Simplicity:
@diousk
diousk / offset.md
Created December 12, 2024 16:08 — forked from hexcowboy/offset.md
Twitch Helix API - Get Video/VOD Offset and Comments from Clip ID

Since Twitch decomissioned API V5, there's no correct way to get the VOD offset for a clip. So I just inspected what the Twitch web app was doing and came up with a super cool hack.

I know this looks really complicated but really it just does two things. First it gets the clip information from the official API, then it uses Twitch GraphQL API to get the offset.

kimne78kx3ncx6brgo4mv6wki5h1ko is the Client ID that the Twitch web app uses. It can be used to access Twitch's GraphQL API (undocumented & not for public use). The postData variable contains a request and a sha256Hash. The sha256Hash is basically a job ID and may change in the future, but I added the current hash which should work for all clips as of posting this.

const clientId = "" // Put your Twitch Client ID here
const clientSecret = "" // Put your Twitch Client Secret here
@Singleton
class SessionManager @Inject constructor(
private val sessionComponentFactory: SessionComponent.Factory
) {
var sessionComponent: SessionComponent? = null
private set
fun isUserLoggedIn() = sessionComponent != null
fun logout() {
class SettingActivity : DaggerSessionActivity() {
@Inject
lateinit var sessionManager: SessionManager
@Inject
lateinit var sessionPrefs: SessionPrefs
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_setting)
class MainActivity : DaggerSessionActivity() {
@Inject
lateinit var sessionPrefs: SessionPrefs
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Timber.d("main sessionPrefs = $sessionPrefs")
class LoginActivity : DaggerAppCompatActivity() {
@Inject lateinit var sessionManager: SessionManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
Timber.d("sessionManager = $sessionManager")
goMain.setOnClickListener {
abstract class DaggerSessionActivity : AppCompatActivity(), HasAndroidInjector {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any>
override fun onCreate(savedInstanceState: Bundle?) {
val sessionManager = (application as App).appComponent.sessionManager()
sessionManager.sessionComponent?.injector()?.inject(this)
super.onCreate(savedInstanceState)
}
@SessionScope
@Subcomponent(modules = [SessionActivityBuilder::class, SessionModule::class])
interface SessionComponent {
@Subcomponent.Factory
interface Factory {
fun create(): SessionComponent
}
fun injector(): DispatchingAndroidInjector<Any>
}
@Module
abstract class ActivityBuilder {
 @ContributesAndroidInjector
 abstract fun bindLoginActivity(): LoginActivity
}
@Module(subcomponents = [SessionComponent::class])
abstract class AppSubcomponents