@@ -4,8 +4,10 @@ import android.annotation.SuppressLint
44import android.content.Context
55import android.content.Intent
66import android.content.SharedPreferences
7+ import android.os.Build
78import android.os.Bundle
89import android.os.Vibrator
10+ import android.os.VibratorManager
911import android.widget.Toast
1012import androidx.activity.ComponentActivity
1113import androidx.activity.compose.setContent
@@ -15,13 +17,17 @@ import androidx.compose.animation.core.tween
1517import androidx.compose.foundation.ExperimentalFoundationApi
1618import androidx.compose.foundation.ScrollState
1719import androidx.compose.foundation.background
20+ import androidx.compose.foundation.border
1821import androidx.compose.foundation.clickable
1922import androidx.compose.foundation.combinedClickable
2023import androidx.compose.foundation.layout.Box
2124import androidx.compose.foundation.layout.Column
25+ import androidx.compose.foundation.layout.PaddingValues
2226import androidx.compose.foundation.layout.Row
2327import androidx.compose.foundation.layout.Spacer
2428import androidx.compose.foundation.layout.fillMaxWidth
29+ import androidx.compose.foundation.layout.height
30+ import androidx.compose.foundation.layout.heightIn
2531import androidx.compose.foundation.layout.imePadding
2632import androidx.compose.foundation.layout.navigationBarsPadding
2733import androidx.compose.foundation.layout.padding
@@ -32,6 +38,8 @@ import androidx.compose.foundation.lazy.LazyColumn
3238import androidx.compose.foundation.lazy.itemsIndexed
3339import androidx.compose.foundation.rememberScrollState
3440import androidx.compose.foundation.shape.CircleShape
41+ import androidx.compose.foundation.shape.RoundedCornerShape
42+ import androidx.compose.foundation.text.BasicTextField
3543import androidx.compose.foundation.text.selection.SelectionContainer
3644import androidx.compose.foundation.verticalScroll
3745import androidx.compose.material.icons.Icons
@@ -53,15 +61,16 @@ import androidx.compose.material3.DropdownMenuItem
5361import androidx.compose.material3.ExperimentalMaterial3Api
5462import androidx.compose.material3.Icon
5563import androidx.compose.material3.IconButton
64+ import androidx.compose.material3.LocalTextStyle
5665import androidx.compose.material3.MaterialTheme
5766import androidx.compose.material3.ModalDrawerSheet
5867import androidx.compose.material3.ModalNavigationDrawer
5968import androidx.compose.material3.OutlinedTextField
6069import androidx.compose.material3.Scaffold
70+ import androidx.compose.material3.Slider
6171import androidx.compose.material3.Surface
6272import androidx.compose.material3.Text
6373import androidx.compose.material3.TextButton
64- import androidx.compose.material3.TextField
6574import androidx.compose.material3.TopAppBar
6675import androidx.compose.material3.rememberDrawerState
6776import androidx.compose.runtime.Composable
@@ -79,6 +88,7 @@ import androidx.compose.ui.draw.clip
7988import androidx.compose.ui.focus.FocusRequester
8089import androidx.compose.ui.focus.focusRequester
8190import androidx.compose.ui.graphics.Color
91+ import androidx.compose.ui.graphics.RectangleShape
8292import androidx.compose.ui.graphics.vector.ImageVector
8393import androidx.compose.ui.layout.onSizeChanged
8494import androidx.compose.ui.platform.LocalContext
@@ -114,6 +124,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
114124import java.io.BufferedReader
115125import java.io.InputStreamReader
116126import java.util.concurrent.TimeUnit
127+ import kotlin.math.round
117128
118129@Keep
119130data class Message (val role : String , val content : String )
@@ -126,6 +137,7 @@ class ChatViewModel : ViewModel() {
126137 var cancel= false
127138 var currentSession by mutableStateOf(" " )
128139 var parseMd by mutableStateOf(true )
140+ var temperature by mutableIntStateOf(- 1 )
129141
130142 fun addUserMessage (content : String ) {
131143 msgs.add(Message (" user" , content))
@@ -353,7 +365,7 @@ fun MainUI(viewModel: ChatViewModel) {
353365 },
354366 sendImg = if (sendImg== 1 ){Icons .Default .ArrowUpward }
355367 else {ImageVector .vectorResource(R .drawable.ic_rectangle)},
356- vibrator
368+ viewModel, vibrator
357369 )
358370 }
359371 ) { innerPadding ->
@@ -480,49 +492,102 @@ fun MainUI(viewModel: ChatViewModel) {
480492})
481493}
482494
495+ @OptIn(ExperimentalMaterial3Api ::class )
483496@Composable
484497fun MessageInputBar (
485498 msg : String ,
486499 onMsgChange : (String ) -> Unit ,
487500 onSend : (String ) -> Unit ,
488501 sendImg : ImageVector ,
502+ viewModel : ChatViewModel ,
489503 vibrator : Vibrator
490504) {
505+ var expanded by remember { mutableStateOf(false ) }
491506 Surface (
492507 modifier = Modifier
493508 .fillMaxWidth()
494509 .navigationBarsPadding()
495510 .imePadding(), shadowElevation = 8 .dp
496511 ) {
497- Row (
498- modifier = Modifier .padding(16 .dp),
499- verticalAlignment = Alignment .CenterVertically
500- ) {
501- TextField (
502- value = msg,
503- onValueChange = onMsgChange,
504- modifier = Modifier .weight(1f ),
505- placeholder = { Text (" 输入消息..." ) },
506- maxLines = 7
507- )
508- Spacer (Modifier .size(6 .dp))
509- Box (
510- modifier = Modifier
511- .size(36 .dp)
512- .clip(CircleShape )
513- .background(MaterialTheme .colorScheme.primary)
514- .clickable {
515- clickVibrate(vibrator)
516- onSend(msg)
517- },
518- contentAlignment = Alignment .Center
512+ Column (modifier = Modifier .padding(horizontal = 16 .dp, vertical = 10 .dp)) {
513+ Row (
514+ verticalAlignment = Alignment .CenterVertically
519515 ) {
520- Icon (
521- imageVector = sendImg,
522- contentDescription = null ,
523- tint = MaterialTheme .colorScheme.onPrimary,
524- modifier = Modifier .size(24 .dp))
516+ BasicTextField (
517+ value = msg,
518+ onValueChange = onMsgChange,
519+ modifier = Modifier
520+ .weight(1f ).heightIn(min = 36 .dp),
521+ textStyle = LocalTextStyle .current.copy(
522+ color = MaterialTheme .colorScheme.onSurface
523+ ),
524+ maxLines = 7 ,
525+ decorationBox = { innerTextField ->
526+ Box (
527+ modifier = Modifier
528+ .border(
529+ width = 1 .dp,
530+ color = MaterialTheme .colorScheme.outline,
531+ shape = RoundedCornerShape (18 .dp)
532+ )
533+ .padding(vertical = 5 .dp, horizontal = 8 .dp)
534+ ) {
535+ if (msg.isEmpty()) {
536+ Text (
537+ text = " 输入消息..." ,
538+ style = LocalTextStyle .current.copy(
539+ color = MaterialTheme .colorScheme.onSurfaceVariant
540+ )
541+ )
542+ }
543+ innerTextField()
544+ }
545+ }
546+ )
547+ Spacer (Modifier .size(6 .dp))
548+ Box (
549+ modifier = Modifier
550+ .size(36 .dp)
551+ .clip(CircleShape )
552+ .background(MaterialTheme .colorScheme.primary)
553+ .clickable {
554+ clickVibrate(vibrator)
555+ onSend(msg)
556+ },
557+ contentAlignment = Alignment .Center
558+ ) {
559+ Icon (
560+ imageVector = sendImg,
561+ contentDescription = null ,
562+ tint = MaterialTheme .colorScheme.onPrimary,
563+ modifier = Modifier .size(24 .dp)
564+ )
565+ }
525566 }
567+ TextButton ({ expanded = true }, Modifier .height(28 .dp), contentPadding = PaddingValues (5 .dp),shape = RectangleShape ) {
568+ Text (
569+ " 温度:${
570+ if (viewModel.temperature >= 0 ) {
571+ viewModel.temperature.toFloat() / 10
572+ } else {
573+ " 未设置"
574+ }
575+ } "
576+ )
577+ }
578+ }
579+ DropdownMenu (
580+ expanded = expanded,
581+ onDismissRequest = { expanded = false },
582+ Modifier .width(200 .dp)
583+ ) {
584+ Slider (value = viewModel.temperature.toFloat(), onValueChange = {
585+ val tmp= round(it).toInt()
586+ if (tmp!= viewModel.temperature) {
587+ viewModel.temperature = tmp
588+ clickVibrate(vibrator)
589+ }
590+ }, valueRange = - 1f .. 20f , steps = 20 )
526591 }
527592 }
528593}
@@ -539,13 +604,17 @@ private fun send(
539604 .readTimeout(0 , TimeUnit .SECONDS )
540605 .build()
541606
542- val requestBody = Gson ().toJson(
543- mapOf (
544- " model" to model,
545- " messages" to viewModel.withoutReasoning(),
546- " stream" to true
547- )
607+ var bodyMap= mutableMapOf (
608+ " model" to model,
609+ " messages" to viewModel.withoutReasoning(),
610+ " stream" to true
548611 )
612+ bodyMap.apply {
613+ if (viewModel.temperature >= 0 ) {
614+ put(" temperature" , viewModel.temperature.toFloat() / 10 )
615+ }
616+ }
617+ val requestBody = Gson ().toJson(bodyMap)
549618 .toRequestBody(" application/json" .toMediaTypeOrNull())
550619
551620 val request = Request .Builder ()
0 commit comments