UI: polish UI for ModelsManagementScreen; inject ModelsManagementVieModel

This commit is contained in:
Han Yin 2025-04-14 12:55:26 -07:00
parent 6e82bb37d3
commit eebc05b559
4 changed files with 336 additions and 122 deletions

View File

@ -73,6 +73,7 @@ fun StorageAppScaffold(
storageTotal: Float, storageTotal: Float,
onNavigateBack: (() -> Unit)? = null, onNavigateBack: (() -> Unit)? = null,
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }, snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
bottomBar: @Composable () -> Unit = {},
content: @Composable (PaddingValues) -> Unit content: @Composable (PaddingValues) -> Unit
) { ) {
Scaffold( Scaffold(
@ -87,6 +88,7 @@ fun StorageAppScaffold(
snackbarHost = { snackbarHost = {
SnackbarHost(hostState = snackbarHostState) SnackbarHost(hostState = snackbarHostState)
}, },
bottomBar = bottomBar,
content = content content = content
) )
} }

View File

@ -1,5 +1,6 @@
package com.example.llama.revamp.ui.screens package com.example.llama.revamp.ui.screens
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@ -7,35 +8,52 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Sort
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ClearAll
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.DeleteSweep
import androidx.compose.material.icons.filled.FilterAlt
import androidx.compose.material.icons.filled.FolderOpen
import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.SelectAll
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.example.llama.revamp.data.model.ModelInfo import com.example.llama.revamp.data.model.ModelInfo
import com.example.llama.revamp.ui.components.StorageAppScaffold import com.example.llama.revamp.ui.components.StorageAppScaffold
import com.example.llama.revamp.viewmodel.ModelSortOrder
import com.example.llama.revamp.viewmodel.ModelsManagementViewModel
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import com.example.llama.R
/** /**
* Screen for managing LLM models (view, download, delete) * Screen for managing LLM models (view, download, delete)
@ -43,132 +61,317 @@ import java.util.Locale
@Composable @Composable
fun ModelsManagementScreen( fun ModelsManagementScreen(
onBackPressed: () -> Unit, onBackPressed: () -> Unit,
viewModel: ModelsManagementViewModel = hiltViewModel()
) { ) {
// For demo purposes, we'll use sample models // For demo purposes, we'll use sample models
val installedModels = remember { ModelInfo.getSampleModels() } val models by viewModel.availableModels.collectAsState()
val storageMetrics by viewModel.storageMetrics.collectAsState()
// Edit mode for models' batch deletion // UI states
var isEditMode by remember { mutableStateOf(false) } var isMultiSelectionMode by remember { mutableStateOf(false) }
val selectedModels = remember { mutableStateMapOf<String, ModelInfo>() }
var showSortMenu by remember { mutableStateOf(false) }
var showAddModelMenu by remember { mutableStateOf(false) }
// Calculate storage info val exitSelectionMode = {
val storageUsed = 14.6f // This would be calculated from actual models isMultiSelectionMode = false
val storageTotal = 32.0f // This would be from device storage info selectedModels.clear()
}
StorageAppScaffold( StorageAppScaffold(
title = "Models Management", title = "Models Management",
storageUsed = storageUsed, storageUsed = storageMetrics.usedGB,
storageTotal = storageTotal, storageTotal = storageMetrics.totalGB,
onNavigateBack = onBackPressed, onNavigateBack = onBackPressed,
) { paddingValues -> bottomBar = {
Column( BottomAppBar(
modifier = Modifier actions = {
.fillMaxSize() if (isMultiSelectionMode) {
.padding(paddingValues) // Multi-selection mode actions
.padding(16.dp) IconButton(onClick = {
) { // Select all
// Summary card selectedModels.putAll(models.map { it.id to it })
Card( }) {
modifier = Modifier Icon(
.fillMaxWidth() imageVector = Icons.Default.SelectAll,
.padding(bottom = 16.dp) contentDescription = "Select all"
) {
Column(
modifier = Modifier.padding(16.dp)
) {
Text(
text = "Models Storage",
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(8.dp))
Row(
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "Storage Used: 14.6GB / 32GB",
style = MaterialTheme.typography.bodyMedium
)
Spacer(modifier = Modifier.height(4.dp))
LinearProgressIndicator(
progress = { 0.45f },
modifier = Modifier.fillMaxWidth()
) )
} }
OutlinedButton( IconButton(onClick = {
onClick = { /* Download new model */ }, // Deselect all
modifier = Modifier.padding(start = 16.dp) selectedModels.clear()
}) {
Icon(
imageVector = Icons.Default.ClearAll,
contentDescription = "Deselect all"
)
}
IconButton(
onClick = {
// Delete selected
if (selectedModels.isNotEmpty()) {
viewModel.deleteModels(selectedModels)
exitSelectionMode()
}
},
enabled = selectedModels.isNotEmpty()
) { ) {
Text("Add Model") Icon(
imageVector = Icons.Default.Delete,
contentDescription = "Delete selected",
tint = if (selectedModels.isNotEmpty())
MaterialTheme.colorScheme.error
else
MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.38f)
)
}
} else {
// Default mode actions
IconButton(onClick = { showSortMenu = true }) {
Icon(
imageVector = Icons.AutoMirrored.Filled.Sort,
contentDescription = "Sort models"
)
}
// Sort dropdown menu
DropdownMenu(
expanded = showSortMenu,
onDismissRequest = { showSortMenu = false }
) {
DropdownMenuItem(
text = { Text("Name (A-Z)") },
onClick = {
viewModel.setSortOrder(ModelSortOrder.NAME_ASC)
showSortMenu = false
}
)
DropdownMenuItem(
text = { Text("Name (Z-A)") },
onClick = {
viewModel.setSortOrder(ModelSortOrder.NAME_DESC)
showSortMenu = false
}
)
DropdownMenuItem(
text = { Text("Size (Largest first)") },
onClick = {
viewModel.setSortOrder(ModelSortOrder.SIZE_DESC)
showSortMenu = false
}
)
DropdownMenuItem(
text = { Text("Size (Smallest first)") },
onClick = {
viewModel.setSortOrder(ModelSortOrder.SIZE_ASC)
showSortMenu = false
}
)
DropdownMenuItem(
text = { Text("Last used") },
onClick = {
viewModel.setSortOrder(ModelSortOrder.LAST_USED)
showSortMenu = false
}
)
}
IconButton(onClick = { /* Filter action - stub for now */ }) {
Icon(
imageVector = Icons.Default.FilterAlt,
contentDescription = "Filter models"
)
}
IconButton(onClick = {
isMultiSelectionMode = true
}) {
Icon(
imageVector = Icons.Default.DeleteSweep,
contentDescription = "Delete models"
)
} }
} }
} },
} floatingActionButton = {
FloatingActionButton(
onClick = {
if (isMultiSelectionMode) {
exitSelectionMode()
} else {
showAddModelMenu = true
}
},
containerColor = MaterialTheme.colorScheme.primaryContainer
) {
Icon(
imageVector = if (isMultiSelectionMode) Icons.Default.Close else Icons.Default.Add,
contentDescription = if (isMultiSelectionMode) "Exit selection mode" else "Add model"
)
}
// Installed models list // Add model dropdown menu
Text( DropdownMenu(
text = "Installed Models", expanded = showAddModelMenu,
style = MaterialTheme.typography.titleMedium, onDismissRequest = { showAddModelMenu = false }
modifier = Modifier.padding(vertical = 8.dp) ) {
DropdownMenuItem(
text = { Text("Import local model") },
leadingIcon = {
Icon(
imageVector = Icons.Default.FolderOpen,
contentDescription = "Import a local model on the device"
)
},
onClick = {
viewModel.importLocalModel()
showAddModelMenu = false
}
)
DropdownMenuItem(
text = { Text("Download from HuggingFace") },
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.logo_huggingface),
contentDescription = "Browse and download a model from HuggingFace",
modifier = Modifier.size(24.dp),
tint = Color.Unspecified,
)
},
onClick = {
viewModel.importFromHuggingFace()
showAddModelMenu = false
}
)
}
}
) )
},
LazyColumn { ) { paddingValues ->
items(installedModels) { model -> // Main content
ModelManagementItem( ModelList(
model = model, models = models,
onInfoClick = { /* Show model details */ }, isMultiSelectionMode = isMultiSelectionMode,
onDeleteClick = { /* Delete model */ } selectedModels = selectedModels,
) onModelClick = { modelId ->
Spacer(modifier = Modifier.height(8.dp)) if (isMultiSelectionMode) {
// Toggle selection
if (selectedModels.contains(modelId)) {
selectedModels.remove(modelId)
} else {
selectedModels.put(modelId, models.first { it.id == modelId } )
}
} else {
// View model details
viewModel.viewModelDetails(modelId)
} }
} },
onModelInfoClick = { modelId ->
viewModel.viewModelDetails(modelId)
},
onModelDeleteClick = { modelId ->
viewModel.deleteModel(modelId)
},
modifier = Modifier.padding(paddingValues)
)
}
}
@Composable
private fun ModelList(
models: List<ModelInfo>,
isMultiSelectionMode: Boolean,
selectedModels: Map<String, ModelInfo>,
onModelClick: (String) -> Unit,
onModelInfoClick: (String) -> Unit,
onModelDeleteClick: (String) -> Unit,
modifier: Modifier = Modifier
) {
LazyColumn(
modifier = modifier
.fillMaxSize()
.padding(16.dp)
) {
items(
items = models,
key = { it.id }
) { model ->
ModelItem(
model = model,
isMultiSelectionMode = isMultiSelectionMode,
isSelected = selectedModels.contains(model.id),
onClick = { onModelClick(model.id) },
onInfoClick = { onModelInfoClick(model.id) },
onDeleteClick = { onModelDeleteClick(model.id) }
)
Spacer(modifier = Modifier.height(8.dp))
} }
} }
} }
@Composable @Composable
fun ModelManagementItem( private fun ModelItem(
model: ModelInfo, model: ModelInfo,
isMultiSelectionMode: Boolean,
isSelected: Boolean,
onClick: () -> Unit,
onInfoClick: () -> Unit, onInfoClick: () -> Unit,
onDeleteClick: () -> Unit onDeleteClick: () -> Unit
) { ) {
// Model item implementation with selection support
Card( Card(
modifier = Modifier.fillMaxWidth(), modifier = Modifier
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp) .fillMaxWidth()
.clickable(onClick = onClick),
colors = if (isSelected && isMultiSelectionMode)
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.primaryContainer)
else
CardDefaults.cardColors()
) { ) {
Column( Row(
modifier = Modifier.padding(16.dp) modifier = Modifier.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) { ) {
Row( // Show checkbox in selection mode
verticalAlignment = Alignment.CenterVertically if (isMultiSelectionMode) {
) { Checkbox(
Column( checked = isSelected,
modifier = Modifier.weight(1f) onCheckedChange = { onClick() },
) { modifier = Modifier.padding(end = 8.dp)
Text( )
text = model.name, }
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
// Model info
Column(modifier = Modifier.weight(1f)) {
Text(
text = model.name,
style = MaterialTheme.typography.titleMedium
)
Text(
text = "${model.parameters}${model.quantization}${model.formattedSize}",
style = MaterialTheme.typography.bodySmall
)
model.lastUsed?.let { lastUsed ->
val dateFormat = SimpleDateFormat("MMM d, yyyy", Locale.getDefault())
Text( Text(
text = "${model.parameters}${model.quantization}${model.formattedSize}", text = "Last used: ${dateFormat.format(Date(lastUsed))}",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant color = MaterialTheme.colorScheme.onSurfaceVariant
) )
} }
}
// Only show action buttons in non-selection mode
if (!isMultiSelectionMode) {
IconButton(onClick = onInfoClick) { IconButton(onClick = onInfoClick) {
Icon( Icon(
imageVector = Icons.Default.Info, imageVector = Icons.Default.Info,
contentDescription = "Model details", contentDescription = "Model details"
tint = MaterialTheme.colorScheme.primary
) )
} }
@ -180,35 +383,6 @@ fun ModelManagementItem(
) )
} }
} }
HorizontalDivider(
modifier = Modifier.padding(vertical = 8.dp)
)
Row(
verticalAlignment = Alignment.CenterVertically
) {
Column(
modifier = Modifier.weight(1f)
) {
Text(
text = "Location: ${model.path}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
model.lastUsed?.let { lastUsed ->
val dateFormat = SimpleDateFormat("MMM d, yyyy", Locale.getDefault())
Text(
text = "Last used: ${dateFormat.format(Date(lastUsed))}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
} }
} }
} }

View File

@ -97,6 +97,10 @@ class ModelsManagementViewModel @Inject constructor(
// TODO-han.yin: Stub for now. Would open file picker and import model // TODO-han.yin: Stub for now. Would open file picker and import model
} }
fun importFromHuggingFace() {
// TODO-han.yin: Stub for now. Would need to investigate HuggingFace APIs
}
private fun updateStorageMetrics() { private fun updateStorageMetrics() {
// Recalculate storage metrics after model changes // Recalculate storage metrics after model changes
// TODO-han.yin: Stub for now. Would query actual storage // TODO-han.yin: Stub for now. Would query actual storage

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="95dp"
android:height="88dp"
android:viewportWidth="95"
android:viewportHeight="88">
<path
android:pathData="M47.21,76.5a34.75,34.75 0,1 0,0 -69.5,34.75 34.75,0 0,0 0,69.5Z"
android:fillColor="#FFD21E"/>
<path
android:pathData="M81.96,41.75a34.75,34.75 0,1 0,-69.5 0,34.75 34.75,0 0,0 69.5,0ZM8.46,41.75a38.75,38.75 0,1 1,77.5 0,38.75 38.75,0 0,1 -77.5,0Z"
android:fillColor="#FF9D0B"/>
<path
android:pathData="M58.5,32.3c1.28,0.44 1.78,3.06 3.07,2.38a5,5 0,1 0,-6.76 -2.07c0.61,1.15 2.55,-0.72 3.7,-0.32ZM34.95,32.3c-1.28,0.44 -1.79,3.06 -3.07,2.38a5,5 0,1 1,6.76 -2.07c-0.61,1.15 -2.56,-0.72 -3.7,-0.32Z"
android:fillColor="#3A3B45"/>
<path
android:pathData="M46.96,56.29c9.83,0 13,-8.76 13,-13.26 0,-2.34 -1.57,-1.6 -4.09,-0.36 -2.33,1.15 -5.46,2.74 -8.9,2.74 -7.19,0 -13,-6.88 -13,-2.38s3.16,13.26 13,13.26Z"
android:fillColor="#FF323D"/>
<path
android:pathData="M39.43,54a8.7,8.7 0,0 1,5.3 -4.49c0.4,-0.12 0.81,0.57 1.24,1.28 0.4,0.68 0.82,1.37 1.24,1.37 0.45,0 0.9,-0.68 1.33,-1.35 0.45,-0.7 0.89,-1.38 1.32,-1.25a8.61,8.61 0,0 1,5 4.17c3.73,-2.94 5.1,-7.74 5.1,-10.7 0,-2.34 -1.57,-1.6 -4.09,-0.36l-0.14,0.07c-2.31,1.15 -5.39,2.67 -8.77,2.67s-6.45,-1.52 -8.77,-2.67c-2.6,-1.29 -4.23,-2.1 -4.23,0.29 0,3.05 1.46,8.06 5.47,10.97Z"
android:fillColor="#3A3B45"
android:fillType="evenOdd"/>
<path
android:pathData="M70.71,37a3.25,3.25 0,1 0,0 -6.5,3.25 3.25,0 0,0 0,6.5ZM24.21,37a3.25,3.25 0,1 0,0 -6.5,3.25 3.25,0 0,0 0,6.5ZM17.52,48c-1.62,0 -3.06,0.66 -4.07,1.87a5.97,5.97 0,0 0,-1.33 3.76,7.1 7.1,0 0,0 -1.94,-0.3c-1.55,0 -2.95,0.59 -3.94,1.66a5.8,5.8 0,0 0,-0.8 7,5.3 5.3,0 0,0 -1.79,2.82c-0.24,0.9 -0.48,2.8 0.8,4.74a5.22,5.22 0,0 0,-0.37 5.02c1.02,2.32 3.57,4.14 8.52,6.1 3.07,1.22 5.89,2 5.91,2.01a44.33,44.33 0,0 0,10.93 1.6c5.86,0 10.05,-1.8 12.46,-5.34 3.88,-5.69 3.33,-10.9 -1.7,-15.92 -2.77,-2.78 -4.62,-6.87 -5,-7.77 -0.78,-2.66 -2.84,-5.62 -6.25,-5.62a5.7,5.7 0,0 0,-4.6 2.46c-1,-1.26 -1.98,-2.25 -2.86,-2.82A7.4,7.4 0,0 0,17.52 48ZM17.52,52c0.51,0 1.14,0.22 1.82,0.65 2.14,1.36 6.25,8.43 7.76,11.18 0.5,0.92 1.37,1.31 2.14,1.31 1.55,0 2.75,-1.53 0.15,-3.48 -3.92,-2.93 -2.55,-7.72 -0.68,-8.01 0.08,-0.02 0.17,-0.02 0.24,-0.02 1.7,0 2.45,2.93 2.45,2.93s2.2,5.52 5.98,9.3c3.77,3.77 3.97,6.8 1.22,10.83 -1.88,2.75 -5.47,3.58 -9.16,3.58 -3.81,0 -7.73,-0.9 -9.92,-1.46 -0.11,-0.03 -13.45,-3.8 -11.76,-7 0.28,-0.54 0.75,-0.76 1.34,-0.76 2.38,0 6.7,3.54 8.57,3.54 0.41,0 0.7,-0.17 0.83,-0.6 0.79,-2.85 -12.06,-4.05 -10.98,-8.17 0.2,-0.73 0.71,-1.02 1.44,-1.02 3.14,0 10.2,5.53 11.68,5.53 0.11,0 0.2,-0.03 0.24,-0.1 0.74,-1.2 0.33,-2.04 -4.9,-5.2 -5.21,-3.16 -8.88,-5.06 -6.8,-7.33 0.24,-0.26 0.58,-0.38 1,-0.38 3.17,0 10.66,6.82 10.66,6.82s2.02,2.1 3.25,2.1c0.28,0 0.52,-0.1 0.68,-0.38 0.86,-1.46 -8.06,-8.22 -8.56,-11.01 -0.34,-1.9 0.24,-2.85 1.31,-2.85Z"
android:fillColor="#FF9D0B"/>
<path
android:pathData="M38.6,76.69c2.75,-4.04 2.55,-7.07 -1.22,-10.84 -3.78,-3.77 -5.98,-9.3 -5.98,-9.3s-0.82,-3.2 -2.69,-2.9c-1.87,0.3 -3.24,5.08 0.68,8.01 3.91,2.93 -0.78,4.92 -2.29,2.17 -1.5,-2.75 -5.62,-9.82 -7.76,-11.18 -2.13,-1.35 -3.63,-0.6 -3.13,2.2 0.5,2.79 9.43,9.55 8.56,11 -0.87,1.47 -3.93,-1.71 -3.93,-1.71s-9.57,-8.71 -11.66,-6.44c-2.08,2.27 1.59,4.17 6.8,7.33 5.23,3.16 5.64,4 4.9,5.2 -0.75,1.2 -12.28,-8.53 -13.36,-4.4 -1.08,4.11 11.77,5.3 10.98,8.15 -0.8,2.85 -9.06,-5.38 -10.74,-2.18 -1.7,3.21 11.65,6.98 11.76,7.01 4.3,1.12 15.25,3.49 19.08,-2.12Z"
android:fillColor="#FFD21E"/>
<path
android:pathData="M77.4,48c1.62,0 3.07,0.66 4.07,1.87a5.97,5.97 0,0 1,1.33 3.76,7.1 7.1,0 0,1 1.95,-0.3c1.55,0 2.95,0.59 3.94,1.66a5.8,5.8 0,0 1,0.8 7,5.3 5.3,0 0,1 1.78,2.82c0.24,0.9 0.48,2.8 -0.8,4.74a5.22,5.22 0,0 1,0.37 5.02c-1.02,2.32 -3.57,4.14 -8.51,6.1 -3.08,1.22 -5.9,2 -5.92,2.01a44.33,44.33 0,0 1,-10.93 1.6c-5.86,0 -10.05,-1.8 -12.46,-5.34 -3.88,-5.69 -3.33,-10.9 1.7,-15.92 2.78,-2.78 4.63,-6.87 5.01,-7.77 0.78,-2.66 2.83,-5.62 6.24,-5.62a5.7,5.7 0,0 1,4.6 2.46c1,-1.26 1.98,-2.25 2.87,-2.82A7.4,7.4 0,0 1,77.4 48ZM77.4,52c-0.51,0 -1.13,0.22 -1.82,0.65 -2.13,1.36 -6.25,8.43 -7.76,11.18a2.43,2.43 0,0 1,-2.14 1.31c-1.54,0 -2.75,-1.53 -0.14,-3.48 3.91,-2.93 2.54,-7.72 0.67,-8.01a1.54,1.54 0,0 0,-0.24 -0.02c-1.7,0 -2.45,2.93 -2.45,2.93s-2.2,5.52 -5.97,9.3c-3.78,3.77 -3.98,6.8 -1.22,10.83 1.87,2.75 5.47,3.58 9.15,3.58 3.82,0 7.73,-0.9 9.93,-1.46 0.1,-0.03 13.45,-3.8 11.76,-7 -0.29,-0.54 -0.75,-0.76 -1.34,-0.76 -2.38,0 -6.71,3.54 -8.57,3.54 -0.42,0 -0.71,-0.17 -0.83,-0.6 -0.8,-2.85 12.05,-4.05 10.97,-8.17 -0.19,-0.73 -0.7,-1.02 -1.44,-1.02 -3.14,0 -10.2,5.53 -11.68,5.53 -0.1,0 -0.19,-0.03 -0.23,-0.1 -0.74,-1.2 -0.34,-2.04 4.88,-5.2 5.23,-3.16 8.9,-5.06 6.8,-7.33 -0.23,-0.26 -0.57,-0.38 -0.98,-0.38 -3.18,0 -10.67,6.82 -10.67,6.82s-2.02,2.1 -3.24,2.1a0.74,0.74 0,0 1,-0.68 -0.38c-0.87,-1.46 8.05,-8.22 8.55,-11.01 0.34,-1.9 -0.24,-2.85 -1.31,-2.85Z"
android:fillColor="#FF9D0B"/>
<path
android:pathData="M56.33,76.69c-2.75,-4.04 -2.56,-7.07 1.22,-10.84 3.77,-3.77 5.97,-9.3 5.97,-9.3s0.82,-3.2 2.7,-2.9c1.86,0.3 3.23,5.08 -0.68,8.01 -3.92,2.93 0.78,4.92 2.28,2.17 1.51,-2.75 5.63,-9.82 7.76,-11.18 2.13,-1.35 3.64,-0.6 3.13,2.2 -0.5,2.79 -9.42,9.55 -8.55,11 0.86,1.47 3.92,-1.71 3.92,-1.71s9.58,-8.71 11.66,-6.44c2.08,2.27 -1.58,4.17 -6.8,7.33 -5.23,3.16 -5.63,4 -4.9,5.2 0.75,1.2 12.28,-8.53 13.36,-4.4 1.08,4.11 -11.76,5.3 -10.97,8.15 0.8,2.85 9.05,-5.38 10.74,-2.18 1.69,3.21 -11.65,6.98 -11.76,7.01 -4.31,1.12 -15.26,3.49 -19.08,-2.12Z"
android:fillColor="#FFD21E"/>
</vector>