Pith - shim
package com.vgmlr.shim

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.DialogWindowProvider

private const val TAG_TOP = 30
private const val CLOUD_MIN = 15f
private const val CLOUD_MAX = 18f
private const val CLOUD_NUM_SCALE = 0.6f
private const val CLOUD_NUM_ALPHA = 0.5f
private val CLOUD_GAP_H = 12.dp
private val CLOUD_GAP_V = 2.dp

@OptIn(ExperimentalLayoutApi::class)
@Composable
fun TagsDialog(
    tagSets: List<String>,
    onDismiss: () -> Unit,
    onTagClick: (String) -> Unit
) {
    val counts = remember(tagSets) {
        tagSets.flatMap { set -> set.split(" ").filter { it.isNotBlank() } }
            .groupingBy { it }
            .eachCount()
    }
    val cloud = remember(counts) {
        val top = counts.entries
            .sortedWith(compareByDescending<Map.Entry<String, Int>> { it.value }.thenBy { it.key })
            .take(TAG_TOP)
        val hi = top.firstOrNull()?.value ?: 0
        val lo = top.lastOrNull()?.value ?: 0
        top.map { e ->
            val t = if (hi == lo) 0.5f else (e.value - lo).toFloat() / (hi - lo)
            Triple(e.key, e.value, CLOUD_MIN + (CLOUD_MAX - CLOUD_MIN) * t)
        }.sortedBy { it.first }
    }
    val ink = colorResource(id = R.color.dialog_color)

    Dialog(
        onDismissRequest = onDismiss,
        properties = DialogProperties(usePlatformDefaultWidth = false)
    ) {
        (LocalView.current.parent as? DialogWindowProvider)?.window?.setDimAmount(0.8f)
        Surface(
            modifier = Modifier
                .padding(horizontal = 40.dp)
                .fillMaxWidth(),
            shape = RoundedCornerShape(ROUND_END),
            color = colorResource(id = R.color.dialog_bg_color),
            border = EDGE
        ) {
            FlowRow(
                modifier = Modifier.padding(horizontal = 26.dp, vertical = 24.dp),
                horizontalArrangement = Arrangement.spacedBy(CLOUD_GAP_H, Alignment.CenterHorizontally),
                verticalArrangement = Arrangement.spacedBy(CLOUD_GAP_V)
            ) {
                cloud.forEach { (tag, count, size) ->
                    Row(
                        modifier = Modifier
                            .align(Alignment.CenterVertically)
                            .clickable { onTagClick(tag); onDismiss() }
                    ) {
                        Text(
                            tag,
                            color = ink,
                            fontSize = size.sp,
                            maxLines = 1,
                            modifier = Modifier.alignByBaseline()
                        )
                        if (count > 1) {
                            Text(
                                " $count",
                                color = ink.copy(alpha = CLOUD_NUM_ALPHA),
                                fontSize = (size * CLOUD_NUM_SCALE).sp,
                                fontFamily = FontFamily.Monospace,
                                maxLines = 1,
                                modifier = Modifier.alignByBaseline()
                            )
                        }
                    }
                }
            }
        }
    }
}