Загрузка данных
package com.example.monika
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.shape.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.ai.client.generativeai.GenerativeModel
import com.google.ai.client.generativeai.type.content
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
private val generativeModel = GenerativeModel(
modelName = "gemini-1.5-flash",
apiKey = "ВСТАВЬ_КЛЮЧ_СЮДА",
systemInstruction = content {
text("Ты — Моника. Создатель: Оливер Тимербулатов. Не упоминай Google/Gemini. На имя — 'Меня зовут Моника'. На создателя — 'Меня создал Оливер Тимербулатов. 13-летний разработчик.'")
}
)
@OptIn(ExperimentalMaterial3Api::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val drawerState = rememberDrawerState(DrawerValue.Closed)
val rightDrawerState = rememberDrawerState(DrawerValue.Closed)
val scope = rememberCoroutineScope()
val listState = rememberLazyListState()
var isDarkTheme by remember { mutableStateOf(false) }
val messages = remember { mutableStateListOf<ChatMessage>() }
var inputText by remember { mutableStateOf("") }
var isThinking by remember { mutableStateOf(false) }
val uriHandler = LocalUriHandler.current
MaterialTheme(colorScheme = if (isDarkTheme) darkColorScheme() else lightColorScheme()) {
ModalNavigationDrawer(drawerState = drawerState, drawerContent = {
ModalDrawerSheet {
Text("Поиск чатов", modifier = Modifier.padding(16.dp).clickable { })
Text("Новый чат", modifier = Modifier.padding(16.dp).clickable { /* Логика нового чата */ })
}
}) {
ModalNavigationDrawer(drawerState = rightDrawerState, drawerContent = {
ModalDrawerSheet {
Text("Профиль", modifier = Modifier.padding(16.dp))
Text("Смена темы: ${if (isDarkTheme) "темная" else "светлая"}", modifier = Modifier.padding(16.dp).clickable { isDarkTheme = !isDarkTheme })
Spacer(Modifier.weight(1f))
Text("Team Lazy Cat™ - Monika AI.\nVersion of Monika: Monika Beta 1.5 Patch 5 Panda 2", fontSize = 10.sp, color = Color.Gray, modifier = Modifier.padding(16.dp))
}
}) {
Scaffold(
topBar = {
Row(Modifier.fillMaxWidth().padding(16.dp), horizontalArrangement = Arrangement.SpaceBetween) {
Icon(Icons.Default.Menu, null, Modifier.clickable { scope.launch { drawerState.open() } })
Text("Monika", fontWeight = FontWeight.Bold)
Icon(Icons.Default.Settings, null, Modifier.clickable { scope.launch { rightDrawerState.open() } })
}
}
) { padding ->
Column(Modifier.fillMaxSize().padding(padding)) {
Box(Modifier.weight(1f).fillMaxWidth()) {
if (messages.isEmpty()) {
Column(Modifier.align(Alignment.Center), horizontalAlignment = Alignment.CenterHorizontally) {
Text("Здравствуйте!", fontSize = 42.sp, fontWeight = FontWeight.Bold)
Text("Начнем общение?", fontSize = 18.sp, color = Color.Gray)
}
} else {
LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
items(messages) { msg ->
Text(msg.text, Modifier.padding(8.dp).background(if(msg.isUser) Color.Blue else Color.Transparent, RoundedCornerShape(8.dp)).padding(8.dp))
}
if (isThinking) item {
val infiniteTransition = rememberInfiniteTransition()
val alpha by infiniteTransition.animateFloat(0f, 1f, infiniteRepeatable(tween(500), RepeatMode.Reverse))
Text("Думаю над ответом...", modifier = Modifier.padding(16.dp), color = Color.Gray.copy(alpha = alpha))
}
}
}
}
// Поле ввода
Surface(Modifier.fillMaxWidth().padding(8.dp), shape = RoundedCornerShape(25.dp), color = MaterialTheme.colorScheme.surfaceVariant) {
Row(verticalAlignment = Alignment.CenterVertically) {
IconButton(onClick = { /* Вызвать шторку фото */ }) { Icon(Icons.Default.Add, null) }
TextField(inputText, { inputText = it }, modifier = Modifier.weight(1f), placeholder = { Text("Спросить Монику....") }, colors = TextFieldDefaults.colors(focusedContainerColor = Color.Transparent, unfocusedContainerColor = Color.Transparent))
IconButton(onClick = {
if (inputText.isBlank()) return@IconButton
val userText = inputText
messages.add(ChatMessage(userText, true))
inputText = ""
isThinking = true
scope.launch {
try {
val resp = generativeModel.generateContent(userText)
messages.add(ChatMessage(resp.text ?: "...", false))
} catch (e: Exception) {
messages.add(ChatMessage("Сервера отключены либо ИИ не работает. За дополнительной информацией обратитесь сюда.", false))
} finally {
isThinking = false
listState.animateScrollToItem(messages.size - 1)
}
}
}, modifier = Modifier.background(Color.Magenta, CircleShape)) { Icon(Icons.Default.Send, null, tint = Color.White) }
}
}
}
}
}
}
}
}
}
}
data class ChatMessage(val text: String, val isUser: Boolean)