优化配置页面和首页布局:添加自定义提示词功能,简化UI设计,去掉圆角边框,添加返回首页按钮
This commit is contained in:
@@ -6,85 +6,114 @@ import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.util.Log
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var inputEditText: EditText
|
||||
private lateinit var configButton: Button
|
||||
private lateinit var submitToZhiPuAIButton: Button
|
||||
private lateinit var submitToSparkAIButton: Button
|
||||
private lateinit var tabLayout: TabLayout
|
||||
private lateinit var submitToServerButton: Button
|
||||
private lateinit var statusText: TextView
|
||||
private lateinit var outputStatusLabel: TextView
|
||||
private lateinit var outputTextView: TextView
|
||||
private lateinit var promptSelector: Spinner
|
||||
private lateinit var promptContentText: TextView
|
||||
|
||||
// Data classes matching SecondActivity
|
||||
data class HeaderConfig(val key: String, val value: String)
|
||||
data class PromptConfig(val id: String, val title: String, val content: String, val expanded: Boolean = false)
|
||||
data class ButtonConfig(val id: String, val label: String, val action: String, val apiUrl: String? = null, val apiMethod: String? = null, val apiBodyTemplate: String? = null, val expanded: Boolean = false)
|
||||
data class LLMConfig(val baseUrl: String, val apiKey: String, val model: String)
|
||||
data class SettingsData(
|
||||
val llmConfig: LLMConfig?,
|
||||
val headerConfigs: List<HeaderConfig>?,
|
||||
val promptConfigs: List<PromptConfig>?,
|
||||
val buttonConfigs: List<ButtonConfig>?
|
||||
)
|
||||
|
||||
@SuppressLint("MissingInflatedId", "CutPasteId", "SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.d("MainActivity", "onCreate: Starting MainActivity")
|
||||
setContentView(R.layout.activity_main)
|
||||
Log.d("MainActivity", "onCreate: Layout set")
|
||||
|
||||
// Initialize views
|
||||
val promptSelector = findViewById<Spinner>(R.id.promptSelector)
|
||||
val inputEditText = findViewById<EditText>(R.id.inputEditText)
|
||||
promptSelector = findViewById<Spinner>(R.id.promptSelector)
|
||||
promptContentText = findViewById<TextView>(R.id.promptContentText)
|
||||
inputEditText = findViewById<EditText>(R.id.inputEditText)
|
||||
val sendButton = findViewById<Button>(R.id.sendButton)
|
||||
val stopButton = findViewById<Button>(R.id.stopButton)
|
||||
val outputStatusLabel = findViewById<TextView>(R.id.outputStatusLabel)
|
||||
val outputTextView = findViewById<TextView>(R.id.outputTextView)
|
||||
val copyButton = findViewById<Button>(R.id.copyButton)
|
||||
outputStatusLabel = findViewById<TextView>(R.id.outputStatusLabel)
|
||||
outputTextView = findViewById<TextView>(R.id.outputTextView)
|
||||
val btnCopyResult = findViewById<Button>(R.id.btnCopyResult)
|
||||
val headerTitle = findViewById<TextView>(R.id.headerTitle)
|
||||
val headerModelName = findViewById<TextView>(R.id.headerModelName)
|
||||
Log.d("MainActivity", "onCreate: Views initialized")
|
||||
|
||||
// Set header values from JSON
|
||||
headerTitle.text = "AI优化"
|
||||
headerModelName.text = "gpt-4o"
|
||||
|
||||
// Setup prompt selector
|
||||
val promptOptions = listOf("无系统提示词", "翻译助手", "代码解释")
|
||||
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, promptOptions)
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
promptSelector.adapter = adapter
|
||||
promptSelector.setSelection(0) // Default to "无系统提示词"
|
||||
// Load prompts from configuration
|
||||
loadPromptsFromConfig()
|
||||
|
||||
// Setup initial output state
|
||||
outputStatusLabel.text = "等待发送"
|
||||
outputTextView.text = "发送消息后结果将在此显示"
|
||||
|
||||
// Send button click listener
|
||||
// Setup prompt selector listener
|
||||
promptSelector.setOnItemSelectedListener(object : android.widget.AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: android.widget.AdapterView<*>, view: android.view.View?, position: Int, id: Long) {
|
||||
val selectedTitle = promptSelector.getItemAtPosition(position) as String
|
||||
|
||||
// Get the prompt map from tag
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val promptMap = promptSelector.tag as? MutableMap<String, String>
|
||||
|
||||
val content = if (promptMap != null && promptMap.containsKey(selectedTitle)) {
|
||||
promptMap[selectedTitle] ?: "无特殊指令"
|
||||
} else {
|
||||
"无特殊指令"
|
||||
}
|
||||
|
||||
promptContentText.text = content
|
||||
Log.d("MainActivity", "Prompt selected: $selectedTitle, content: $content")
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: android.widget.AdapterView<*>) {
|
||||
promptContentText.text = "无特殊指令"
|
||||
}
|
||||
})
|
||||
|
||||
sendButton.setOnClickListener {
|
||||
Log.d("MainActivity", "Send button clicked")
|
||||
// Test log
|
||||
Log.e("MainActivity", "TEST ERROR LOG")
|
||||
val inputText = inputEditText.text.toString()
|
||||
if (inputText.isNotEmpty()) {
|
||||
outputStatusLabel.text = "连接中…"
|
||||
outputTextView.text = "正在生成..."
|
||||
|
||||
// Simulate API call with coroutine
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
try {
|
||||
// Simulate network delay
|
||||
Log.d("MainActivity", "Starting text processing")
|
||||
delay(1000)
|
||||
|
||||
// For demo purposes, we'll show a sample optimized text
|
||||
val optimizedText = "今天阳光明媚,微风拂面,我漫步于公园之中,享受这难得的惬意时光。"
|
||||
|
||||
outputStatusLabel.text = "已完成"
|
||||
outputTextView.text = optimizedText
|
||||
|
||||
// Update selected prompt ID in JSON structure (simulated)
|
||||
val selectedPromptId = when (promptSelector.selectedItemPosition) {
|
||||
0 -> "none"
|
||||
1 -> "default-1"
|
||||
@@ -92,8 +121,8 @@ class MainActivity : AppCompatActivity() {
|
||||
else -> "none"
|
||||
}
|
||||
|
||||
// In a real app, you would update your JSON state here
|
||||
Log.d("MainActivity", "Selected prompt ID: $selectedPromptId")
|
||||
Log.d("MainActivity", "Text processing completed successfully")
|
||||
} catch (e: Exception) {
|
||||
outputStatusLabel.text = "发生错误"
|
||||
outputTextView.text = "错误: ${e.message}"
|
||||
@@ -101,169 +130,128 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w("MainActivity", "Input text is empty")
|
||||
Toast.makeText(this, "请输入内容", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
// Stop button click listener
|
||||
stopButton.setOnClickListener {
|
||||
Log.d("MainActivity", "Stop button clicked")
|
||||
outputStatusLabel.text = "已停止"
|
||||
Toast.makeText(this, "生成已停止", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// Copy button click listener
|
||||
copyButton.setOnClickListener {
|
||||
val textToCopy = outputTextView.text.toString()
|
||||
if (textToCopy.isNotEmpty() && textToCopy != "发送消息后结果将在此显示") {
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("优化结果", textToCopy)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(this, "结果已复制到剪贴板", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this, "没有可复制的内容", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
// Custom copy result button
|
||||
btnCopyResult.setOnClickListener {
|
||||
Log.d("MainActivity", "btnCopyResult clicked")
|
||||
val textToCopy = outputTextView.text.toString()
|
||||
if (textToCopy.isNotEmpty() && textToCopy != "发送消息后结果将在此显示") {
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("优化结果", textToCopy)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(this, "结果已复制到剪贴板", Toast.LENGTH_SHORT).show()
|
||||
Log.d("MainActivity", "Text copied to clipboard")
|
||||
} else {
|
||||
Toast.makeText(this, "没有可复制的内容", Toast.LENGTH_SHORT).show()
|
||||
Log.w("MainActivity", "No text to copy")
|
||||
}
|
||||
}
|
||||
|
||||
// Keep existing functionality for other buttons (config, etc.)
|
||||
// 点击配置按钮
|
||||
val configButton = findViewById<Button>(R.id.configButton)
|
||||
try {
|
||||
configButton = findViewById<Button>(R.id.configButton)
|
||||
Log.d("MainActivity", "Config button found: $configButton")
|
||||
configButton.setOnClickListener {
|
||||
Log.d("MainActivity", "Config button clicked, launching SecondActivity")
|
||||
Toast.makeText(this, "Opening settings...", Toast.LENGTH_SHORT).show()
|
||||
try {
|
||||
val intent = Intent(this, SecondActivity::class.java)
|
||||
startActivity(intent)
|
||||
Log.d("MainActivity", "SecondActivity started successfully")
|
||||
} catch (e: Exception) {
|
||||
Log.e("MainActivity", "Error starting SecondActivity", e)
|
||||
Toast.makeText(this, "Error opening settings: ${e.message}", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// 提交到flomo的服务器按钮
|
||||
val submitToServerButton = findViewById<Button>(R.id.submitToServerButton)
|
||||
val inputEditText = findViewById<EditText>(R.id.inputEditText)
|
||||
|
||||
submitToServerButton.setOnClickListener {
|
||||
val textFromEditText = inputEditText.text.toString()
|
||||
submitToServer(textFromEditText)
|
||||
}
|
||||
|
||||
// 创建4个按钮 (保留原有的标签功能)
|
||||
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
|
||||
// 维持原来的创建标签按钮的代码
|
||||
(1..4).forEach { tabIndex ->
|
||||
tabLayout.newTab().apply {
|
||||
text = "标签示例$tabIndex"
|
||||
tabLayout.addTab(this)
|
||||
}
|
||||
Log.d("MainActivity", "onCreate: Completed successfully")
|
||||
} catch (e: Exception) {
|
||||
Log.e("MainActivity", "onCreate: Error setting up config button", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == SecondActivity.REQUEST_CODE_PICK_IMAGE && resultCode == Activity.RESULT_OK && data != null) {
|
||||
val selectedImageUri = data.getStringExtra("selectedImageUri")
|
||||
if (selectedImageUri != null) {
|
||||
val imageView = findViewById<ImageView>(R.id.imageViewBackground) // 假设你的背景是一个ImageView
|
||||
imageView.setImageURI(Uri.parse(selectedImageUri))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// 获取从其他 Activity 传递过来的按钮颜色值,如果没有传递颜色值,则默认值为透明色。
|
||||
val statusTextView = findViewById<TextView>(R.id.statusTextView)
|
||||
updateStatusTextViewColor(statusTextView)
|
||||
}
|
||||
|
||||
private fun updateStatusTextViewColor(statusTextView: TextView) {
|
||||
private fun loadPromptsFromConfig() {
|
||||
Log.d("MainActivity", "loadPromptsFromConfig: Starting")
|
||||
try {
|
||||
// Load shared preferences
|
||||
val sharedPrefs = getSharedPreferences("APIConfigs", Context.MODE_PRIVATE)
|
||||
val colorValue = sharedPrefs.getString("buttonColor", "")
|
||||
Log.d("SharedPrefsDebug", "读取颜色值 MainActivity: $colorValue")
|
||||
val json = sharedPrefs.getString("configs", null)
|
||||
|
||||
if (colorValue.isNullOrEmpty()) {
|
||||
statusTextView.setBackgroundResource(android.R.color.holo_blue_dark)
|
||||
} else {
|
||||
// 根据提取的颜色值设置背景颜色,这里只是一个示例,实际应用中可能需要更复杂的逻辑
|
||||
when (colorValue) {
|
||||
"red" -> statusTextView.setBackgroundResource(android.R.color.holo_red_light)
|
||||
"green" -> statusTextView.setBackgroundResource(android.R.color.holo_green_light)
|
||||
"blue" -> statusTextView.setBackgroundResource(android.R.color.holo_blue_light)
|
||||
"orange" -> statusTextView.setBackgroundResource(android.R.color.holo_orange_light)
|
||||
else -> {
|
||||
// 如果颜色值不在预定义的列表中,使用默认颜色
|
||||
statusTextView.setBackgroundResource(android.R.color.holo_blue_dark)
|
||||
Log.e("SharedPrefsError", "Invalid color value: $colorValue")
|
||||
}
|
||||
val promptTitles = mutableListOf<String>()
|
||||
val promptContents = mutableListOf<String>()
|
||||
|
||||
// Add default prompt
|
||||
promptTitles.add("无系统提示词")
|
||||
promptContents.add("无特殊指令")
|
||||
|
||||
if (json != null) {
|
||||
try {
|
||||
val settings = Gson().fromJson(json, SettingsData::class.java)
|
||||
val promptConfigs = settings.promptConfigs ?: listOf()
|
||||
|
||||
for (prompt in promptConfigs) {
|
||||
if (prompt.title.isNotBlank() && prompt.content.isNotBlank()) {
|
||||
promptTitles.add(prompt.title)
|
||||
promptContents.add(prompt.content)
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("MainActivity", "Loaded ${promptConfigs.size} custom prompts from config")
|
||||
} catch (e: Exception) {
|
||||
// 捕获并记录任何异常
|
||||
Log.e("SharedPrefsError", "更新状态文本视图颜色时出错\n: ${e.message}", e)
|
||||
// 设置默认颜色
|
||||
statusTextView.setBackgroundResource(android.R.color.holo_blue_dark)
|
||||
Log.e("MainActivity", "Error loading prompts from config", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBitmapFromUri(uri: Uri): Bitmap? {
|
||||
val inputStream: InputStream? = contentResolver.openInputStream(uri)
|
||||
return BitmapFactory.decodeStream(inputStream)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun submitToServer(content: String) {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
statusText.text = "提交到flomo服务器..."
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
postDataToServer(content)
|
||||
}
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
findViewById<EditText>(R.id.inputEditText).setText("")
|
||||
statusText.text = "提交成功!"
|
||||
}
|
||||
is Result.Error -> {
|
||||
statusText.text = "提交失误: ${result.exception.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提交到笔记服务器,flomo服务器
|
||||
private fun postDataToServer(content: String): Result {
|
||||
return try {
|
||||
val client = OkHttpClient()
|
||||
val mediaType = "application/json".toMediaType()
|
||||
val json = JSONObject().apply {
|
||||
put("content", content)
|
||||
}.toString()
|
||||
val body = json.toRequestBody(mediaType)
|
||||
val request = Request.Builder()
|
||||
.url("https://flomoapp.com/iwh/MTY5NTQy/b671d4930ecd1eae63e50cc0cb8ca4ae/")
|
||||
.post(body)
|
||||
.build()
|
||||
val response = client.newCall(request).execute()
|
||||
if (response.isSuccessful) {
|
||||
Result.Success(response)
|
||||
} else {
|
||||
Result.Error(Exception("服务器返回错误: ${response.code}"))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Result.Error(e)
|
||||
}
|
||||
Log.d("MainActivity", "No saved config found, using default prompts")
|
||||
}
|
||||
|
||||
sealed class Result {
|
||||
data class Success(val response: Response) : Result()
|
||||
data class Error(val exception: Exception) : Result()
|
||||
// Add default prompts if no custom prompts found
|
||||
if (promptTitles.size == 1) {
|
||||
promptTitles.add("翻译助手")
|
||||
promptContents.add("将输入的文本翻译成指定语言")
|
||||
promptTitles.add("代码解释")
|
||||
promptContents.add("解释代码的功能和逻辑")
|
||||
}
|
||||
|
||||
// Store prompt contents in a map for easy access
|
||||
val promptMap = mutableMapOf<String, String>()
|
||||
for (i in promptTitles.indices) {
|
||||
promptMap[promptTitles[i]] = promptContents[i]
|
||||
}
|
||||
|
||||
// Save prompt map to use in onItemSelectedListener
|
||||
promptSelector.tag = promptMap
|
||||
|
||||
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, promptTitles)
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
promptSelector.adapter = adapter
|
||||
promptSelector.setSelection(0)
|
||||
|
||||
Log.d("MainActivity", "loadPromptsFromConfig: Completed with ${promptTitles.size} prompts")
|
||||
} catch (e: Exception) {
|
||||
Log.e("MainActivity", "loadPromptsFromConfig: Error", e)
|
||||
// Fallback to default prompts
|
||||
val promptTitles = listOf("无系统提示词", "翻译助手", "代码解释")
|
||||
val promptContents = listOf("无特殊指令", "将输入的文本翻译成指定语言", "解释代码的功能和逻辑")
|
||||
|
||||
val promptMap = mutableMapOf<String, String>()
|
||||
for (i in promptTitles.indices) {
|
||||
promptMap[promptTitles[i]] = promptContents[i]
|
||||
}
|
||||
|
||||
promptSelector.tag = promptMap
|
||||
|
||||
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, promptTitles)
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
promptSelector.adapter = adapter
|
||||
promptSelector.setSelection(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
269
app/src/main/java/com/example/flomo_ai/MainActivity.kt.backup
Normal file
269
app/src/main/java/com/example/flomo_ai/MainActivity.kt.backup
Normal file
@@ -0,0 +1,269 @@
|
||||
package com.example.flomo_ai
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.Spinner
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
import android.util.Log
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var inputEditText: EditText
|
||||
private lateinit var configButton: Button
|
||||
private lateinit var submitToZhiPuAIButton: Button
|
||||
private lateinit var submitToSparkAIButton: Button
|
||||
private lateinit var tabLayout: TabLayout
|
||||
private lateinit var submitToServerButton: Button
|
||||
private lateinit var statusText: TextView
|
||||
|
||||
@SuppressLint("MissingInflatedId", "CutPasteId", "SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
// Initialize views
|
||||
val promptSelector = findViewById<Spinner>(R.id.promptSelector)
|
||||
val inputEditText = findViewById<EditText>(R.id.inputEditText)
|
||||
val sendButton = findViewById<Button>(R.id.sendButton)
|
||||
val stopButton = findViewById<Button>(R.id.stopButton)
|
||||
val outputStatusLabel = findViewById<TextView>(R.id.outputStatusLabel)
|
||||
val outputTextView = findViewById<TextView>(R.id.outputTextView)
|
||||
val copyButton = findViewById<Button>(R.id.copyButton)
|
||||
val btnCopyResult = findViewById<Button>(R.id.btnCopyResult)
|
||||
val headerTitle = findViewById<TextView>(R.id.headerTitle)
|
||||
val headerModelName = findViewById<TextView>(R.id.headerModelName)
|
||||
|
||||
// Set header values from JSON
|
||||
headerTitle.text = "AI优化"
|
||||
headerModelName.text = "gpt-4o"
|
||||
|
||||
// Setup prompt selector
|
||||
val promptOptions = listOf("无系统提示词", "翻译助手", "代码解释")
|
||||
val adapter = ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, promptOptions)
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
promptSelector.adapter = adapter
|
||||
promptSelector.setSelection(0) // Default to "无系统提示词"
|
||||
|
||||
// Setup initial output state
|
||||
outputStatusLabel.text = "等待发送"
|
||||
outputTextView.text = "发送消息后结果将在此显示"
|
||||
|
||||
// Send button click listener
|
||||
sendButton.setOnClickListener {
|
||||
val inputText = inputEditText.text.toString()
|
||||
if (inputText.isNotEmpty()) {
|
||||
outputStatusLabel.text = "连接中…"
|
||||
outputTextView.text = "正在生成..."
|
||||
|
||||
// Simulate API call with coroutine
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
try {
|
||||
// Simulate network delay
|
||||
delay(1000)
|
||||
|
||||
// For demo purposes, we'll show a sample optimized text
|
||||
val optimizedText = "今天阳光明媚,微风拂面,我漫步于公园之中,享受这难得的惬意时光。"
|
||||
|
||||
outputStatusLabel.text = "已完成"
|
||||
outputTextView.text = optimizedText
|
||||
|
||||
// Update selected prompt ID in JSON structure (simulated)
|
||||
val selectedPromptId = when (promptSelector.selectedItemPosition) {
|
||||
0 -> "none"
|
||||
1 -> "default-1"
|
||||
2 -> "default-2"
|
||||
else -> "none"
|
||||
}
|
||||
|
||||
// In a real app, you would update your JSON state here
|
||||
Log.d("MainActivity", "Selected prompt ID: $selectedPromptId")
|
||||
} catch (e: Exception) {
|
||||
outputStatusLabel.text = "发生错误"
|
||||
outputTextView.text = "错误: ${e.message}"
|
||||
Log.e("MainActivity", "Error processing request", e)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, "请输入内容", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
// Stop button click listener
|
||||
stopButton.setOnClickListener {
|
||||
outputStatusLabel.text = "已停止"
|
||||
Toast.makeText(this, "生成已停止", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
// Copy button click listener
|
||||
copyButton.setOnClickListener {
|
||||
val textToCopy = outputTextView.text.toString()
|
||||
if (textToCopy.isNotEmpty() && textToCopy != "发送消息后结果将在此显示") {
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("优化结果", textToCopy)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(this, "结果已复制到剪贴板", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this, "没有可复制的内容", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
// Custom copy result button
|
||||
btnCopyResult.setOnClickListener {
|
||||
val textToCopy = outputTextView.text.toString()
|
||||
if (textToCopy.isNotEmpty() && textToCopy != "发送消息后结果将在此显示") {
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("优化结果", textToCopy)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(this, "结果已复制到剪贴板", Toast.LENGTH_SHORT).show()
|
||||
} else {
|
||||
Toast.makeText(this, "没有可复制的内容", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
// Keep existing functionality for other buttons (config, etc.)
|
||||
// 点击配置按钮
|
||||
val configButton = findViewById<Button>(R.id.configButton)
|
||||
configButton.setOnClickListener {
|
||||
val intent = Intent(this, SecondActivity::class.java)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
// 提交到flomo的服务器按钮
|
||||
val submitToServerButton = findViewById<Button>(R.id.submitToServerButton)
|
||||
val inputEditText = findViewById<EditText>(R.id.inputEditText)
|
||||
|
||||
submitToServerButton.setOnClickListener {
|
||||
val textFromEditText = inputEditText.text.toString()
|
||||
submitToServer(textFromEditText)
|
||||
}
|
||||
|
||||
// 创建4个按钮 (保留原有的标签功能)
|
||||
val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
|
||||
// 维持原来的创建标签按钮的代码
|
||||
(1..4).forEach { tabIndex ->
|
||||
tabLayout.newTab().apply {
|
||||
text = "标签示例$tabIndex"
|
||||
tabLayout.addTab(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == SecondActivity.REQUEST_CODE_PICK_IMAGE && resultCode == Activity.RESULT_OK && data != null) {
|
||||
val selectedImageUri = data.getStringExtra("selectedImageUri")
|
||||
if (selectedImageUri != null) {
|
||||
val imageView = findViewById<ImageView>(R.id.imageViewBackground) // 假设你的背景是一个ImageView
|
||||
imageView.setImageURI(Uri.parse(selectedImageUri))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
// 获取从其他 Activity 传递过来的按钮颜色值,如果没有传递颜色值,则默认值为透明色。
|
||||
val statusTextView = findViewById<TextView>(R.id.statusTextView)
|
||||
updateStatusTextViewColor(statusTextView)
|
||||
}
|
||||
|
||||
private fun updateStatusTextViewColor(statusTextView: TextView) {
|
||||
try {
|
||||
val sharedPrefs = getSharedPreferences("APIConfigs", Context.MODE_PRIVATE)
|
||||
val colorValue = sharedPrefs.getString("buttonColor", "")
|
||||
Log.d("SharedPrefsDebug", "读取颜色值 MainActivity: $colorValue")
|
||||
|
||||
if (colorValue.isNullOrEmpty()) {
|
||||
statusTextView.setBackgroundResource(android.R.color.holo_blue_dark)
|
||||
} else {
|
||||
// 根据提取的颜色值设置背景颜色,这里只是一个示例,实际应用中可能需要更复杂的逻辑
|
||||
when (colorValue) {
|
||||
"red" -> statusTextView.setBackgroundResource(android.R.color.holo_red_light)
|
||||
"green" -> statusTextView.setBackgroundResource(android.R.color.holo_green_light)
|
||||
"blue" -> statusTextView.setBackgroundResource(android.R.color.holo_blue_light)
|
||||
"orange" -> statusTextView.setBackgroundResource(android.R.color.holo_orange_light)
|
||||
else -> {
|
||||
// 如果颜色值不在预定义的列表中,使用默认颜色
|
||||
statusTextView.setBackgroundResource(android.R.color.holo_blue_dark)
|
||||
Log.e("SharedPrefsError", "Invalid color value: $colorValue")
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// 捕获并记录任何异常
|
||||
Log.e("SharedPrefsError", "更新状态文本视图颜色时出错\n: ${e.message}", e)
|
||||
// 设置默认颜色
|
||||
statusTextView.setBackgroundResource(android.R.color.holo_blue_dark)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBitmapFromUri(uri: Uri): Bitmap? {
|
||||
val inputStream: InputStream? = contentResolver.openInputStream(uri)
|
||||
return BitmapFactory.decodeStream(inputStream)
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun submitToServer(content: String) {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
statusText.text = "提交到flomo服务器..."
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
postDataToServer(content)
|
||||
}
|
||||
when (result) {
|
||||
is Result.Success -> {
|
||||
findViewById<EditText>(R.id.inputEditText).setText("")
|
||||
statusText.text = "提交成功!"
|
||||
}
|
||||
is Result.Error -> {
|
||||
statusText.text = "提交失误: ${result.exception.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 提交到笔记服务器,flomo服务器
|
||||
private fun postDataToServer(content: String): Result {
|
||||
return try {
|
||||
val client = OkHttpClient()
|
||||
val mediaType = "application/json".toMediaType()
|
||||
val json = JSONObject().apply {
|
||||
put("content", content)
|
||||
}.toString()
|
||||
val body = json.toRequestBody(mediaType)
|
||||
val request = Request.Builder()
|
||||
.url("https://flomoapp.com/iwh/MTY5NTQy/b671d4930ecd1eae63e50cc0cb8ca4ae/")
|
||||
.post(body)
|
||||
.build()
|
||||
val response = client.newCall(request).execute()
|
||||
if (response.isSuccessful) {
|
||||
Result.Success(response)
|
||||
} else {
|
||||
Result.Error(Exception("服务器返回错误: ${response.code}"))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Result.Error(e)
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Result {
|
||||
data class Success(val response: Response) : Result()
|
||||
data class Error(val exception: Exception) : Result()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.text.method.PasswordTransformationMethod
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
@@ -45,12 +47,16 @@ class SecondActivity : AppCompatActivity() {
|
||||
private lateinit var etModel: EditText
|
||||
private lateinit var llHeadersList: LinearLayout
|
||||
private lateinit var btnAddHeader: Button
|
||||
private lateinit var llPromptsList: LinearLayout
|
||||
private lateinit var layoutHeaderContent: LinearLayout
|
||||
private lateinit var ivHeaderArrow: ImageView
|
||||
private lateinit var layoutHeaderToggle: LinearLayout
|
||||
|
||||
// Prompt view references
|
||||
private lateinit var llPromptList: LinearLayout
|
||||
private lateinit var btnAddPrompt: Button
|
||||
private lateinit var tvEmptyPrompts: TextView
|
||||
private lateinit var llButtonsList: LinearLayout
|
||||
private lateinit var btnAddButton: Button
|
||||
private lateinit var tvEmptyButtons: TextView
|
||||
private lateinit var layoutPromptContent: LinearLayout
|
||||
private lateinit var ivPromptArrow: ImageView
|
||||
private lateinit var layoutPromptToggle: LinearLayout
|
||||
|
||||
// Data storage
|
||||
private var headerConfigs = mutableListOf<HeaderConfig>()
|
||||
@@ -62,75 +68,150 @@ class SecondActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Log.d("SecondActivity", "onCreate: Starting SecondActivity")
|
||||
try {
|
||||
setContentView(R.layout.activity_second)
|
||||
Log.d("SecondActivity", "onCreate: Layout set")
|
||||
} catch (e: Exception) {
|
||||
Log.e("SecondActivity", "onCreate: Error setting layout", e)
|
||||
throw e
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialize views
|
||||
initViews()
|
||||
Log.d("SecondActivity", "onCreate: Views initialized")
|
||||
|
||||
// Load existing configurations
|
||||
loadConfigurations()
|
||||
Log.d("SecondActivity", "onCreate: Configurations loaded")
|
||||
|
||||
// Setup UI based on loaded data
|
||||
setupUI()
|
||||
Log.d("SecondActivity", "onCreate: UI setup completed")
|
||||
|
||||
// Back button functionality
|
||||
findViewById<Button>(R.id.btnBack).setOnClickListener {
|
||||
findViewById<ImageButton>(R.id.btnBack).setOnClickListener {
|
||||
Log.d("SecondActivity", "Back button clicked")
|
||||
finish()
|
||||
}
|
||||
|
||||
// Home button functionality
|
||||
findViewById<Button>(R.id.btnHome).setOnClickListener {
|
||||
Log.d("SecondActivity", "Home button clicked")
|
||||
// Create intent to go back to MainActivity
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
// Clear the activity stack to start fresh
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
startActivity(intent)
|
||||
finish()
|
||||
}
|
||||
|
||||
// Add header button
|
||||
btnAddHeader.setOnClickListener {
|
||||
Log.d("SecondActivity", "Add header button clicked")
|
||||
addHeaderEntry()
|
||||
}
|
||||
|
||||
// Add prompt button
|
||||
btnAddPrompt.setOnClickListener {
|
||||
Log.d("SecondActivity", "Add prompt button clicked")
|
||||
addPromptEntry()
|
||||
}
|
||||
|
||||
// Add button
|
||||
btnAddButton.setOnClickListener {
|
||||
addButtonEntry()
|
||||
Log.d("SecondActivity", "onCreate: Completed successfully")
|
||||
} catch (e: Exception) {
|
||||
Log.e("SecondActivity", "onCreate: Error during initialization", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun initViews() {
|
||||
Log.d("SecondActivity", "initViews: Starting")
|
||||
try {
|
||||
etBaseUrl = findViewById(R.id.etBaseUrl)
|
||||
etApiKey = findViewById(R.id.etApiKey)
|
||||
btnToggleApiKey = findViewById(R.id.btnToggleApiKey)
|
||||
etModel = findViewById(R.id.etModel)
|
||||
|
||||
// Header Section
|
||||
llHeadersList = findViewById(R.id.llHeadersList)
|
||||
btnAddHeader = findViewById(R.id.btnAddHeader)
|
||||
llPromptsList = findViewById(R.id.llPromptsList)
|
||||
layoutHeaderContent = findViewById(R.id.layoutHeaderContent)
|
||||
ivHeaderArrow = findViewById(R.id.ivHeaderArrow)
|
||||
layoutHeaderToggle = findViewById(R.id.layoutHeaderToggle)
|
||||
|
||||
// Prompt Section
|
||||
llPromptList = findViewById(R.id.llPromptList)
|
||||
btnAddPrompt = findViewById(R.id.btnAddPrompt)
|
||||
tvEmptyPrompts = findViewById(R.id.tvEmptyPrompts)
|
||||
llButtonsList = findViewById(R.id.llButtonsList)
|
||||
btnAddButton = findViewById(R.id.btnAddButton)
|
||||
tvEmptyButtons = findViewById(R.id.tvEmptyButtons)
|
||||
layoutPromptContent = findViewById(R.id.layoutPromptContent)
|
||||
ivPromptArrow = findViewById(R.id.ivPromptArrow)
|
||||
layoutPromptToggle = findViewById(R.id.layoutPromptToggle)
|
||||
|
||||
Log.d("SecondActivity", "initViews: All views found")
|
||||
|
||||
// Setup API key toggle
|
||||
btnToggleApiKey.setOnClickListener {
|
||||
Log.d("SecondActivity", "API key toggle clicked")
|
||||
val isPassword = etApiKey.transformationMethod is PasswordTransformationMethod
|
||||
etApiKey.transformationMethod = if (isPassword) null else PasswordTransformationMethod()
|
||||
// Move cursor to end
|
||||
etApiKey.setSelection(etApiKey.text.length)
|
||||
// Toggle icon
|
||||
val iconRes = if (isPassword)
|
||||
android.R.drawable.ic_lock_idle_lock else
|
||||
android.R.drawable.ic_lock_idle_unlocked
|
||||
btnToggleApiKey.setImageResource(iconRes)
|
||||
|
||||
// Update icon based on state
|
||||
if (isPassword) {
|
||||
btnToggleApiKey.setImageResource(android.R.drawable.ic_menu_view) // Show eye
|
||||
} else {
|
||||
btnToggleApiKey.setImageResource(android.R.drawable.ic_lock_idle_lock) // Show lock
|
||||
}
|
||||
}
|
||||
|
||||
// Setup Header Toggle (Fold/Unfold)
|
||||
layoutHeaderToggle.setOnClickListener {
|
||||
Log.d("SecondActivity", "Header toggle clicked")
|
||||
val isExpanded = layoutHeaderContent.visibility == View.VISIBLE
|
||||
if (isExpanded) {
|
||||
layoutHeaderContent.visibility = View.GONE
|
||||
ivHeaderArrow.rotation = 0f // Point right
|
||||
} else {
|
||||
layoutHeaderContent.visibility = View.VISIBLE
|
||||
ivHeaderArrow.rotation = 90f // Point down
|
||||
}
|
||||
}
|
||||
|
||||
// Setup Prompt Toggle (Fold/Unfold)
|
||||
layoutPromptToggle.setOnClickListener {
|
||||
Log.d("SecondActivity", "Prompt toggle clicked")
|
||||
val isExpanded = layoutPromptContent.visibility == View.VISIBLE
|
||||
if (isExpanded) {
|
||||
layoutPromptContent.visibility = View.GONE
|
||||
ivPromptArrow.rotation = 0f // Point right
|
||||
} else {
|
||||
layoutPromptContent.visibility = View.VISIBLE
|
||||
ivPromptArrow.rotation = 90f // Point down
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("SecondActivity", "initViews: Completed")
|
||||
} catch (e: Exception) {
|
||||
Log.e("SecondActivity", "initViews: Error finding views", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadConfigurations() {
|
||||
Log.d("SecondActivity", "loadConfigurations: Starting")
|
||||
// Load shared preferences
|
||||
val sharedPrefs = getSharedPreferences("APIConfigs", Context.MODE_PRIVATE)
|
||||
val json = sharedPrefs.getString("configs", null)
|
||||
Log.d("SecondActivity", "loadConfigurations: JSON loaded: ${json?.substring(0, minOf(json.length, 100))}")
|
||||
|
||||
if (json != null) {
|
||||
try {
|
||||
// Try to load as new format first
|
||||
Log.d("SecondActivity", "loadConfigurations: Trying to parse as SettingsData")
|
||||
val settings = Gson().fromJson(json, SettingsData::class.java)
|
||||
Log.d("SecondActivity", "loadConfigurations: SettingsData parsed successfully")
|
||||
headerConfigs = settings.headerConfigs?.toMutableList() ?: mutableListOf()
|
||||
promptConfigs = settings.promptConfigs?.toMutableList() ?: mutableListOf()
|
||||
buttonConfigs = settings.buttonConfigs?.toMutableList() ?: mutableListOf()
|
||||
@@ -144,8 +225,10 @@ class SecondActivity : AppCompatActivity() {
|
||||
updateApiKeyVisibility()
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("SecondActivity", "loadConfigurations: Error parsing SettingsData", e)
|
||||
// If new format fails, try to load old format for migration
|
||||
try {
|
||||
Log.d("SecondActivity", "loadConfigurations: Trying to parse as List<APIConfig>")
|
||||
val type = object : TypeToken<List<APIConfig>>() {}.type
|
||||
val oldConfigs = Gson().fromJson<List<APIConfig>>(json, type)
|
||||
if (oldConfigs.isNotEmpty()) {
|
||||
@@ -156,6 +239,7 @@ class SecondActivity : AppCompatActivity() {
|
||||
updateApiKeyVisibility()
|
||||
}
|
||||
} catch (e2: Exception) {
|
||||
Log.e("SecondActivity", "loadConfigurations: Error parsing List<APIConfig>", e2)
|
||||
// If both fail, use defaults
|
||||
etBaseUrl.setText("https://api.openai.com/v1")
|
||||
etModel.setText("gpt-4o")
|
||||
@@ -164,19 +248,17 @@ class SecondActivity : AppCompatActivity() {
|
||||
}
|
||||
} else {
|
||||
// No saved config, use defaults
|
||||
Log.d("SecondActivity", "loadConfigurations: No saved config, using defaults")
|
||||
etBaseUrl.setText("https://api.openai.com/v1")
|
||||
etModel.setText("gpt-4o")
|
||||
updateApiKeyVisibility()
|
||||
}
|
||||
Log.d("SecondActivity", "loadConfigurations: Completed")
|
||||
}
|
||||
|
||||
private fun updateApiKeyVisibility() {
|
||||
val isEmpty = etApiKey.text.toString().isEmpty()
|
||||
etApiKey.transformationMethod = if (isEmpty) null else PasswordTransformationMethod()
|
||||
val iconRes = if (isEmpty || etApiKey.transformationMethod == null)
|
||||
android.R.drawable.ic_lock_idle_lock else
|
||||
android.R.drawable.ic_lock_idle_unlocked
|
||||
btnToggleApiKey.setImageResource(iconRes)
|
||||
// Keep cursor at end
|
||||
etApiKey.setSelection(etApiKey.text.length)
|
||||
}
|
||||
@@ -193,35 +275,14 @@ class SecondActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
// Setup prompts
|
||||
llPromptsList.removeAllViews()
|
||||
llPromptList.removeAllViews()
|
||||
if (promptConfigs.isEmpty()) {
|
||||
// Add default prompts from JSON
|
||||
promptConfigs.add(PromptConfig("default-1", "翻译助手", "你是一个专业翻译,请将用户输入的内容翻译成中文,保持原意,语言自然流畅。"))
|
||||
promptConfigs.add(PromptConfig("default-2", "代码解释", "你是一个资深程序员,请详细解释用户提供的代码,用中文说明其功能和逻辑。"))
|
||||
}
|
||||
addPromptEntry() // Add one empty entry by default
|
||||
} else {
|
||||
for (prompt in promptConfigs) {
|
||||
addPromptEntry(prompt)
|
||||
addPromptEntry(prompt.title, prompt.content)
|
||||
}
|
||||
updateEmptyStates()
|
||||
|
||||
// Setup buttons
|
||||
llButtonsList.removeAllViews()
|
||||
if (buttonConfigs.isEmpty()) {
|
||||
// Add default buttons from JSON
|
||||
buttonConfigs.add(ButtonConfig("btn-copy", "复制结果", "copy"))
|
||||
buttonConfigs.add(ButtonConfig(
|
||||
"btn-webhook",
|
||||
"发送到飞书",
|
||||
"api",
|
||||
"https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx",
|
||||
"POST",
|
||||
"{\"msg_type\": \"text\", \"content\": {\"text\": \"{output}\"}}"
|
||||
))
|
||||
}
|
||||
for (button in buttonConfigs) {
|
||||
addButtonEntry(button)
|
||||
}
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun addHeaderEntry(key: String = "", value: String = "") {
|
||||
@@ -235,89 +296,25 @@ class SecondActivity : AppCompatActivity() {
|
||||
|
||||
btnRemove.setOnClickListener {
|
||||
llHeadersList.removeView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
llHeadersList.addView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun addPromptEntry(config: PromptConfig = PromptConfig("", "", "")) {
|
||||
private fun addPromptEntry(title: String = "", content: String = "") {
|
||||
val view = layoutInflater.inflate(R.layout.prompt_entry, null)
|
||||
val etTitle = view.findViewById<EditText>(R.id.etPromptTitle)
|
||||
val etContent = view.findViewById<EditText>(R.id.etPromptContent)
|
||||
val btnExpand = view.findViewById<Button>(R.id.btnExpandPrompt)
|
||||
val btnRemove = view.findViewById<ImageButton>(R.id.btnRemovePrompt)
|
||||
val vDivider = view.findViewById<View>(R.id.viewDivider)
|
||||
|
||||
etTitle.setText(config.title)
|
||||
etContent.setText(config.content)
|
||||
// Set expanded state (we'd need to store this in the view tag or similar)
|
||||
etTitle.setText(title)
|
||||
etContent.setText(content)
|
||||
|
||||
btnRemove.setOnClickListener {
|
||||
llPromptsList.removeView(view)
|
||||
updateEmptyStates()
|
||||
llPromptList.removeView(view)
|
||||
}
|
||||
|
||||
// For simplicity, we're not implementing expand/collapse here
|
||||
// but in a full implementation we would toggle the content visibility
|
||||
|
||||
llPromptsList.addView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun addButtonEntry(config: ButtonConfig = ButtonConfig("", "", "")) {
|
||||
val view = layoutInflater.inflate(R.layout.button_entry, null)
|
||||
val etLabel = view.findViewById<EditText>(R.id.etButtonLabel)
|
||||
val btnAction = view.findViewById<Button>(R.id.btnButtonAction)
|
||||
val btnRemove = view.findViewById<ImageButton>(R.id.btnRemoveButton)
|
||||
val llApiFields = view.findViewById<LinearLayout>(R.id.llApiFields)
|
||||
|
||||
etLabel.setText(config.label)
|
||||
btnAction.text = when (config.action) {
|
||||
"copy" -> "复制输出内容"
|
||||
"api" -> "提交到第三方 API"
|
||||
else -> "未知操作"
|
||||
}
|
||||
|
||||
// Show/hide API fields based on action
|
||||
llApiFields.visibility = if (config.action == "api") View.VISIBLE else View.GONE
|
||||
|
||||
btnAction.setOnClickListener {
|
||||
// Cycle through action options
|
||||
val newAction = when (btnAction.text.toString()) {
|
||||
"复制输出内容" -> "提交到第三方 API"
|
||||
"提交到第三方 API" -> "未知操作"
|
||||
else -> "复制输出内容"
|
||||
}
|
||||
btnAction.text = when (newAction) {
|
||||
"复制输出内容" -> "复制输出内容"
|
||||
"提交到第三方 API" -> "提交到第三方 API"
|
||||
else -> "未知操作"
|
||||
}
|
||||
llApiFields.visibility = if (newAction == "提交到第三方 API") View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// If we have existing API config, populate fields
|
||||
if (config.action == "api") {
|
||||
// In a full implementation, we would populate the API fields here
|
||||
}
|
||||
|
||||
btnRemove.setOnClickListener {
|
||||
llButtonsList.removeView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
llButtonsList.addView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun updateEmptyStates() {
|
||||
// Update prompts empty state
|
||||
tvEmptyPrompts.visibility = if (llPromptsList.childCount == 0) View.VISIBLE else View.GONE
|
||||
|
||||
// Update buttons empty state
|
||||
tvEmptyButtons.visibility = if (llButtonsList.childCount == 0) View.VISIBLE else View.GONE
|
||||
llPromptList.addView(view)
|
||||
}
|
||||
|
||||
// Save all configurations when leaving or explicitly saving
|
||||
@@ -340,42 +337,18 @@ class SecondActivity : AppCompatActivity() {
|
||||
|
||||
// Update prompt configs from UI
|
||||
promptConfigs.clear()
|
||||
for (i in 0 until llPromptsList.childCount) {
|
||||
val view = llPromptsList.getChildAt(i)
|
||||
for (i in 0 until llPromptList.childCount) {
|
||||
val view = llPromptList.getChildAt(i)
|
||||
val title = view.findViewById<EditText>(R.id.etPromptTitle).text.toString()
|
||||
val content = view.findViewById<EditText>(R.id.etPromptContent).text.toString()
|
||||
if (title.isNotBlank() && content.isNotBlank()) {
|
||||
promptConfigs.add(PromptConfig(
|
||||
if (title.equals("翻译助手", ignoreCase = true)) "default-1"
|
||||
else if (title.equals("代码解释", ignoreCase = true)) "default-2"
|
||||
else UUID.randomUUID().toString(),
|
||||
title,
|
||||
content
|
||||
))
|
||||
promptConfigs.add(PromptConfig(id = "prompt_$i", title = title, content = content))
|
||||
}
|
||||
}
|
||||
|
||||
// Update button configs from UI
|
||||
// Note: Buttons are removed from this UI as per new design.
|
||||
// We keep the list empty for data compatibility.
|
||||
buttonConfigs.clear()
|
||||
for (i in 0 until llButtonsList.childCount) {
|
||||
val view = llButtonsList.getChildAt(i)
|
||||
val label = view.findViewById<EditText>(R.id.etButtonLabel).text.toString()
|
||||
val actionText = view.findViewById<Button>(R.id.btnButtonAction).text.toString()
|
||||
val action = when (actionText) {
|
||||
"复制输出内容" -> "copy"
|
||||
"提交到第三方 API" -> "api"
|
||||
else -> "unknown"
|
||||
}
|
||||
if (label.isNotBlank()) {
|
||||
buttonConfigs.add(ButtonConfig(
|
||||
if (label.equals("复制结果", ignoreCase = true)) "btn-copy"
|
||||
else if (label.equals("发送到飞书", ignoreCase = true)) "btn-webhook"
|
||||
else UUID.randomUUID().toString(),
|
||||
label,
|
||||
action
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Save LLM config
|
||||
val llmConfig = LLMConfig(
|
||||
|
||||
433
app/src/main/java/com/example/flomo_ai/SecondActivity.kt.backup
Normal file
433
app/src/main/java/com/example/flomo_ai/SecondActivity.kt.backup
Normal file
@@ -0,0 +1,433 @@
|
||||
package com.example.flomo_ai
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.text.method.PasswordTransformationMethod
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.json.JSONObject
|
||||
import java.util.*
|
||||
|
||||
// Data classes for the new settings structure
|
||||
data class HeaderConfig(val key: String, val value: String)
|
||||
data class PromptConfig(val id: String, val title: String, val content: String, val expanded: Boolean = false)
|
||||
data class ButtonConfig(val id: String, val label: String, val action: String, val apiUrl: String? = null, val apiMethod: String? = null, val apiBodyTemplate: String? = null, val expanded: Boolean = false)
|
||||
|
||||
class SecondActivity : AppCompatActivity() {
|
||||
|
||||
// View references
|
||||
private lateinit var etBaseUrl: EditText
|
||||
private lateinit var etApiKey: EditText
|
||||
private lateinit var btnToggleApiKey: ImageButton
|
||||
private lateinit var etModel: EditText
|
||||
private lateinit var llHeadersList: LinearLayout
|
||||
private lateinit var btnAddHeader: Button
|
||||
private lateinit var llPromptsList: LinearLayout
|
||||
private lateinit var btnAddPrompt: Button
|
||||
private lateinit var tvEmptyPrompts: TextView
|
||||
private lateinit var llButtonsList: LinearLayout
|
||||
private lateinit var btnAddButton: Button
|
||||
private lateinit var tvEmptyButtons: TextView
|
||||
|
||||
// Data storage
|
||||
private var headerConfigs = mutableListOf<HeaderConfig>()
|
||||
private var promptConfigs = mutableListOf<PromptConfig>()
|
||||
private var buttonConfigs = mutableListOf<ButtonConfig>()
|
||||
|
||||
// API config (for backward compatibility with existing API calls)
|
||||
private lateinit var apiConfig: APIConfig
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_second)
|
||||
|
||||
// Initialize views
|
||||
initViews()
|
||||
|
||||
// Load existing configurations
|
||||
loadConfigurations()
|
||||
|
||||
// Setup UI based on loaded data
|
||||
setupUI()
|
||||
|
||||
// Back button functionality
|
||||
findViewById<Button>(R.id.btnBack).setOnClickListener {
|
||||
finish()
|
||||
}
|
||||
|
||||
// Add header button
|
||||
btnAddHeader.setOnClickListener {
|
||||
addHeaderEntry()
|
||||
}
|
||||
|
||||
// Add prompt button
|
||||
btnAddPrompt.setOnClickListener {
|
||||
addPromptEntry()
|
||||
}
|
||||
|
||||
// Add button
|
||||
btnAddButton.setOnClickListener {
|
||||
addButtonEntry()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initViews() {
|
||||
etBaseUrl = findViewById(R.id.etBaseUrl)
|
||||
etApiKey = findViewById(R.id.etApiKey)
|
||||
btnToggleApiKey = findViewById(R.id.btnToggleApiKey)
|
||||
etModel = findViewById(R.id.etModel)
|
||||
llHeadersList = findViewById(R.id.llHeadersList)
|
||||
btnAddHeader = findViewById(R.id.btnAddHeader)
|
||||
llPromptsList = findViewById(R.id.llPromptsList)
|
||||
btnAddPrompt = findViewById(R.id.btnAddPrompt)
|
||||
tvEmptyPrompts = findViewById(R.id.tvEmptyPrompts)
|
||||
llButtonsList = findViewById(R.id.llButtonsList)
|
||||
btnAddButton = findViewById(R.id.btnAddButton)
|
||||
tvEmptyButtons = findViewById(R.id.tvEmptyButtons)
|
||||
|
||||
// Setup API key toggle
|
||||
btnToggleApiKey.setOnClickListener {
|
||||
val isPassword = etApiKey.transformationMethod is PasswordTransformationMethod
|
||||
etApiKey.transformationMethod = if (isPassword) null else PasswordTransformationMethod()
|
||||
// Move cursor to end
|
||||
etApiKey.setSelection(etApiKey.text.length)
|
||||
// Toggle icon
|
||||
val iconRes = if (isPassword)
|
||||
android.R.drawable.ic_lock_idle_lock else
|
||||
android.R.drawable.ic_lock_idle_unlocked
|
||||
btnToggleApiKey.setImageResource(iconRes)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadConfigurations() {
|
||||
// Load shared preferences
|
||||
val sharedPrefs = getSharedPreferences("APIConfigs", Context.MODE_PRIVATE)
|
||||
val json = sharedPrefs.getString("configs", null)
|
||||
|
||||
if (json != null) {
|
||||
try {
|
||||
// Try to load as new format first
|
||||
val settings = Gson().fromJson(json, SettingsData::class.java)
|
||||
headerConfigs = settings.headerConfigs?.toMutableList() ?: mutableListOf()
|
||||
promptConfigs = settings.promptConfigs?.toMutableList() ?: mutableListOf()
|
||||
buttonConfigs = settings.buttonConfigs?.toMutableList() ?: mutableListOf()
|
||||
|
||||
// Load LLM config
|
||||
etBaseUrl.setText(settings.llmConfig?.baseUrl ?: "https://api.openai.com/v1")
|
||||
etApiKey.setText(settings.llmConfig?.apiKey ?: "")
|
||||
etModel.setText(settings.llmConfig?.model ?: "gpt-4o")
|
||||
|
||||
// Update API key visibility based on whether it has text
|
||||
updateApiKeyVisibility()
|
||||
|
||||
} catch (e: Exception) {
|
||||
// If new format fails, try to load old format for migration
|
||||
try {
|
||||
val type = object : TypeToken<List<APIConfig>>() {}.type
|
||||
val oldConfigs = Gson().fromJson<List<APIConfig>>(json, type)
|
||||
if (oldConfigs.isNotEmpty()) {
|
||||
val oldConfig = oldConfigs[0]
|
||||
etBaseUrl.setText(oldConfig.url)
|
||||
etApiKey.setText(oldConfig.key)
|
||||
etModel.setText(oldConfig.model)
|
||||
updateApiKeyVisibility()
|
||||
}
|
||||
} catch (e2: Exception) {
|
||||
// If both fail, use defaults
|
||||
etBaseUrl.setText("https://api.openai.com/v1")
|
||||
etModel.setText("gpt-4o")
|
||||
updateApiKeyVisibility()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No saved config, use defaults
|
||||
etBaseUrl.setText("https://api.openai.com/v1")
|
||||
etModel.setText("gpt-4o")
|
||||
updateApiKeyVisibility()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateApiKeyVisibility() {
|
||||
val isEmpty = etApiKey.text.toString().isEmpty()
|
||||
etApiKey.transformationMethod = if (isEmpty) null else PasswordTransformationMethod()
|
||||
val iconRes = if (isEmpty || etApiKey.transformationMethod == null)
|
||||
android.R.drawable.ic_lock_idle_lock else
|
||||
android.R.drawable.ic_lock_idle_unlocked
|
||||
btnToggleApiKey.setImageResource(iconRes)
|
||||
// Keep cursor at end
|
||||
etApiKey.setSelection(etApiKey.text.length)
|
||||
}
|
||||
|
||||
private fun setupUI() {
|
||||
// Setup headers
|
||||
llHeadersList.removeAllViews()
|
||||
if (headerConfigs.isEmpty()) {
|
||||
addHeaderEntry() // Add one empty entry by default
|
||||
} else {
|
||||
for (header in headerConfigs) {
|
||||
addHeaderEntry(header.key, header.value)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup prompts
|
||||
llPromptsList.removeAllViews()
|
||||
if (promptConfigs.isEmpty()) {
|
||||
// Add default prompts from JSON
|
||||
promptConfigs.add(PromptConfig("default-1", "翻译助手", "你是一个专业翻译,请将用户输入的内容翻译成中文,保持原意,语言自然流畅。"))
|
||||
promptConfigs.add(PromptConfig("default-2", "代码解释", "你是一个资深程序员,请详细解释用户提供的代码,用中文说明其功能和逻辑。"))
|
||||
}
|
||||
for (prompt in promptConfigs) {
|
||||
addPromptEntry(prompt)
|
||||
}
|
||||
updateEmptyStates()
|
||||
|
||||
// Setup buttons
|
||||
llButtonsList.removeAllViews()
|
||||
if (buttonConfigs.isEmpty()) {
|
||||
// Add default buttons from JSON
|
||||
buttonConfigs.add(ButtonConfig("btn-copy", "复制结果", "copy"))
|
||||
buttonConfigs.add(ButtonConfig(
|
||||
"btn-webhook",
|
||||
"发送到飞书",
|
||||
"api",
|
||||
"https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxxxx",
|
||||
"POST",
|
||||
"{\"msg_type\": \"text\", \"content\": {\"text\": \"{output}\"}}"
|
||||
))
|
||||
}
|
||||
for (button in buttonConfigs) {
|
||||
addButtonEntry(button)
|
||||
}
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun addHeaderEntry(key: String = "", value: String = "") {
|
||||
val view = layoutInflater.inflate(R.layout.header_entry, null)
|
||||
val etKey = view.findViewById<EditText>(R.id.etHeaderKey)
|
||||
val etValue = view.findViewById<EditText>(R.id.etHeaderValue)
|
||||
val btnRemove = view.findViewById<ImageButton>(R.id.btnRemoveHeader)
|
||||
|
||||
etKey.setText(key)
|
||||
etValue.setText(value)
|
||||
|
||||
btnRemove.setOnClickListener {
|
||||
llHeadersList.removeView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
llHeadersList.addView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun addPromptEntry(config: PromptConfig = PromptConfig("", "", "")) {
|
||||
val view = layoutInflater.inflate(R.layout.prompt_entry, null)
|
||||
val etTitle = view.findViewById<EditText>(R.id.etPromptTitle)
|
||||
val etContent = view.findViewById<EditText>(R.id.etPromptContent)
|
||||
val btnExpand = view.findViewById<Button>(R.id.btnExpandPrompt)
|
||||
val btnRemove = view.findViewById<ImageButton>(R.id.btnRemovePrompt)
|
||||
val vDivider = view.findViewById<View>(R.id.viewDivider)
|
||||
|
||||
etTitle.setText(config.title)
|
||||
etContent.setText(config.content)
|
||||
// Set expanded state (we'd need to store this in the view tag or similar)
|
||||
|
||||
btnRemove.setOnClickListener {
|
||||
llPromptsList.removeView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
// For simplicity, we're not implementing expand/collapse here
|
||||
// but in a full implementation we would toggle the content visibility
|
||||
|
||||
llPromptsList.addView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun addButtonEntry(config: ButtonConfig = ButtonConfig("", "", "")) {
|
||||
val view = layoutInflater.inflate(R.layout.button_entry, null)
|
||||
val etLabel = view.findViewById<EditText>(R.id.etButtonLabel)
|
||||
val btnAction = view.findViewById<Button>(R.id.btnButtonAction)
|
||||
val btnRemove = view.findViewById<ImageButton>(R.id.btnRemoveButton)
|
||||
val llApiFields = view.findViewById<LinearLayout>(R.id.llApiFields)
|
||||
|
||||
etLabel.setText(config.label)
|
||||
btnAction.text = when (config.action) {
|
||||
"copy" -> "复制输出内容"
|
||||
"api" -> "提交到第三方 API"
|
||||
else -> "未知操作"
|
||||
}
|
||||
|
||||
// Show/hide API fields based on action
|
||||
llApiFields.visibility = if (config.action == "api") View.VISIBLE else View.GONE
|
||||
|
||||
btnAction.setOnClickListener {
|
||||
// Cycle through action options
|
||||
val newAction = when (btnAction.text.toString()) {
|
||||
"复制输出内容" -> "提交到第三方 API"
|
||||
"提交到第三方 API" -> "未知操作"
|
||||
else -> "复制输出内容"
|
||||
}
|
||||
btnAction.text = when (newAction) {
|
||||
"复制输出内容" -> "复制输出内容"
|
||||
"提交到第三方 API" -> "提交到第三方 API"
|
||||
else -> "未知操作"
|
||||
}
|
||||
llApiFields.visibility = if (newAction == "提交到第三方 API") View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// If we have existing API config, populate fields
|
||||
if (config.action == "api") {
|
||||
// In a full implementation, we would populate the API fields here
|
||||
}
|
||||
|
||||
btnRemove.setOnClickListener {
|
||||
llButtonsList.removeView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
llButtonsList.addView(view)
|
||||
updateEmptyStates()
|
||||
}
|
||||
|
||||
private fun updateEmptyStates() {
|
||||
// Update prompts empty state
|
||||
tvEmptyPrompts.visibility = if (llPromptsList.childCount == 0) View.VISIBLE else View.GONE
|
||||
|
||||
// Update buttons empty state
|
||||
tvEmptyButtons.visibility = if (llButtonsList.childCount == 0) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
// Save all configurations when leaving or explicitly saving
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
saveConfigurations()
|
||||
}
|
||||
|
||||
private fun saveConfigurations() {
|
||||
// Update header configs from UI
|
||||
headerConfigs.clear()
|
||||
for (i in 0 until llHeadersList.childCount) {
|
||||
val view = llHeadersList.getChildAt(i)
|
||||
val key = view.findViewById<EditText>(R.id.etHeaderKey).text.toString()
|
||||
val value = view.findViewById<EditText>(R.id.etHeaderValue).text.toString()
|
||||
if (key.isNotBlank() && value.isNotBlank()) {
|
||||
headerConfigs.add(HeaderConfig(key, value))
|
||||
}
|
||||
}
|
||||
|
||||
// Update prompt configs from UI
|
||||
promptConfigs.clear()
|
||||
for (i in 0 until llPromptsList.childCount) {
|
||||
val view = llPromptsList.getChildAt(i)
|
||||
val title = view.findViewById<EditText>(R.id.etPromptTitle).text.toString()
|
||||
val content = view.findViewById<EditText>(R.id.etPromptContent).text.toString()
|
||||
if (title.isNotBlank() && content.isNotBlank()) {
|
||||
promptConfigs.add(PromptConfig(
|
||||
if (title.equals("翻译助手", ignoreCase = true)) "default-1"
|
||||
else if (title.equals("代码解释", ignoreCase = true)) "default-2"
|
||||
else UUID.randomUUID().toString(),
|
||||
title,
|
||||
content
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Update button configs from UI
|
||||
buttonConfigs.clear()
|
||||
for (i in 0 until llButtonsList.childCount) {
|
||||
val view = llButtonsList.getChildAt(i)
|
||||
val label = view.findViewById<EditText>(R.id.etButtonLabel).text.toString()
|
||||
val actionText = view.findViewById<Button>(R.id.btnButtonAction).text.toString()
|
||||
val action = when (actionText) {
|
||||
"复制输出内容" -> "copy"
|
||||
"提交到第三方 API" -> "api"
|
||||
else -> "unknown"
|
||||
}
|
||||
if (label.isNotBlank()) {
|
||||
buttonConfigs.add(ButtonConfig(
|
||||
if (label.equals("复制结果", ignoreCase = true)) "btn-copy"
|
||||
else if (label.equals("发送到飞书", ignoreCase = true)) "btn-webhook"
|
||||
else UUID.randomUUID().toString(),
|
||||
label,
|
||||
action
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Save LLM config
|
||||
val llmConfig = LLMConfig(
|
||||
baseUrl = etBaseUrl.text.toString(),
|
||||
apiKey = etApiKey.text.toString(),
|
||||
model = etModel.text.toString()
|
||||
)
|
||||
|
||||
// Save everything
|
||||
val settingsData = SettingsData(
|
||||
llmConfig = llmConfig,
|
||||
headerConfigs = headerConfigs,
|
||||
promptConfigs = promptConfigs,
|
||||
buttonConfigs = buttonConfigs
|
||||
)
|
||||
|
||||
val json = Gson().toJson(settingsData)
|
||||
val sharedPrefs = getSharedPreferences("APIConfigs", Context.MODE_PRIVATE)
|
||||
sharedPrefs.edit().putString("configs", json).apply()
|
||||
|
||||
// Also update the legacy APIConfig for backward compatibility
|
||||
apiConfig = APIConfig(
|
||||
System.currentTimeMillis(),
|
||||
"llm-config",
|
||||
etBaseUrl.text.toString(),
|
||||
etApiKey.text.toString(),
|
||||
"",
|
||||
etModel.text.toString()
|
||||
)
|
||||
}
|
||||
|
||||
// Legacy APIConfig class for backward compatibility with existing code
|
||||
data class APIConfig(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val url: String,
|
||||
val key: String,
|
||||
val secretKey: String,
|
||||
val model: String
|
||||
)
|
||||
|
||||
// New data classes for settings structure
|
||||
data class LLMConfig(
|
||||
val baseUrl: String,
|
||||
val apiKey: String,
|
||||
val model: String
|
||||
)
|
||||
|
||||
data class SettingsData(
|
||||
val llmConfig: LLMConfig?,
|
||||
val headerConfigs: List<HeaderConfig>?,
|
||||
val promptConfigs: List<PromptConfig>?,
|
||||
val buttonConfigs: List<ButtonConfig>?
|
||||
)
|
||||
}
|
||||
6
app/src/main/res/drawable/button_config_bg.xml
Normal file
6
app/src/main/res/drawable/button_config_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/secondary" />
|
||||
<corners android:radius="12dp" />
|
||||
</shape>
|
||||
6
app/src/main/res/drawable/button_primary_bg.xml
Normal file
6
app/src/main/res/drawable/button_primary_bg.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/primary" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
9
app/src/main/res/drawable/button_secondary_bg.xml
Normal file
9
app/src/main/res/drawable/button_secondary_bg.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/primary" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@android:color/transparent" />
|
||||
<solid android:color="@color/surface" />
|
||||
<stroke
|
||||
android:width="2dp"
|
||||
android:color="@color/foreground_color" />
|
||||
<corners android:radius="8dp" />
|
||||
android:width="1dp"
|
||||
android:color="@color/border" />
|
||||
<corners android:radius="16dp" />
|
||||
</shape>
|
||||
10
app/src/main/res/drawable/ic_check_circle.xml
Normal file
10
app/src/main/res/drawable/ic_check_circle.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
||||
</vector>
|
||||
10
app/src/main/res/drawable/ic_copy.xml
Normal file
10
app/src/main/res/drawable/ic_copy.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#42A5F5"
|
||||
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
|
||||
</vector>
|
||||
@@ -1,30 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/mainLinearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="@drawable/appbackground"
|
||||
android:backgroundTint="@color/semi_transparent_background"
|
||||
android:backgroundTintMode="src_over">
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
<!-- 顶部导航栏 - 去掉圆角 -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
android:background="@color/surface"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="AI优化"
|
||||
android:textSize="20sp"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/black"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerModelName"
|
||||
@@ -32,40 +31,75 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="gpt-4o"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"/>
|
||||
android:textColor="@color/text_hint"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@id/headerTitle"/>
|
||||
|
||||
</LinearLayout>
|
||||
<Button
|
||||
android:id="@+id/configButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:text="配置"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/white"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="@drawable/button_config_bg"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"/>
|
||||
|
||||
<!-- Prompt Selector -->
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- 提示词选择区域 - 去掉圆角 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
android:background="@color/surface"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="1dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="提示词"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/black"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
android:textColor="@color/text_primary"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/promptSelector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:spinnerMode="dropdown"/>
|
||||
android:spinnerMode="dropdown"
|
||||
android:padding="8dp"/>
|
||||
|
||||
<!-- 提示词内容显示区域 -->
|
||||
<TextView
|
||||
android:id="@+id/promptContentText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:padding="4dp"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@color/text_hint"
|
||||
android:minLines="1"
|
||||
android:maxLines="3"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Input Area -->
|
||||
<!-- 输入区域 - 去掉圆角 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
android:background="@color/surface"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="1dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/inputEditText"
|
||||
@@ -75,53 +109,66 @@
|
||||
android:hint="输入待发送内容…"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="5"
|
||||
android:padding="8sp"
|
||||
android:textSize="14sp"/>
|
||||
android:padding="12dp"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textColorHint="@color/text_hint"
|
||||
android:gravity="top|start"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="8dp">
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:text="发送"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginEnd="4dp"/>
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/white"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/button_primary_bg"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/stopButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:text="停止生成"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginStart="4dp"/>
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/primary"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/button_secondary_bg"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Output Area -->
|
||||
<!-- 输出区域 - 去掉圆角 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="16dp">
|
||||
android:background="@color/surface"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="1dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/outputStatusLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="等待发送"
|
||||
android:textSize="12sp"
|
||||
android:textColor="@android:color/holo_blue_dark"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/outputTextView"
|
||||
@@ -129,36 +176,32 @@
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"
|
||||
android:textSize="14sp"
|
||||
android:padding="12dp"
|
||||
android:textSize="16sp"
|
||||
android:text="发送消息后结果将在此显示"
|
||||
android:textColor="@android:color/black"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/copyButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="复制"
|
||||
android:textSize="12sp"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="4dp"/>
|
||||
android:textColor="@color/text_secondary"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Custom Buttons -->
|
||||
<!-- 复制结果按钮 - 去掉圆角 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="vertical"
|
||||
android:background="@color/surface"
|
||||
android:padding="16dp"
|
||||
android:layout_marginTop="1dp">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCopyResult"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:text="复制结果"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginEnd="4dp"/>
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/primary"
|
||||
android:background="@drawable/button_secondary_bg"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -1,373 +1,420 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp">
|
||||
android:background="@color/background"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header -->
|
||||
<LinearLayout
|
||||
<!-- 1. 顶部导航栏 -->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
android:background="@color/surface"
|
||||
android:elevation="4dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<Button
|
||||
<!-- 返回按钮 -->
|
||||
<ImageButton
|
||||
android:id="@+id/btnBack"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="返回主界面"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="返回"
|
||||
android:src="@android:drawable/ic_media_previous"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- 标题和副标题容器 -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/tvAutoSaveStatus"
|
||||
app:layout_constraintStart_toEndOf="@id/btnBack"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerTitle"
|
||||
android:id="@+id/tvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="设置"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/black"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerSubtitle"
|
||||
android:id="@+id/tvSubtitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="配置自动保存到本地"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"/>
|
||||
|
||||
android:textColor="@color/text_hint"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- LLM Config Section -->
|
||||
<!-- 自动保存状态图标 -->
|
||||
<ImageView
|
||||
android:id="@+id/tvAutoSaveStatus"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@drawable/ic_check_circle"
|
||||
android:tint="@color/success"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btnHome"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<!-- 返回首页按钮 -->
|
||||
<Button
|
||||
android:id="@+id/btnHome"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:text="首页"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/primary"
|
||||
android:background="@drawable/button_secondary_bg"
|
||||
android:minWidth="0dp"
|
||||
android:minHeight="0dp"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<!-- 2. 大模型配置卡片 -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 卡片标题 -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="大模型配置"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="设置 API 接口地址、密钥与模型"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
android:textColor="@color/text_hint"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<!-- Base URL Field -->
|
||||
<!-- Base URL -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Base URL"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etBaseUrl"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:hint="https://api.openai.com/v1"
|
||||
android:inputType="textUri"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"/>
|
||||
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textColorHint="@color/text_hint"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- API Key Field -->
|
||||
<!-- API Key -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="API Key"
|
||||
android:textSize="14sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/edittext_border">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etApiKey"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:hint="sk-..."
|
||||
android:inputType="textPassword"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="48dp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textColorHint="@color/text_hint"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnToggleApiKey"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_lock_idle_lock"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical"/>
|
||||
|
||||
android:contentDescription="显示/隐藏"
|
||||
android:src="@android:drawable/ic_lock_idle_lock"
|
||||
app:tint="@color/text_hint" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etApiKey"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:hint="sk-..."
|
||||
android:inputType="textPassword"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Model Field -->
|
||||
<!-- Model -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
android:layout_marginTop="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="模型"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
android:text="Model"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etModel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:hint="gpt-4o"
|
||||
android:inputType="text"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"/>
|
||||
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textColorHint="@color/text_hint"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 3. 自定义提示词卡片 -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<!-- Custom Headers Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 标题栏 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutPromptToggle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="自定义提示词"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="设置系统级指令和角色扮演"
|
||||
android:textColor="@color/text_hint"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivPromptArrow"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@android:drawable/ic_media_play"
|
||||
android:tint="@color/primary"
|
||||
android:rotation="0" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 折叠内容区域 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutPromptContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<!-- 添加按钮 -->
|
||||
<Button
|
||||
android:id="@+id/btnAddPrompt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:text="+ 添加提示词"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/primary"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
<!-- 提示词列表容器 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/llPromptList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- 4. 自定义请求头折叠卡片 -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardBackgroundColor="@color/surface"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 可点击的标题栏 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutHeaderToggle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="自定义请求头"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="向请求附加额外的 HTTP Header"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="向请求附加额外的HTTP Header"
|
||||
android:textColor="@color/text_hint"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Headers List -->
|
||||
<ImageView
|
||||
android:id="@+id/ivHeaderArrow"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:src="@android:drawable/ic_media_play"
|
||||
android:tint="@color/primary"
|
||||
android:rotation="0" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 折叠内容区域 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutHeaderContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<!-- 添加按钮 -->
|
||||
<Button
|
||||
android:id="@+id/btnAddHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:text="+ 添加请求头"
|
||||
android:textSize="14sp"
|
||||
android:backgroundTint="@color/primary"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
<!-- 请求头列表容器 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/llHeadersList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<!-- Default Header Entry -->
|
||||
<LinearLayout
|
||||
android:id="@+id/headerEntryTemplate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etHeaderKey"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="Header 名称"
|
||||
android:inputType="text"
|
||||
android:padding="4sp"/>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/darker_gray"
|
||||
android:layout_marginHorizontal="8dp"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etHeaderValue"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="2"
|
||||
android:hint="值"
|
||||
android:inputType="text"
|
||||
android:padding="4sp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnRemoveHeader"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_close_clear_cancel"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical"/>
|
||||
android:layout_marginTop="12dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Add Header Button -->
|
||||
<Button
|
||||
android:id="@+id/btnAddHeader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="添加请求头"
|
||||
android:layout_gravity="start"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Preset Prompts Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="预设提示词"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="管理可快速选用的系统提示词"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Prompts List -->
|
||||
<LinearLayout
|
||||
android:id="@+id/llPromptsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<!-- Prompt entries will be added dynamically -->
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Add Prompt Button -->
|
||||
<Button
|
||||
android:id="@+id/btnAddPrompt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="添加提示词"
|
||||
android:layout_gravity="start"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"/>
|
||||
|
||||
<!-- Empty State -->
|
||||
<TextView
|
||||
android:id="@+id/tvEmptyPrompts"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="暂无预设提示词"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="12dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Custom Buttons Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="24dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="自定义按钮"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="配置主界面中显示的操作按钮"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Buttons List -->
|
||||
<LinearLayout
|
||||
android:id="@+id/llButtonsList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp">
|
||||
|
||||
<!-- Button entries will be added dynamically -->
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Add Button -->
|
||||
<Button
|
||||
android:id="@+id/btnAddButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="添加按钮"
|
||||
android:layout_gravity="start"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp"/>
|
||||
|
||||
<!-- Empty State -->
|
||||
<TextView
|
||||
android:id="@+id/tvEmptyButtons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="暂无自定义按钮"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@android:color/darker_gray"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="12dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
@@ -5,7 +5,7 @@
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="8sp">
|
||||
android:padding="8dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etHeaderKey"
|
||||
@@ -14,7 +14,7 @@
|
||||
android:layout_weight="1"
|
||||
android:hint="Header 名称"
|
||||
android:inputType="text"
|
||||
android:padding="4sp"/>
|
||||
android:padding="4dp"/>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
@@ -29,7 +29,7 @@
|
||||
android:layout_weight="2"
|
||||
android:hint="值"
|
||||
android:inputType="text"
|
||||
android:padding="4sp"/>
|
||||
android:padding="4dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnRemoveHeader"
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:background="@drawable/edittext_border"
|
||||
android:padding="12sp">
|
||||
android:padding="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8sp">
|
||||
android:layout_marginBottom="4dp">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPromptTitle"
|
||||
@@ -20,7 +20,8 @@
|
||||
android:layout_weight="1"
|
||||
android:hint="提示词标题"
|
||||
android:inputType="text"
|
||||
android:padding="4sp"/>
|
||||
android:padding="4dp"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnRemovePrompt"
|
||||
@@ -28,33 +29,17 @@
|
||||
android:layout_height="24dp"
|
||||
android:src="@android:drawable/ic_menu_close_clear_cancel"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="end"/>
|
||||
|
||||
android:layout_gravity="center_vertical"/>
|
||||
</LinearLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPromptContent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:hint="提示词内容(System Prompt)"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="4"
|
||||
android:background="@android:color/white"
|
||||
android:padding="8sp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnExpandPrompt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="展开"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="4sp"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/viewDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="@android:color/darker_gray"
|
||||
android:layout_marginVertical="8sp"/>
|
||||
android:hint="提示词内容"
|
||||
android:inputType="textMultiLine"
|
||||
android:minLines="3"
|
||||
android:padding="4dp"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -7,8 +7,33 @@
|
||||
<color name="teal_700">#FF018786</color>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
<color name="foreground_color">#eFeFeF</color> <!-- 示例前景色(白色) -->
|
||||
<color name="background_color">#333333</color> <!-- 示例背景色(深灰色) -->
|
||||
<color name="foreground_color">#eFeFeF</color>
|
||||
<color name="background_color">#333333</color>
|
||||
<color name="gray_light">#CCCCCC</color>
|
||||
<color name="semi_transparent_background">#19000000</color>
|
||||
|
||||
<!-- 核心色值 -->
|
||||
<color name="primary">#42A5F5</color>
|
||||
<color name="primary_variant">#1976D2</color>
|
||||
<color name="secondary">#81C784</color>
|
||||
<color name="secondary_variant">#4CAF50</color>
|
||||
|
||||
<!-- 中性色 -->
|
||||
<color name="background">#F5F5F5</color>
|
||||
<color name="surface">#FAFAFA</color>
|
||||
<color name="surface_variant">#EEEEEE</color> <!-- 用于卡片阴影/边框 -->
|
||||
|
||||
<!-- 文本色 -->
|
||||
<color name="text_primary">#212121</color>
|
||||
<color name="text_secondary">#424242</color>
|
||||
<color name="text_hint">#757575</color>
|
||||
<color name="text_disabled">#BDBDBD</color>
|
||||
|
||||
<!-- 边框色 -->
|
||||
<color name="border">#E0E0E0</color>
|
||||
|
||||
<!-- 状态色 -->
|
||||
<color name="success">#4CAF50</color>
|
||||
<color name="warning">#FF9800</color>
|
||||
<color name="error">#F44336</color>
|
||||
</resources>
|
||||
21
test_logcat.bat
Normal file
21
test_logcat.bat
Normal file
@@ -0,0 +1,21 @@
|
||||
@echo off
|
||||
echo 测试日志系统...
|
||||
echo.
|
||||
echo 当前设备:
|
||||
adb devices
|
||||
echo.
|
||||
echo 清除旧日志...
|
||||
adb logcat -c
|
||||
echo.
|
||||
echo 等待5秒让日志系统稳定...
|
||||
timeout /t 5 /nobreak >nul
|
||||
echo.
|
||||
echo 测试日志输出(应显示系统日志):
|
||||
adb logcat -d -v time | findstr /C:"I/" | head -n 5
|
||||
echo.
|
||||
echo 如果看到上述日志,说明日志系统工作正常
|
||||
echo 现在请在模拟器中运行APP,然后按回车查看日志...
|
||||
pause >nul
|
||||
echo.
|
||||
echo 开始监控应用日志...
|
||||
adb logcat -v time -s MainActivity:* SecondActivity:*
|
||||
18
view_detailed_logs.bat
Normal file
18
view_detailed_logs.bat
Normal file
@@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
echo ========================================
|
||||
echo 应用日志查看工具
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
echo 1. 清除旧日志...
|
||||
adb logcat -c
|
||||
echo.
|
||||
|
||||
echo 2. 开始监控应用日志...
|
||||
echo 标签: MainActivity, SecondActivity
|
||||
echo 按 Ctrl+C 停止监控
|
||||
echo.
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
adb logcat -v time -s MainActivity:* SecondActivity:*
|
||||
10
view_logs.bat
Normal file
10
view_logs.bat
Normal file
@@ -0,0 +1,10 @@
|
||||
@echo off
|
||||
echo 正在清除旧日志...
|
||||
adb logcat -c
|
||||
|
||||
echo.
|
||||
echo 正在启动日志监控(MainActivity 和 SecondActivity)...
|
||||
echo 按 Ctrl+C 停止监控
|
||||
echo.
|
||||
|
||||
adb logcat -s MainActivity:* SecondActivity:*
|
||||
Reference in New Issue
Block a user