diff --git a/app/src/main/java/me/kbai/zhenxunui/api/WebSocketHolder.kt b/app/src/main/java/me/kbai/zhenxunui/api/WebSocketHolder.kt index f576ed4..f479ff2 100644 --- a/app/src/main/java/me/kbai/zhenxunui/api/WebSocketHolder.kt +++ b/app/src/main/java/me/kbai/zhenxunui/api/WebSocketHolder.kt @@ -13,36 +13,44 @@ import okio.ByteString open class WebSocketHolder(private val path: String, private val scope: CoroutineScope) { companion object { private const val NOT_STARTED = 0 - private const val RUNNING = 1 - private const val CANCELED = 2 + private const val CONNECTING = 1 + private const val CONNECTED = 2 + private const val CLOSING = 3 + private const val CLOSED = 4 + private const val FAILURE = 5 + private const val CANCELED = -1 } private var mWebSocket: WebSocket? = null private var mStatus = NOT_STARTED fun connect() { - if (mStatus != NOT_STARTED) return + if (mStatus in CONNECTING .. CLOSING) return - mStatus = RUNNING + mStatus = CONNECTING mWebSocket = BotApi.openWebSocket(path, object : WebSocketListener() { override fun onOpen(webSocket: WebSocket, response: Response) { logI("WebSocket is connected.") + mStatus = CONNECTED } override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { logI("WebSocket is closed.") + mStatus = CLOSED } override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { - logI("WebSocket is closing: $reason") + logI("WebSocket is closing, reason: $reason") webSocket.close(code, reason) + mStatus = CLOSING } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { logE("WebSocket on failure: $response \n $t") webSocket.cancel() + mStatus = FAILURE scope.launch { delay(5_000) connect() diff --git a/app/src/main/java/me/kbai/zhenxunui/tool/Ansi2SpannedHelper.kt b/app/src/main/java/me/kbai/zhenxunui/tool/Ansi2SpannedHelper.kt index 8f81000..af48d8f 100644 --- a/app/src/main/java/me/kbai/zhenxunui/tool/Ansi2SpannedHelper.kt +++ b/app/src/main/java/me/kbai/zhenxunui/tool/Ansi2SpannedHelper.kt @@ -2,14 +2,17 @@ package me.kbai.zhenxunui.tool import android.graphics.Color import android.graphics.Typeface +import android.os.Build import android.text.SpannableStringBuilder import android.text.Spanned +import android.text.SpannedString import android.text.style.BackgroundColorSpan import android.text.style.CharacterStyle import android.text.style.ForegroundColorSpan import android.text.style.StrikethroughSpan import android.text.style.StyleSpan import android.text.style.UnderlineSpan +import androidx.annotation.RequiresApi import pk.ansi4j.core.DefaultFunctionFinder import pk.ansi4j.core.DefaultParserFactory import pk.ansi4j.core.DefaultTextHandler @@ -27,12 +30,16 @@ import pk.ansi4j.core.iso6429.IndependentControlFunctionHandler import java.util.AbstractCollection class Ansi2SpannedHelper { - private val mFactory: ParserFactory = initFactory() + private val mFactory: ParserFactory? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + initFactory() + } else { + null + } private val mStyles: ArrayList = ArrayList() fun parse(text: String): Spanned { val builder = SpannableStringBuilder() - val parser = mFactory.createParser(text) + val parser = (mFactory ?: return SpannedString(text)).createParser(text) while (true) { val fragment = parser.parse() ?: break @@ -97,6 +104,7 @@ class Ansi2SpannedHelper { } } + @RequiresApi(24) private fun initFactory() = DefaultParserFactory.Builder() .environment(Environment._7_BIT) .textHandler(DefaultTextHandler()) diff --git a/app/src/main/java/me/kbai/zhenxunui/tool/ReflectionUtils.java b/app/src/main/java/me/kbai/zhenxunui/tool/ReflectionUtils.java index 7dc2a60..006fd89 100644 --- a/app/src/main/java/me/kbai/zhenxunui/tool/ReflectionUtils.java +++ b/app/src/main/java/me/kbai/zhenxunui/tool/ReflectionUtils.java @@ -1,5 +1,6 @@ package me.kbai.zhenxunui.tool; +import android.text.TextUtils; import android.util.Log; import androidx.annotation.Nullable; @@ -106,15 +107,24 @@ public static boolean setFieldValue(Object object, Field field, T fieldValue return false; } + /** @noinspection CallToPrintStackTrace*/ public static boolean setFieldValue(Object object, String fieldName, T fieldValue) { - try { - Class clazz = object.getClass(); - Field field = clazz.getDeclaredField(fieldName); - field.setAccessible(true); - field.set(object, fieldValue); - return true; - } catch (NoSuchFieldException | IllegalAccessException | NullPointerException e) { - Log.e(TAG, e.getMessage()); + Class clazz = object.getClass(); + while (clazz != null) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(object, fieldValue); + return true; + } catch (NoSuchFieldException | IllegalAccessException | NullPointerException e) { + String log = e.getMessage(); + if (TextUtils.isEmpty(log)) { + e.printStackTrace(); + } else { + Log.e(TAG, log); + } + } + clazz = clazz.getSuperclass(); } return false; } diff --git a/app/src/main/java/me/kbai/zhenxunui/ui/console/ConsoleFragment.kt b/app/src/main/java/me/kbai/zhenxunui/ui/console/ConsoleFragment.kt index b675219..1235185 100644 --- a/app/src/main/java/me/kbai/zhenxunui/ui/console/ConsoleFragment.kt +++ b/app/src/main/java/me/kbai/zhenxunui/ui/console/ConsoleFragment.kt @@ -40,9 +40,9 @@ class ConsoleFragment : BaseFragment() { companion object { private const val LOCAL_DOMAIN = "local.host" - private const val BAR_CHART_FILE = "$LOCAL_DOMAIN/assets/console_bar_charts.html" + private const val BAR_CHART_FILE = "http://$LOCAL_DOMAIN/assets/console_bar_charts.html" private const val TANGENTIAL_BAR_FILE = - "$LOCAL_DOMAIN/assets/console_horizontal_bar_charts.html" + "http://$LOCAL_DOMAIN/assets/console_horizontal_bar_charts.html" } private val mViewModel by viewModels() diff --git a/app/src/main/java/me/kbai/zhenxunui/ui/group/ConversationFragment.kt b/app/src/main/java/me/kbai/zhenxunui/ui/group/ConversationFragment.kt index ad0f4c7..9f16ffc 100644 --- a/app/src/main/java/me/kbai/zhenxunui/ui/group/ConversationFragment.kt +++ b/app/src/main/java/me/kbai/zhenxunui/ui/group/ConversationFragment.kt @@ -5,15 +5,11 @@ import android.view.ViewGroup import androidx.appcompat.widget.Toolbar import androidx.core.widget.addTextChangedListener import androidx.fragment.app.viewModels -import me.kbai.zhenxunui.Constants import me.kbai.zhenxunui.R import me.kbai.zhenxunui.base.BaseFragment import me.kbai.zhenxunui.databinding.FragmentConversationBinding import me.kbai.zhenxunui.extends.launchAndCollectIn -import me.kbai.zhenxunui.extends.logI import me.kbai.zhenxunui.extends.setOnDebounceClickListener -import me.kbai.zhenxunui.model.ChatMessage -import me.kbai.zhenxunui.model.MessageType import me.kbai.zhenxunui.tool.GlobalToast import me.kbai.zhenxunui.viewmodel.ConversationViewModel diff --git a/app/src/main/java/me/kbai/zhenxunui/ui/group/FriendListFragment.kt b/app/src/main/java/me/kbai/zhenxunui/ui/group/FriendListFragment.kt index d113ed8..719cf2a 100644 --- a/app/src/main/java/me/kbai/zhenxunui/ui/group/FriendListFragment.kt +++ b/app/src/main/java/me/kbai/zhenxunui/ui/group/FriendListFragment.kt @@ -80,9 +80,7 @@ class FriendListFragment : BaseFragment() { private fun requestData( type: Int = FriendListType.FRIEND or FriendListType.GROUP ) = viewLifecycleScope.launch { -// if (refresh) { viewBinding.root.isRefreshing = true -// } viewBinding.icError.root.isVisible = false val result = mViewModel.requestList(type) diff --git a/app/src/main/java/me/kbai/zhenxunui/viewmodel/ConsoleViewModel.kt b/app/src/main/java/me/kbai/zhenxunui/viewmodel/ConsoleViewModel.kt index 17e3593..10892c3 100644 --- a/app/src/main/java/me/kbai/zhenxunui/viewmodel/ConsoleViewModel.kt +++ b/app/src/main/java/me/kbai/zhenxunui/viewmodel/ConsoleViewModel.kt @@ -1,17 +1,6 @@ package me.kbai.zhenxunui.viewmodel -import android.graphics.Color -import android.graphics.Typeface -import android.text.Html -import android.text.SpannableString import android.text.SpannableStringBuilder -import android.text.Spanned -import android.text.style.ForegroundColorSpan -import android.text.style.StyleSpan -import android.text.style.TextAppearanceSpan -import android.text.style.TypefaceSpan -import androidx.core.text.toSpannable -import androidx.core.text.toSpanned import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -28,15 +17,6 @@ import me.kbai.zhenxunui.model.SystemStatus import me.kbai.zhenxunui.repository.ApiRepository import me.kbai.zhenxunui.tool.AlwaysDifferent import me.kbai.zhenxunui.tool.Ansi2SpannedHelper -import pk.ansi4j.core.DefaultFunctionFinder -import pk.ansi4j.core.DefaultParserFactory -import pk.ansi4j.core.DefaultTextHandler -import pk.ansi4j.core.api.Environment -import pk.ansi4j.core.iso6429.C0ControlFunctionHandler -import pk.ansi4j.core.iso6429.C1ControlFunctionHandler -import pk.ansi4j.core.iso6429.ControlSequenceHandler -import pk.ansi4j.core.iso6429.ControlStringHandler -import pk.ansi4j.core.iso6429.IndependentControlFunctionHandler class ConsoleViewModel : ViewModel() { diff --git a/app/src/main/java/me/kbai/zhenxunui/widget/SemicircleProgressView.kt b/app/src/main/java/me/kbai/zhenxunui/widget/SemicircleProgressView.kt index 5478f7c..3f07422 100644 --- a/app/src/main/java/me/kbai/zhenxunui/widget/SemicircleProgressView.kt +++ b/app/src/main/java/me/kbai/zhenxunui/widget/SemicircleProgressView.kt @@ -5,6 +5,7 @@ import android.graphics.Canvas import android.graphics.Paint import android.util.AttributeSet import android.view.View +import androidx.core.content.res.use import me.kbai.zhenxunui.R import me.kbai.zhenxunui.extends.dp import me.kbai.zhenxunui.extends.getThemeColor @@ -20,7 +21,7 @@ class SemicircleProgressView @JvmOverloads constructor( private const val SMOOTH_ANIM_TIME = 500F } - private var mStrokeWidth: Int + private var mStrokeWidth: Int = 0 private val mBackgroundPaint: Paint private val mFillPaint: Paint