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

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.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction import androidx.room.Transaction
import androidx.room.Update import androidx.room.Update
import androidx.sqlite.db.SupportSQLiteQuery
import com.idormy.sms.forwarder.database.entity.Logs import com.idormy.sms.forwarder.database.entity.Logs
import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
import io.reactivex.Completable import io.reactivex.Completable
@ -67,4 +69,7 @@ interface LogsDao {
@Query("SELECT * FROM Logs WHERE type = :type ORDER BY id DESC") @Query("SELECT * FROM Logs WHERE type = :type ORDER BY id DESC")
fun pagingSource(type: String): PagingSource<Int, LogsAndRuleAndSender> 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 package com.idormy.sms.forwarder.database.repository
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.LogsDao import com.idormy.sms.forwarder.database.dao.LogsDao
import com.idormy.sms.forwarder.database.entity.Logs 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 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, CoreAnim.slide,
R.drawable.auto_task_icon_alarm 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() { override fun initArgs() {

View File

@ -141,7 +141,7 @@ class CleanerFragment : BaseFragment<FragmentTasksActionCleanerBinding?>(), View
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun checkSetting(): CleanerSetting { private fun checkSetting(): CleanerSetting {
val days = binding!!.xsbDays.selectedNumber val days = binding!!.xsbDays.selectedNumber
val description = "自动删除${days}天前的转发记录" val description = String.format(getString(R.string.task_cleaner_desc), days)
return CleanerSetting(description, 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_RULE = 2006
const val TASK_ACTION_SENDER = 2007 const val TASK_ACTION_SENDER = 2007
const val TASK_ACTION_ALARM = 2008 const val TASK_ACTION_ALARM = 2008
const val TASK_ACTION_RESEND = 2009
const val SP_BATTERY_INFO = "battery_info" const val SP_BATTERY_INFO = "battery_info"
const val SP_BATTERY_STATUS = "battery_status" 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_SIM_STATE
import com.idormy.sms.forwarder.utils.SP_WIFI_SSID import com.idormy.sms.forwarder.utils.SP_WIFI_SSID
import com.idormy.sms.forwarder.utils.SharedPreference 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_CLEANER
import com.idormy.sms.forwarder.utils.TASK_ACTION_FRPC 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_HTTPSERVER
import com.idormy.sms.forwarder.utils.TASK_ACTION_NOTIFICATION 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_RULE
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS 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_HTTPSERVER -> R.drawable.auto_task_icon_http_server
TASK_ACTION_RULE -> R.drawable.auto_task_icon_rule TASK_ACTION_RULE -> R.drawable.auto_task_icon_rule
TASK_ACTION_SENDER -> R.drawable.auto_task_icon_sender 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 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_HTTPSERVER -> R.drawable.auto_task_icon_http_server_grey
TASK_ACTION_RULE -> R.drawable.auto_task_icon_rule_grey TASK_ACTION_RULE -> R.drawable.auto_task_icon_rule_grey
TASK_ACTION_SENDER -> R.drawable.auto_task_icon_sender_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 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.CleanerSetting
import com.idormy.sms.forwarder.entity.action.FrpcSetting import com.idormy.sms.forwarder.entity.action.FrpcSetting
import com.idormy.sms.forwarder.entity.action.HttpServerSetting 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.RuleSetting
import com.idormy.sms.forwarder.entity.action.SenderSetting import com.idormy.sms.forwarder.entity.action.SenderSetting
import com.idormy.sms.forwarder.entity.action.SettingsSetting 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_FRPC
import com.idormy.sms.forwarder.utils.TASK_ACTION_HTTPSERVER 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_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_RULE
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS 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") 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 -> { else -> {
writeLog("action.type is ${action.type}") 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 <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:checked="true"
android:text="@string/user_app" android:text="@string/user_app"
android:textSize="@dimen/text_size_small" android:textSize="@dimen/text_size_small"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />

View File

@ -56,38 +56,22 @@
android:layout_marginBottom="5dp" android:layout_marginBottom="5dp"
android:background="?attr/xui_config_color_separator_light" /> android:background="?attr/xui_config_color_separator_light" />
<LinearLayout <com.xuexiang.xui.widget.picker.XSeekBar
android:id="@+id/layout_start_server" android:id="@+id/xsb_days"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> app:xsb_insideRangeLineColor="#0bd97f"
app:xsb_insideRangeLineStrokeWidth="10dp"
<com.xuexiang.xui.widget.picker.XSeekBar app:xsb_isShowBubble="true"
android:id="@+id/xsb_days" app:xsb_isShowRuler="true"
android:layout_width="match_parent" app:xsb_max="60"
android:layout_height="wrap_content" app:xsb_min="0"
app:xsb_insideRangeLineColor="#0bd97f" app:xsb_numberTextColor="#ffffff"
app:xsb_insideRangeLineStrokeWidth="10dp" app:xsb_numberTextSize="@dimen/text_size_small"
app:xsb_isShowBubble="true" app:xsb_outsideRangeLineColor="#f0f0f0"
app:xsb_isShowRuler="true" app:xsb_outsideRangeLineStrokeWidth="10dp"
app:xsb_max="60" app:xsb_rulerColor="@color/xui_config_color_gray_4"
app:xsb_min="0" app:xsb_rulerInterval="ten" />
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>
</LinearLayout> </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="rule">Rule: </string>
<string name="time">Time: </string> <string name="time">Time: </string>
<string name="result">Result:</string> <string name="result">Result:</string>
<string name="original_result">Original Result:</string>
<string name="success">success</string> <string name="success">success</string>
<string name="failed">failed</string> <string name="failed">failed</string>
<string name="processing">In the processing…</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_http_server_tips">Manage HttpServer start/stop and enable/disable functions</string>
<string name="task_cleaner">Cleaner</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_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">Settings</string>
<string name="task_settings_tips">Control the configuration switch of "Settings".</string> <string name="task_settings_tips">Control the configuration switch of "Settings".</string>
<string name="task_rule">Rules On/Off</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_sender_tips">Control enabling/disabling of "Senders"</string>
<string name="task_alarm">Alarm</string> <string name="task_alarm">Alarm</string>
<string name="task_alarm_tips">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="second">Second</string>
<string name="minute">Minute</string> <string name="minute">Minute</string>

View File

@ -605,6 +605,7 @@
<string name="rule">规则:</string> <string name="rule">规则:</string>
<string name="time">时间:</string> <string name="time">时间:</string>
<string name="result">转发结果:</string> <string name="result">转发结果:</string>
<string name="original_result">原转发状态:</string>
<string name="success">成功</string> <string name="success">成功</string>
<string name="failed">失败</string> <string name="failed">失败</string>
<string name="processing">处理中</string> <string name="processing">处理中</string>
@ -1194,6 +1195,7 @@
<string name="task_http_server_tips">控制HttpServer的启动/停止,并支持启用/禁用功能</string> <string name="task_http_server_tips">控制HttpServer的启动/停止,并支持启用/禁用功能</string>
<string name="task_cleaner">清理日志</string> <string name="task_cleaner">清理日志</string>
<string name="task_cleaner_tips">批量删除N天前的转发记录、删除缓存等</string> <string name="task_cleaner_tips">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_cleaner_desc">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_settings">通用设置</string> <string name="task_settings">通用设置</string>
<string name="task_settings_tips">控制【通用设置】的配置开关</string> <string name="task_settings_tips">控制【通用设置】的配置开关</string>
<string name="task_rule">启停规则</string> <string name="task_rule">启停规则</string>
@ -1202,6 +1204,10 @@
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string> <string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
<string name="task_alarm">声音警报</string> <string name="task_alarm">声音警报</string>
<string name="task_alarm_tips">声音警报</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="second"></string>
<string name="minute"></string> <string name="minute"></string>

View File

@ -605,6 +605,7 @@
<string name="rule">規則:</string> <string name="rule">規則:</string>
<string name="time">時間:</string> <string name="time">時間:</string>
<string name="result">轉發結果:</string> <string name="result">轉發結果:</string>
<string name="original_result">原轉發狀態:</string>
<string name="success">成功</string> <string name="success">成功</string>
<string name="failed">失敗</string> <string name="failed">失敗</string>
<string name="processing">處理中</string> <string name="processing">處理中</string>
@ -1194,6 +1195,7 @@
<string name="task_http_server_tips">控制HttpServer的啟動/停止,並支持啟用/禁用功能</string> <string name="task_http_server_tips">控制HttpServer的啟動/停止,並支持啟用/禁用功能</string>
<string name="task_cleaner">清理日誌</string> <string name="task_cleaner">清理日誌</string>
<string name="task_cleaner_tips">批量刪除N天前的轉發記錄、刪除快取等</string> <string name="task_cleaner_tips">批量刪除N天前的轉發記錄、刪除快取等</string>
<string name="task_cleaner_desc">批量刪除N天前的轉發記錄、刪除快取等</string>
<string name="task_settings">通用設置</string> <string name="task_settings">通用設置</string>
<string name="task_settings_tips">控制「通用設置」的設定開關</string> <string name="task_settings_tips">控制「通用設置」的設定開關</string>
<string name="task_rule">啟停規則</string> <string name="task_rule">啟停規則</string>
@ -1202,6 +1204,10 @@
<string name="task_sender_tips">控制【發送通道】的啟用/禁用</string> <string name="task_sender_tips">控制【發送通道】的啟用/禁用</string>
<string name="task_alarm">聲音警報</string> <string name="task_alarm">聲音警報</string>
<string name="task_alarm_tips">聲音警報</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="second"></string>
<string name="minute"></string> <string name="minute"></string>

View File

@ -605,6 +605,7 @@
<string name="rule">规则:</string> <string name="rule">规则:</string>
<string name="time">时间:</string> <string name="time">时间:</string>
<string name="result">转发结果:</string> <string name="result">转发结果:</string>
<string name="original_result">原转发状态:</string>
<string name="success">成功</string> <string name="success">成功</string>
<string name="failed">失败</string> <string name="failed">失败</string>
<string name="processing">处理中</string> <string name="processing">处理中</string>
@ -1194,6 +1195,7 @@
<string name="task_http_server_tips">控制HttpServer的启动/停止,并支持启用/禁用功能</string> <string name="task_http_server_tips">控制HttpServer的启动/停止,并支持启用/禁用功能</string>
<string name="task_cleaner">清理日志</string> <string name="task_cleaner">清理日志</string>
<string name="task_cleaner_tips">批量删除N天前的转发记录、删除缓存等</string> <string name="task_cleaner_tips">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_cleaner_desc">批量删除N天前的转发记录、删除缓存等</string>
<string name="task_settings">通用设置</string> <string name="task_settings">通用设置</string>
<string name="task_settings_tips">控制【通用设置】的配置开关</string> <string name="task_settings_tips">控制【通用设置】的配置开关</string>
<string name="task_rule">启停规则</string> <string name="task_rule">启停规则</string>
@ -1202,6 +1204,10 @@
<string name="task_sender_tips">控制【发送通道】的启用/禁用</string> <string name="task_sender_tips">控制【发送通道】的启用/禁用</string>
<string name="task_alarm">声音警报</string> <string name="task_alarm">声音警报</string>
<string name="task_alarm_tips">播放音乐提醒</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="second"></string>
<string name="minute"></string> <string name="minute"></string>