diff --git a/app/build.gradle b/app/build.gradle index ca961cb..df93208 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "top.fumiama.simpledict" minSdkVersion 26 targetSdkVersion 30 - versionCode 6 - versionName '1.4' + versionCode 7 + versionName '1.5' resConfigs "zh", "zh-rCN" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/java/top/fumiama/simpledict/MainActivity.kt b/app/src/main/java/top/fumiama/simpledict/MainActivity.kt index bb3086e..bd39339 100644 --- a/app/src/main/java/top/fumiama/simpledict/MainActivity.kt +++ b/app/src/main/java/top/fumiama/simpledict/MainActivity.kt @@ -25,20 +25,13 @@ 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 - } - } - } private var cm: ClipboardManager? = null + private var ad: ListViewHolder.RecyclerViewAdapter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - val ad = LikeViewHolder(ffr).RecyclerViewAdapter() + ad = LikeViewHolder(ffr).RecyclerViewAdapter() cm = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager ffr.apply { layoutManager = LinearLayoutManager(this@MainActivity) @@ -48,23 +41,22 @@ class MainActivity : AppCompatActivity() { } ffsw.apply { setOnRefreshListener { - ad.refresh() - fetchThread.start() + fetchThread() } isRefreshing = true - fetchThread.start() + fetchThread() } } ffms.apply { setAdapterLayoutManager(LinearLayoutManager(this@MainActivity)) - val adapter = SearchViewHolder(findViewById(R.id.search_recycler_view)).RecyclerViewAdapter() + val adapter = SearchViewHolder(findViewById(R.id.search_recycler_view), findViewById(R.id.search_search_edit_text)).RecyclerViewAdapter() setAdapter(adapter) navigationIconSupport = SearchLayout.NavigationIconSupport.SEARCH setOnNavigationClickListener(object : SearchLayout.OnNavigationClickListener { override fun onNavigationClick(hasFocus: Boolean) { if (hasFocus()) { - if(hasLiked) ad.refresh() + if(hasLiked) ad?.refresh() clearFocus() } else requestFocus() @@ -73,7 +65,7 @@ class MainActivity : AppCompatActivity() { setTextHint(android.R.string.search_go) setOnQueryTextListener(object : SearchLayout.OnQueryTextListener { override fun onQueryTextChange(newText: CharSequence): Boolean { - if (newText.isNotEmpty()) adapter.filter(newText) + if (newText.isNotEmpty()) adapter.refresh() return true } @@ -81,7 +73,7 @@ class MainActivity : AppCompatActivity() { if(query.isNotEmpty()) { val key = query.toString() val data = dict[key] - showDictAlert(key, data) + showDictAlert(key, data) { adapter.refresh() } } return true } @@ -104,7 +96,7 @@ class MainActivity : AppCompatActivity() { override fun onBackPressed() { if(ffms.hasFocus()) { - if(hasLiked) (ffr.adapter as ListViewHolder.RecyclerViewAdapter).refresh() + if(hasLiked) ad?.refresh() ffms.clearFocus() } else super.onBackPressed() @@ -122,7 +114,19 @@ class MainActivity : AppCompatActivity() { } } - private fun showDictAlert(key: String, data: String?) { + private fun fetchThread() { + Thread{ + dict.fetchDict { + runOnUiThread { + Toast.makeText(this@MainActivity, "刷新成功", Toast.LENGTH_SHORT).show() + ffsw.isRefreshing = false + ad?.refresh() + } + } + }.start() + } + + private fun showDictAlert(key: String, data: String?, notify: ()->Unit) { val hintAdd = if(data != null && data != "null") "重设" else "添加" hasLiked = false AlertDialog.Builder(this@MainActivity) @@ -135,8 +139,10 @@ class MainActivity : AppCompatActivity() { .setTitle("$hintAdd$key") .setView(t) .setPositiveButton(android.R.string.ok) { _, _ -> - if (t.text.isNotEmpty() && t.text.toString() != data) Thread { - dict[key] = t.text.toString() + val newText = t.text.toString() + if (t.text.isNotEmpty() && newText != data) Thread { + dict[key] = newText + notify() }.start() else Toast.makeText(this, "未更改", Toast.LENGTH_SHORT).show() } @@ -144,46 +150,48 @@ class MainActivity : AppCompatActivity() { .show() } .setNeutralButton("删除") { _, _ -> - Thread{dict -= key}.start() + Thread{ + dict -= key + notify() + }.start() } .setNegativeButton(android.R.string.cancel) { _, _ -> } .show() } - inner class SearchViewHolder(itemView: View) : ListViewHolder(itemView) { + inner class SearchViewHolder(itemView: View, private val editText: EditText) : ListViewHolder(itemView) { inner class RecyclerViewAdapter : ListViewHolder.RecyclerViewAdapter() { + override fun getKeys() = filter(editText.text) override fun getValue(key: String) = dict[key] - fun filter(text: CharSequence) { - Thread{ - val selectSet = dict.keys.filter { it.contains(text, true) }.toSet() + - dict.filterValues { it?.contains(text, true)?:false }.let { - val newSet = mutableSetOf() - it.keys.forEach { - newSet += it - } - newSet + private fun filter(text: CharSequence): List { + val selectSet = dict.keys.filter { it.contains(text, true) }.toSet() + + dict.filterValues { it?.contains(text, true) ?: false }.let { + val newSet = mutableSetOf() + it.keys.forEach { + newSet += it } - listKeys = selectSet.toList().let { if(it.size > 50) it.subList(0, 49) else it } - listKeys?.forEach { - Log.d("MyMain", "Select key: $it") - } - runOnUiThread { notifyDataSetChanged() } - }.start() + newSet + } + return selectSet.toList().let { if (it.size > 50) it.subList(0, 49) else it } } } } inner class LikeViewHolder(itemView: View) : ListViewHolder(itemView) { inner class RecyclerViewAdapter: ListViewHolder.RecyclerViewAdapter(){ - override fun getKeys() = getSharedPreferences("dict", MODE_PRIVATE).all.keys.toList() - override fun getValue(key: String) = getSharedPreferences("dict", MODE_PRIVATE).getString(key, "null") + override fun getKeys() = getSharedPreferences("dict", MODE_PRIVATE).all.keys.toTypedArray().let{ + val end = dict.latestKeys.size + val start = if(end > 5) end - 5 else 0 + (dict.latestKeys.copyOfRange(start, end) + it).toList() + } + override fun getValue(key: String) = dict[key]?:getSharedPreferences("dict", MODE_PRIVATE).getString(key, "null") } } open inner class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { open inner class RecyclerViewAdapter : RecyclerView.Adapter() { - var listKeys = getKeys() + private var listKeys: List? = null open fun getKeys(): List? = null open fun getValue(key: String): String? = null override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder { @@ -195,20 +203,22 @@ class MainActivity : AppCompatActivity() { @SuppressLint("ClickableViewAccessibility", "SetTextI18n") override fun onBindViewHolder(holder: ListViewHolder, position: Int) { - Log.d("MyMain", "Bind like at $position") + Log.d("MyMain", "Bind open at $position") 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 { + Log.d("MyMain", "Like status of $key is $like") + holder.itemView.apply { + runOnUiThread { ta.text = key tb.text = data - if(like) vl.setBackgroundResource(R.drawable.ic_like_filled) + vl.setBackgroundResource(if(like) R.drawable.ic_like_filled else R.drawable.ic_like) + Log.d("MyMain", "Set like of $key: $like") setOnClickListener { - showDictAlert(key, data) + showDictAlert(key, data) {refresh()} } setOnLongClickListener { cm?.setPrimaryClip(ClipData.newPlainText("SimpleDict", "$key\n$data")) @@ -239,10 +249,10 @@ class MainActivity : AppCompatActivity() { override fun getItemCount() = listKeys?.size?:0 - fun refresh() { + fun refresh() = Thread{ listKeys = getKeys() runOnUiThread { notifyDataSetChanged() } - } + }.start() } } } \ No newline at end of file diff --git a/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt b/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt index 54fe9f7..0254168 100644 --- a/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt +++ b/app/src/main/java/top/fumiama/simpledict/SimpleDict.kt @@ -8,6 +8,7 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must val keys get() = dict.keys //val values get() = dict.values //val size get() = dict.size + var latestKeys = arrayOf() private val raw: ByteArray get() { var times = 3 @@ -61,7 +62,10 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must val dataEnd = 64 + dictBlock[127].toInt().let { if (it > 63) 63 else it } val key = dictBlock.copyOf(keyLen).decodeToString() val data = if (dataEnd > 64) dictBlock.copyOfRange(64, dataEnd).decodeToString() else null - dict[key] = data + if(key != "") { + dict[key] = data + latestKeys += key + } Log.d("MySD", "Fetch $key=$data") } @@ -73,6 +77,7 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must }) { val dictBlock = ByteArray(128) dict = hashMapOf() + latestKeys = arrayOf() raw.inputStream().let { while (it.read(dictBlock, 0, 128) == 128) analyzeDictBlk(dictBlock) doOnLoadSuccess() @@ -86,6 +91,15 @@ class SimpleDict(private val client: Client, private val pwd: String) { //must sendMessageWithDelay(key) client.receiveMessage() closeDict() + dict.remove(key) + val end = latestKeys.size-1 + if(end > 0) latestKeys = latestKeys.let { oldArr -> + var index = -1 + Array(end) { + if(oldArr[it] == key) index = it + return@Array if(index < 0 || (index > 0 && it < index)) oldArr[it] else oldArr[it+1] + } + } } operator fun get(key: String) = dict[key] diff --git a/app/src/main/res/layout/line_word.xml b/app/src/main/res/layout/line_word.xml index 6b20e36..13f3a6b 100644 --- a/app/src/main/res/layout/line_word.xml +++ b/app/src/main/res/layout/line_word.xml @@ -38,7 +38,6 @@ android:layout_width="32dp" android:layout_height="32dp" android:layout_marginEnd="16dp" - android:background="@drawable/ic_like" android:clickable="true" android:focusable="true" android:foreground="?android:attr/selectableItemBackground" diff --git a/app/winrelease/app-winrelease.apk b/app/winrelease/app-winrelease.apk index f51c813..202f56d 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 2bdf04d..4b73e84 100644 --- a/app/winrelease/output-metadata.json +++ b/app/winrelease/output-metadata.json @@ -10,8 +10,8 @@ { "type": "SINGLE", "filters": [], - "versionCode": 6, - "versionName": "1.4", + "versionCode": 7, + "versionName": "1.5", "outputFile": "app-winrelease.apk" } ]