Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,8 @@ dependencies {
// CoordinatorLayout (用于FloatingActionButton)
implementation("androidx.coordinatorlayout:coordinatorlayout:1.2.0")

}
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

}
6 changes: 5 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
android:windowSoftInputMode="adjustResize"
android:exported="false" />

<activity
android:name=".ui.guide.ChatKnowledgeActivity"
android:exported="false" />

</application>

</manifest>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.example.chatapp.R
import com.example.chatapp.data.database.entity.Conversation
import com.example.chatapp.ui.chat.ChatActivity
import com.example.chatapp.ui.guide.ChatKnowledgeActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton

class ConversationListActivity : AppCompatActivity() {
Expand Down Expand Up @@ -138,6 +139,10 @@ class ConversationListActivity : AppCompatActivity() {

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_knowledge_guide -> {
startActivity(Intent(this, ChatKnowledgeActivity::class.java))
true
}
R.id.action_clear_all -> {
showClearAllDialog()
true
Expand All @@ -163,4 +168,4 @@ class ConversationListActivity : AppCompatActivity() {
super.onDestroy()
recyclerView.adapter = null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.example.chatapp.ui.guide

import android.os.Bundle
import android.view.MenuItem
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.example.chatapp.R

class ChatKnowledgeActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat_knowledge)

supportActionBar?.apply {
title = getString(R.string.knowledge_intro_title)
setDisplayHomeAsUpEnabled(true)
}

val content = ChatKnowledgeContentProvider.getContent()
findViewById<TextView>(R.id.tv_knowledge_intro).setText(content.introductionResId)
findViewById<TextView>(R.id.tv_knowledge_code).setText(content.codeExampleResId)
findViewById<TextView>(R.id.tv_knowledge_scenario).setText(content.scenarioDesignResId)
findViewById<TextView>(R.id.tv_knowledge_explanation).setText(content.explanationResId)
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {
finish()
true
}
else -> super.onOptionsItemSelected(item)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.example.chatapp.ui.guide

import androidx.annotation.StringRes
import com.example.chatapp.R

data class ChatKnowledgeContent(
@StringRes val introductionResId: Int,
@StringRes val codeExampleResId: Int,
@StringRes val scenarioDesignResId: Int,
@StringRes val explanationResId: Int
)

object ChatKnowledgeContentProvider {

fun getContent(): ChatKnowledgeContent {
return ChatKnowledgeContent(
introductionResId = R.string.knowledge_intro_content,
codeExampleResId = R.string.knowledge_code_content,
scenarioDesignResId = R.string.knowledge_scenario_content,
explanationResId = R.string.knowledge_explanation_content
)
}
}
80 changes: 80 additions & 0 deletions app/src/main/res/layout/activity_chat_knowledge.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/knowledge_intro_label"
android:textSize="20sp"
android:textStyle="bold" />

<TextView
android:id="@+id/tv_knowledge_intro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:lineSpacingExtra="4dp"
android:textSize="16sp" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/knowledge_code_label"
android:textSize="20sp"
android:textStyle="bold" />

<TextView
android:id="@+id/tv_knowledge_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="#F5F5F5"
android:fontFamily="monospace"
android:padding="12dp"
android:textSize="14sp" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/knowledge_scenario_label"
android:textSize="20sp"
android:textStyle="bold" />

<TextView
android:id="@+id/tv_knowledge_scenario"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:lineSpacingExtra="4dp"
android:textSize="16sp" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/knowledge_explanation_label"
android:textSize="20sp"
android:textStyle="bold" />

<TextView
android:id="@+id/tv_knowledge_explanation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="24dp"
android:lineSpacingExtra="4dp"
android:textSize="16sp" />

</LinearLayout>

</ScrollView>
8 changes: 7 additions & 1 deletion app/src/main/res/menu/menu_conversation_list.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
android:id="@+id/action_knowledge_guide"
android:title="@string/knowledge_intro_label"
android:icon="@android:drawable/ic_menu_info_details"
app:showAsAction="never" />

<item
android:id="@+id/action_clear_all"
android:title="清空会话"
android:icon="@android:drawable/ic_menu_delete"
app:showAsAction="never" />

</menu>
</menu>
22 changes: 21 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
<resources>
<string name="app_name">Chatapp</string>
</resources>
<string name="knowledge_intro_title">聊天应用知识点介绍</string>
<string name="knowledge_intro_label">知识点介绍</string>
<string name="knowledge_code_label">编写代码</string>
<string name="knowledge_scenario_label">场景设计</string>
<string name="knowledge_explanation_label">解释说明</string>
<string name="knowledge_intro_content">1. 会话列表:通过 RecyclerView 展示联系人、最后一条消息和未读数,帮助用户快速定位目标会话。
2. 消息流:聊天页根据消息发送者区分左右气泡,并支持文字与图片两种消息类型。
3. 数据持久化:使用 Room 保存会话与消息记录,保证重新进入应用后仍能查看历史内容。</string>
<string name="knowledge_code_content">viewModel.sendMessage(
conversationId = conversationId,
senderId = currentUserId,
content = "你好,欢迎来到聊天学习页!",
type = MessageType.TEXT
)</string>
<string name="knowledge_scenario_content">场景:新成员首次接触本项目,需要在几分钟内理解聊天应用的核心结构。
做法:先阅读会话列表与聊天页的职责,再结合示例代码理解消息对象如何创建、保存和展示。
结果:学习者可以快速上手新增消息类型、优化自动回复逻辑,或扩展更多聊天功能。</string>
<string name="knowledge_explanation_content">上面的示例代码强调“由界面层调用 ViewModel 完成消息发送”的流程。
这种设计将界面层与数据层解耦,既方便测试,也方便未来接入网络请求或更复杂的业务规则。
因此,这个学习页既能帮助理解知识点,也能作为后续功能设计时的参考模板。</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.chatapp.ui.guide

import com.example.chatapp.R
import org.junit.Assert.assertEquals
import org.junit.Test

class ChatKnowledgeContentProviderTest {

@Test
fun getContent_returnsAllLearningSections() {
val content = ChatKnowledgeContentProvider.getContent()

assertEquals(R.string.knowledge_intro_content, content.introductionResId)
assertEquals(R.string.knowledge_code_content, content.codeExampleResId)
assertEquals(R.string.knowledge_scenario_content, content.scenarioDesignResId)
assertEquals(R.string.knowledge_explanation_content, content.explanationResId)
}
}
1 change: 0 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,3 @@ androidx-compose-material3 = { group = "androidx.compose.material3", name = "mat
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }

Empty file modified gradlew
100644 → 100755
Empty file.