Clarify avatar editor ownership and UI publication state
This commit is contained in:
1 parent
977992e834
commit
81f36d15c8
3 files changed
+23
-3
No files matched your search
@@ -24,7 +24,10 @@ import com.utun.chat.ChatApplication
|
||||
import com.utun.chat.R
|
||||
import com.utun.chat.ui.screens.AvatarViewerScreen
|
||||
|
||||
/** Короткое нажатие открывает просмотр; удержание можно передать меню содержащей строки. */
|
||||
/** Круглое превью участника из app-scoped AvatarRepository с инициалами до загрузки.
|
||||
* group=null ищет ссылку owner среди доступных групп; revision запускает повторную проверку кеша.
|
||||
* Короткое нажатие открывает галерею оригиналов, удержание передаётся onLongClick; enabled выключает оба жеста.
|
||||
* profile=true показывает локальный профиль текущего аккаунта и отключает жесты независимо от enabled. */
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun UserAvatar(group: String?, owner: Long, name: String, modifier: Modifier = Modifier,
|
||||
@@ -41,6 +44,7 @@ fun UserAvatar(group: String?, owner: Long, name: String, modifier: Modifier = M
|
||||
if (viewing) AvatarViewerScreen(group,owner,name,onClose={ viewing=false })
|
||||
}
|
||||
|
||||
/** Превью отдельного аватара группы, подгружаемое через ensureGroup; клики задаёт содержащий компонент. */
|
||||
@Composable
|
||||
fun GroupAvatar(group: String, name: String, modifier: Modifier = Modifier, size: Dp = 44.dp) {
|
||||
val repository = ChatApplication.instance.avatars
|
||||
@@ -49,6 +53,7 @@ fun GroupAvatar(group: String, name: String, modifier: Modifier = Modifier, size
|
||||
AvatarImage(repository.groupBitmap(group), name, modifier, size)
|
||||
}
|
||||
|
||||
/** Круглый crop Bitmap либо инициалы первых двух слов name; при пустом имени — "#". Bitmap не изменяется. */
|
||||
@Composable
|
||||
private fun AvatarImage(bitmap: Bitmap?, name: String, modifier: Modifier, size: Dp) {
|
||||
Box(modifier.size(size).clip(CircleShape).background(MaterialTheme.colorScheme.secondaryContainer),
|
||||
|
||||
+8
-1
@@ -39,7 +39,14 @@ import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/** Фото перемещается под круглой рамкой аватара. Подтверждение передаёт владение исходным файлом репозиторию. */
|
||||
/**
|
||||
* Редактор пользовательского аватара: копирует URI в cacheDir на IO worker, учитывает EXIF,
|
||||
* принимает JPEG/PNG/WebP до 32 МиБ и 16×1024×1024 пикселей. Для экрана декодирует уменьшенную копию.
|
||||
* Сдвиг и zoom 1..16 выбирают квадрат полного ориентированного оригинала; круг — только маска просмотра.
|
||||
* onConfirm получает временный File и нормализованный AvatarCrop и принимает обязанность удалить файл
|
||||
* (ProfileAvatarControls передаёт его в AvatarRepository.editProfile). После подтверждения диалог его не удаляет.
|
||||
* onCancel должен убрать диалог из композиции: при dispose неподтверждённая копия удаляется на IO worker.
|
||||
*/
|
||||
@Composable
|
||||
fun AvatarCropDialog(uri: Uri, onCancel: () -> Unit, onConfirm: (File, AvatarCrop) -> Unit) {
|
||||
val context=LocalContext.current
|
||||
|
||||
+9
-1
@@ -15,7 +15,11 @@ import com.utun.chat.R
|
||||
import com.utun.chat.data.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** Один диалог для меню списка и кнопки в шапке группового чата. */
|
||||
/** Свойства CHAT-группы: отдельный аватар группы и локальный звук уведомлений.
|
||||
* При открытии обновляет снимок; canEdit показывает кнопки публикации, окончательный допуск проверяет core.
|
||||
* Выбранный URI передаётся в editGroup без crop-диалога: репозиторий берёт центральный квадрат.
|
||||
* Account/group фиксируются до picker, изменения применяются сразу и продолжаются после закрытия диалога.
|
||||
*/
|
||||
@Composable
|
||||
fun GroupPropertiesDialog(channel: Channel, onDismiss: () -> Unit) {
|
||||
val repository = ChatApplication.instance.avatars
|
||||
@@ -71,6 +75,10 @@ fun GroupPropertiesDialog(channel: Channel, onDismiss: () -> Unit) {
|
||||
confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(R.string.close)) } })
|
||||
}
|
||||
|
||||
/** Настройки локального профиля: выбор подписанного хранителя, crop-редактор и снятие аватара.
|
||||
* Список хранителей не требует online; account/server фиксируются до запуска picker.
|
||||
* Временный файл редактора передаётся во владение editProfile. SAVED подтверждает локальное намерение;
|
||||
* файлы и ссылки публикуются репозиторием отдельно в подходящих группах, без ожидания в этом UI. */
|
||||
@Composable
|
||||
fun ProfileAvatarControls() {
|
||||
val repository = ChatApplication.instance.avatars
|
||||
|
||||
Reference in new issue
Block a user