添加新的表单文本输入组件 FormTextInput2,包含错误提示和动态显示功能;新增图标和图片资源。
This commit is contained in:
@@ -20,6 +20,7 @@ open class AppThemeData(
|
|||||||
var decentBackground: Color,
|
var decentBackground: Color,
|
||||||
var divider: Color,
|
var divider: Color,
|
||||||
var inputBackground: Color,
|
var inputBackground: Color,
|
||||||
|
var inputBackground2: Color,
|
||||||
var inputHint: Color,
|
var inputHint: Color,
|
||||||
var error: Color,
|
var error: Color,
|
||||||
var checkedBackground: Color,
|
var checkedBackground: Color,
|
||||||
@@ -30,7 +31,7 @@ open class AppThemeData(
|
|||||||
)
|
)
|
||||||
|
|
||||||
class LightThemeColors : AppThemeData(
|
class LightThemeColors : AppThemeData(
|
||||||
main = Color(0xffda3832),
|
main = Color(0xffD80264),
|
||||||
mainText = Color(0xffffffff),
|
mainText = Color(0xffffffff),
|
||||||
basicMain = Color(0xfff0f0f0),
|
basicMain = Color(0xfff0f0f0),
|
||||||
nonActive = Color(0xfff5f5f5),
|
nonActive = Color(0xfff5f5f5),
|
||||||
@@ -43,6 +44,7 @@ class LightThemeColors : AppThemeData(
|
|||||||
background = Color(0xFFFFFFFF),
|
background = Color(0xFFFFFFFF),
|
||||||
divider = Color(0xFFEbEbEb),
|
divider = Color(0xFFEbEbEb),
|
||||||
inputBackground = Color(0xFFF7f7f7),
|
inputBackground = Color(0xFFF7f7f7),
|
||||||
|
inputBackground2 = Color(0xFFFFFFFF),
|
||||||
inputHint = Color(0xffdadada),
|
inputHint = Color(0xffdadada),
|
||||||
error = Color(0xffFF0000),
|
error = Color(0xffFF0000),
|
||||||
checkedBackground = Color(0xff000000),
|
checkedBackground = Color(0xff000000),
|
||||||
@@ -68,6 +70,7 @@ class DarkThemeColors : AppThemeData(
|
|||||||
background = Color(0xFF121212),
|
background = Color(0xFF121212),
|
||||||
divider = Color(0xFF282828),
|
divider = Color(0xFF282828),
|
||||||
inputBackground = Color(0xFF1C1C1C),
|
inputBackground = Color(0xFF1C1C1C),
|
||||||
|
inputBackground2 = Color(0xFF1C1C1C),
|
||||||
inputHint = Color(0xff888888),
|
inputHint = Color(0xff888888),
|
||||||
error = Color(0xffFF0000),
|
error = Color(0xffFF0000),
|
||||||
checkedBackground = Color(0xffffffff),
|
checkedBackground = Color(0xffffffff),
|
||||||
|
|||||||
@@ -148,6 +148,10 @@ interface MomentService {
|
|||||||
relPostId: Int? = null
|
relPostId: Int? = null
|
||||||
): MomentEntity
|
): MomentEntity
|
||||||
|
|
||||||
|
suspend fun agentMoment(
|
||||||
|
content: String,
|
||||||
|
): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收藏动态
|
* 收藏动态
|
||||||
* @param id 动态ID
|
* @param id 动态ID
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ data class RegisterRequestBody(
|
|||||||
@SerializedName("password")
|
@SerializedName("password")
|
||||||
val password: String
|
val password: String
|
||||||
)
|
)
|
||||||
|
data class AgentMomentRequestBody(
|
||||||
|
@SerializedName("generateText")
|
||||||
|
val generateText: String,
|
||||||
|
@SerializedName("sessionId")
|
||||||
|
val sessionId: String
|
||||||
|
)
|
||||||
|
|
||||||
data class LoginUserRequestBody(
|
data class LoginUserRequestBody(
|
||||||
@SerializedName("username")
|
@SerializedName("username")
|
||||||
@@ -472,6 +478,17 @@ interface RaveNowAPI {
|
|||||||
@Query("pageSize") pageSize: Int = 20,
|
@Query("pageSize") pageSize: Int = 20,
|
||||||
): Response<ListContainer<Agent>>
|
): Response<ListContainer<Agent>>
|
||||||
|
|
||||||
|
@Multipart
|
||||||
|
@POST("outside/prompts")
|
||||||
|
suspend fun createAgent(
|
||||||
|
@Part avatar: MultipartBody.Part?,
|
||||||
|
@Part("title") title: RequestBody?,
|
||||||
|
@Part("desc") desc: RequestBody?,
|
||||||
|
): Response<DataContainer<Agent>>
|
||||||
|
|
||||||
|
|
||||||
|
@POST("generate/postText")
|
||||||
|
suspend fun agentMoment(@Body body: AgentMomentRequestBody): Response<DataContainer<String>>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,35 @@ import androidx.paging.PagingState
|
|||||||
import com.aiosman.ravenow.data.ListContainer
|
import com.aiosman.ravenow.data.ListContainer
|
||||||
import com.aiosman.ravenow.data.AgentService
|
import com.aiosman.ravenow.data.AgentService
|
||||||
import com.aiosman.ravenow.data.ServiceException
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 智能体
|
* 智能体
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
suspend fun createAgent(
|
||||||
|
title: String,
|
||||||
|
desc: String,
|
||||||
|
avatar: UploadImage,
|
||||||
|
): AgentEntity {
|
||||||
|
val textTitle = title.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val textDesc = desc.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val avatarField: MultipartBody.Part? = avatar?.let {
|
||||||
|
createMultipartBody(it.file, it.filename, "avatar")
|
||||||
|
}
|
||||||
|
val response = ApiClient.api.createAgent(avatarField, textTitle ,textDesc)
|
||||||
|
val body = response.body()?.data ?: throw ServiceException("Failed to create agent")
|
||||||
|
return body.toAgentEntity()
|
||||||
|
|
||||||
|
}
|
||||||
data class AgentEntity(
|
data class AgentEntity(
|
||||||
val author: String,
|
val author: String,
|
||||||
val avatar: String,
|
val avatar: String,
|
||||||
@@ -39,7 +60,10 @@ data class ProfileEntity(
|
|||||||
val trtcUserId: String,
|
val trtcUserId: String,
|
||||||
val username: String
|
val username: String
|
||||||
)
|
)
|
||||||
|
fun createMultipartBody(file: File, filename: String, name: String): MultipartBody.Part {
|
||||||
|
val requestFile = file.asRequestBody("image/*".toMediaTypeOrNull())
|
||||||
|
return MultipartBody.Part.createFormData(name, filename, requestFile)
|
||||||
|
}
|
||||||
class AgentLoaderExtraArgs(
|
class AgentLoaderExtraArgs(
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.aiosman.ravenow.data.ListContainer
|
|||||||
import com.aiosman.ravenow.data.MomentService
|
import com.aiosman.ravenow.data.MomentService
|
||||||
import com.aiosman.ravenow.data.ServiceException
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
import com.aiosman.ravenow.data.UploadImage
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
|
import com.aiosman.ravenow.data.api.AgentMomentRequestBody
|
||||||
import com.aiosman.ravenow.data.api.ApiClient
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
import com.aiosman.ravenow.data.parseErrorResponse
|
import com.aiosman.ravenow.data.parseErrorResponse
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
@@ -127,6 +128,10 @@ class MomentServiceImpl() : MomentService {
|
|||||||
return momentBackend.createMoment(content, authorId, images, relPostId)
|
return momentBackend.createMoment(content, authorId, images, relPostId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun agentMoment(content: String): String {
|
||||||
|
return momentBackend.agentMoment(content)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun favoriteMoment(id: Int) {
|
override suspend fun favoriteMoment(id: Int) {
|
||||||
momentBackend.favoriteMoment(id)
|
momentBackend.favoriteMoment(id)
|
||||||
}
|
}
|
||||||
@@ -212,6 +217,17 @@ class MomentBackend {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun agentMoment(
|
||||||
|
content: String,
|
||||||
|
): String {
|
||||||
|
val textContent = content.toRequestBody("text/plain".toMediaTypeOrNull())
|
||||||
|
val sessionId = ""
|
||||||
|
val response = ApiClient.api.agentMoment(AgentMomentRequestBody(generateText = content, sessionId =sessionId ))
|
||||||
|
val body = response.body()?.data ?: throw ServiceException("Failed to agent moment")
|
||||||
|
return body.toString()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun favoriteMoment(id: Int) {
|
suspend fun favoriteMoment(id: Int) {
|
||||||
ApiClient.api.favoritePost(id)
|
ApiClient.api.favoritePost(id)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ 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.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -42,6 +43,7 @@ import com.aiosman.ravenow.ui.composables.ActionButton
|
|||||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||||
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
import com.aiosman.ravenow.ui.composables.StatusBarSpacer
|
||||||
import com.aiosman.ravenow.ui.composables.form.FormTextInput
|
import com.aiosman.ravenow.ui.composables.form.FormTextInput
|
||||||
|
import com.aiosman.ravenow.ui.composables.form.FormTextInput2
|
||||||
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
import com.aiosman.ravenow.ui.modifiers.noRippleClickable
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -84,12 +86,13 @@ fun AddAgentScreen() {
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(color = appColors.background),
|
.background(color = appColors.decentBackground),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
StatusBarSpacer()
|
StatusBarSpacer()
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
|
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
|
||||||
|
.background(color = appColors.decentBackground)
|
||||||
) {
|
) {
|
||||||
ScreenHeader (
|
ScreenHeader (
|
||||||
title = stringResource(R.string.agent_add),
|
title = stringResource(R.string.agent_add),
|
||||||
@@ -150,15 +153,17 @@ fun AddAgentScreen() {
|
|||||||
value = model.name,
|
value = model.name,
|
||||||
label = stringResource(R.string.agent_name),
|
label = stringResource(R.string.agent_name),
|
||||||
hint = stringResource(R.string.agent_name_hint),
|
hint = stringResource(R.string.agent_name_hint),
|
||||||
|
background = appColors.inputBackground2,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) { value ->
|
) { value ->
|
||||||
onNicknameChange(value)
|
onNicknameChange(value)
|
||||||
}
|
}
|
||||||
// Spacer(modifier = Modifier.height(16.dp))
|
// Spacer(modifier = Modifier.height(16.dp))
|
||||||
FormTextInput(
|
FormTextInput2(
|
||||||
value = model.desc,
|
value = model.desc,
|
||||||
label = stringResource(R.string.agent_desc),
|
label = stringResource(R.string.agent_desc),
|
||||||
hint = stringResource(R.string.agent_desc_hint),
|
hint = stringResource(R.string.agent_desc_hint),
|
||||||
|
background = appColors.inputBackground2,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) { value ->
|
) { value ->
|
||||||
onDescChange(value)
|
onDescChange(value)
|
||||||
@@ -167,7 +172,20 @@ fun AddAgentScreen() {
|
|||||||
Spacer(modifier = Modifier.height(58.dp))
|
Spacer(modifier = Modifier.height(58.dp))
|
||||||
ActionButton(
|
ActionButton(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.width(345.dp),
|
.width(345.dp)
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.background(
|
||||||
|
brush = Brush.linearGradient(
|
||||||
|
colors = listOf(
|
||||||
|
Color(0xFFEE2A33),
|
||||||
|
Color(0xFFD80264),
|
||||||
|
Color(0xFF8468BC)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
shape = RoundedCornerShape(24.dp)
|
||||||
|
),
|
||||||
|
color = Color.White,
|
||||||
|
backgroundColor = Color.Transparent,
|
||||||
text = stringResource(R.string.agent_create),
|
text = stringResource(R.string.agent_create),
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ fun ScreenHeader(
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.size(12.dp))
|
Spacer(modifier = Modifier.size(12.dp))
|
||||||
Text(title,
|
Text(title,
|
||||||
fontWeight = FontWeight.W800,
|
fontWeight = FontWeight.W600,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
fontSize = 17.sp,
|
fontSize = 17.sp,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import androidx.compose.foundation.gestures.scrollBy
|
|||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.grid.GridCells
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyGridItemInfo
|
import androidx.compose.foundation.lazy.grid.LazyGridItemInfo
|
||||||
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
|
import androidx.compose.foundation.lazy.grid.LazyGridItemScope
|
||||||
@@ -18,6 +19,7 @@ import androidx.compose.foundation.lazy.grid.LazyGridState
|
|||||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -26,6 +28,7 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
@@ -58,12 +61,12 @@ fun <T : Any> DraggableGrid(
|
|||||||
val dragDropState =
|
val dragDropState =
|
||||||
rememberGridDragDropState(gridState, onMove, onDragModeStart, onDragModeEnd, lockedIndices)
|
rememberGridDragDropState(gridState, onMove, onDragModeStart, onDragModeEnd, lockedIndices)
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(5),
|
||||||
modifier = Modifier.dragContainer(dragDropState),
|
modifier = Modifier.dragContainer(dragDropState).padding(horizontal = 8.dp),
|
||||||
state = gridState,
|
state = gridState,
|
||||||
contentPadding = PaddingValues(16.dp),
|
contentPadding = PaddingValues(8.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
|
||||||
) {
|
) {
|
||||||
itemsIndexed(items, key = { _, item ->
|
itemsIndexed(items, key = { _, item ->
|
||||||
@@ -122,7 +125,7 @@ fun LazyGridItemScope.DraggableItem(
|
|||||||
} else {
|
} else {
|
||||||
Modifier.animateItemPlacement()
|
Modifier.animateItemPlacement()
|
||||||
}
|
}
|
||||||
Box(modifier = modifier.then(draggingModifier), propagateMinConstraints = true) {
|
Box(modifier = modifier.then(draggingModifier).clip(RoundedCornerShape(8.dp)), propagateMinConstraints = true) {
|
||||||
content(dragging)
|
content(dragging)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,10 +57,29 @@ fun CustomAsyncImage(
|
|||||||
|
|
||||||
val imageLoader = getImageLoader(context ?: localContext)
|
val imageLoader = getImageLoader(context ?: localContext)
|
||||||
|
|
||||||
|
// 处理 imageUrl 为 null 的情况
|
||||||
|
if (imageUrl == null|| imageUrl == "") {
|
||||||
|
// 如果 imageUrl 为 null 且有占位符,则直接显示占位符
|
||||||
|
if (placeholderRes != null) {
|
||||||
|
androidx.compose.foundation.Image(
|
||||||
|
painter = androidx.compose.ui.res.painterResource(placeholderRes),
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
modifier = modifier,
|
||||||
|
contentScale = contentScale
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = ImageRequest.Builder(context ?: localContext)
|
model = ImageRequest.Builder(context ?: localContext)
|
||||||
.data(imageUrl)
|
.data(imageUrl)
|
||||||
.crossfade(200)
|
.crossfade(200)
|
||||||
|
.apply {
|
||||||
|
// 设置占位符图片
|
||||||
|
if (placeholderRes != null) {
|
||||||
|
placeholder(placeholderRes)
|
||||||
|
}
|
||||||
|
}
|
||||||
.build(),
|
.build(),
|
||||||
contentDescription = contentDescription,
|
contentDescription = contentDescription,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
@@ -32,6 +33,9 @@ import androidx.compose.ui.unit.sp
|
|||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 水平布局的输入框
|
||||||
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun FormTextInput(
|
fun FormTextInput(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@@ -39,6 +43,7 @@ fun FormTextInput(
|
|||||||
label: String? = null,
|
label: String? = null,
|
||||||
error: String? = null,
|
error: String? = null,
|
||||||
hint: String? = null,
|
hint: String? = null,
|
||||||
|
background: Color? = null,
|
||||||
onValueChange: (String) -> Unit
|
onValueChange: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
@@ -48,7 +53,7 @@ fun FormTextInput(
|
|||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(16.dp))
|
.clip(RoundedCornerShape(16.dp))
|
||||||
.background(AppColors.inputBackground)
|
.background(background ?: AppColors.inputBackground)
|
||||||
.let {
|
.let {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
it.border(1.dp, AppColors.error, RoundedCornerShape(24.dp))
|
it.border(1.dp, AppColors.error, RoundedCornerShape(24.dp))
|
||||||
@@ -66,7 +71,7 @@ fun FormTextInput(
|
|||||||
.widthIn(100.dp),
|
.widthIn(100.dp),
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.W600,
|
||||||
color = AppColors.text
|
color = AppColors.text
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
package com.aiosman.ravenow.ui.composables.form
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedContent
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.widthIn
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
|
import com.aiosman.ravenow.R
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 垂直布局的输入框
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun FormTextInput2(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
value: String,
|
||||||
|
label: String? = null,
|
||||||
|
error: String? = null,
|
||||||
|
hint: String? = null,
|
||||||
|
background: Color? = null,
|
||||||
|
onValueChange: (String) -> Unit
|
||||||
|
) {
|
||||||
|
val AppColors = LocalAppTheme.current
|
||||||
|
Column(
|
||||||
|
modifier = modifier.height(150.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
.clip(RoundedCornerShape(16.dp))
|
||||||
|
.background(background ?: AppColors.inputBackground)
|
||||||
|
.let {
|
||||||
|
if (error != null) {
|
||||||
|
it.border(1.dp, AppColors.error, RoundedCornerShape(24.dp))
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(17.dp),
|
||||||
|
|
||||||
|
) {
|
||||||
|
label?.let {
|
||||||
|
Text(
|
||||||
|
text = it,
|
||||||
|
modifier = Modifier
|
||||||
|
.widthIn(100.dp),
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.W600,
|
||||||
|
color = AppColors.text
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(top = 8.dp)
|
||||||
|
) {
|
||||||
|
if (value.isEmpty()) {
|
||||||
|
Text(
|
||||||
|
text = hint ?: "",
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = AppColors.inputHint
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicTextField(
|
||||||
|
maxLines = 5,
|
||||||
|
value = value,
|
||||||
|
onValueChange = {
|
||||||
|
onValueChange(it)
|
||||||
|
},
|
||||||
|
textStyle = TextStyle(
|
||||||
|
fontSize = 16.sp,
|
||||||
|
fontWeight = FontWeight.Normal,
|
||||||
|
color = AppColors.text,
|
||||||
|
lineHeight = 20.sp
|
||||||
|
),
|
||||||
|
cursorBrush = SolidColor(AppColors.text),
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = error != null,
|
||||||
|
enter = fadeIn(),
|
||||||
|
exit = fadeOut()
|
||||||
|
) {
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.rider_pro_input_error),
|
||||||
|
contentDescription = "Error",
|
||||||
|
modifier = Modifier.size(8.dp)
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.size(4.dp))
|
||||||
|
AnimatedContent(targetState = error) { targetError ->
|
||||||
|
Text(targetError ?: "", color = AppColors.error, fontSize = 12.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -62,16 +62,16 @@ fun Agent() {
|
|||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(36.dp) // 设置高度为36dp
|
.height(36.dp)
|
||||||
.fillMaxWidth(), // 占据整行宽度
|
.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Start,
|
horizontalArrangement = Arrangement.Start,
|
||||||
verticalAlignment = Alignment.Bottom
|
verticalAlignment = Alignment.Bottom
|
||||||
) {
|
) {
|
||||||
// 搜索框 - 占据剩余空间
|
// 搜索框
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(36.dp)
|
.height(36.dp)
|
||||||
.weight(1f) // 权重为1,占据剩余空间
|
.weight(1f)
|
||||||
.clip(shape = RoundedCornerShape(18.dp))
|
.clip(shape = RoundedCornerShape(18.dp))
|
||||||
.background(AppColors.inputBackground)
|
.background(AppColors.inputBackground)
|
||||||
.padding(horizontal = 8.dp, vertical = 0.dp)
|
.padding(horizontal = 8.dp, vertical = 0.dp)
|
||||||
@@ -94,16 +94,13 @@ fun Agent() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 间隔
|
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
||||||
// 新增
|
// 新增
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(36.dp)
|
.size(36.dp)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
// 图标点击事件
|
//
|
||||||
navController.navigate(
|
navController.navigate(
|
||||||
NavigationRoute.AddAgent.route
|
NavigationRoute.AddAgent.route
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.aiosman.ravenow.ui.index.tabs.message
|
package com.aiosman.ravenow.ui.index.tabs.message
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -14,7 +15,10 @@ 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.layout.size
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
@@ -28,6 +32,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
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
|
||||||
@@ -60,13 +65,15 @@ import kotlinx.coroutines.launch
|
|||||||
/**
|
/**
|
||||||
* 消息列表界面
|
* 消息列表界面
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun NotificationsScreen() {
|
fun NotificationsScreen() {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
var pagerState = rememberPagerState (pageCount = { 4 })
|
||||||
|
var scope = rememberCoroutineScope()
|
||||||
val state = rememberPullRefreshState(MessageListViewModel.isLoading, onRefresh = {
|
val state = rememberPullRefreshState(MessageListViewModel.isLoading, onRefresh = {
|
||||||
MessageListViewModel.viewModelScope.launch {
|
MessageListViewModel.viewModelScope.launch {
|
||||||
MessageListViewModel.initData(context, force = true, loadChat = AppState.enableChat)
|
MessageListViewModel.initData(context, force = true, loadChat = AppState.enableChat)
|
||||||
@@ -96,10 +103,9 @@ fun NotificationsScreen() {
|
|||||||
.padding(horizontal = 15.dp, vertical = 8.dp),
|
.padding(horizontal = 15.dp, vertical = 8.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
// 左侧占位元素
|
|
||||||
Box(modifier = Modifier.size(24.dp))
|
Box(modifier = Modifier.size(24.dp))
|
||||||
|
|
||||||
// 左侧 Column:label 居中显示
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
@@ -113,7 +119,7 @@ fun NotificationsScreen() {
|
|||||||
color = AppColors.text
|
color = AppColors.text
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// 右侧图标
|
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_group),
|
painter = painterResource(id = R.drawable.rider_pro_group),
|
||||||
contentDescription = "add",
|
contentDescription = "add",
|
||||||
@@ -169,8 +175,111 @@ fun NotificationsScreen() {
|
|||||||
navController.navigate(NavigationRoute.CommentNoticeScreen.route)
|
navController.navigate(NavigationRoute.CommentNoticeScreen.route)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HorizontalDivider(color = AppColors.divider, modifier = Modifier.padding(16.dp))
|
Row(
|
||||||
Box(
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
// center the tabs
|
||||||
|
horizontalArrangement = Arrangement.Start,
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.noRippleClickable {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(0)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.chat_ai),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = if (pagerState.currentPage == 0) AppColors.mainText else AppColors.checkedBackground,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(if (pagerState.currentPage == 0) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
|
.padding(horizontal = 11.dp, vertical = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.noRippleClickable {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
|
||||||
|
) {
|
||||||
|
androidx.compose.material.Text(
|
||||||
|
text = stringResource(R.string.chat_group),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = if (pagerState.currentPage == 1) AppColors.mainText else AppColors.checkedBackground,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(if (pagerState.currentPage == 1) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
|
.padding(horizontal = 11.dp, vertical = 4.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.noRippleClickable {
|
||||||
|
scope.launch {
|
||||||
|
pagerState.animateScrollToPage(2)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
|
||||||
|
) {
|
||||||
|
androidx.compose.material.Text(
|
||||||
|
text = stringResource(R.string.chat_friend),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
color = if (pagerState.currentPage == 2) AppColors.mainText else AppColors.checkedBackground,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(8.dp))
|
||||||
|
.background(if (pagerState.currentPage == 2) AppColors.checkedBackground else AppColors.unCheckedBackground)
|
||||||
|
.padding(horizontal = 11.dp, vertical = 4.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
HorizontalPager(
|
||||||
|
state = pagerState,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
) {
|
||||||
|
when (it) {
|
||||||
|
0 -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
2 -> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
@@ -194,7 +303,7 @@ fun NotificationsScreen() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
PullRefreshIndicator(
|
PullRefreshIndicator(
|
||||||
MessageListViewModel.isLoading,
|
MessageListViewModel.isLoading,
|
||||||
@@ -226,28 +335,14 @@ fun NotificationIndicator(
|
|||||||
onClick()
|
onClick()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (notificationCount > 0) {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.background(AppColors.main, RoundedCornerShape(16.dp))
|
|
||||||
.padding(4.dp)
|
|
||||||
.align(Alignment.TopEnd)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = notificationCount.toString(),
|
|
||||||
color = AppColors.mainText,
|
|
||||||
fontSize = 10.sp,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
modifier = Modifier.align(Alignment.Center)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(64.dp)
|
.size(69.dp)
|
||||||
|
.padding(5.dp)
|
||||||
.background(color = backgroundColor,
|
.background(color = backgroundColor,
|
||||||
shape = RoundedCornerShape(16.dp)),
|
shape = RoundedCornerShape(16.dp)),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
@@ -265,6 +360,22 @@ fun NotificationIndicator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (notificationCount > 0) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(AppColors.main, RoundedCornerShape(16.dp))
|
||||||
|
.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = if (notificationCount > 99) "99+" else notificationCount.toString(),
|
||||||
|
color = AppColors.mainText,
|
||||||
|
fontSize = 10.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.align(Alignment.Center)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import android.net.Uri
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.animation.core.LinearEasing
|
||||||
|
import androidx.compose.animation.core.RepeatMode
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.animation.core.infiniteRepeatable
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -31,6 +36,8 @@ import androidx.compose.material3.BasicAlertDialog
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
|
import androidx.compose.material3.Switch
|
||||||
|
import androidx.compose.material3.SwitchDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -42,6 +49,8 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.drawBehind
|
import androidx.compose.ui.draw.drawBehind
|
||||||
|
import androidx.compose.ui.draw.rotate
|
||||||
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.geometry.CornerRadius
|
import androidx.compose.ui.geometry.CornerRadius
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -49,20 +58,25 @@ import androidx.compose.ui.graphics.ColorFilter
|
|||||||
import androidx.compose.ui.graphics.PathEffect
|
import androidx.compose.ui.graphics.PathEffect
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.aiosman.ravenow.AppState
|
import com.aiosman.ravenow.AppState
|
||||||
import com.aiosman.ravenow.LocalAppTheme
|
import com.aiosman.ravenow.LocalAppTheme
|
||||||
import com.aiosman.ravenow.LocalNavController
|
import com.aiosman.ravenow.LocalNavController
|
||||||
import com.aiosman.ravenow.R
|
import com.aiosman.ravenow.R
|
||||||
|
import com.aiosman.ravenow.entity.createAgent
|
||||||
import com.aiosman.ravenow.ui.NavigationRoute
|
import com.aiosman.ravenow.ui.NavigationRoute
|
||||||
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
import com.aiosman.ravenow.ui.composables.CustomAsyncImage
|
||||||
import com.aiosman.ravenow.ui.composables.DraggableGrid
|
import com.aiosman.ravenow.ui.composables.DraggableGrid
|
||||||
@@ -78,6 +92,10 @@ import java.io.File
|
|||||||
@Composable
|
@Composable
|
||||||
fun NewPostScreen() {
|
fun NewPostScreen() {
|
||||||
val AppColors = LocalAppTheme.current
|
val AppColors = LocalAppTheme.current
|
||||||
|
var isAiEnabled by remember { mutableStateOf(false) }
|
||||||
|
var isRotating by remember { mutableStateOf(false) }
|
||||||
|
var isRequesting by remember { mutableStateOf(false) }
|
||||||
|
val keyboardController = LocalSoftwareKeyboardController.current // 添加这行
|
||||||
|
|
||||||
val model = NewPostViewModel
|
val model = NewPostViewModel
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
@@ -102,9 +120,6 @@ fun NewPostScreen() {
|
|||||||
) {
|
) {
|
||||||
NewPostTopBar {
|
NewPostTopBar {
|
||||||
}
|
}
|
||||||
NewPostTextField("Share your adventure…", NewPostViewModel.textContent) {
|
|
||||||
NewPostViewModel.textContent = it
|
|
||||||
}
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -128,7 +143,168 @@ fun NewPostScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddImageGrid()
|
AddImageGrid()
|
||||||
// AdditionalPostItem()
|
NewPostTextField(stringResource(R.string.moment_content_hint), NewPostViewModel.textContent) {
|
||||||
|
NewPostViewModel.textContent = it
|
||||||
|
}
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(1.dp)
|
||||||
|
.background(AppColors.divider)
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 8.dp, start = 16.dp, end = 16.dp, bottom = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.rider_pro_moment_ai),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(24.dp)
|
||||||
|
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.moment_ai_co),
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(start = 8.dp)
|
||||||
|
.weight(1f),
|
||||||
|
color = AppColors.text,
|
||||||
|
)
|
||||||
|
Switch(
|
||||||
|
checked = isAiEnabled,
|
||||||
|
onCheckedChange = {
|
||||||
|
isChecked ->
|
||||||
|
isAiEnabled = isChecked
|
||||||
|
if (isChecked) {
|
||||||
|
// 收起键盘
|
||||||
|
keyboardController?.hide()
|
||||||
|
isRequesting = true
|
||||||
|
isRotating = true
|
||||||
|
model.viewModelScope.launch {
|
||||||
|
try {
|
||||||
|
model.agentMoment(model.textContent)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}finally {
|
||||||
|
isRequesting = false
|
||||||
|
isRotating = false
|
||||||
|
isAiEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enabled = !isRequesting && model.textContent.isNotEmpty(),
|
||||||
|
colors = SwitchDefaults.colors(
|
||||||
|
checkedThumbColor = Color.White,
|
||||||
|
checkedTrackColor = AppColors.brandColorsColor,
|
||||||
|
uncheckedThumbColor = Color.White,
|
||||||
|
uncheckedTrackColor = Color(0xFFE9E9EA),
|
||||||
|
uncheckedBorderColor = Color.White,
|
||||||
|
disabledCheckedTrackColor = AppColors.brandColorsColor.copy(alpha = 0.8f),
|
||||||
|
disabledCheckedThumbColor= Color.White,
|
||||||
|
disabledUncheckedTrackColor = Color(0xFFE9E9EA),
|
||||||
|
disabledUncheckedThumbColor= Color.White
|
||||||
|
|
||||||
|
),
|
||||||
|
modifier = Modifier.scale(0.8f)
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
BasicTextField(
|
||||||
|
value = model.aiTextContent,
|
||||||
|
onValueChange = { newValue ->
|
||||||
|
model.aiTextContent = newValue
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.height(160.dp)
|
||||||
|
.heightIn(160.dp)
|
||||||
|
.padding(horizontal = 16.dp, vertical = 10.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
cursorBrush = SolidColor(AppColors.text),
|
||||||
|
textStyle = TextStyle(
|
||||||
|
lineHeight = 24.sp,
|
||||||
|
color = AppColors.text,
|
||||||
|
),
|
||||||
|
readOnly = true
|
||||||
|
)
|
||||||
|
if (model.aiTextContent.isNotEmpty()) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
horizontalArrangement = Arrangement.End // 靠右对齐
|
||||||
|
) {
|
||||||
|
// 删除按钮
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.noRippleClickable {
|
||||||
|
model.aiTextContent = ""
|
||||||
|
}
|
||||||
|
.background(
|
||||||
|
color = AppColors.basicMain,
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_moment_delete),
|
||||||
|
contentDescription = "delete",
|
||||||
|
modifier = Modifier.size(16.dp),
|
||||||
|
tint = AppColors.text
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.moment_ai_delete),
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = AppColors.text,
|
||||||
|
modifier = Modifier.padding(start = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(14.dp))
|
||||||
|
//应用生成文案
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.noRippleClickable {
|
||||||
|
if (model.aiTextContent.isNotEmpty()) {
|
||||||
|
model.textContent = model.aiTextContent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.background(
|
||||||
|
color = AppColors.basicMain,
|
||||||
|
shape = RoundedCornerShape(16.dp)
|
||||||
|
)
|
||||||
|
.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.rider_pro_moment_apply),
|
||||||
|
contentDescription = "apply",
|
||||||
|
modifier = Modifier.size(16.dp),
|
||||||
|
tint = AppColors.text
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.moment_ai_apply),
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = AppColors.text,
|
||||||
|
modifier = Modifier.padding(start = 4.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,7 +348,7 @@ fun NewPostTopBar(onSendClick: () -> Unit = {}) {
|
|||||||
modifier = Modifier.align(Alignment.CenterStart),
|
modifier = Modifier.align(Alignment.CenterStart),
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_back_icon),
|
painter = painterResource(id = R.drawable.rider_pro_close),
|
||||||
contentDescription = "Back",
|
contentDescription = "Back",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(24.dp)
|
.size(24.dp)
|
||||||
@@ -182,12 +358,11 @@ fun NewPostTopBar(onSendClick: () -> Unit = {}) {
|
|||||||
colorFilter = ColorFilter.tint(AppColors.text)
|
colorFilter = ColorFilter.tint(AppColors.text)
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Icon(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.rider_pro_video_share),
|
painter = painterResource(id = R.mipmap.rider_pro_moment_post),
|
||||||
tint = AppColors.text,
|
|
||||||
contentDescription = "Send",
|
contentDescription = "Send",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(32.dp)
|
.size(24.dp)
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
// 检查输入
|
// 检查输入
|
||||||
val errorMessage = model.validateMoment()
|
val errorMessage = model.validateMoment()
|
||||||
@@ -208,7 +383,7 @@ fun NewPostTopBar(onSendClick: () -> Unit = {}) {
|
|||||||
uploading = false
|
uploading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传完成后隐藏进度条
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,13 +402,15 @@ fun NewPostTextField(hint: String, value: String, onValueChange: (String) -> Uni
|
|||||||
value = value,
|
value = value,
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.height(160.dp)
|
||||||
.heightIn(200.dp)
|
.heightIn(160.dp)
|
||||||
.padding(horizontal = 18.dp, vertical = 10.dp),
|
.padding(horizontal = 16.dp, vertical = 10.dp),
|
||||||
cursorBrush = SolidColor(AppColors.text),
|
cursorBrush = SolidColor(AppColors.text),
|
||||||
textStyle = TextStyle(
|
textStyle = TextStyle(
|
||||||
|
lineHeight = 24.sp,
|
||||||
color = AppColors.text,
|
color = AppColors.text,
|
||||||
)
|
|
||||||
|
),
|
||||||
|
|
||||||
)
|
)
|
||||||
if (value.isEmpty()) {
|
if (value.isEmpty()) {
|
||||||
@@ -326,11 +503,11 @@ fun AddImageGrid() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Fixed(3),
|
columns = GridCells.Fixed(5),
|
||||||
contentPadding = PaddingValues(16.dp),
|
contentPadding = PaddingValues(8.dp),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(18.dp),
|
.padding(horizontal = 8.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
@@ -339,18 +516,8 @@ fun AddImageGrid() {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.aspectRatio(1f)
|
.aspectRatio(1f)
|
||||||
.drawBehind {
|
.clip(RoundedCornerShape(16.dp)) // 设置圆角
|
||||||
val strokeWidth = 1.dp.toPx()
|
.background(Color(0xFFFAF9FB)) // 设置背景色
|
||||||
val dashLength = 10f
|
|
||||||
val dashGap = 10f
|
|
||||||
val pathEffect =
|
|
||||||
PathEffect.dashPathEffect(floatArrayOf(dashLength, dashGap))
|
|
||||||
drawRoundRect(
|
|
||||||
color = Color(0xFFD6D6D6),
|
|
||||||
style = Stroke(strokeWidth, pathEffect = pathEffect),
|
|
||||||
cornerRadius = CornerRadius(8.dp.toPx())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
pickImagesLauncher.launch("image/*")
|
pickImagesLauncher.launch("image/*")
|
||||||
},
|
},
|
||||||
@@ -359,7 +526,7 @@ fun AddImageGrid() {
|
|||||||
painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
|
painter = painterResource(id = R.drawable.rider_pro_new_post_add_pic),
|
||||||
contentDescription = "Add Image",
|
contentDescription = "Add Image",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(48.dp)
|
.size(24.dp)
|
||||||
.align(Alignment.Center),
|
.align(Alignment.Center),
|
||||||
tint = Color(0xFFD6D6D6)
|
tint = Color(0xFFD6D6D6)
|
||||||
|
|
||||||
@@ -371,18 +538,8 @@ fun AddImageGrid() {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.aspectRatio(1f)
|
.aspectRatio(1f)
|
||||||
.drawBehind {
|
.clip(RoundedCornerShape(16.dp)) // 设置圆角
|
||||||
val strokeWidth = 1.dp.toPx()
|
.background(Color(0xFFFAF9FB)) // 设置背景色
|
||||||
val dashLength = 10f
|
|
||||||
val dashGap = 10f
|
|
||||||
val pathEffect =
|
|
||||||
PathEffect.dashPathEffect(floatArrayOf(dashLength, dashGap))
|
|
||||||
drawRoundRect(
|
|
||||||
color = Color(0xFFD6D6D6),
|
|
||||||
style = Stroke(strokeWidth, pathEffect = pathEffect),
|
|
||||||
cornerRadius = CornerRadius(8.dp.toPx())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.noRippleClickable {
|
.noRippleClickable {
|
||||||
val photoFile = File(context.cacheDir, "photo.jpg")
|
val photoFile = File(context.cacheDir, "photo.jpg")
|
||||||
val photoUri: Uri = FileProvider.getUriForFile(
|
val photoUri: Uri = FileProvider.getUriForFile(
|
||||||
@@ -398,7 +555,7 @@ fun AddImageGrid() {
|
|||||||
painter = painterResource(id = R.drawable.rider_pro_camera),
|
painter = painterResource(id = R.drawable.rider_pro_camera),
|
||||||
contentDescription = "Take Photo",
|
contentDescription = "Take Photo",
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(48.dp)
|
.size(24.dp)
|
||||||
.align(Alignment.Center),
|
.align(Alignment.Center),
|
||||||
tint = Color(0xFFD6D6D6)
|
tint = Color(0xFFD6D6D6)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,12 +8,18 @@ import android.net.Uri
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.aiosman.ravenow.data.MomentService
|
import com.aiosman.ravenow.data.MomentService
|
||||||
|
import com.aiosman.ravenow.data.ServiceException
|
||||||
import com.aiosman.ravenow.data.UploadImage
|
import com.aiosman.ravenow.data.UploadImage
|
||||||
|
import com.aiosman.ravenow.data.api.ApiClient
|
||||||
|
import com.aiosman.ravenow.entity.AccountProfileEntity
|
||||||
|
import com.aiosman.ravenow.entity.AgentEntity
|
||||||
import com.aiosman.ravenow.entity.MomentEntity
|
import com.aiosman.ravenow.entity.MomentEntity
|
||||||
import com.aiosman.ravenow.entity.MomentServiceImpl
|
import com.aiosman.ravenow.entity.MomentServiceImpl
|
||||||
|
import com.aiosman.ravenow.entity.createMultipartBody
|
||||||
import com.aiosman.ravenow.event.MomentAddEvent
|
import com.aiosman.ravenow.event.MomentAddEvent
|
||||||
import com.aiosman.ravenow.exp.rotate
|
import com.aiosman.ravenow.exp.rotate
|
||||||
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
import com.aiosman.ravenow.ui.index.tabs.profile.MyProfileViewModel
|
||||||
@@ -21,6 +27,9 @@ import com.aiosman.ravenow.ui.modification.Modification
|
|||||||
import com.aiosman.ravenow.utils.FileUtil
|
import com.aiosman.ravenow.utils.FileUtil
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
@@ -96,6 +105,7 @@ data class Draft(
|
|||||||
object NewPostViewModel : ViewModel() {
|
object NewPostViewModel : ViewModel() {
|
||||||
var momentService: MomentService = MomentServiceImpl()
|
var momentService: MomentService = MomentServiceImpl()
|
||||||
var textContent by mutableStateOf("")
|
var textContent by mutableStateOf("")
|
||||||
|
var aiTextContent by mutableStateOf("")
|
||||||
var searchPlaceAddressResult by mutableStateOf<SearchPlaceAddressResult?>(null)
|
var searchPlaceAddressResult by mutableStateOf<SearchPlaceAddressResult?>(null)
|
||||||
var modificationList by mutableStateOf<List<Modification>>(listOf())
|
var modificationList by mutableStateOf<List<Modification>>(listOf())
|
||||||
var imageList by mutableStateOf(listOf<ImageItem>())
|
var imageList by mutableStateOf(listOf<ImageItem>())
|
||||||
@@ -111,6 +121,7 @@ object NewPostViewModel : ViewModel() {
|
|||||||
// }
|
// }
|
||||||
fun asNewPost() {
|
fun asNewPost() {
|
||||||
textContent = ""
|
textContent = ""
|
||||||
|
aiTextContent = ""
|
||||||
searchPlaceAddressResult = null
|
searchPlaceAddressResult = null
|
||||||
modificationList = listOf()
|
modificationList = listOf()
|
||||||
imageList = listOf()
|
imageList = listOf()
|
||||||
@@ -163,12 +174,17 @@ object NewPostViewModel : ViewModel() {
|
|||||||
onUploadProgress(((index / imageList.size).toFloat())) // progressValue 是当前上传进度,例如 0.5 表示 50%
|
onUploadProgress(((index / imageList.size).toFloat())) // progressValue 是当前上传进度,例如 0.5 表示 50%
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
|
aiTextContent = ""
|
||||||
val result = momentService.createMoment(textContent, 1, uploadImageList, relPostId)
|
val result = momentService.createMoment(textContent, 1, uploadImageList, relPostId)
|
||||||
// 刷新个人动态
|
// 刷新个人动态
|
||||||
MyProfileViewModel.loadProfile(pullRefresh = true)
|
MyProfileViewModel.loadProfile(pullRefresh = true)
|
||||||
EventBus.getDefault().post(MomentAddEvent(result))
|
EventBus.getDefault().post(MomentAddEvent(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun agentMoment(textContent: String,) {
|
||||||
|
aiTextContent = momentService.agentMoment(textContent)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun init() {
|
suspend fun init() {
|
||||||
relPostId?.let {
|
relPostId?.let {
|
||||||
val moment = momentService.getMomentById(it)
|
val moment = momentService.getMomentById(it)
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
|
||||||
android:pathData="M9.5,6L12.5,10L15.5,6L19,6L14.5,12L19,18L15.5,18L12.5,14L9.5,18L6,18L10.5,12L6,6L9.5,6Z"
|
<group
|
||||||
android:strokeWidth="1"
|
android:translateX="-16"
|
||||||
android:fillColor="#000000"
|
android:translateY="-64">
|
||||||
android:fillType="evenOdd"
|
<group
|
||||||
android:strokeColor="#00000000"/>
|
android:translateX="16"
|
||||||
</vector>
|
android:translateY="64">
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z" />
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeColor="#000000"
|
||||||
|
android:strokeWidth="3"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeLineCap="round"
|
||||||
|
android:pathData="M 18 6 L 6 18" />
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeColor="#000000"
|
||||||
|
android:strokeWidth="3"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeLineCap="round"
|
||||||
|
android:pathData="M 6 6 L 18 18" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -7,32 +7,27 @@
|
|||||||
|
|
||||||
<group
|
<group
|
||||||
android:translateX="2"
|
android:translateX="2"
|
||||||
android:translateY="4">
|
android:translateY="2.945">
|
||||||
<path
|
<path
|
||||||
android:fillType="evenOdd"
|
android:fillType="evenOdd"
|
||||||
android:strokeColor="#000"
|
android:strokeColor="#000"
|
||||||
android:strokeWidth="1.778"
|
android:strokeWidth="2"
|
||||||
android:pathData="M7.273 10.777c4.016 0 7.272 1.791 7.272 4 0 0.706-0.331 1.368-0.914 1.944-0.392 0.179 -0.828 0.278 -1.288 0.278 H2.202a3.1 3.1 0 0 1-1.288-0.278C0.332 16.145 0 15.483 0 14.777c0-2.209 3.256-4 7.273-4z" />
|
android:pathData="M13 14.055c3.314 0 6 1.44 6 3.215 0 0.564-0.272 1.095-0.749 1.556-0.324 0.147 -0.684 0.23 -1.063 0.23 H8.812c-0.379 0-0.739-0.083-1.062-0.23-0.478-0.461-0.75-0.992-0.75-1.556 0-1.775 2.686-3.215 6-3.215zm0-3a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" />
|
||||||
<path
|
<path
|
||||||
android:fillType="evenOdd"
|
android:fillType="evenOdd"
|
||||||
android:strokeColor="#000"
|
android:strokeColor="#000"
|
||||||
android:strokeWidth="1.778"
|
android:strokeWidth="2"
|
||||||
android:strokeLineJoin="round"
|
android:pathData="M 5 2.056 C 6.38071187458 2.056 7.5 3.20707590819 7.5 4.627 C 7.5 6.04692409181 6.38071187458 7.198 5 7.198 C 3.61928812542 7.198 2.5 6.04692409181 2.5 4.627 C 2.5 3.20707590819 3.61928812542 2.056 5 2.056 Z" />
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeWidth="2"
|
||||||
|
android:pathData="M5.677 14.055H1.51c-0.312 0-0.608-0.066-0.875-0.187C0.23 13.471 0 13.013 0 12.525 0 11.003 2.239 9.77 5 9.77c1.558 0 2.95 0.393 3.867 1.008" />
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeColor="#110C13"
|
||||||
|
android:strokeWidth="1.5"
|
||||||
android:strokeLineCap="round"
|
android:strokeLineCap="round"
|
||||||
android:pathData="M16.491 17h1.236c0.5 0 2.273-0.398 2.273-2.223 0-1.49-1.482-2.79-3.68-3.478" />
|
android:pathData="M16.364 2h4M18.364 0v4" />
|
||||||
<path
|
|
||||||
android:fillType="evenOdd"
|
|
||||||
android:strokeColor="#000"
|
|
||||||
android:strokeWidth="1.778"
|
|
||||||
android:strokeLineJoin="round"
|
|
||||||
android:strokeLineCap="round"
|
|
||||||
android:pathData="M 7.273 0 C 9.28110735038 0 10.909 1.59162771435 10.909 3.555 C 10.909 5.51837228565 9.28110735038 7.11 7.273 7.11 C 5.26489264962 7.11 3.637 5.51837228565 3.637 3.555 C 3.637 1.59162771435 5.26489264962 0 7.273 0 Z" />
|
|
||||||
<path
|
|
||||||
android:fillType="evenOdd"
|
|
||||||
android:strokeColor="#000"
|
|
||||||
android:strokeWidth="1.778"
|
|
||||||
android:strokeLineJoin="round"
|
|
||||||
android:strokeLineCap="round"
|
|
||||||
android:pathData="M13.636 0.116 c1.61 0.402 2.735 1.82 2.735 3.444 0 1.624-1.126 3.041-2.735 3.444" />
|
|
||||||
</group>
|
</group>
|
||||||
</vector>
|
</vector>
|
||||||
32
app/src/main/res/drawable/rider_pro_moment_apply.xml
Normal file
32
app/src/main/res/drawable/rider_pro_moment_apply.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:pathData="M0,0 L16,0 L16,16 L0,16 Z" />
|
||||||
|
<path
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:strokeColor="#000000"
|
||||||
|
android:strokeWidth="1.33333333"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeLineCap="round"
|
||||||
|
android:pathData="M14,2 L9.66667,14 C9.60694,14.1303,9.47671,14.2139,9.33333,14.2139
|
||||||
|
C9.18996,14.2139,9.05973,14.1303,9,14 L6.66667,9.33333 L2,7
|
||||||
|
C1.86966,6.94027,1.78609,6.81004,1.78609,6.66667
|
||||||
|
C1.78609,6.52329,1.86966,6.39306,2,6.33333 L14,2" />
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_moment_ai.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_moment_ai.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_moment_post.png
Normal file
BIN
app/src/main/res/mipmap-xhdpi/rider_pro_moment_post.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -125,5 +125,13 @@
|
|||||||
<string name="agent_desc">设定描述</string>
|
<string name="agent_desc">设定描述</string>
|
||||||
<string name="agent_desc_hint">示例: 一位经验丰富的销售员,擅长通过幽默风趣的语言和生动的案例,将复杂的产品转化为客户易于理解并感兴趣的话题</string>
|
<string name="agent_desc_hint">示例: 一位经验丰富的销售员,擅长通过幽默风趣的语言和生动的案例,将复杂的产品转化为客户易于理解并感兴趣的话题</string>
|
||||||
<string name="agent_create">创建智能体</string>
|
<string name="agent_create">创建智能体</string>
|
||||||
|
<string name="moment_content_hint">需要一些灵感来写文章吗?让人工智能来帮你!</string>
|
||||||
|
<string name="moment_ai_co">AI文案优化</string>
|
||||||
|
<string name="moment_ai_delete">删除</string>
|
||||||
|
<string name="moment_ai_apply">应用</string>
|
||||||
|
<string name="chat_ai">智能体</string>
|
||||||
|
<string name="chat_group">群聊</string>
|
||||||
|
<string name="chat_friend">朋友</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -124,4 +124,11 @@
|
|||||||
<string name="agent_desc">设定描述</string>
|
<string name="agent_desc">设定描述</string>
|
||||||
<string name="agent_desc_hint">示例: 一位经验丰富的销售员,擅长通过幽默风趣的语言和生动的案例,将复杂的产品转化为客户易于理解并感兴趣的话题</string>
|
<string name="agent_desc_hint">示例: 一位经验丰富的销售员,擅长通过幽默风趣的语言和生动的案例,将复杂的产品转化为客户易于理解并感兴趣的话题</string>
|
||||||
<string name="agent_create">创建智能体</string>
|
<string name="agent_create">创建智能体</string>
|
||||||
|
<string name="moment_content_hint">Need some inspiration for your post? Let AI assist you!</string>
|
||||||
|
<string name="moment_ai_co">AI copywriting optimization</string>
|
||||||
|
<string name="moment_ai_delete">Delete</string>
|
||||||
|
<string name="moment_ai_apply">Apply</string>
|
||||||
|
<string name="chat_ai">Ai</string>
|
||||||
|
<string name="chat_group">Group</string>
|
||||||
|
<string name="chat_friend">Friends</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user