mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
新增:自动任务·快捷指令 —— 通道推送动作(开发中)
This commit is contained in:
parent
51129509f9
commit
e03a9b8198
@ -1,46 +1,34 @@
|
||||
package com.idormy.sms.forwarder.fragment.action
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Looper
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.adapter.spinner.AppListAdapterItem
|
||||
import com.idormy.sms.forwarder.adapter.spinner.AppListSpinnerAdapter
|
||||
import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem
|
||||
import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter
|
||||
import com.idormy.sms.forwarder.core.BaseFragment
|
||||
import com.idormy.sms.forwarder.database.AppDatabase
|
||||
import com.idormy.sms.forwarder.database.entity.Rule
|
||||
import com.idormy.sms.forwarder.database.entity.Sender
|
||||
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
|
||||
import com.idormy.sms.forwarder.database.viewmodel.RuleViewModel
|
||||
import com.idormy.sms.forwarder.databinding.FragmentRulesEditBinding
|
||||
import com.idormy.sms.forwarder.databinding.FragmentTasksActionNotificationBinding
|
||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
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.xrouter.utils.TextUtils
|
||||
import com.xuexiang.xui.utils.CountDownButtonHelper
|
||||
import com.xuexiang.xui.utils.ResUtils
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
|
||||
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
|
||||
import com.xuexiang.xui.widget.picker.widget.builder.OptionsPickerBuilder
|
||||
import com.xuexiang.xui.widget.picker.widget.listener.OnOptionsSelectListener
|
||||
import com.xuexiang.xui.widget.spinner.materialspinner.MaterialSpinner
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import io.reactivex.SingleObserver
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
@ -50,14 +38,15 @@ import java.util.*
|
||||
|
||||
@Page(name = "Notification")
|
||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||
class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClickListener, CompoundButton.OnCheckedChangeListener {
|
||||
class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding?>(), View.OnClickListener, CompoundButton.OnCheckedChangeListener {
|
||||
|
||||
private val TAG: String = NotificationFragment::class.java.simpleName
|
||||
var titleBar: TitleBar? = null
|
||||
private val viewModel by viewModels<RuleViewModel> { BaseViewModelFactory(context) }
|
||||
private var mCountDownHelper: CountDownButtonHelper? = null
|
||||
|
||||
var callType = 1
|
||||
var callTypeIndex = 0
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_EVENT_DATA_ACTION)
|
||||
var eventData: String? = null
|
||||
|
||||
//免打扰(禁用转发)时间段
|
||||
private val mTimeOption = DataProvider.timePeriodOption
|
||||
@ -74,25 +63,8 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
private val senderSpinnerList = ArrayList<SenderAdapterItem>()
|
||||
private lateinit var senderSpinnerAdapter: SenderSpinnerAdapter<*>
|
||||
|
||||
//已安装App信息列表
|
||||
private val appListSpinnerList = ArrayList<AppListAdapterItem>()
|
||||
private lateinit var appListSpinnerAdapter: AppListSpinnerAdapter<*>
|
||||
private val appListObserver = Observer { it: String ->
|
||||
Log.d(TAG, "EVENT_LOAD_APP_LIST: $it")
|
||||
initAppSpinner()
|
||||
}
|
||||
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_RULE_ID)
|
||||
var ruleId: Long = 0
|
||||
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_RULE_TYPE)
|
||||
var ruleType: String = "sms"
|
||||
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_RULE_CLONE)
|
||||
var isClone: Boolean = false
|
||||
private var ruleId: Long = 0
|
||||
private var ruleType: String = "app"
|
||||
|
||||
override fun initArgs() {
|
||||
XRouter.getInstance().inject(this)
|
||||
@ -101,8 +73,8 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
override fun viewBindingInflate(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
): FragmentRulesEditBinding {
|
||||
return FragmentRulesEditBinding.inflate(inflater, container, false)
|
||||
): FragmentTasksActionNotificationBinding {
|
||||
return FragmentTasksActionNotificationBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun initTitle(): TitleBar? {
|
||||
@ -115,74 +87,46 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
* 初始化控件
|
||||
*/
|
||||
override fun initViews() {
|
||||
when (ruleType) {
|
||||
"app" -> {
|
||||
titleBar?.setTitle(R.string.app_rule)
|
||||
binding!!.layoutSimSlot.visibility = View.GONE
|
||||
binding!!.rbPhone.visibility = View.GONE
|
||||
binding!!.rbCallType.visibility = View.GONE
|
||||
binding!!.rbContent.visibility = View.GONE
|
||||
binding!!.tvMuRuleTips.setText(R.string.mu_rule_app_tips)
|
||||
binding!!.btInsertExtra.visibility = View.GONE
|
||||
binding!!.btInsertSender.visibility = View.GONE
|
||||
binding!!.btInsertContent.visibility = View.GONE
|
||||
//初始化APP下拉列表
|
||||
initAppSpinner()
|
||||
//监听已安装App信息列表加载完成事件
|
||||
LiveEventBus.get(EVENT_LOAD_APP_LIST, String::class.java).observeStickyForever(appListObserver)
|
||||
//测试按钮增加倒计时,避免重复点击
|
||||
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
|
||||
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
|
||||
override fun onCountDown(time: Int) {
|
||||
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
|
||||
}
|
||||
|
||||
"call" -> {
|
||||
titleBar?.setTitle(R.string.call_rule)
|
||||
binding!!.rbContent.visibility = View.GONE
|
||||
binding!!.rbPackageName.visibility = View.GONE
|
||||
binding!!.rbUid.visibility = View.GONE
|
||||
binding!!.rbInformContent.visibility = View.GONE
|
||||
//binding!!.rbMultiMatch.visibility = View.GONE
|
||||
binding!!.tvMuRuleTips.setText(R.string.mu_rule_call_tips)
|
||||
binding!!.btInsertContent.visibility = View.GONE
|
||||
binding!!.btInsertSenderApp.visibility = View.GONE
|
||||
binding!!.btInsertUid.visibility = View.GONE
|
||||
binding!!.btInsertTitleApp.visibility = View.GONE
|
||||
binding!!.btInsertContentApp.visibility = View.GONE
|
||||
override fun onFinished() {
|
||||
binding!!.btnTest.text = getString(R.string.test)
|
||||
}
|
||||
})
|
||||
|
||||
//通话类型:1.来电挂机 2.去电挂机 3.未接来电 4.来电提醒 5.来电接通 6.去电拨出
|
||||
binding!!.spCallType.setItems(CALL_TYPE_MAP.values.toList())
|
||||
binding!!.spCallType.setOnItemSelectedListener { _: MaterialSpinner?, _: Int, _: Long, item: Any ->
|
||||
CALL_TYPE_MAP.forEach {
|
||||
if (it.value == item) callType = it.key.toInt()
|
||||
}
|
||||
}
|
||||
binding!!.spCallType.setOnNothingSelectedListener {
|
||||
callType = 1
|
||||
callTypeIndex = 0
|
||||
binding!!.spCallType.selectedIndex = callTypeIndex
|
||||
}
|
||||
binding!!.spCallType.selectedIndex = callTypeIndex
|
||||
Log.d(TAG, "initViews eventData:$eventData")
|
||||
if (eventData != null) {
|
||||
val settingVo = Gson().fromJson(eventData, Rule::class.java)
|
||||
Log.d(TAG, "initViews settingVo:$settingVo")
|
||||
|
||||
Log.d(TAG, settingVo.senderList.toString())
|
||||
settingVo.senderList.forEach {
|
||||
senderId = it.id
|
||||
senderListSelected.add(it)
|
||||
}
|
||||
|
||||
else -> {
|
||||
titleBar?.setTitle(R.string.sms_rule)
|
||||
binding!!.rbCallType.visibility = View.GONE
|
||||
binding!!.rbPackageName.visibility = View.GONE
|
||||
binding!!.rbUid.visibility = View.GONE
|
||||
binding!!.rbInformContent.visibility = View.GONE
|
||||
binding!!.btInsertSenderApp.visibility = View.GONE
|
||||
binding!!.btInsertUid.visibility = View.GONE
|
||||
binding!!.btInsertTitleApp.visibility = View.GONE
|
||||
binding!!.btInsertContentApp.visibility = View.GONE
|
||||
binding!!.rgSenderLogic.check(settingVo.getSenderLogicCheckId())
|
||||
if (!TextUtils.isEmpty(settingVo.smsTemplate.trim())) {
|
||||
binding!!.sbSmsTemplate.isChecked = true
|
||||
binding!!.layoutSmsTemplate.visibility = View.VISIBLE
|
||||
binding!!.etSmsTemplate.setText(settingVo.smsTemplate.trim())
|
||||
}
|
||||
if (!TextUtils.isEmpty(settingVo.regexReplace.trim())) {
|
||||
binding!!.sbRegexReplace.isChecked = true
|
||||
binding!!.layoutRegexReplace.visibility = View.VISIBLE
|
||||
binding!!.etRegexReplace.setText(settingVo.regexReplace.trim())
|
||||
}
|
||||
silentPeriodStart = settingVo.silentPeriodStart
|
||||
silentPeriodEnd = settingVo.silentPeriodEnd
|
||||
}
|
||||
|
||||
if (ruleId <= 0) { //新增
|
||||
titleBar?.setSubTitle(getString(R.string.add_rule))
|
||||
binding!!.btnDel.setText(R.string.discard)
|
||||
//初始化发送通道下拉框
|
||||
initSenderSpinner()
|
||||
} else { //编辑 & 克隆
|
||||
binding!!.btnDel.setText(R.string.del)
|
||||
initForm()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun initListeners() {
|
||||
@ -200,64 +144,8 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
binding!!.btnDel.setOnClickListener(this)
|
||||
binding!!.btnSave.setOnClickListener(this)
|
||||
|
||||
binding!!.sbStatus.setOnCheckedChangeListener(this)
|
||||
binding!!.sbSmsTemplate.setOnCheckedChangeListener(this)
|
||||
binding!!.sbRegexReplace.setOnCheckedChangeListener(this)
|
||||
|
||||
binding!!.rgFiled.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
||||
if (ruleType == "app" && appListSpinnerList.isNotEmpty()) {
|
||||
binding!!.layoutAppList.visibility = if (checkedId == R.id.rb_inform_content) View.GONE else View.VISIBLE
|
||||
}
|
||||
when (checkedId) {
|
||||
R.id.rb_transpond_all -> {
|
||||
binding!!.rgCheck.check(R.id.rb_is)
|
||||
binding!!.spCallType.visibility = View.GONE
|
||||
binding!!.tvMuRuleTips.visibility = View.GONE
|
||||
binding!!.layoutMatchType.visibility = View.GONE
|
||||
binding!!.layoutMatchValue.visibility = View.GONE
|
||||
}
|
||||
|
||||
R.id.rb_multi_match -> {
|
||||
binding!!.rgCheck.check(R.id.rb_is)
|
||||
binding!!.spCallType.visibility = View.GONE
|
||||
binding!!.tvMuRuleTips.visibility = View.VISIBLE
|
||||
binding!!.layoutMatchType.visibility = View.GONE
|
||||
binding!!.layoutMatchValue.visibility = View.VISIBLE
|
||||
binding!!.etValue.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
R.id.rb_call_type -> {
|
||||
binding!!.rgCheck.check(R.id.rb_is)
|
||||
binding!!.tvMuRuleTips.visibility = View.GONE
|
||||
binding!!.layoutMatchType.visibility = View.GONE
|
||||
binding!!.layoutMatchValue.visibility = View.VISIBLE
|
||||
binding!!.etValue.visibility = View.GONE
|
||||
binding!!.spCallType.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
else -> {
|
||||
binding!!.spCallType.visibility = View.GONE
|
||||
binding!!.tvMuRuleTips.visibility = View.GONE
|
||||
binding!!.layoutMatchType.visibility = View.VISIBLE
|
||||
binding!!.layoutMatchValue.visibility = View.VISIBLE
|
||||
binding!!.etValue.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding!!.rgCheck.setOnCheckedChangeListener { group: RadioGroup?, checkedId: Int ->
|
||||
if (group != null && checkedId > 0) {
|
||||
binding!!.rgCheck2.clearCheck()
|
||||
group.check(checkedId)
|
||||
}
|
||||
}
|
||||
|
||||
binding!!.rgCheck2.setOnCheckedChangeListener { group: RadioGroup?, checkedId: Int ->
|
||||
if (group != null && checkedId > 0) {
|
||||
binding!!.rgCheck.clearCheck()
|
||||
group.check(checkedId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
|
||||
@ -353,31 +241,46 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
}
|
||||
|
||||
R.id.btn_test -> {
|
||||
val ruleNew = checkForm()
|
||||
testRule(ruleNew)
|
||||
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))
|
||||
}
|
||||
|
||||
Thread {
|
||||
try {
|
||||
SendUtils.sendMsgSender(msgInfo, settingVo)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
LiveEventBus.get(EVENT_TOAST_ERROR, String::class.java).post(e.message.toString())
|
||||
}
|
||||
}.start()
|
||||
return
|
||||
}
|
||||
|
||||
R.id.btn_del -> {
|
||||
if (ruleId <= 0 || isClone) {
|
||||
popToBack()
|
||||
return
|
||||
}
|
||||
|
||||
MaterialDialog.Builder(requireContext()).title(R.string.delete_rule_title).content(R.string.delete_rule_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||
viewModel.delete(ruleId)
|
||||
XToastUtils.success(R.string.delete_rule_toast)
|
||||
popToBack()
|
||||
}.show()
|
||||
return
|
||||
}
|
||||
|
||||
R.id.btn_save -> {
|
||||
val ruleNew = checkForm()
|
||||
if (isClone) ruleNew.id = 0
|
||||
Log.d(TAG, ruleNew.toString())
|
||||
viewModel.insertOrUpdate(ruleNew)
|
||||
XToastUtils.success(R.string.tipSaveSuccess)
|
||||
val settingVo = checkSetting()
|
||||
var description = getString(R.string.select_sender) + ": "
|
||||
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))
|
||||
setFragmentResult(TASK_ACTION_NOTIFICATION, intent)
|
||||
popToBack()
|
||||
return
|
||||
}
|
||||
@ -511,148 +414,23 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
}
|
||||
}
|
||||
|
||||
//初始化APP下拉列表
|
||||
private fun initAppSpinner() {
|
||||
if (ruleType != "app") return
|
||||
|
||||
//未开启异步获取已安装App信息开关时,规则编辑不显示已安装APP下拉框
|
||||
if (!SettingUtils.enableLoadUserAppList && !SettingUtils.enableLoadSystemAppList) return
|
||||
|
||||
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
|
||||
XToastUtils.info(getString(R.string.loading_app_list))
|
||||
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
|
||||
WorkManager.getInstance(XUtil.getContext()).enqueue(request)
|
||||
return
|
||||
}
|
||||
|
||||
appListSpinnerList.clear()
|
||||
if (SettingUtils.enableLoadUserAppList) {
|
||||
for (appInfo in App.UserAppList) {
|
||||
if (TextUtils.isEmpty(appInfo.packageName)) continue
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
if (SettingUtils.enableLoadSystemAppList) {
|
||||
for (appInfo in App.SystemAppList) {
|
||||
if (TextUtils.isEmpty(appInfo.packageName)) continue
|
||||
appListSpinnerList.add(AppListAdapterItem(appInfo.name, appInfo.icon, appInfo.packageName))
|
||||
}
|
||||
}
|
||||
|
||||
//列表为空也不显示下拉框
|
||||
if (appListSpinnerList.isEmpty()) return
|
||||
|
||||
appListSpinnerAdapter = AppListSpinnerAdapter(appListSpinnerList).setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
|
||||
binding!!.spApp.setAdapter(appListSpinnerAdapter)
|
||||
binding!!.spApp.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
|
||||
try {
|
||||
val appInfo = appListSpinnerAdapter.getItemSource(position) as AppListAdapterItem
|
||||
CommonUtils.insertOrReplaceText2Cursor(binding!!.etValue, appInfo.packageName.toString())
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString())
|
||||
}
|
||||
}
|
||||
binding!!.layoutAppList.visibility = View.VISIBLE
|
||||
|
||||
}
|
||||
|
||||
//初始化表单
|
||||
private fun initForm() {
|
||||
AppDatabase.getInstance(requireContext()).ruleDao().get(ruleId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Rule> {
|
||||
override fun onSubscribe(d: Disposable) {}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
override fun onSuccess(rule: Rule) {
|
||||
Log.d(TAG, rule.senderList.toString())
|
||||
rule.senderList.forEach {
|
||||
senderId = it.id
|
||||
senderListSelected.add(it)
|
||||
}
|
||||
|
||||
if (isClone) {
|
||||
titleBar?.setSubTitle(getString(R.string.clone_rule))
|
||||
binding!!.btnDel.setText(R.string.discard)
|
||||
} else {
|
||||
titleBar?.setSubTitle(getString(R.string.edit_rule))
|
||||
}
|
||||
Log.d(TAG, rule.toString())
|
||||
|
||||
binding!!.rgSenderLogic.check(rule.getSenderLogicCheckId())
|
||||
binding!!.rgSimSlot.check(rule.getSimSlotCheckId())
|
||||
binding!!.rgFiled.check(rule.getFiledCheckId())
|
||||
val checkId = rule.getCheckCheckId()
|
||||
if (checkId == R.id.rb_is || checkId == R.id.rb_contain || checkId == R.id.rb_not_contain) {
|
||||
binding!!.rgCheck.check(checkId)
|
||||
} else {
|
||||
binding!!.rgCheck2.check(checkId)
|
||||
}
|
||||
binding!!.etValue.setText(rule.value)
|
||||
if (ruleType == "call" && rule.filed == FILED_CALL_TYPE) {
|
||||
callType = rule.value.toInt()
|
||||
callTypeIndex = callType - 1
|
||||
binding!!.spCallType.selectedIndex = callTypeIndex
|
||||
}
|
||||
binding!!.sbSmsTemplate.isChecked = !TextUtils.isEmpty(rule.smsTemplate.trim())
|
||||
binding!!.etSmsTemplate.setText(rule.smsTemplate.trim())
|
||||
binding!!.sbRegexReplace.isChecked = !TextUtils.isEmpty(rule.regexReplace.trim())
|
||||
binding!!.etRegexReplace.setText(rule.regexReplace.trim())
|
||||
binding!!.sbStatus.isChecked = rule.statusChecked
|
||||
silentPeriodStart = rule.silentPeriodStart
|
||||
silentPeriodEnd = rule.silentPeriodEnd
|
||||
//初始化发送通道下拉框
|
||||
initSenderSpinner()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//提交前检查表单
|
||||
private fun checkForm(): Rule {
|
||||
private fun checkSetting(): Rule {
|
||||
if (senderListSelected.isEmpty() || senderId == 0L) {
|
||||
throw Exception(getString(R.string.new_sender_first))
|
||||
}
|
||||
val filed = when (binding!!.rgFiled.checkedRadioButtonId) {
|
||||
R.id.rb_content -> FILED_MSG_CONTENT
|
||||
R.id.rb_phone -> FILED_PHONE_NUM
|
||||
R.id.rb_call_type -> FILED_CALL_TYPE
|
||||
R.id.rb_package_name -> FILED_PACKAGE_NAME
|
||||
R.id.rb_uid -> FILED_UID
|
||||
R.id.rb_inform_content -> FILED_INFORM_CONTENT
|
||||
R.id.rb_multi_match -> FILED_MULTI_MATCH
|
||||
else -> FILED_TRANSPOND_ALL
|
||||
}
|
||||
val check = when (kotlin.math.max(binding!!.rgCheck.checkedRadioButtonId, binding!!.rgCheck2.checkedRadioButtonId)) {
|
||||
R.id.rb_contain -> CHECK_CONTAIN
|
||||
R.id.rb_not_contain -> CHECK_NOT_CONTAIN
|
||||
R.id.rb_start_with -> CHECK_START_WITH
|
||||
R.id.rb_end_with -> CHECK_END_WITH
|
||||
R.id.rb_regex -> CHECK_REGEX
|
||||
else -> CHECK_IS
|
||||
}
|
||||
var value = binding!!.etValue.text.toString().trim()
|
||||
if (FILED_CALL_TYPE == filed) {
|
||||
value = callType.toString()
|
||||
if (callType !in 1..6) {
|
||||
throw Exception(getString(R.string.invalid_call_type))
|
||||
}
|
||||
} else if (FILED_TRANSPOND_ALL != filed && TextUtils.isEmpty(value)) {
|
||||
throw Exception(getString(R.string.invalid_match_value))
|
||||
}
|
||||
if (FILED_MULTI_MATCH == filed) {
|
||||
val lineError = checkMultiMatch(value)
|
||||
if (lineError > 0) {
|
||||
throw Exception(String.format(getString(R.string.invalid_multi_match), lineError))
|
||||
}
|
||||
}
|
||||
|
||||
val filed = FILED_TRANSPOND_ALL
|
||||
val check = CHECK_IS
|
||||
val value = ""
|
||||
val smsTemplate = binding!!.etSmsTemplate.text.toString().trim()
|
||||
val regexReplace = binding!!.etRegexReplace.text.toString().trim()
|
||||
val lineNum = checkRegexReplace(regexReplace)
|
||||
if (lineNum > 0) {
|
||||
throw Exception(String.format(getString(R.string.invalid_regex_replace), lineNum))
|
||||
}
|
||||
val simSlot = CHECK_SIM_SLOT_ALL
|
||||
val status = STATUS_ON
|
||||
|
||||
val senderLogic = when (binding!!.rgSenderLogic.checkedRadioButtonId) {
|
||||
R.id.rb_sender_logic_until_fail -> SENDER_LOGIC_UNTIL_FAIL
|
||||
@ -660,15 +438,6 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
else -> SENDER_LOGIC_ALL
|
||||
}
|
||||
|
||||
val simSlot = when (binding!!.rgSimSlot.checkedRadioButtonId) {
|
||||
R.id.rb_sim_slot_1 -> CHECK_SIM_SLOT_1
|
||||
R.id.rb_sim_slot_2 -> CHECK_SIM_SLOT_2
|
||||
else -> CHECK_SIM_SLOT_ALL
|
||||
}
|
||||
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
||||
//if (status == STATUS_OFF) {
|
||||
// throw Exception(getString(R.string.invalid_rule_status))
|
||||
//}
|
||||
return Rule(
|
||||
ruleId,
|
||||
ruleType,
|
||||
@ -688,23 +457,6 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
)
|
||||
}
|
||||
|
||||
//检查多重匹配规则是否正确
|
||||
private fun checkMultiMatch(ruleStr: String?): Int {
|
||||
if (TextUtils.isEmpty(ruleStr)) return 0
|
||||
|
||||
//Log.d(TAG, getString(R.string.regex_multi_match))
|
||||
val regex = Regex(pattern = getString(R.string.regex_multi_match))
|
||||
var lineNum = 1
|
||||
val lineArray = ruleStr?.split("\\n".toRegex())?.toTypedArray()
|
||||
for (line in lineArray!!) {
|
||||
Log.d(TAG, line)
|
||||
if (!line.matches(regex)) return lineNum
|
||||
lineNum++
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
//检查正则替换填写是否正确
|
||||
private fun checkRegexReplace(regexReplace: String?): Int {
|
||||
if (TextUtils.isEmpty(regexReplace)) return 0
|
||||
@ -719,109 +471,4 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun testRule(rule: Rule) {
|
||||
val dialogTest = View.inflate(requireContext(), R.layout.dialog_rule_test, null)
|
||||
val tvSimSlot = dialogTest.findViewById<TextView>(R.id.tv_sim_slot)
|
||||
val rgSimSlot = dialogTest.findViewById<RadioGroup>(R.id.rg_sim_slot)
|
||||
val tvFrom = dialogTest.findViewById<TextView>(R.id.tv_from)
|
||||
val etFrom = dialogTest.findViewById<EditText>(R.id.et_from)
|
||||
val tvTitle = dialogTest.findViewById<TextView>(R.id.tv_title)
|
||||
val etTitle = dialogTest.findViewById<EditText>(R.id.et_title)
|
||||
val tvContent = dialogTest.findViewById<TextView>(R.id.tv_content)
|
||||
val etContent = dialogTest.findViewById<EditText>(R.id.et_content)
|
||||
//通话类型
|
||||
val tvCallType = dialogTest.findViewById<TextView>(R.id.tv_call_type)
|
||||
val spCallType = dialogTest.findViewById<MaterialSpinner>(R.id.sp_call_type)
|
||||
var callTypeTest = callType
|
||||
var callTypeIndexTest = callTypeIndex
|
||||
|
||||
if ("app" == ruleType) {
|
||||
tvSimSlot.visibility = View.GONE
|
||||
rgSimSlot.visibility = View.GONE
|
||||
tvTitle.visibility = View.VISIBLE
|
||||
etTitle.visibility = View.VISIBLE
|
||||
tvFrom.setText(R.string.test_package_name)
|
||||
tvContent.setText(R.string.test_inform_content)
|
||||
tvCallType.visibility = View.GONE
|
||||
spCallType.visibility = View.GONE
|
||||
} else if ("call" == ruleType) {
|
||||
tvContent.visibility = View.GONE
|
||||
etContent.visibility = View.GONE
|
||||
tvCallType.visibility = View.VISIBLE
|
||||
spCallType.visibility = View.VISIBLE
|
||||
spCallType.setItems(CALL_TYPE_MAP.values.toList())
|
||||
spCallType.setOnItemSelectedListener { _: MaterialSpinner?, _: Int, _: Long, item: Any ->
|
||||
CALL_TYPE_MAP.forEach {
|
||||
if (it.value == item) callTypeTest = it.key.toInt()
|
||||
}
|
||||
}
|
||||
spCallType.setOnNothingSelectedListener {
|
||||
callTypeTest = callType
|
||||
callTypeIndexTest = callTypeIndex
|
||||
spCallType.selectedIndex = callTypeIndexTest
|
||||
}
|
||||
spCallType.selectedIndex = callTypeIndexTest
|
||||
}
|
||||
|
||||
MaterialDialog.Builder(requireContext()).iconRes(android.R.drawable.ic_dialog_email).title(R.string.rule_tester).customView(dialogTest, true).cancelable(false).autoDismiss(false).neutralText(R.string.action_back).neutralColor(ResUtils.getColors(R.color.darkGrey)).onNeutral { dialog: MaterialDialog?, _: DialogAction? ->
|
||||
dialog?.dismiss()
|
||||
}.positiveText(R.string.action_test).onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||
try {
|
||||
val simSlot = when (if (ruleType == "app") -1 else rgSimSlot.checkedRadioButtonId) {
|
||||
R.id.rb_sim_slot_1 -> 0
|
||||
R.id.rb_sim_slot_2 -> 1
|
||||
else -> -1
|
||||
}
|
||||
|
||||
val testSim = "SIM" + (simSlot + 1)
|
||||
val ruleSim: String = rule.simSlot
|
||||
if (ruleSim != "ALL" && ruleSim != testSim) {
|
||||
throw Exception(getString(R.string.card_slot_does_not_match))
|
||||
}
|
||||
|
||||
//获取卡槽信息
|
||||
val simInfo = when (simSlot) {
|
||||
0 -> "SIM1_" + SettingUtils.extraSim1
|
||||
1 -> "SIM2_" + SettingUtils.extraSim2
|
||||
else -> etTitle.text.toString()
|
||||
}
|
||||
val subId = when (simSlot) {
|
||||
0 -> SettingUtils.subidSim1
|
||||
1 -> SettingUtils.subidSim2
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val msg = StringBuilder()
|
||||
if (ruleType == "call") {
|
||||
val phoneNumber = etFrom.text.toString()
|
||||
val contacts = PhoneUtils.getContactByNumber(phoneNumber)
|
||||
val contactName = if (contacts.isNotEmpty()) contacts[0].name else ResUtils.getString(R.string.unknown_number)
|
||||
msg.append(ResUtils.getString(R.string.contact)).append(contactName).append("\n")
|
||||
msg.append(ResUtils.getString(R.string.mandatory_type))
|
||||
msg.append(CALL_TYPE_MAP[callType.toString()] ?: ResUtils.getString(R.string.unknown_call))
|
||||
} else {
|
||||
msg.append(etContent.text.toString())
|
||||
}
|
||||
|
||||
val msgInfo = MsgInfo(ruleType, etFrom.text.toString(), msg.toString(), Date(), simInfo, simSlot, subId, callTypeTest)
|
||||
if (!rule.checkMsg(msgInfo)) {
|
||||
throw Exception(getString(R.string.unmatched_rule))
|
||||
}
|
||||
|
||||
Thread {
|
||||
try {
|
||||
SendUtils.sendMsgSender(msgInfo, rule)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
if (Looper.myLooper() == null) Looper.prepare()
|
||||
XToastUtils.error(e.message.toString())
|
||||
Looper.loop()
|
||||
}
|
||||
}.start()
|
||||
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString())
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import com.idormy.sms.forwarder.utils.EVENT_KEY_PHONE_NUMBERS
|
||||
import com.idormy.sms.forwarder.utils.EVENT_KEY_SIM_SLOT
|
||||
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.PhoneUtils
|
||||
@ -191,6 +192,7 @@ class SendSmsFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View
|
||||
R.id.btn_save -> {
|
||||
val settingVo = checkSetting()
|
||||
val intent = Intent()
|
||||
intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, description)
|
||||
intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo))
|
||||
setFragmentResult(TASK_ACTION_SENDSMS, intent)
|
||||
popToBack()
|
||||
|
@ -10,9 +10,14 @@ import androidx.work.WorkerParameters
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.database.entity.Rule
|
||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||
import com.idormy.sms.forwarder.entity.task.SmsSetting
|
||||
import com.idormy.sms.forwarder.utils.PhoneUtils
|
||||
import com.idormy.sms.forwarder.utils.SendUtils
|
||||
import com.idormy.sms.forwarder.utils.TASK_ACTION_NOTIFICATION
|
||||
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
|
||||
import com.idormy.sms.forwarder.utils.Worker
|
||||
import com.xuexiang.xui.utils.ResUtils
|
||||
import com.xuexiang.xutil.XUtil
|
||||
|
||||
@ -22,14 +27,16 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
|
||||
private val TAG: String = ActionWorker::class.java.simpleName
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
val taskId = inputData.getLong("taskId", -1L)
|
||||
val actionType = inputData.getInt("actionType", -1)
|
||||
val actionSetting = inputData.getString("actionSetting")
|
||||
Log.d(TAG, "taskId: $taskId, actionSetting: $actionSetting")
|
||||
val taskId = inputData.getLong(Worker.taskId, -1L)
|
||||
val actionType = inputData.getInt(Worker.actionType, -1)
|
||||
val actionSetting = inputData.getString(Worker.actionSetting)
|
||||
val msgInfoJson = inputData.getString(Worker.sendMsgInfo)
|
||||
Log.d(TAG, "taskId: $taskId, actionType: $actionType, actionSetting: $actionSetting, msgInfoJson: $msgInfoJson")
|
||||
if (taskId == -1L || actionSetting == null) {
|
||||
Log.d(TAG, "taskId is -1L or actionSetting is null")
|
||||
return Result.failure()
|
||||
}
|
||||
val msgInfo = Gson().fromJson(msgInfoJson, MsgInfo::class.java)
|
||||
|
||||
when (actionType) {
|
||||
TASK_ACTION_SENDSMS -> {
|
||||
@ -59,6 +66,18 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
TASK_ACTION_NOTIFICATION -> {
|
||||
return try {
|
||||
val settingVo = Gson().fromJson(actionSetting, Rule::class.java)
|
||||
//自动任务的不需要吐司或者更新日志,特殊处理 logId = -1,msgId = -1
|
||||
SendUtils.sendMsgSender(msgInfo, settingVo, 0, -1L, -1L)
|
||||
Result.success()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Result.failure()
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
Log.d(TAG, "任务$taskId:action.type is $actionType")
|
||||
return Result.failure()
|
||||
|
@ -10,8 +10,10 @@ import androidx.work.WorkerParameters
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.database.AppDatabase
|
||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||
import com.idormy.sms.forwarder.utils.Worker
|
||||
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
||||
import gatewayapps.crondroid.CronExpression
|
||||
import java.util.Date
|
||||
@ -80,6 +82,9 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
//组装消息体
|
||||
val msgInfo = MsgInfo("task", task.name, task.description, Date(), task.name)
|
||||
|
||||
// TODO: 执行具体任务
|
||||
val actionList = Gson().fromJson(task.actions, Array<TaskSetting>::class.java).toMutableList()
|
||||
if (actionList.isEmpty()) {
|
||||
@ -88,9 +93,10 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
||||
}
|
||||
for (action in actionList) {
|
||||
val actionData = Data.Builder()
|
||||
.putLong("taskId", task.id)
|
||||
.putInt("actionType", action.type)
|
||||
.putString("actionSetting", action.setting)
|
||||
.putLong(Worker.taskId, task.id)
|
||||
.putInt(Worker.actionType, action.type)
|
||||
.putString(Worker.actionSetting, action.setting)
|
||||
.putString(Worker.sendMsgInfo, Gson().toJson(msgInfo))
|
||||
.build()
|
||||
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
|
||||
WorkManager.getInstance().enqueue(actionRequest)
|
||||
|
@ -42,6 +42,9 @@
|
||||
android:id="@+id/tv_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start"
|
||||
android:maxLines="2"
|
||||
android:text="@string/add_action_tips"
|
||||
android:textSize="12sp" />
|
||||
|
||||
|
355
app/src/main/res/layout/fragment_tasks_action_notification.xml
Normal file
355
app/src/main/res/layout/fragment_tasks_action_notification.xml
Normal file
@ -0,0 +1,355 @@
|
||||
<?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:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
style="@style/ruleBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/select_sender"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.xuexiang.xui.widget.spinner.editspinner.EditSpinner
|
||||
android:id="@+id/sp_sender"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
app:es_hint="@string/choose_sender"
|
||||
app:es_maxLength="20"
|
||||
app:es_maxLine="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/xui_config_color_separator_light" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_Senders"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_sender_logic"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sender_logic"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_sender_logic"
|
||||
style="@style/rg_style"
|
||||
android:layout_marginStart="5dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_sender_logic_all"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:checked="true"
|
||||
android:text="@string/sender_logic_all" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_sender_logic_until_fail"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/sender_logic_until_fail" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_sender_logic_until_success"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/sender_logic_until_success" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/ruleBarStyleWithSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="3"
|
||||
android:text="@string/enable_custom_templates"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||
android:id="@+id/sb_sms_template"
|
||||
style="@style/SwitchButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="DuplicateSpeakableTextCheck,TouchTargetSizeCheck" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_sms_template"
|
||||
style="@style/ruleBarStyleNoMarginTop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enable_custom_templates_tips"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_sms_template"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
app:met_clearButton="true" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_sender"
|
||||
style="@style/insertButtonStyle"
|
||||
android:text="@string/insert_sender" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_content"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_content" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_extra"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_extra" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_sender_app"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_sender_app" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_uid"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_uid" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_title_app"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_title_app" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_content_app"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_content_app" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_time"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_time" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/bt_insert_device_name"
|
||||
style="@style/insertButtonStyle"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/insert_device_name" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/ruleBarStyleWithSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="3"
|
||||
android:text="@string/enable_regex_replace"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||
android:id="@+id/sb_regex_replace"
|
||||
style="@style/SwitchButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="TouchTargetSizeCheck" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_regex_replace"
|
||||
style="@style/ruleBarStyleNoMarginTop"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enable_regex_replace_tips"
|
||||
android:textSize="11sp" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_regex_replace"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine"
|
||||
app:met_clearButton="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_silent_period"
|
||||
style="@style/ruleBarStyleWithSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="15dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="180dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="TextSizeCheck">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/silent_time_period"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/silent_time_period_tips"
|
||||
android:textSize="9sp"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_silent_period"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/btn_silent_period"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:text="@string/select"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="10sp"
|
||||
app:sb_color_unpressed="@color/colorPrimary"
|
||||
app:sb_ripple_color="@color/white"
|
||||
app:sb_ripple_duration="500"
|
||||
app:sb_shape_type="rectangle"
|
||||
tools:ignore="SmallSp,TextContrastCheck,TouchTargetSizeCheck" />
|
||||
|
||||
</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"
|
||||
android:drawableStart="@drawable/icon_delete"
|
||||
android:paddingStart="15dp"
|
||||
android:text="@string/del"
|
||||
android:textSize="11sp"
|
||||
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||
|
||||
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||
android:id="@+id/btn_save"
|
||||
style="@style/SuperButton.Blue.Icon"
|
||||
android:layout_marginStart="10dp"
|
||||
android:drawableStart="@drawable/icon_save"
|
||||
android:paddingStart="15dp"
|
||||
android:text="@string/save"
|
||||
android:textSize="11sp"
|
||||
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||
|
||||
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||
android:id="@+id/btn_test"
|
||||
style="@style/SuperButton.Green.Icon"
|
||||
android:layout_marginStart="10dp"
|
||||
android:drawableStart="@drawable/icon_test"
|
||||
android:paddingStart="15dp"
|
||||
android:text="@string/test"
|
||||
android:textSize="11sp"
|
||||
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
Loading…
x
Reference in New Issue
Block a user