diff --git a/.idea/dictionaries/spayi.xml b/.idea/dictionaries/spayi.xml
new file mode 100644
index 0000000..15b1e8c
--- /dev/null
+++ b/.idea/dictionaries/spayi.xml
@@ -0,0 +1,7 @@
+
+
+
+ recv
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index f7d993c..0b0226d 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,8 +13,9 @@ android {
applicationId "top.fumiama.simpledict"
minSdkVersion 26
targetSdkVersion 30
- versionCode 4
- versionName '1.2'
+ versionCode 5
+ versionName '1.3'
+ resConfigs "zh", "zh-rCN"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/app/src/main/java/top/fumiama/simpledict/Client.kt b/app/src/main/java/top/fumiama/simpledict/Client.kt
index 1ad560b..2c70b10 100644
--- a/app/src/main/java/top/fumiama/simpledict/Client.kt
+++ b/app/src/main/java/top/fumiama/simpledict/Client.kt
@@ -6,7 +6,7 @@ import java.io.InputStream
import java.io.OutputStream
import java.net.Socket
-class Client(val ip: String, val port: Int) {
+class Client(private val ip: String, private val port: Int) {
//普通数据交互接口
private var sc: Socket? = null
@@ -15,23 +15,22 @@ class Client(val ip: String, val port: Int) {
private var din: InputStream? = null
//已连接标记
- var isConnect = false
+ private val isConnect get() = sc != null && din != null && dout != null
/**
* 初始化普通交互连接
*/
- fun initConnect(){
- try {
+ fun initConnect(depth: Int = 0){
+ if(depth > 3) Log.d("MyC", "connect server failed after $depth tries")
+ else try {
sc = Socket(ip, port) //通过socket连接服务器
din = sc?.getInputStream() //获取输入流并转换为StreamReader,约定编码格式
dout = sc?.getOutputStream() //获取输出流
- sc?.soTimeout = 10000 //设置连接超时限制
- if (sc != null && din != null && dout != null) { //判断一下是否都连上,避免NullPointException
- isConnect = true
- Log.d("MyC", "connect server successful")
- } else {
- Log.d("MyC", "connect server failed,now retry...")
- initConnect()
+ sc?.soTimeout = 2333 //设置连接超时限制
+ if (isConnect) Log.d("MyC", "connect server successful")
+ else {
+ Log.d("MyC", "connect server failed, now retry...")
+ initConnect(depth + 1)
}
} catch (e: IOException) { //获取输入输出流是可能报IOException的,所以必须try-catch
e.printStackTrace()
@@ -45,30 +44,31 @@ class Client(val ip: String, val port: Int) {
fun sendMessage(message: CharSequence?) {
try {
if (isConnect) {
- if (dout != null && message != null) { //判断输出流或者消息是否为空,为空的话会产生nullpoint错误
- dout!!.write(message.toString().toByteArray())
- dout!!.flush()
- } else Log.d("MyC", "The message to be sent is empty or have no connect")
+ if (message != null) { //判断输出流或者消息是否为空,为空的话会产生nullpoint错误
+ dout?.write(message.toString().toByteArray())
+ dout?.flush()
+ Log.d("MyC", "Send msg: $message")
+ } else Log.d("MyC", "The message to be sent is empty")
Log.d("MyC", "send message succeed")
- } else Log.d("MyC", "no connect to send message")
+ } else Log.d("MyC", "send message failed: no connect")
} catch (e: IOException) {
- Log.d("MyC", "send message to cilent failed")
+ Log.d("MyC", "send message failed: crash")
e.printStackTrace()
}
}
- fun receiveRawMessage() : ByteArray {
+ fun receiveRawMessage(totalSize: Int = -1, bufferSize: Int = 4096) : ByteArray {
var re = byteArrayOf()
try {
if (isConnect) {
Log.d("MyC", "开始接收服务端信息")
- val inMessage = ByteArray(4096) //设置接受缓冲,避免接受数据过长占用过多内存
+ val inMessage = ByteArray(bufferSize) //设置接受缓冲,避免接受数据过长占用过多内存
var a: Int
do {
a = din?.read(inMessage)?:0 //a存储返回消息的长度
- Log.d("MyC", "reply length:$a: ${inMessage.decodeToString()}")
re += inMessage.copyOf(a)
- } while (a == 4096)
+ Log.d("MyC", "reply length:$a: ${re.decodeToString()}")
+ } while (a == bufferSize || totalSize > re.size)
} else Log.d("MyC", "no connect to receive message")
} catch (e: IOException) {
Log.d("MyC", "receive message failed")
@@ -87,10 +87,12 @@ class Client(val ip: String, val port: Int) {
din?.close()
dout?.close()
sc?.close()
+ sc = null
+ din = null
+ dout = null
} catch (e: IOException) {
e.printStackTrace()
}
- isConnect = false
Log.d("MyC", "关闭连接")
}
}
diff --git a/app/src/main/java/top/fumiama/simpledict/MainActivity.kt b/app/src/main/java/top/fumiama/simpledict/MainActivity.kt
index ad887a0..a05c9fd 100644
--- a/app/src/main/java/top/fumiama/simpledict/MainActivity.kt
+++ b/app/src/main/java/top/fumiama/simpledict/MainActivity.kt
@@ -9,10 +9,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
+import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.textfield.TextInputLayout
import com.lapism.search.internal.SearchLayout
import com.lapism.search.util.SearchUtils
import kotlinx.android.synthetic.main.activity_main.*
@@ -21,6 +23,14 @@ import kotlinx.android.synthetic.main.line_word.view.*
class MainActivity : AppCompatActivity() {
private val dict = SimpleDict(Client("127.0.0.1", 8000), "fumiama")
private var hasLiked = false
+ private val fetchThread get() = Thread{
+ dict.fetchDict {
+ runOnUiThread {
+ Toast.makeText(this@MainActivity, "刷新成功", Toast.LENGTH_SHORT).show()
+ ffsw.isRefreshing = false
+ }
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -35,8 +45,10 @@ class MainActivity : AppCompatActivity() {
ffsw.apply {
setOnRefreshListener {
ad.refresh()
- isRefreshing = false
+ fetchThread.start()
}
+ isRefreshing = true
+ fetchThread.start()
}
}
@@ -107,15 +119,15 @@ class MainActivity : AppCompatActivity() {
}
private fun showDictAlert(key: String, data: String?) {
- val like = getSharedPreferences("dict", MODE_PRIVATE)?.contains(key)?:false
+ val hintAdd = if(data != null && data != "null") "重设" else "添加"
hasLiked = false
AlertDialog.Builder(this@MainActivity)
.setTitle(key)
.setMessage(data)
- .setPositiveButton(if(data != "null") "重设" else "添加") { _, _ ->
+ .setPositiveButton(hintAdd) { _, _ ->
val t = EditText(this@MainActivity)
AlertDialog.Builder(this@MainActivity)
- .setTitle("重设$key")
+ .setTitle("$hintAdd$key")
.setView(t)
.setPositiveButton(android.R.string.ok) { _, _ ->
if (t.text.isNotEmpty()) Thread {
@@ -125,12 +137,8 @@ class MainActivity : AppCompatActivity() {
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
}
- .setNeutralButton(if(like) "取消收藏" else "收藏") { _, _ ->
- getSharedPreferences("dict", MODE_PRIVATE)?.edit()?.apply {
- if(like) remove(key) else putString(key, data)
- hasLiked = true
- apply()
- }
+ .setNeutralButton("删除") { _, _ ->
+ Thread{dict -= key}.start()
}
.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show()
@@ -182,19 +190,38 @@ class MainActivity : AppCompatActivity() {
@SuppressLint("ClickableViewAccessibility", "SetTextI18n")
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
Log.d("MyMain", "Bind like at $position")
- listKeys?.apply {
- if (position < size) {
- val key = get(position)
- val data = getValue(key)
- holder.itemView.apply {
- ta.text = key
- tb.text = data
- setOnClickListener {
- showDictAlert(key, data)
+ Thread{
+ listKeys?.apply {
+ if (position < size) {
+ val key = get(position)
+ val data = getValue(key)
+ val like = getSharedPreferences("dict", MODE_PRIVATE)?.contains(key) == true
+ runOnUiThread {
+ holder.itemView.apply {
+ ta.text = key
+ tb.text = data
+ if(like) vl.setBackgroundResource(R.drawable.ic_like_filled)
+ setOnClickListener {
+ showDictAlert(key, data)
+ }
+ vl.setOnClickListener {
+ getSharedPreferences("dict", MODE_PRIVATE)?.edit()?.apply {
+ if(like) {
+ remove(key)
+ it.setBackgroundResource(R.drawable.ic_like)
+ } else {
+ putString(key, data)
+ it.setBackgroundResource(R.drawable.ic_like_filled)
+ }
+ hasLiked = true
+ apply()
+ }
+ }
+ }
}
}
}
- }
+ }.start()
}
override fun getItemCount() = listKeys?.size?:0
diff --git a/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt b/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt
index 8cb9315..54fe9f7 100644
--- a/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt
+++ b/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt
@@ -10,21 +10,44 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must
//val size get() = dict.size
private val raw: ByteArray
get() {
- initDict()
- client.sendMessage("cat")
- sleep(2333)
- val re = client.receiveRawMessage()
- closeDict()
+ var times = 3
+ var re: ByteArray
+ var firstRecv: ByteArray
+ do {
+ re = byteArrayOf()
+ initDict()
+ sendMessageWithDelay("cat", 2333)
+ try {
+ firstRecv = client.receiveRawMessage()
+ val firstStr = firstRecv.decodeToString()
+ var length = ""
+ for ((i, c) in firstStr.withIndex()) {
+ if(c.isDigit()) length += c
+ else {
+ if(i + 1 < firstRecv.size) re = firstRecv.copyOfRange(i, firstRecv.size)
+ break
+ }
+ }
+ re += client.receiveRawMessage(length.toInt() - re.size)
+ break
+ } catch (e: Exception){
+ e.printStackTrace()
+ }
+ closeDict()
+ } while (times-- > 0)
return re
}
-
- init {
- Thread{ fetchDict() }.start()
- }
+
+ private fun sendMessageWithDelay(msg: CharSequence, delay: Long = 233) = Thread{
+ client.sendMessage(msg)
+ sleep(delay)
+ }.start()
private fun initDict() {
client.initConnect()
client.sendMessage(pwd)
+ client.receiveRawMessage()
+ sleep(233)
}
private fun closeDict() {
@@ -45,59 +68,36 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must
//fun filterKeys(predicate: (String) -> Boolean) = dict.filterKeys(predicate)
fun filterValues(predicate: (String?) -> Boolean) = dict.filterValues(predicate)
- fun fetchDict() {
+ fun fetchDict(doOnLoadSuccess: ()->Unit = {
+ Log.d("MySD", "Fetch dict success")
+ }) {
val dictBlock = ByteArray(128)
+ dict = hashMapOf()
raw.inputStream().let {
- var c = '1'
- while (!it.read().toChar().isDigit()) Log.d("MySD", "Skip banner.")
- while (c.isDigit()) {
- c = it.read().toChar()
- Log.d("MySD", "Skip digit $c.")
- }
- dictBlock[0] = c.toByte()
- if(it.read(dictBlock, 1, 127) == 127) {
- analyzeDictBlk(dictBlock)
- while (it.read(dictBlock, 0, 128) == 128) analyzeDictBlk(dictBlock)
- }
+ while (it.read(dictBlock, 0, 128) == 128) analyzeDictBlk(dictBlock)
+ doOnLoadSuccess()
}
}
- /*fun keysWithPattern(pattern: String): MutableSet{
- val re = mutableSetOf()
+ operator fun minusAssign(key: String) {
initDict()
- client.sendMessage("lst")
- sleep(233)
+ sendMessageWithDelay("del")
+ client.receiveMessage()
+ sendMessageWithDelay(key)
client.receiveMessage()
- client.sendMessage(pattern)
- client.receiveMessage()?.substringBeforeLast('\n')?.split('\n')?.forEach {
- re.add(it)
- }
closeDict()
- return re
}
- fun getDirectly(key: String): String? {
- initDict()
- client.sendMessage("get")
- sleep(233)
- client.receiveMessage()
- client.sendMessage(key)
- val re = client.receiveMessage()
- closeDict()
- return re
- }*/
-
operator fun get(key: String) = dict[key]
operator fun set(key: String, value: String): String? {
val p = dict[key]
initDict()
- client.sendMessage("set")
- sleep(233)
+ sendMessageWithDelay("set")
client.receiveMessage()
- client.sendMessage(key)
+ sendMessageWithDelay(key)
client.receiveMessage()
- client.sendMessage(value)
+ sendMessageWithDelay(value)
client.receiveMessage()
closeDict()
dict[key] = value
diff --git a/app/src/main/res/drawable-anydpi/ic_like.xml b/app/src/main/res/drawable-anydpi/ic_like.xml
new file mode 100644
index 0000000..87c647d
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_like.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_like_filled.xml b/app/src/main/res/drawable-anydpi/ic_like_filled.xml
new file mode 100644
index 0000000..a4344c9
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_like_filled.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index b7fc59a..fa4202f 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,32 +1,33 @@
-
- app:layout_scrollFlags="scroll"
- app:toolbarId="@+id/toolbar">
-
-
-
+ android:layout_height="match_parent"
+ app:contentScrim="?attr/colorSurface"
+ app:toolbarId="@+id/toolbar">
+
+
+
+
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/line_word.xml b/app/src/main/res/layout/line_word.xml
index 2f3b9bd..c0d5939 100644
--- a/app/src/main/res/layout/line_word.xml
+++ b/app/src/main/res/layout/line_word.xml
@@ -1,31 +1,50 @@
-
+ android:foreground="?android:attr/selectableItemBackground">
-
+ android:background="@drawable/ic_like"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ android:clickable="true"
+ android:focusable="true"
+ android:foreground="?android:attr/selectableItemBackground"/>
-
-
\ No newline at end of file
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
index 5b24d00..517f8e3 100644
--- a/app/src/main/res/values-night/themes.xml
+++ b/app/src/main/res/values-night/themes.xml
@@ -4,11 +4,11 @@
- @color/purple_200
- @color/purple_700
- - @color/black
+ - @android:color/black
- @color/teal_200
- @color/teal_200
- - @color/black
+ - @android:color/black
- ?attr/colorPrimaryVariant
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 699a436..37fc22d 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,12 +1,8 @@
#FFBB86FC
- #FF6200EE
#FF3700B3
#FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
#BA8D08
#FF9800
#FF845E
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
deleted file mode 100644
index 125df87..0000000
--- a/app/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
- 16dp
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 87f9780..32425cb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,12 +1,3 @@
SimpleDict
- Settings
-
- First Fragment
- Second Fragment
- Next
- Previous
-
- Hello first fragment
- Hello second fragment. Arg: %1$s
\ No newline at end of file
diff --git a/app/winrelease/app-winrelease.apk b/app/winrelease/app-winrelease.apk
index 55c24c1..a8e5cf4 100644
Binary files a/app/winrelease/app-winrelease.apk and b/app/winrelease/app-winrelease.apk differ
diff --git a/app/winrelease/output-metadata.json b/app/winrelease/output-metadata.json
index 8f98f00..fbc96a3 100644
--- a/app/winrelease/output-metadata.json
+++ b/app/winrelease/output-metadata.json
@@ -10,8 +10,8 @@
{
"type": "SINGLE",
"filters": [],
- "versionCode": 4,
- "versionName": "1.2",
+ "versionCode": 5,
+ "versionName": "1.3",
"outputFile": "app-winrelease.apk"
}
]