新增:自动任务·快捷指令 —— 执行动作:重发消息

This commit is contained in:
pppscn 2024-02-20 22:20:58 +08:00
parent 26bd64a1e2
commit 3fc0a953e7
18 changed files with 491 additions and 32 deletions

View File

@ -6,8 +6,10 @@ import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction
import androidx.room.Update
import androidx.sqlite.db.SupportSQLiteQuery
import com.idormy.sms.forwarder.database.entity.Logs
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
import io.reactivex.Completable
@ -67,4 +69,7 @@ interface LogsDao {
@Query("SELECT * FROM Logs WHERE type = :type ORDER BY id DESC")
fun pagingSource(type: String): PagingSource<Int, LogsAndRuleAndSender>
@Transaction
@RawQuery(observedEntities = [Logs::class])
fun getLogsRaw(query: SupportSQLiteQuery): List<Logs>
}

View File

@ -1,6 +1,7 @@
package com.idormy.sms.forwarder.database.repository
import androidx.annotation.WorkerThread
import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.LogsDao
import com.idormy.sms.forwarder.database.entity.Logs
@ -22,4 +23,20 @@ class LogsRepository(private val logsDao: LogsDao) {
fun getOne(id: Long) = logsDao.getOne(id)
fun getIdsByTimeAndStatus(hours: Int, statusList: List<Int>): List<Logs> {
var sql = "SELECT * FROM Logs WHERE 1=1"
if (hours > 0) {
val time = System.currentTimeMillis() - hours * 3600000
sql += " AND time>=$time"
}
if (statusList.isNotEmpty()) {
val statusListStr = statusList.joinToString(",")
sql += " AND forward_status IN ($statusListStr)"
}
sql += " ORDER BY id ASC"
val query = SimpleSQLiteQuery(sql)
return logsDao.getLogsRaw(query)
}
}

View File

@ -0,0 +1,9 @@
package com.idormy.sms.forwarder.entity.action
import java.io.Serializable
data class ResendSetting(
var description: String = "", //描述
var hours: Int = 1, //自动重发N小时以来的转发记录0=不限制
var statusList: List<Int> = listOf(0), //状态列表,默认只重发失败的
) : Serializable

View File

@ -201,6 +201,13 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
CoreAnim.slide,
R.drawable.auto_task_icon_alarm
),
PageInfo(
getString(R.string.task_resend),
"com.idormy.sms.forwarder.fragment.action.ResendFragment",
"{\"\":\"\"}",
CoreAnim.slide,
R.drawable.auto_task_icon_resend
),
)
override fun initArgs() {

View File

@ -141,7 +141,7 @@ class CleanerFragment : BaseFragment<FragmentTasksActionCleanerBinding?>(), View
@SuppressLint("SetTextI18n")
private fun checkSetting(): CleanerSetting {
val days = binding!!.xsbDays.selectedNumber
val description = "自动删除${days}天前的转发记录"
val description = String.format(getString(R.string.task_cleaner_desc), days)
return CleanerSetting(description, days)
}
}

View File

@ -0,0 +1,171 @@
package com.idormy.sms.forwarder.fragment.action
import android.annotation.SuppressLint
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.FragmentTasksActionResendBinding
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.action.ResendSetting
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.Log
import com.idormy.sms.forwarder.utils.TASK_ACTION_RESEND
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.XToastUtils
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 = "Resend")
@Suppress("PrivatePropertyName", "DEPRECATION")
class ResendFragment : BaseFragment<FragmentTasksActionResendBinding?>(), View.OnClickListener {
private val TAG: String = ResendFragment::class.java.simpleName
private var titleBar: TitleBar? = null
private var mCountDownHelper: CountDownButtonHelper? = null
@JvmField
@AutoWired(name = KEY_EVENT_DATA_ACTION)
var eventData: String? = null
override fun initArgs() {
XRouter.getInstance().inject(this)
}
override fun viewBindingInflate(
inflater: LayoutInflater,
container: ViewGroup,
): FragmentTasksActionResendBinding {
return FragmentTasksActionResendBinding.inflate(inflater, container, false)
}
override fun initTitle(): TitleBar? {
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_resend)
return titleBar
}
/**
* 初始化控件
*/
override fun initViews() {
//测试按钮增加倒计时,避免重复点击
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)
}
override fun onFinished() {
binding!!.btnTest.text = getString(R.string.test)
}
})
var settingVo = ResendSetting(getString(R.string.task_resend_tips), 1, listOf(0))
Log.d(TAG, "initViews eventData:$eventData")
if (eventData != null) {
settingVo = Gson().fromJson(eventData, ResendSetting::class.java)
Log.d(TAG, "initViews settingVo:$settingVo")
}
binding!!.xsbHours.setDefaultValue(settingVo.hours)
settingVo.statusList.forEach { item ->
when (item) {
0 -> binding!!.scbFailed.isChecked = true
1 -> binding!!.scbProcessing.isChecked = true
2 -> binding!!.scbSuccess.isChecked = true
}
}
}
@SuppressLint("SetTextI18n")
override fun initListeners() {
binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this)
}
@SingleClick
override fun onClick(v: View) {
try {
when (v.id) {
R.id.btn_test -> {
mCountDownHelper?.start()
try {
val settingVo = checkSetting()
Log.d(TAG, settingVo.toString())
val taskAction = TaskSetting(TASK_ACTION_RESEND, getString(R.string.task_resend), settingVo.description, Gson().toJson(settingVo), requestCode)
val taskActionsJson = Gson().toJson(arrayListOf(taskAction))
val msgInfo = MsgInfo("task", getString(R.string.task_resend), settingVo.description, Date(), getString(R.string.task_resend))
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
}
R.id.btn_del -> {
popToBack()
return
}
R.id.btn_save -> {
val settingVo = checkSetting()
val intent = Intent()
intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, settingVo.description)
intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo))
setFragmentResult(TASK_ACTION_RESEND, intent)
popToBack()
return
}
}
} catch (e: Exception) {
XToastUtils.error(e.message.toString(), 30000)
e.printStackTrace()
Log.e(TAG, "onClick error: ${e.message}")
}
}
//检查设置
@SuppressLint("SetTextI18n")
private fun checkSetting(): ResendSetting {
val hours = binding!!.xsbHours.selectedNumber
val statusList = mutableListOf<Int>()
val statusStrList = mutableListOf<String>()
if (binding!!.scbFailed.isChecked) {
statusList.add(0)
statusStrList.add(getString(R.string.failed))
}
if (binding!!.scbProcessing.isChecked) {
statusList.add(1)
statusStrList.add(getString(R.string.processing))
}
if (binding!!.scbSuccess.isChecked) {
statusList.add(2)
statusStrList.add(getString(R.string.success))
}
if (statusList.isEmpty()) {
throw Exception(getString(R.string.task_resend_error))
}
val description = String.format(getString(R.string.task_resend_desc), hours, statusStrList.joinToString("/"))
return ResendSetting(description, hours, statusList)
}
}

View File

@ -244,6 +244,7 @@ const val TASK_ACTION_HTTPSERVER = 2005
const val TASK_ACTION_RULE = 2006
const val TASK_ACTION_SENDER = 2007
const val TASK_ACTION_ALARM = 2008
const val TASK_ACTION_RESEND = 2009
const val SP_BATTERY_INFO = "battery_info"
const val SP_BATTERY_STATUS = "battery_status"

View File

@ -18,10 +18,12 @@ import com.idormy.sms.forwarder.utils.SP_NETWORK_STATE
import com.idormy.sms.forwarder.utils.SP_SIM_STATE
import com.idormy.sms.forwarder.utils.SP_WIFI_SSID
import com.idormy.sms.forwarder.utils.SharedPreference
import com.idormy.sms.forwarder.utils.TASK_ACTION_ALARM
import com.idormy.sms.forwarder.utils.TASK_ACTION_CLEANER
import com.idormy.sms.forwarder.utils.TASK_ACTION_FRPC
import com.idormy.sms.forwarder.utils.TASK_ACTION_HTTPSERVER
import com.idormy.sms.forwarder.utils.TASK_ACTION_NOTIFICATION
import com.idormy.sms.forwarder.utils.TASK_ACTION_RESEND
import com.idormy.sms.forwarder.utils.TASK_ACTION_RULE
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
@ -61,6 +63,8 @@ class TaskUtils private constructor() {
TASK_ACTION_HTTPSERVER -> R.drawable.auto_task_icon_http_server
TASK_ACTION_RULE -> R.drawable.auto_task_icon_rule
TASK_ACTION_SENDER -> R.drawable.auto_task_icon_sender
TASK_ACTION_ALARM -> R.drawable.auto_task_icon_alarm
TASK_ACTION_RESEND -> R.drawable.auto_task_icon_resend
else -> R.drawable.auto_task_icon_custom_time
}
}
@ -84,6 +88,8 @@ class TaskUtils private constructor() {
TASK_ACTION_HTTPSERVER -> R.drawable.auto_task_icon_http_server_grey
TASK_ACTION_RULE -> R.drawable.auto_task_icon_rule_grey
TASK_ACTION_SENDER -> R.drawable.auto_task_icon_sender_grey
TASK_ACTION_ALARM -> R.drawable.auto_task_icon_alarm_grey
TASK_ACTION_RESEND -> R.drawable.auto_task_icon_resend_grey
else -> R.drawable.auto_task_icon_custom_time_grey
}
}

View File

@ -20,6 +20,7 @@ import com.idormy.sms.forwarder.entity.action.AlarmSetting
import com.idormy.sms.forwarder.entity.action.CleanerSetting
import com.idormy.sms.forwarder.entity.action.FrpcSetting
import com.idormy.sms.forwarder.entity.action.HttpServerSetting
import com.idormy.sms.forwarder.entity.action.ResendSetting
import com.idormy.sms.forwarder.entity.action.RuleSetting
import com.idormy.sms.forwarder.entity.action.SenderSetting
import com.idormy.sms.forwarder.entity.action.SettingsSetting
@ -43,6 +44,7 @@ import com.idormy.sms.forwarder.utils.TASK_ACTION_CLEANER
import com.idormy.sms.forwarder.utils.TASK_ACTION_FRPC
import com.idormy.sms.forwarder.utils.TASK_ACTION_HTTPSERVER
import com.idormy.sms.forwarder.utils.TASK_ACTION_NOTIFICATION
import com.idormy.sms.forwarder.utils.TASK_ACTION_RESEND
import com.idormy.sms.forwarder.utils.TASK_ACTION_RULE
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
@ -322,6 +324,23 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
writeLog(String.format(getString(R.string.successful_execution), alarmSetting.description), "SUCCESS")
}
TASK_ACTION_RESEND -> {
val resendSetting = Gson().fromJson(action.setting, ResendSetting::class.java)
if (resendSetting == null) {
writeLog("resendSetting is null")
continue
}
val logsList = Core.logs.getIdsByTimeAndStatus(resendSetting.hours, resendSetting.statusList)
logsList.forEach { item ->
Log.d(TAG, "resend logsList item: $item")
SendUtils.retrySendMsg(item.id)
}
successNum++
writeLog(String.format(getString(R.string.successful_execution), resendSetting.description), "SUCCESS")
}
else -> {
writeLog("action.type is ${action.type}")
}

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25.0dip"
android:height="25.0dip"
android:autoMirrored="true"
android:viewportWidth="25.0"
android:viewportHeight="25.0">
<path
android:fillColor="#ff36d167"
android:pathData="M6.66,0.66L18.66,0.66A6,6 0,0 1,24.66 6.66L24.66,18.66A6,6 0,0 1,18.66 24.66L6.66,24.66A6,6 0,0 1,0.66 18.66L0.66,6.66A6,6 0,0 1,6.66 0.66z" />
<group
android:scaleX="0.02"
android:scaleY="0.02"
android:translateX="2.5"
android:translateY="2.5">
<path
android:fillColor="#ffffff"
android:pathData="M876.4,436.3C822,381.9 749.6,352 672.7,352s-149.3,30 -203.6,84.4C414.7,490.7 384.7,563 384.7,640s30,149.3 84.4,203.6C523.5,898 595.8,928 672.7,928s149.3,-30 203.6,-84.4c54.4,-54.4 84.4,-126.7 84.4,-203.6s-29.9,-149.3 -84.3,-203.7zM699,784H595.6c-17.7,0 -32,-14.3 -32,-32s14.3,-32 32,-32H699c29.6,0 53.7,-24.1 53.7,-53.7s-24.1,-53.7 -53.7,-53.7h-61.1c10.3,12.6 9.6,31.2 -2.1,42.9 -6.2,6.2 -14.4,9.4 -22.6,9.4s-16.4,-3.1 -22.6,-9.4l-50.4,-50.4c-7,-5.9 -11.4,-14.7 -11.4,-24.5s4.4,-18.6 11.4,-24.5l50.8,-50.8c12.5,-12.5 32.8,-12.5 45.3,0 11.9,11.9 12.5,30.7 1.8,43.3h61c64.9,0 117.7,52.8 117.7,117.7S763.9,784 699,784zM360.3,565.2l-55.2,101.7c-4.8,8.8 -18.2,5.4 -18.2,-4.6V540.4c0,-6.7 6.7,-11.4 13,-9.1l55.2,20.1c5.5,2.1 8,8.6 5.2,13.8zM355.8,527.8c16.5,-46.7 43.3,-89.4 79.3,-125.4 39.4,-39.4 86.9,-67.8 138.7,-83.7L639,121.8v-0.1c0.2,-0.5 0.3,-0.9 0.4,-1.4 0,-0.1 0,-0.2 0.1,-0.2l0.3,-1.5v-0.1c0.2,-1.6 0.3,-3.3 0.1,-4.9v-0.1c-0.1,-0.5 -0.1,-1 -0.2,-1.5v-0.2c-0.1,-0.5 -0.2,-1 -0.4,-1.5 0,-0.1 0,-0.1 -0.1,-0.2 -0.1,-0.5 -0.3,-0.9 -0.5,-1.4 0,-0.1 0,-0.1 -0.1,-0.2 -0.2,-0.5 -0.4,-0.9 -0.6,-1.3 0,-0.1 -0.1,-0.2 -0.1,-0.2 -0.2,-0.4 -0.5,-0.9 -0.7,-1.3 0,-0.1 -0.1,-0.1 -0.1,-0.2 -0.3,-0.4 -0.6,-0.9 -0.9,-1.3v-0.1,-0.1c-0.3,-0.4 -0.7,-0.9 -1,-1.3l-0.1,-0.1c-0.4,-0.4 -0.7,-0.8 -1.1,-1.2h-0.1c-0.8,-0.7 -1.7,-1.4 -2.6,-2 -0.4,-0.3 -0.9,-0.5 -1.3,-0.8 -0.1,0 -0.1,-0.1 -0.2,-0.1 -0.4,-0.2 -0.9,-0.4 -1.3,-0.6 -0.1,0 -0.2,-0.1 -0.2,-0.1 -0.4,-0.2 -0.9,-0.4 -1.3,-0.5h-0.1c-0.5,-0.2 -0.9,-0.3 -1.4,-0.4 -0.1,0 -0.2,0 -0.2,-0.1l-1.5,-0.3h-0.1c-1.1,-0.2 -2.1,-0.2 -3.2,-0.2 -0.5,0 -1.1,0 -1.6,0.1h-0.2c-0.5,0.1 -1,0.1 -1.5,0.2h-0.2c-0.5,0.1 -1,0.2 -1.5,0.4 -0.1,0 -0.1,0 -0.2,0.1 -0.5,0.2 -1,0.3 -1.5,0.5s-1,0.4 -1.5,0.7L74.7,366.1c-6.6,3.3 -10.7,10 -10.7,17.3s4.1,14.1 10.7,17.4l130.4,65.4c14.1,7.1 31.1,4.9 43,-5.5 1.7,-1.5 3.5,-3 5.2,-4.6 10.1,-8.9 20.1,-17.9 29.9,-27.2l29.4,-27.7 29.5,-27.5 29.7,-27.3 29.9,-27.2 30,-27.1c10.1,-9 20.1,-18 30.2,-26.9 10.1,-9 20.2,-17.9 30.3,-26.8l15.3,-13.3 7.6,-6.6 7.6,-6.5c1.4,-1.2 3.6,-1.2 4.9,0.1 1.2,1.3 1.3,3.2 0.3,4.6l-6.2,8 -6.2,8 -12.5,15.9c-8.4,10.6 -16.8,21.1 -25.2,31.6 -8.4,10.5 -16.9,21 -25.3,31.5L427,343.1l-25.6,31.3 -25.8,31.1 -26,30.9 -26.1,30.8c-15.1,18.6 -7.3,46.6 15.3,54.6l17,6z" />
</group>
</vector>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="25.0dip"
android:height="25.0dip"
android:autoMirrored="true"
android:viewportWidth="25.0"
android:viewportHeight="25.0">
<path
android:fillColor="#ffe6e6e6"
android:pathData="M6.66,0.66L18.66,0.66A6,6 0,0 1,24.66 6.66L24.66,18.66A6,6 0,0 1,18.66 24.66L6.66,24.66A6,6 0,0 1,0.66 18.66L0.66,6.66A6,6 0,0 1,6.66 0.66z" />
<group
android:scaleX="0.02"
android:scaleY="0.02"
android:translateX="2.5"
android:translateY="2.5">
<path
android:fillColor="#ffffff"
android:pathData="M876.4,436.3C822,381.9 749.6,352 672.7,352s-149.3,30 -203.6,84.4C414.7,490.7 384.7,563 384.7,640s30,149.3 84.4,203.6C523.5,898 595.8,928 672.7,928s149.3,-30 203.6,-84.4c54.4,-54.4 84.4,-126.7 84.4,-203.6s-29.9,-149.3 -84.3,-203.7zM699,784H595.6c-17.7,0 -32,-14.3 -32,-32s14.3,-32 32,-32H699c29.6,0 53.7,-24.1 53.7,-53.7s-24.1,-53.7 -53.7,-53.7h-61.1c10.3,12.6 9.6,31.2 -2.1,42.9 -6.2,6.2 -14.4,9.4 -22.6,9.4s-16.4,-3.1 -22.6,-9.4l-50.4,-50.4c-7,-5.9 -11.4,-14.7 -11.4,-24.5s4.4,-18.6 11.4,-24.5l50.8,-50.8c12.5,-12.5 32.8,-12.5 45.3,0 11.9,11.9 12.5,30.7 1.8,43.3h61c64.9,0 117.7,52.8 117.7,117.7S763.9,784 699,784zM360.3,565.2l-55.2,101.7c-4.8,8.8 -18.2,5.4 -18.2,-4.6V540.4c0,-6.7 6.7,-11.4 13,-9.1l55.2,20.1c5.5,2.1 8,8.6 5.2,13.8zM355.8,527.8c16.5,-46.7 43.3,-89.4 79.3,-125.4 39.4,-39.4 86.9,-67.8 138.7,-83.7L639,121.8v-0.1c0.2,-0.5 0.3,-0.9 0.4,-1.4 0,-0.1 0,-0.2 0.1,-0.2l0.3,-1.5v-0.1c0.2,-1.6 0.3,-3.3 0.1,-4.9v-0.1c-0.1,-0.5 -0.1,-1 -0.2,-1.5v-0.2c-0.1,-0.5 -0.2,-1 -0.4,-1.5 0,-0.1 0,-0.1 -0.1,-0.2 -0.1,-0.5 -0.3,-0.9 -0.5,-1.4 0,-0.1 0,-0.1 -0.1,-0.2 -0.2,-0.5 -0.4,-0.9 -0.6,-1.3 0,-0.1 -0.1,-0.2 -0.1,-0.2 -0.2,-0.4 -0.5,-0.9 -0.7,-1.3 0,-0.1 -0.1,-0.1 -0.1,-0.2 -0.3,-0.4 -0.6,-0.9 -0.9,-1.3v-0.1,-0.1c-0.3,-0.4 -0.7,-0.9 -1,-1.3l-0.1,-0.1c-0.4,-0.4 -0.7,-0.8 -1.1,-1.2h-0.1c-0.8,-0.7 -1.7,-1.4 -2.6,-2 -0.4,-0.3 -0.9,-0.5 -1.3,-0.8 -0.1,0 -0.1,-0.1 -0.2,-0.1 -0.4,-0.2 -0.9,-0.4 -1.3,-0.6 -0.1,0 -0.2,-0.1 -0.2,-0.1 -0.4,-0.2 -0.9,-0.4 -1.3,-0.5h-0.1c-0.5,-0.2 -0.9,-0.3 -1.4,-0.4 -0.1,0 -0.2,0 -0.2,-0.1l-1.5,-0.3h-0.1c-1.1,-0.2 -2.1,-0.2 -3.2,-0.2 -0.5,0 -1.1,0 -1.6,0.1h-0.2c-0.5,0.1 -1,0.1 -1.5,0.2h-0.2c-0.5,0.1 -1,0.2 -1.5,0.4 -0.1,0 -0.1,0 -0.2,0.1 -0.5,0.2 -1,0.3 -1.5,0.5s-1,0.4 -1.5,0.7L74.7,366.1c-6.6,3.3 -10.7,10 -10.7,17.3s4.1,14.1 10.7,17.4l130.4,65.4c14.1,7.1 31.1,4.9 43,-5.5 1.7,-1.5 3.5,-3 5.2,-4.6 10.1,-8.9 20.1,-17.9 29.9,-27.2l29.4,-27.7 29.5,-27.5 29.7,-27.3 29.9,-27.2 30,-27.1c10.1,-9 20.1,-18 30.2,-26.9 10.1,-9 20.2,-17.9 30.3,-26.8l15.3,-13.3 7.6,-6.6 7.6,-6.5c1.4,-1.2 3.6,-1.2 4.9,0.1 1.2,1.3 1.3,3.2 0.3,4.6l-6.2,8 -6.2,8 -12.5,15.9c-8.4,10.6 -16.8,21.1 -25.2,31.6 -8.4,10.5 -16.9,21 -25.3,31.5L427,343.1l-25.6,31.3 -25.8,31.1 -26,30.9 -26.1,30.8c-15.1,18.6 -7.3,46.6 15.3,54.6l17,6z" />
</group>
</vector>

View File

@ -681,7 +681,6 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/user_app"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />

View File

@ -56,38 +56,22 @@
android:layout_marginBottom="5dp"
android:background="?attr/xui_config_color_separator_light" />
<LinearLayout
android:id="@+id/layout_start_server"
<com.xuexiang.xui.widget.picker.XSeekBar
android:id="@+id/xsb_days"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.xuexiang.xui.widget.picker.XSeekBar
android:id="@+id/xsb_days"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:xsb_insideRangeLineColor="#0bd97f"
app:xsb_insideRangeLineStrokeWidth="10dp"
app:xsb_isShowBubble="true"
app:xsb_isShowRuler="true"
app:xsb_max="60"
app:xsb_min="0"
app:xsb_numberTextColor="#ffffff"
app:xsb_numberTextSize="@dimen/text_size_small"
app:xsb_outsideRangeLineColor="#f0f0f0"
app:xsb_outsideRangeLineStrokeWidth="10dp"
app:xsb_rulerColor="@color/xui_config_color_gray_4"
app:xsb_rulerInterval="ten" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:text="@string/day"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
app:xsb_insideRangeLineColor="#0bd97f"
app:xsb_insideRangeLineStrokeWidth="10dp"
app:xsb_isShowBubble="true"
app:xsb_isShowRuler="true"
app:xsb_max="60"
app:xsb_min="0"
app:xsb_numberTextColor="#ffffff"
app:xsb_numberTextSize="@dimen/text_size_small"
app:xsb_outsideRangeLineColor="#f0f0f0"
app:xsb_outsideRangeLineStrokeWidth="10dp"
app:xsb_rulerColor="@color/xui_config_color_gray_4"
app:xsb_rulerInterval="ten" />
</LinearLayout>

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/xui_config_color_background"
android:orientation="vertical">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:gravity="center_horizontal"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_margin="10dp"
android:contentDescription="@string/task_resend"
app:srcCompat="@drawable/auto_task_icon_resend"
tools:ignore="ImageContrastCheck" />
<LinearLayout
style="@style/BarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/task_resend"
android:textSize="@dimen/text_size_big"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/task_resend_tips"
android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:background="?attr/xui_config_color_separator_light" />
<com.xuexiang.xui.widget.picker.XSeekBar
android:id="@+id/xsb_hours"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:xsb_insideRangeLineColor="#0bd97f"
app:xsb_insideRangeLineStrokeWidth="10dp"
app:xsb_isShowBubble="true"
app:xsb_isShowRuler="true"
app:xsb_max="50"
app:xsb_min="0"
app:xsb_numberTextColor="#ffffff"
app:xsb_numberTextSize="@dimen/text_size_small"
app:xsb_outsideRangeLineColor="#f0f0f0"
app:xsb_outsideRangeLineStrokeWidth="10dp"
app:xsb_rulerColor="@color/xui_config_color_gray_4"
app:xsb_rulerInterval="ten" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="25dp"
android:gravity="center_vertical"
android:orientation="horizontal"
tools:ignore="TextSizeCheck">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/original_result"
android:textSize="@dimen/text_size_small"
android:textStyle="bold"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_failed"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="10dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:text="@string/failed"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_processing"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="10dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:text="@string/processing"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
<com.xuexiang.xui.widget.button.SmoothCheckBox
android:id="@+id/scb_success"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginStart="10dp"
app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:text="@string/success"
android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:padding="10dp">
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
android:id="@+id/btn_del"
style="@style/SuperButton.Gray.Icon.Spacing"
android:drawableStart="@drawable/ic_delete"
android:text="@string/discard"
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
android:id="@+id/btn_save"
style="@style/SuperButton.Blue.Icon.Spacing"
android:drawableStart="@drawable/ic_save"
android:text="@string/submit"
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
android:id="@+id/btn_test"
style="@style/SuperButton.Green.Icon.Spacing"
android:drawableStart="@drawable/ic_test"
android:text="@string/test"
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
</LinearLayout>
</LinearLayout>

View File

@ -604,6 +604,7 @@
<string name="rule">Rule: </string>
<string name="time">Time: </string>
<string name="result">Result:</string>
<string name="original_result">Original Result:</string>
<string name="success">success</string>
<string name="failed">failed</string>
<string name="processing">In the processing…</string>
@ -1193,6 +1194,7 @@
<string name="task_http_server_tips">Manage HttpServer start/stop and enable/disable functions</string>
<string name="task_cleaner">Cleaner</string>
<string name="task_cleaner_tips">Delete FW. logs older than N days, delete cache, etc.</string>
<string name="task_cleaner_desc">Delete FW. logs older than %s days, delete cache, etc.</string>
<string name="task_settings">Settings</string>
<string name="task_settings_tips">Control the configuration switch of "Settings".</string>
<string name="task_rule">Rules On/Off</string>
@ -1201,6 +1203,10 @@
<string name="task_sender_tips">Control enabling/disabling of "Senders"</string>
<string name="task_alarm">Alarm</string>
<string name="task_alarm_tips">Alarm</string>
<string name="task_resend">Resend Message</string>
<string name="task_resend_tips">Resend forwarded records since N hours ago, 0=ALL</string>
<string name="task_resend_desc">Resend forwarding records since %s hours ago for %s</string>
<string name="task_resend_error">At least one "Original Result" must be selected</string>
<string name="second">Second</string>
<string name="minute">Minute</string>

View File

@ -605,6 +605,7 @@
<string name="rule">规则:</string>
<string name="time">时间:</string>
<string name="result">转发结果:</string>
<string name="original_result">原转发状态:</string>
<string name="success">成功</string>
<string name="failed">失败</string>
<string name="processing">处理中</string>
@ -1194,6 +1195,7 @@
<string name="task_http_server_tips">控制HttpServer的启动/停止,并支持启用/禁用功能</string>
<string name="task_cleaner">清理日志</string>
<string name="task_cleaner_tips">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_cleaner_desc">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_settings">通用设置</string>
<string name="task_settings_tips">控制【通用设置】的配置开关</string>
<string name="task_rule">启停规则</string>
@ -1202,6 +1204,10 @@
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
<string name="task_alarm">声音警报</string>
<string name="task_alarm_tips">声音警报</string>
<string name="task_resend">重发消息</string>
<string name="task_resend_tips">自动重发N小时以来的转发记录0=全部</string>
<string name="task_resend_desc">自动重发%s小时以来%s的转发记录</string>
<string name="task_resend_error">必须至少选择一个【原转发状态】</string>
<string name="second"></string>
<string name="minute"></string>

View File

@ -605,6 +605,7 @@
<string name="rule">規則:</string>
<string name="time">時間:</string>
<string name="result">轉發結果:</string>
<string name="original_result">原轉發狀態:</string>
<string name="success">成功</string>
<string name="failed">失敗</string>
<string name="processing">處理中</string>
@ -1194,6 +1195,7 @@
<string name="task_http_server_tips">控制HttpServer的啟動/停止,並支持啟用/禁用功能</string>
<string name="task_cleaner">清理日誌</string>
<string name="task_cleaner_tips">批量刪除N天前的轉發記錄、刪除快取等</string>
<string name="task_cleaner_desc">批量刪除N天前的轉發記錄、刪除快取等</string>
<string name="task_settings">通用設置</string>
<string name="task_settings_tips">控制「通用設置」的設定開關</string>
<string name="task_rule">啟停規則</string>
@ -1202,6 +1204,10 @@
<string name="task_sender_tips">控制【發送通道】的啟用/禁用</string>
<string name="task_alarm">聲音警報</string>
<string name="task_alarm_tips">聲音警報</string>
<string name="task_resend">重發消息</string>
<string name="task_resend_tips">自動重發N小時以來的轉發記錄0=全部</string>
<string name="task_resend_desc">自動重發%s小時以來%s的轉發記錄</string>
<string name="task_resend_error">必须至少选择一個「原轉發狀態」</string>
<string name="second"></string>
<string name="minute"></string>

View File

@ -605,6 +605,7 @@
<string name="rule">规则:</string>
<string name="time">时间:</string>
<string name="result">转发结果:</string>
<string name="original_result">原转发状态:</string>
<string name="success">成功</string>
<string name="failed">失败</string>
<string name="processing">处理中</string>
@ -1194,6 +1195,7 @@
<string name="task_http_server_tips">控制HttpServer的启动/停止,并支持启用/禁用功能</string>
<string name="task_cleaner">清理日志</string>
<string name="task_cleaner_tips">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_cleaner_desc">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_settings">通用设置</string>
<string name="task_settings_tips">控制【通用设置】的配置开关</string>
<string name="task_rule">启停规则</string>
@ -1202,6 +1204,10 @@
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
<string name="task_alarm">声音警报</string>
<string name="task_alarm_tips">播放音乐提醒</string>
<string name="task_resend">重发消息</string>
<string name="task_resend_tips">自动重发N小时以来的转发记录0=全部</string>
<string name="task_resend_desc">自动重发%s小时以来%s的转发记录</string>
<string name="task_resend_error">必须至少选择一个【原转发状态】</string>
<string name="second"></string>
<string name="minute"></string>