File Item
Uygulamanın aldığı bir dosya, bir satırda: ikonu, adı, boyutu ya da onunla ilgili neyin yanlış gittiği, ne kadarının gönderildiği ve onu kaldıran düğme. Satırlar bir PantrixFileDrop'un altında, her biri uygulamanın tuttuğu bir dosya için durur.
import com.pantrixui.components.elements.filedrop.PantrixFileItem
- Basmak her yerde çalışır. Bölgeye basmak (ya da odaktayken Enter veya Boşluk) platformun seçicisini açar: Android'de belgeler, iOS'ta Dosyalar, masaüstünde sistemin penceresi, web'de tarayıcınınki. Yalnızca görsel alınıyorsa Android ve iOS fotoğraf seçicisini açar. Hiçbiri izin istemez.
- Bırakmak işaretçinin işidir. Masaüstünde ve web'de dosyalar bölgenin üstüne sürüklenip bırakılır; Android'de ve iPad'de yandaki bir uygulamadan da. Sürüklerken bölge birincil rolün rengine döner ve "Eklemek için bırakın" der. Yazısı da buna göredir: masaüstünde ve web'de önce bırakmayı, telefonda önce seçmeyi söyler.
- Eleme.
acceptalınan türleri,maxSizeen büyük boyutu,multiplebirden fazla dosyayı belirler. Uymayan dosyalar nedenleriyle (tür, boyut, sayı)onRejected'a gider, gerisionFiles'a; ne söyleneceği uygulamanındır. - Bölge durum tutmaz. Alınan dosyaları uygulama tutar ve bölgenin altına
PantrixFileItemsatırları olarak dizer: ad (uzunsa ortası kısaltılır), dile göre boyut, kaldırma düğmesi, isteğe bağlı ilerleme ve hata. - Okumak.
PantrixFileadını, boyutunu ve türünü taşır; baytlarınıreadBytes()istendiğinde okur. Platformun kendi dosyası da oradadır: Android'deuri, iOS'taurl, masaüstündefile, web'dedomFile. - Platform. Bölge telefonda 140dp, masaüstünde ve web'de 120dp yüksekliğindedir; satırlar telefonda 56dp, işaretçinin altında 44dp.
Örnekler
Ekler: türler, boyut ve satırlar
Bir formun ekleri: PDF ya da görsel, birden fazla, her biri en çok 10 MB. Alınan her dosya bir satır olur ve gönderiliyormuş gibi dolan bir çubuk alır; kaldırma düğmesi satırı siler. Alınmayanlar nedenleriyle yardım metninde yazılır.
val attachments = remember { mutableStateListOf<PantrixFile>() }
val sent = remember { mutableStateMapOf<PantrixFile, Float>() }
var refused by remember { mutableStateOf(emptyList<RejectedFile>()) }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixFileDrop(
onFiles = { files ->
attachments += files
refused = emptyList()
},
accept = listOf(PantrixFileType.Pdf, PantrixFileType.Images),
multiple = true,
maxSize = TEN_MEGABYTES,
onRejected = { refused = it },
supportingText = if (refused.isEmpty()) "PDF ya da görsel, her biri en çok 10 MB" else reasonOf(refused),
error = refused.isNotEmpty(),
tagKey = "attachments"
)
attachments.forEach { file ->
key(file) {
SendingLater(file, sent)
PantrixFileItem(
name = file.name,
size = file.size,
onRemove = {
attachments -= file
sent -= file
},
progress = sent[file]?.takeIf { it < 1f },
tagKey = file.name
)
}
}
}
@Composable
private fun SendingLater(
file: PantrixFile,
sent: MutableMap<PantrixFile, Float>
) {
LaunchedEffect(file) {
if (file in sent) return@LaunchedEffect
repeat(STEPS + 1) { step ->
sent[file] = step / STEPS.toFloat()
delay(STEP_MILLIS)
}
}
}
private fun reasonOf(refused: List<RejectedFile>): String = refused.groupBy { it.reason }.entries.joinToString(" · ") {
val names = it.value.joinToString { rejected -> rejected.file.name }
when (it.key) {
FileRejection.Type -> "Bu tür alınmıyor: $names"
FileRejection.Size -> "Çok büyük: $names"
FileRejection.Count -> "Yalnızca bir dosya alınır: $names"
}
}
private const val TEN_MEGABYTES = 10_000_000L
private const val STEPS = 10
private const val STEP_MILLIS = 150L
Tek bir görsel ve ret nedeni
Tek bir görsel, en çok 2 MB: bir profil resmi. Telefonda fotoğraf seçicisi açılır. Seçilen resim okunur ve gösterilir; daha büyüğü ya da görsel olmayan bir dosya reddedilir ve nedeni bölgenin altında hata olarak yazılır.
var avatar by remember { mutableStateOf<PantrixFile?>(null) }
var refused by remember { mutableStateOf<RejectedFile?>(null) }
var picture by remember { mutableStateOf<ImageBitmap?>(null) }
LaunchedEffect(avatar) {
// Baytlar ancak istenince okunur: burada, bölgenin işi bittikten sonra.
picture = avatar?.let { file -> runCatching { file.readBytes().decodeToImageBitmap() }.getOrNull() }
}
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.sm)) {
PantrixFileDrop(
onFiles = { files ->
avatar = files.single()
refused = null
},
accept = listOf(PantrixFileType.Images),
maxSize = TWO_MEGABYTES,
onRejected = { refused = it.first() },
label = "Profil resmi seçin",
supportingText = refused?.let { reasonOf(listOf(it)) } ?: "PNG, JPEG ya da WebP, en çok 2 MB",
error = refused != null,
tagKey = "avatar"
)
picture?.let {
PantrixImage(bitmap = it, contentDescription = "Seçilen resim", modifier = Modifier.size(PICTURE_SIZE))
}
avatar?.let { PantrixFileItem(name = it.name, size = it.size, onRemove = { avatar = null }, tagKey = "avatar") }
}
private fun reasonOf(refused: List<RejectedFile>): String = refused.groupBy { it.reason }.entries.joinToString(" · ") {
val names = it.value.joinToString { rejected -> rejected.file.name }
when (it.key) {
FileRejection.Type -> "Bu tür alınmıyor: $names"
FileRejection.Size -> "Çok büyük: $names"
FileRejection.Count -> "Yalnızca bir dosya alınır: $names"
}
}
private val PICTURE_SIZE = 96.dp
private const val TWO_MEGABYTES = 2_000_000L
Kendi stiliyle alçak bir alan ve sık satırlar
Kendi stiliyle: FileDropStyle bırakma alanının yüksekliğini, kesik çizgisini ve köşesini, FileItemStyle dosya satırının yüksekliğini ve ilerleme çizgisini verir. Verilmeyen her alan platformun ön ayarıdır.
val files = remember { mutableStateListOf<PantrixFile>() }
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.xs)) {
PantrixFileDrop(
onFiles = { files += it },
multiple = true,
style = FileDropStyle(minHeight = 72.dp, shape = ShapeRole.Large, dashLength = 4.dp, dashGap = 4.dp),
tagKey = "low"
)
files.forEach { file ->
key(file) {
PantrixFileItem(
name = file.name,
size = file.size,
onRemove = { files -= file },
style = FileItemStyle(minHeight = 40.dp, verticalPadding = 4.dp, progressHeight = 2.dp),
tagKey = file.name
)
}
}
}
API
name
Uygulamanın aldığı bir dosya, bir satırda: ikonu, adı, boyutu ya da onunla ilgili neyin yanlış gittiği, ne kadarının gönderildiği ve onu kaldıran düğme. Satırlar bir PantrixFileDrop'un altında, her biri uygulamanın tuttuğu bir dosya için durur.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
name | String | dosyanın adı. | |
modifier | Modifier | Modifier | satırın modifier'ı. Satır kendisine verilen genişliği doldurur. |
size | Long? | null | dosyanın kaç bayt olduğu ya da hiçbir şey söylememek için null. |
onRemove | (() -> Unit)? | null | kaldırma düğmesinin yaptığı ya da düğmesiz bir satır için null. |
progress | Float? | null | dosyanın ne kadarının gönderildiği, sıfırdan bire, ya da çubuk olmaması için null. |
error | String? | null | dosyayla ilgili neyin yanlış gittiği, boyutunun yerinde, ya da null. |
icon | ImageVector | PantrixIcons.File | adın önünde duran: varsayılan olarak bir dosya. |
enabled | Boolean | true | kaldırma düğmesine basılıp basılamayacağı. Basılamayan satır soluk çizilir. |
style | FileItemStyle? | null | Bu çağrının kendi stili: çevresindeki her stili ezer, yoğunluk ona da uygulanır. Yalnızca verdiği alanlar değişir ve her platformda değişir. |
tagKey | String? | null | satırın otomasyon anahtarı: FileItem_<tagKey> olur, düğmesininki de onun içinde IconButton_remove. Yalnızca anahtar verildiğinde etiketlenir. |
FileItemStyle
PantrixFileItem'ın geometrisi: uygulamanın aldığı bir dosya için ikonu, adı ve boyutu ve onu kaldıran düğmesiyle bir satır.
| Parametre | Tür | Varsayılan | Ne olduğu |
|---|---|---|---|
shape | ShapeSpec | ShapeSpec.Unspecified | Satırın köşeleri. |
minHeight | Dp | Dp.Unspecified | Satırın en az yüksekliği. Daha büyük bir yazı, bir ilerleme çubuğu ya da bir hata onu yükseltir. |
horizontalPadding | Dp | Dp.Unspecified | Satırın yanları ile tuttukları arasındaki boşluk. |
verticalPadding | Dp | Dp.Unspecified | Tuttuklarının üstündeki ve altındaki boşluk. |
borderWidth | Dp | Dp.Unspecified | Satırın kenarının kalınlığı. |
iconSize | Dp | Dp.Unspecified | Dosyanın ikonunun genişliği ve yüksekliği. |
gap | Dp | Dp.Unspecified | İkon, sözler ve düğme arasında; sözler ile ilerleme çubuğu arasında. |
progressHeight | Dp | Dp.Unspecified | Sözlerin altındaki ilerleme çubuğunun yüksekliği. |
Erişilebilirlik
- Ekran okuyucu. Bütün bölge tek bir düğmedir. Kaç dosya alındığı ve kaç dosyanın alınmadığı kibarca duyurulur;
errorile yardım metni hata olarak okunur.