新增:自动任务·快捷指令 (开发中)

This commit is contained in:
pppscn 2023-12-27 11:03:02 +08:00
parent 0c950c835a
commit 2930d2ed17
40 changed files with 251 additions and 218 deletions

View File

@ -322,6 +322,18 @@
</intent-filter>
</receiver>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- If you are using androidx.startup to initialize other components -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
</application>
</manifest>

View File

@ -12,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.base.ItemMoveCallback
import com.idormy.sms.forwarder.database.entity.Frpc
import com.idormy.sms.forwarder.utils.STATUS_OFF
import java.util.Collections
@Suppress("DEPRECATION")
@ -71,7 +72,12 @@ class FrpcRecyclerAdapter(
fun bind(frpc: Frpc) {
image.setImageResource(frpc.imageId)
status.setImageResource(frpc.autorunImageId)
status.setImageResource(
when (frpc.status) {
STATUS_OFF -> R.drawable.ic_stop
else -> R.drawable.ic_start
}
)
title.text = frpc.name
}

View File

@ -14,7 +14,7 @@ import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.STATUS_ON
import com.idormy.sms.forwarder.utils.STATUS_OFF
import com.xuexiang.xui.utils.CollectionUtils
import com.xuexiang.xui.widget.spinner.editspinner.BaseEditSpinnerAdapter
import com.xuexiang.xui.widget.spinner.editspinner.EditSpinnerFilter
@ -75,9 +75,13 @@ class FrpcSpinnerAdapter<T> : BaseEditSpinnerAdapter<T>, EditSpinnerFilter {
holder.iconView.setImageDrawable(item.icon)
holder.statusView.setImageDrawable(
getDrawable(
when (item.autorun) {
/*when (item.autorun) {
STATUS_ON -> R.drawable.ic_autorun
else -> R.drawable.ic_manual
}*/
when (item.status) {
STATUS_OFF -> R.drawable.ic_stop
else -> R.drawable.ic_start
}
)
)

View File

@ -7,7 +7,8 @@ class FrpcSpinnerItem(
var title: CharSequence,
var icon: Drawable? = null,
var uid: String = "",
var autorun: Int? = 1
//var autorun: Int? = 1,
var status: Int? = 1
) {
fun setTitle(title: CharSequence): FrpcSpinnerItem {
@ -25,9 +26,14 @@ class FrpcSpinnerItem(
return this
}
fun setAutorun(autorun: Int): FrpcSpinnerItem {
/*fun setAutorun(autorun: Int): FrpcSpinnerItem {
this.autorun = autorun
return this
}*/
fun setStatus(status: Int): FrpcSpinnerItem {
this.status = status
return this
}
// 注意:自定义实体需要重写对象的 toString 方法

View File

@ -6,7 +6,9 @@ import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.utils.STATUS_OFF
import com.idormy.sms.forwarder.utils.STATUS_ON
import frpclib.Frpclib
import kotlinx.parcelize.Parcelize
import java.util.Date
@ -31,4 +33,7 @@ data class Frpc(
else -> R.drawable.ic_manual
}
val status: Int
get() = if (connecting || Frpclib.isRunning(uid)) STATUS_ON else STATUS_OFF
}

View File

@ -5,28 +5,34 @@ import android.content.Intent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.databinding.FragmentTasksActionCleanerBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.action.CleanerSetting
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.TASK_ACTION_CLEANER
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus
import com.idormy.sms.forwarder.workers.ActionWorker
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xrouter.annotation.AutoWired
import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar
import java.util.Date
@Page(name = "Cleaner")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class CleanerFragment : BaseFragment<FragmentTasksActionCleanerBinding?>(), View.OnClickListener {
private val TAG: String = CleanerFragment::class.java.simpleName
@ -58,7 +64,7 @@ class CleanerFragment : BaseFragment<FragmentTasksActionCleanerBinding?>(), View
*/
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 1)
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
@ -83,15 +89,6 @@ class CleanerFragment : BaseFragment<FragmentTasksActionCleanerBinding?>(), View
binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this)
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
mCountDownHelper?.finish()
if (it == "success") {
XToastUtils.success("测试通过", 30000)
} else {
XToastUtils.error(it, 30000)
}
}
}
@SingleClick
@ -100,17 +97,21 @@ class CleanerFragment : BaseFragment<FragmentTasksActionCleanerBinding?>(), View
when (v.id) {
R.id.btn_test -> {
mCountDownHelper?.start()
Thread {
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post("success")
} catch (e: Exception) {
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
}
}.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_CLEANER, getString(R.string.task_cleaner), settingVo.description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_cleaner), settingVo.description, Date(), getString(R.string.task_cleaner))
val actionData = Data.Builder().putLong(TaskWorker.taskId, 0).putString(TaskWorker.taskActions, taskActionsJson).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest)
} catch (e: Exception) {
mCountDownHelper?.finish()
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
XToastUtils.error(e.message.toString(), 30000)
}
return
}

View File

@ -9,6 +9,9 @@ import android.widget.AdapterView
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.FrpcRecyclerAdapter
@ -19,15 +22,17 @@ import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Frpc
import com.idormy.sms.forwarder.databinding.FragmentTasksActionFrpcBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.action.FrpcSetting
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.TASK_ACTION_FRPC
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus
import com.idormy.sms.forwarder.workers.ActionWorker
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xrouter.annotation.AutoWired
@ -39,9 +44,10 @@ import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.Date
@Page(name = "Frpc")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnClickListener {
private val TAG: String = FrpcFragment::class.java.simpleName
@ -84,7 +90,7 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
*/
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 2)
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
@ -92,6 +98,8 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
override fun onFinished() {
binding!!.btnTest.text = getString(R.string.test)
//获取Frpc列表
getFrpcList()
}
})
@ -111,15 +119,6 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this)
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
mCountDownHelper?.finish()
if (it == "success") {
XToastUtils.success("测试通过", 30000)
} else {
XToastUtils.error(it, 30000)
}
}
}
@SingleClick
@ -128,17 +127,21 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
when (v.id) {
R.id.btn_test -> {
mCountDownHelper?.start()
Thread {
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post("success")
} catch (e: Exception) {
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
}
}.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_FRPC, getString(R.string.task_frpc), settingVo.description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_frpc), settingVo.description, Date(), getString(R.string.task_frpc))
val actionData = Data.Builder().putLong(TaskWorker.taskId, 0).putString(TaskWorker.taskActions, taskActionsJson).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest)
} catch (e: Exception) {
mCountDownHelper?.finish()
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
XToastUtils.error(e.message.toString(), 30000)
}
return
}
@ -244,7 +247,7 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
frpcListAll = frpcList as MutableList<Frpc>
for (frpc in frpcList) {
val name = if (frpc.name.length > 20) frpc.name.substring(0, 19) else frpc.name
frpcSpinnerList.add(FrpcSpinnerItem(name, getDrawable(R.drawable.auto_task_icon_frpc), frpc.uid, frpc.autorun))
frpcSpinnerList.add(FrpcSpinnerItem(name, getDrawable(frpc.imageId), frpc.uid, frpc.status))
}
frpcSpinnerAdapter = FrpcSpinnerAdapter(frpcSpinnerList).setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
binding!!.spFrpc.setAdapter(frpcSpinnerAdapter)

View File

@ -6,6 +6,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CompoundButton
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
@ -13,25 +16,28 @@ import com.hjq.permissions.XXPermissions
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.databinding.FragmentTasksActionHttpServerBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.action.HttpServerSetting
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.TASK_ACTION_HTTPSERVER
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus
import com.idormy.sms.forwarder.workers.ActionWorker
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xrouter.annotation.AutoWired
import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar
import java.util.Date
@Page(name = "HttpServer")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class HttpServerFragment : BaseFragment<FragmentTasksActionHttpServerBinding?>(), View.OnClickListener {
private val TAG: String = HttpServerFragment::class.java.simpleName
@ -63,7 +69,7 @@ class HttpServerFragment : BaseFragment<FragmentTasksActionHttpServerBinding?>()
*/
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 1)
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
@ -97,15 +103,6 @@ class HttpServerFragment : BaseFragment<FragmentTasksActionHttpServerBinding?>()
binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this)
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
mCountDownHelper?.finish()
if (it == "success") {
XToastUtils.success("测试通过", 30000)
} else {
XToastUtils.error(it, 30000)
}
}
binding!!.sbApiSendSms.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
if (isChecked) checkSendSmsPermission()
@ -142,17 +139,21 @@ class HttpServerFragment : BaseFragment<FragmentTasksActionHttpServerBinding?>()
when (v.id) {
R.id.btn_test -> {
mCountDownHelper?.start()
Thread {
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post("success")
} catch (e: Exception) {
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
}
}.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_HTTPSERVER, getString(R.string.task_http_server), settingVo.description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_http_server), settingVo.description, Date(), getString(R.string.task_http_server))
val actionData = Data.Builder().putLong(TaskWorker.taskId, 0).putString(TaskWorker.taskActions, taskActionsJson).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest)
} catch (e: Exception) {
mCountDownHelper?.finish()
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
XToastUtils.error(e.message.toString(), 30000)
}
return
}

View File

@ -9,6 +9,9 @@ import android.widget.*
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.SenderRecyclerAdapter
@ -21,8 +24,9 @@ import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.databinding.FragmentTasksActionNotificationBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.utils.*
import com.jeremyliao.liveeventbus.LiveEventBus
import com.idormy.sms.forwarder.workers.ActionWorker
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xrouter.annotation.AutoWired
@ -41,7 +45,7 @@ import kotlinx.coroutines.*
import java.util.*
@Page(name = "Notification")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding?>(), View.OnClickListener, CompoundButton.OnCheckedChangeListener {
private val TAG: String = NotificationFragment::class.java.simpleName
@ -71,6 +75,8 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
private var ruleId: Long = 0
private var ruleType: String = "app"
private var description: String = ""
override fun initArgs() {
XRouter.getInstance().inject(this)
}
@ -93,7 +99,7 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
*/
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 2)
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
@ -247,24 +253,22 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
}
R.id.btn_test -> {
val settingVo = checkSetting()
val from = "测试号码"
val content = "测试内容"
val simInfo = "SIM1_123456789"
val msgInfo = MsgInfo(ruleType, from, content, Date(), simInfo)
if (!settingVo.checkMsg(msgInfo)) {
throw Exception(getString(R.string.unmatched_rule))
mCountDownHelper?.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_NOTIFICATION, getString(R.string.task_notification), description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_notification), description, Date(), getString(R.string.task_notification))
val actionData = Data.Builder().putLong(TaskWorker.taskId, 0).putString(TaskWorker.taskActions, taskActionsJson).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest)
} catch (e: Exception) {
mCountDownHelper?.finish()
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
XToastUtils.error(e.message.toString(), 30000)
}
Thread {
try {
SendUtils.sendMsgSender(msgInfo, settingVo)
} catch (e: Exception) {
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
LiveEventBus.get(EVENT_TOAST_ERROR, String::class.java).post(e.message.toString())
}
}.start()
return
}
@ -275,15 +279,6 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
R.id.btn_save -> {
val settingVo = checkSetting()
var description = getString(R.string.task_notification) + ": "
description += settingVo.senderList.joinToString(",") { it.name }
if (settingVo.senderList.size > 1) {
description += "; " + getString(R.string.sender_logic) + ": " + when (settingVo.senderLogic) {
SENDER_LOGIC_UNTIL_FAIL -> getString(R.string.sender_logic_until_fail)
SENDER_LOGIC_UNTIL_SUCCESS -> getString(R.string.sender_logic_until_success)
else -> getString(R.string.sender_logic_all)
}
}
val intent = Intent()
intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, description)
intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo))
@ -444,7 +439,7 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
else -> SENDER_LOGIC_ALL
}
return Rule(
val settingVo = Rule(
ruleId,
ruleType,
filed,
@ -461,6 +456,18 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
silentPeriodStart,
silentPeriodEnd
)
description = getString(R.string.task_notification) + ": "
description += settingVo.senderList.joinToString(",") { it.name }
if (settingVo.senderList.size > 1) {
description += "; " + getString(R.string.sender_logic) + ": " + when (settingVo.senderLogic) {
SENDER_LOGIC_UNTIL_FAIL -> getString(R.string.sender_logic_until_fail)
SENDER_LOGIC_UNTIL_SUCCESS -> getString(R.string.sender_logic_until_success)
else -> getString(R.string.sender_logic_all)
}
}
return settingVo
}
//检查正则替换填写是否正确

View File

@ -1,22 +1,23 @@
package com.idormy.sms.forwarder.fragment.action
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.PackageManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.app.ActivityCompat
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.action.SmsSetting
import com.idormy.sms.forwarder.server.model.ConfigData
import com.idormy.sms.forwarder.utils.EVENT_KEY_PHONE_NUMBERS
@ -25,11 +26,11 @@ import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.PhoneUtils
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.XToastUtils
import com.idormy.sms.forwarder.workers.ActionWorker
import com.jeremyliao.liveeventbus.LiveEventBus
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
@ -38,10 +39,10 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xrouter.utils.TextUtils
import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.XUtil
import java.util.Date
@Page(name = "SendSms")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class SendSmsFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
private val TAG: String = SendSmsFragment::class.java.simpleName
@ -79,7 +80,7 @@ class SendSmsFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View
@SuppressLint("SetTextI18n")
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 1)
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
@ -124,15 +125,6 @@ class SendSmsFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View
LiveEventBus.get(EVENT_KEY_PHONE_NUMBERS, String::class.java).observeSticky(this) { value: String ->
binding!!.etPhoneNumbers.setText(value)
}
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
mCountDownHelper?.finish()
if (it == "success") {
XToastUtils.success("测试通过", 30000)
} else {
XToastUtils.error(it, 30000)
}
}
}
@SingleClick
@ -147,38 +139,27 @@ class SendSmsFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View
.permission(Permission.SEND_SMS)
.request(object : OnPermissionCallback {
override fun onGranted(permissions: List<String>, all: Boolean) {
Thread {
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
//获取卡槽信息
if (App.SimInfoList.isEmpty()) {
App.SimInfoList = PhoneUtils.getSimMultiInfo()
}
Log.d(TAG, App.SimInfoList.toString())
//发送卡槽: 1=SIM1, 2=SIM2
val simSlotIndex = settingVo.simSlot - 1
//TODO取不到卡槽信息时采用默认卡槽发送
val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1
val msg = if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
getString(R.string.no_sms_sending_permission)
} else {
PhoneUtils.sendSms(mSubscriptionId, settingVo.phoneNumbers, settingVo.msgContent) ?: "success"
}
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(msg)
} catch (e: Exception) {
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
}
}.start()
mCountDownHelper?.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_SENDSMS, getString(R.string.task_sendsms), settingVo.description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_sendsms), settingVo.description, Date(), getString(R.string.task_sendsms))
val actionData = Data.Builder().putLong(TaskWorker.taskId, 0).putString(TaskWorker.taskActions, taskActionsJson).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest)
} catch (e: Exception) {
mCountDownHelper?.finish()
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
XToastUtils.error(e.message.toString(), 30000)
}
return
}
override fun onDenied(permissions: List<String>, never: Boolean) {
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(getString(R.string.no_sms_sending_permission))
XToastUtils.error(getString(R.string.no_sms_sending_permission), 30000)
}
})
return

View File

@ -12,6 +12,7 @@ import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.CompoundButton
import androidx.lifecycle.Observer
import androidx.work.Data
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.gson.Gson
@ -24,17 +25,20 @@ import com.idormy.sms.forwarder.adapter.spinner.AppListAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.AppListSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSettingsBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.action.SettingsSetting
import com.idormy.sms.forwarder.utils.CommonUtils
import com.idormy.sms.forwarder.utils.EVENT_LOAD_APP_LIST
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_ACTION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.TASK_ACTION_SETTINGS
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.XToastUtils
import com.idormy.sms.forwarder.workers.ActionWorker
import com.idormy.sms.forwarder.workers.LoadAppListWorker
import com.jeremyliao.liveeventbus.LiveEventBus
import com.xuexiang.xaop.annotation.SingleClick
@ -44,9 +48,10 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.XUtil
import java.util.Date
@Page(name = "Settings")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class SettingsFragment : BaseFragment<FragmentTasksActionSettingsBinding?>(), View.OnClickListener {
private val TAG: String = SettingsFragment::class.java.simpleName
@ -86,7 +91,7 @@ class SettingsFragment : BaseFragment<FragmentTasksActionSettingsBinding?>(), Vi
*/
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 1)
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
@ -148,15 +153,6 @@ class SettingsFragment : BaseFragment<FragmentTasksActionSettingsBinding?>(), Vi
binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this)
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
mCountDownHelper?.finish()
if (it == "success") {
XToastUtils.success("测试通过", 30000)
} else {
XToastUtils.error(it, 30000)
}
}
//监听已安装App信息列表加载完成事件
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).observeStickyForever(appListObserver)
@ -335,17 +331,21 @@ class SettingsFragment : BaseFragment<FragmentTasksActionSettingsBinding?>(), Vi
when (v.id) {
R.id.btn_test -> {
mCountDownHelper?.start()
Thread {
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post("success")
} catch (e: Exception) {
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
}
}.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_SETTINGS, getString(R.string.task_settings), settingVo.description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_settings), settingVo.description, Date(), getString(R.string.task_settings))
val actionData = Data.Builder().putLong(TaskWorker.taskId, 0).putString(TaskWorker.taskActions, taskActionsJson).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest)
} catch (e: Exception) {
mCountDownHelper?.finish()
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
XToastUtils.error(e.message.toString(), 30000)
}
return
}

View File

@ -216,7 +216,6 @@ const val KEY_BACK_CODE_CONDITION = 1000
const val KEY_BACK_DATA_CONDITION = "back_data_condition"
const val KEY_BACK_DESCRIPTION_CONDITION = "back_description_condition"
const val KEY_TEST_ACTION = "key_test_action"
const val KEY_EVENT_DATA_ACTION = "event_data_action"
const val KEY_BACK_CODE_ACTION = 2000
const val KEY_BACK_DATA_ACTION = "back_data_action"

View File

@ -103,23 +103,26 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
//TODO取不到卡槽信息时采用默认卡槽发送
val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1
if (ActivityCompat.checkSelfPermission(App.context, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
val msg = getString(R.string.no_sms_sending_permission)
writeLog(msg, "ERROR")
val msg = if (ActivityCompat.checkSelfPermission(App.context, Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
getString(R.string.no_sms_sending_permission)
} else {
val msg = PhoneUtils.sendSms(mSubscriptionId, smsSetting.phoneNumbers, smsSetting.msgContent)
PhoneUtils.sendSms(mSubscriptionId, smsSetting.phoneNumbers, smsSetting.msgContent)
}
if (msg == null || msg == "") {
successNum++
writeLog("send sms result: $msg", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), smsSetting.description), "SUCCESS")
} else {
writeLog(msg, "ERROR")
}
}
TASK_ACTION_NOTIFICATION -> {
val settingVo = Gson().fromJson(action.setting, Rule::class.java)
val ruleSetting = Gson().fromJson(action.setting, Rule::class.java)
//自动任务的不需要吐司或者更新日志,特殊处理 logId = -1msgId = -1
SendUtils.sendMsgSender(msgInfo, settingVo, 0, -1L, -1L)
SendUtils.sendMsgSender(msgInfo, ruleSetting, 0, -1L, -1L)
successNum++
writeLog("send notification success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), ruleSetting.name), "SUCCESS")
}
TASK_ACTION_CLEANER -> {
@ -140,7 +143,7 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
CacheUtils.clearAllCache(App.context)
successNum++
writeLog("cleaner success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), cleanerSetting.description), "SUCCESS")
}
TASK_ACTION_SETTINGS -> {
@ -186,7 +189,7 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
}
successNum++
writeLog("send settings success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), settingsSetting.description), "SUCCESS")
}
TASK_ACTION_FRPC -> {
@ -225,7 +228,7 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
}
successNum++
writeLog("frpc success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), frpcSetting.description), "SUCCESS")
}
TASK_ACTION_HTTPSERVER -> {
@ -253,7 +256,7 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
}
successNum++
writeLog("httpServer success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), httpServerSetting.description), "SUCCESS")
}
TASK_ACTION_RULE -> {
@ -269,7 +272,7 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
}
successNum++
writeLog("update rule success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), ruleSetting.description), "SUCCESS")
}
TASK_ACTION_SENDER -> {
@ -285,7 +288,7 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
}
successNum++
writeLog("update sender success", "SUCCESS")
writeLog(String.format(getString(R.string.successful_execution), senderSetting.description), "SUCCESS")
}
else -> {

View File

@ -6,7 +6,7 @@
android:viewportHeight="50.0">
<path
android:fillAlpha="0.8"
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:fillType="evenOdd"
android:pathData="M24.6702,0C26.9147,0 29.0561,0.9429 30.5715,2.5987L37.9014,10.6071C39.2513,12.0821 40,14.009 40,16.0084V44C40,47.3137 37.3137,50 34,50H6C2.6863,50 0,47.3137 0,44V6C0,2.6863 2.6863,0 6,0H24.6702Z"
android:strokeAlpha="0.8" />

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M4,8h4L8,4L4,4v4zM10,20h4v-4h-4v4zM4,20h4v-4L4,16v4zM4,14h4v-4L4,10v4zM10,14h4v-4h-4v4zM16,4v4h4L20,4h-4zM10,8h4L14,4h-4v4zM16,14h4v-4h-4v4zM16,20h4v-4h-4v4z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M20,18c1.1,0 1.99,-0.9 1.99,-2L22,6c0,-1.1 -0.9,-2 -2,-2H4c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2H0v2h24v-2h-4zM4,6h16v10H4V6z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M7.77,6.76L6.23,5.48 0.82,12l5.41,6.52 1.54,-1.28L3.42,12l4.35,-5.24zM7,13h2v-2L7,11v2zM17,11h-2v2h2v-2zM11,13h2v-2h-2v2zM17.77,5.48l-1.54,1.28L20.58,12l-4.35,5.24 1.54,1.28L23.18,12l-5.41,-6.52z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M19,5v14L5,19L5,5h14m1.1,-2L3.9,3c-0.5,0 -0.9,0.4 -0.9,0.9v16.2c0,0.4 0.4,0.9 0.9,0.9h16.2c0.4,0 0.9,-0.5 0.9,-0.9L21,3.9c0,-0.5 -0.5,-0.9 -0.9,-0.9zM11,7h6v2h-6L11,7zM11,11h6v2h-6v-2zM11,15h6v2h-6zM7,7h2v2L7,9zM7,11h2v2L7,13zM7,15h2v2L7,17z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M16.54,11L13,7.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L16.54,11zM11,7H2v2h9V7zM21,13.41L19.59,12L17,14.59L14.41,12L13,13.41L15.59,16L13,18.59L14.41,20L17,17.41L19.59,20L21,18.59L18.41,16L21,13.41zM11,15H2v2h9V15z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M14,12l-2,2l-2,-2l2,-2L14,12zM12,6l2.12,2.12l2.5,-2.5L12,1L7.38,5.62l2.5,2.5L12,6zM6,12l2.12,-2.12l-2.5,-2.5L1,12l4.62,4.62l2.5,-2.5L6,12zM18,12l-2.12,2.12l2.5,2.5L23,12l-4.62,-4.62l-2.5,2.5L18,12zM12,18l-2.12,-2.12l-2.5,2.5L12,23l4.62,-4.62l-2.5,-2.5L12,18z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z" />
</vector>

View File

@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M14,2H6C4.9,2 4.01,2.9 4.01,4L4,20c0,1.1 0.89,2 1.99,2H18c1.1,0 2,-0.9 2,-2V8L14,2zM10.94,18L7.4,14.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L10.94,18zM13,9V3.5L18.5,9H13z" />
</vector>

View File

@ -5,6 +5,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1L21,20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2zM20.16,3.69l-0.71,-0.7L13,9.29L13,5h-1v6h6v-1h-4.15z" />
</vector>

View File

@ -5,6 +5,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M6.5,5.5L12,11l7,-7 -1,-1 -6,6 -4.5,-4.5L11,4.5L11,3L5,3v6h1.5L6.5,5.5zM23.71,16.67C20.66,13.78 16.54,12 12,12 7.46,12 3.34,13.78 0.29,16.67c-0.18,0.18 -0.29,0.43 -0.29,0.71s0.11,0.53 0.29,0.71l2.48,2.48c0.18,0.18 0.43,0.29 0.71,0.29 0.27,0 0.52,-0.11 0.7,-0.28 0.79,-0.74 1.69,-1.36 2.66,-1.85 0.33,-0.16 0.56,-0.5 0.56,-0.9v-3.1c1.45,-0.48 3,-0.73 4.6,-0.73 1.6,0 3.15,0.25 4.6,0.72v3.1c0,0.39 0.23,0.74 0.56,0.9 0.98,0.49 1.87,1.12 2.67,1.85 0.18,0.18 0.43,0.28 0.7,0.28 0.28,0 0.53,-0.11 0.71,-0.29l2.48,-2.48c0.18,-0.18 0.29,-0.43 0.29,-0.71s-0.12,-0.52 -0.3,-0.7z" />
</vector>

View File

@ -5,6 +5,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M18,11l5,-5 -5,-5v3h-4v4h4v3zM20,15.5c-1.25,0 -2.45,-0.2 -3.57,-0.57 -0.35,-0.11 -0.74,-0.03 -1.02,0.24l-2.2,2.2c-2.83,-1.44 -5.15,-3.75 -6.59,-6.59l2.2,-2.21c0.28,-0.26 0.36,-0.65 0.25,-1C8.7,6.45 8.5,5.25 8.5,4c0,-0.55 -0.45,-1 -1,-1L4,3c-0.55,0 -1,0.45 -1,1 0,9.39 7.61,17 17,17 0.55,0 1,-0.45 1,-1v-3.5c0,-0.55 -0.45,-1 -1,-1z" />
</vector>

View File

@ -5,6 +5,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z" />
</vector>

View File

@ -6,7 +6,7 @@
android:viewportHeight="50.0">
<path
android:fillAlpha="0.8"
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:fillType="evenOdd"
android:pathData="M24.6702,0C26.9147,0 29.0561,0.9429 30.5715,2.5987L37.9014,10.6071C39.2513,12.0821 40,14.009 40,16.0084V44C40,47.3137 37.3137,50 34,50H6C2.6863,50 0,47.3137 0,44V6C0,2.6863 2.6863,0 6,0H24.6702Z
M18,43L14,43v-4h4v4z

View File

@ -6,7 +6,7 @@
android:viewportHeight="50.0">
<path
android:fillAlpha="0.8"
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:fillType="evenOdd"
android:pathData="M24.6702,0C26.9147,0 29.0561,0.9429 30.5715,2.5987L37.9014,10.6071C39.2513,12.0821 40,14.009 40,16.0084V44C40,47.3137 37.3137,50 34,50H6C2.6863,50 0,47.3137 0,44V6C0,2.6863 2.6863,0 6,0H24.6702ZM22.785,13.8333H18.8717L13.33,15.4483V20.3117L17.7633,19.045V38H22.785V13.8333Z"
android:strokeAlpha="0.8" />

View File

@ -6,7 +6,7 @@
android:viewportHeight="50.0">
<path
android:fillAlpha="0.8"
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:fillType="evenOdd"
android:pathData="M30.5715,2.5987C29.0561,0.9429 26.9147,0 24.6702,0H6C2.6863,0 0,2.6863 0,6V44C0,47.3137 2.6863,50 6,50H34C37.3137,50 40,47.3137 40,44V16.0084C40,14.009 39.2513,12.0821 37.9014,10.6071L30.5715,2.5987ZM20.1471,13C17.7983,13 15.7604,13.7514 14.3071,15.1044C12.8518,16.4593 12,18.4019 12,20.7467V20.9918H16.7129V20.7467C16.7129,19.6857 17.0933,18.8354 17.7036,18.2496C18.3155,17.6623 19.1728,17.3274 20.1471,17.3274C22.0709,17.3274 23.3606,18.4956 23.3606,20.0899C23.3606,21.317 22.9263,22.2977 21.5103,23.9022L21.5087,23.9041L12.3677,34.4825V38H27.7794V33.7763H18.6271L24.6667,26.89C26.6563,24.638 28,22.6766 28,20.0899C28,16.0219 24.5918,13 20.1471,13Z"
android:strokeAlpha="0.8" />

View File

@ -4,6 +4,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorControlNormal"
android:fillColor="#BEC2C7"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM9,11L7,11L7,9h2v2zM13,11h-2L11,9h2v2zM17,11h-2L15,9h2v2z" />
</vector>

View File

@ -28,7 +28,7 @@
android:text=""
android:textSize="@dimen/text_size_big"
app:sShapeType="oval"
app:sSolidColor="?attr/colorControlNormal"
app:sSolidColor="#BEC2C7"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<LinearLayout

View File

@ -99,7 +99,7 @@
android:layout_width="@dimen/card_view_icon_size"
android:layout_height="@dimen/card_view_icon_size"
android:src="@drawable/ic_add"
app:tint="@color/gray_text_light"
app:tint="#BEC2C7"
tools:ignore="ContentDescription,ImageContrastCheck" />
<LinearLayout
@ -178,7 +178,7 @@
android:layout_width="@dimen/card_view_icon_size"
android:layout_height="@dimen/card_view_icon_size"
android:src="@drawable/ic_add"
app:tint="@color/gray_text_light"
app:tint="#BEC2C7"
tools:ignore="ContentDescription,ImageContrastCheck" />
<LinearLayout

View File

@ -11,13 +11,14 @@
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/item_icon"
android:layout_width="wrap_content"
android:layout_width="60dp"
android:layout_height="60dp"
android:padding="10dp" />
<TextView
android:id="@+id/item_name"
style="@style/TextStyle.Explain"
android:lines="2" />
android:lines="2"
android:textSize="@dimen/text_size_small" />
</LinearLayout>

View File

@ -1319,4 +1319,5 @@
<string name="log_export_success">Log exported successfully! Path:</string>
<string name="all_auto_started_frpc">All auto-started Frpc</string>
<string name="specified_frpc">Specified Frpc</string>
<string name="successful_execution">Execution successful: %s</string>
</resources>

View File

@ -1320,4 +1320,5 @@
<string name="log_export_success">导出日志成功!存放路径:</string>
<string name="all_auto_started_frpc">所有自启动的Frpc</string>
<string name="specified_frpc">指定的Frpc</string>
<string name="successful_execution">执行成功:%s</string>
</resources>

View File

@ -1321,4 +1321,5 @@
<string name="log_export_success">日誌匯出成功!儲存路徑:</string>
<string name="all_auto_started_frpc">所有自動啟動的Frpc</string>
<string name="specified_frpc">特定的Frpc</string>
<string name="successful_execution">執行成功:%s</string>
</resources>

View File

@ -1320,4 +1320,5 @@
<string name="log_export_success">导出日志成功!存放路径:</string>
<string name="all_auto_started_frpc">所有自启动的Frpc</string>
<string name="specified_frpc">指定的Frpc</string>
<string name="successful_execution">执行成功:%s</string>
</resources>