diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1c0de80..d45eac2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -74,7 +74,11 @@
android:label="@string/application_setting_application"
android:exported="false"
android:screenOrientation="portrait" />
-
+
diff --git a/app/src/main/java/com/github/kr328/clash/LogActivity.kt b/app/src/main/java/com/github/kr328/clash/LogActivity.kt
new file mode 100644
index 0000000..cc536f6
--- /dev/null
+++ b/app/src/main/java/com/github/kr328/clash/LogActivity.kt
@@ -0,0 +1,91 @@
+package com.github.kr328.clash
+
+import android.os.Bundle
+import android.os.Handler
+import androidx.collection.CircularArray
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.github.kr328.clash.adapter.LogAdapter
+import com.github.kr328.clash.core.event.Event
+import com.github.kr328.clash.core.event.LogEvent
+import com.github.kr328.clash.core.utils.Log
+import kotlinx.android.synthetic.main.activity_logs.*
+
+
+class LogActivity : BaseActivity() {
+ companion object {
+ const val MAX_EVENT_COUNT = 100
+ }
+
+ private var syncLog = false
+ private val buffer = CircularArray(MAX_EVENT_COUNT)
+ private val handler = Handler()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_logs)
+
+ setSupportActionBar(activity_logs_toolbar)
+
+ activity_logs_list.also {
+ val dividerItemDecoration = DividerItemDecoration(
+ this,
+ DividerItemDecoration.VERTICAL
+ )
+ it.addItemDecoration(dividerItemDecoration)
+
+ it.adapter = LogAdapter(this, buffer)
+ it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
+ }
+ }
+
+ override fun onStart() {
+ super.onStart()
+
+ syncLog = true
+
+ activity_logs_list.adapter?.notifyDataSetChanged()
+
+ runClash {
+ it.eventService.registerEventObserver(LogActivity::class.java.name,
+ this,
+ intArrayOf(Event.EVENT_LOG))
+ }
+ }
+
+ override fun onStop() {
+ super.onStop()
+
+ syncLog = false
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+
+ runClash {
+ it.eventService.unregisterEventObserver(LogActivity::class.java.name)
+ }
+ }
+
+ override fun onLogEvent(event: LogEvent?) {
+ handler.post {
+ buffer.addFirst(event)
+
+ if ( syncLog ) {
+ activity_logs_list.adapter!!.notifyItemInserted(0)
+ if ( activity_logs_list.computeVerticalScrollOffset() < 30 )
+ activity_logs_list.scrollToPosition(0)
+ }
+
+ if ( buffer.size() >= MAX_EVENT_COUNT ) {
+ buffer.removeFromEnd(buffer.size() - MAX_EVENT_COUNT - 1)
+
+ if ( syncLog ) {
+ activity_logs_list.adapter?.notifyItemRangeRemoved(MAX_EVENT_COUNT - 1,
+ buffer.size() - MAX_EVENT_COUNT - 1 )
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/github/kr328/clash/MainActivity.kt b/app/src/main/java/com/github/kr328/clash/MainActivity.kt
index 0f1a8c3..06f73d9 100644
--- a/app/src/main/java/com/github/kr328/clash/MainActivity.kt
+++ b/app/src/main/java/com/github/kr328/clash/MainActivity.kt
@@ -45,6 +45,10 @@ class MainActivity : BaseActivity() {
startActivity(Intent(this, SettingMainActivity::class.java))
}
+ activity_main_clash_logs.setOnClickListener {
+ startActivity(Intent(this, LogActivity::class.java))
+ }
+
activity_main_clash_status_icon.setImageResource(R.drawable.ic_clash_stopped)
activity_main_clash_status_title.text = getString(R.string.clash_status_stopped)
activity_main_clash_status_summary.text = getString(R.string.clash_status_click_to_start)
diff --git a/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt b/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt
index f060cc1..db7e065 100644
--- a/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt
+++ b/app/src/main/java/com/github/kr328/clash/ProxyActivity.kt
@@ -43,8 +43,6 @@ class ProxyActivity : BaseActivity() {
.toMap()
for ((_, p) in proxies) {
- Log.i("$p -> ${p.index}")
-
p.value.delay = -1
}
diff --git a/app/src/main/java/com/github/kr328/clash/adapter/LogAdapter.kt b/app/src/main/java/com/github/kr328/clash/adapter/LogAdapter.kt
new file mode 100644
index 0000000..d0b73d3
--- /dev/null
+++ b/app/src/main/java/com/github/kr328/clash/adapter/LogAdapter.kt
@@ -0,0 +1,42 @@
+package com.github.kr328.clash.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.collection.CircularArray
+import androidx.recyclerview.widget.RecyclerView
+import com.github.kr328.clash.R
+import com.github.kr328.clash.core.event.LogEvent
+import kotlinx.android.synthetic.main.adapter_log.view.*
+import java.text.SimpleDateFormat
+import java.util.*
+
+class LogAdapter(private val content: Context,
+ private val buffer: CircularArray) : RecyclerView.Adapter() {
+ private val formatter = SimpleDateFormat("hh:MM:ss", Locale.getDefault())
+
+ class Holder(view: View) : RecyclerView.ViewHolder(view) {
+ val type: TextView = view.findViewById(R.id.adapter_log_type)
+ val time: TextView = view.findViewById(R.id.adapter_log_time)
+ val content: TextView = view.findViewById(R.id.adapter_log_content)
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
+ return Holder(LayoutInflater.from(content)
+ .inflate(R.layout.adapter_log, parent, false))
+ }
+
+ override fun getItemCount(): Int {
+ return buffer.size()
+ }
+
+ override fun onBindViewHolder(holder: Holder, position: Int) {
+ val current = buffer.get(position)
+
+ holder.type.text = current.level.toString()
+ holder.time.text = formatter.format(Date(current.time))
+ holder.content.text = current.message
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_logs.xml b/app/src/main/res/layout/activity_logs.xml
new file mode 100644
index 0000000..9aecb2e
--- /dev/null
+++ b/app/src/main/res/layout/activity_logs.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/adapter_log.xml b/app/src/main/res/layout/adapter_log.xml
new file mode 100644
index 0000000..1244128
--- /dev/null
+++ b/app/src/main/res/layout/adapter_log.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core/src/main/golang/server/event.go b/core/src/main/golang/server/event.go
index a9387df..f12a253 100644
--- a/core/src/main/golang/server/event.go
+++ b/core/src/main/golang/server/event.go
@@ -18,17 +18,16 @@ func handlePullTrafficEvent(client *net.UnixConn) {
buf := &bytes.Buffer{}
defer ticker.Stop()
+ defer client.Close()
go func() {
for {
var buf [4]byte
- _, err := client.Read(buf[:])
+ client.Read(buf[:])
- if err != nil {
- close(trafficExit)
- return
- }
+ close(trafficExit)
+ return
}
}()
@@ -68,17 +67,16 @@ func handlePullBandwidthEvent(client *net.UnixConn) {
buf := &bytes.Buffer{}
defer ticker.Stop()
+ defer client.Close()
go func() {
for {
var buf [4]byte
- _, err := client.Read(buf[:])
+ client.Read(buf[:])
- if err != nil {
- close(bandWidthExit)
- return
- }
+ close(bandWidthExit)
+ return
}
}()
@@ -118,16 +116,18 @@ func handlePullLogEvent(client *net.UnixConn) {
subseribe := log.Subscribe()
buf := &bytes.Buffer{}
+ defer log.UnSubscribe(subseribe)
+ defer client.Close()
+
go func() {
var buf [4]byte
for {
- _, err := client.Read(buf[:])
+ client.Read(buf[:])
- if err != nil {
- close(logExit)
- return
- }
+ logExit <- 0
+ close(logExit)
+ return
}
}()
diff --git a/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt b/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt
index ed83043..1c21fab 100644
--- a/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt
+++ b/core/src/main/java/com/github/kr328/clash/core/event/LogEvent.kt
@@ -7,7 +7,7 @@ import kotlinx.serialization.*
import kotlinx.serialization.internal.StringDescriptor
@Serializable
-data class LogEvent(val level: Level, val message: String) :
+data class LogEvent(val level: Level, val message: String, val time: Long = System.currentTimeMillis()) :
Event, Parcelable {
companion object {
const val DEBUG_VALUE = 1
diff --git a/service/src/main/java/com/github/kr328/clash/service/ClashEventPuller.kt b/service/src/main/java/com/github/kr328/clash/service/ClashEventPuller.kt
index 21d02bf..ad35862 100644
--- a/service/src/main/java/com/github/kr328/clash/service/ClashEventPuller.kt
+++ b/service/src/main/java/com/github/kr328/clash/service/ClashEventPuller.kt
@@ -127,6 +127,7 @@ class ClashEventPuller(private val clash: Clash, private val master: Master) {
private fun LocalSocket?.closeSilent() {
runCatching {
+ this?.outputStream?.write(0)
this?.close()
}
}