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

This commit is contained in:
pppscn 2023-12-22 22:46:29 +08:00
parent be36ada07f
commit 28f24ef73b
74 changed files with 1350 additions and 1014 deletions

View File

@ -0,0 +1,49 @@
package com.idormy.sms.forwarder.adapter.spinner
import android.graphics.drawable.Drawable
@Suppress("unused")
class FrpcAdapterItem(
var title: CharSequence,
var icon: Drawable? = null,
var uid: String = "",
var autorun: Int? = 1
) {
fun setTitle(title: CharSequence): FrpcAdapterItem {
this.title = title
return this
}
fun setIcon(icon: Drawable?): FrpcAdapterItem {
this.icon = icon
return this
}
fun setUid(uid: String): FrpcAdapterItem {
this.uid = uid
return this
}
fun setAutorun(autorun: Int): FrpcAdapterItem {
this.autorun = autorun
return this
}
// 注意:自定义实体需要重写对象的 toString 方法
override fun toString(): String {
return title.toString()
}
companion object {
@JvmStatic
fun of(title: CharSequence): FrpcAdapterItem {
return FrpcAdapterItem(title)
}
@JvmStatic
fun arrayOf(vararg titles: CharSequence): Array<FrpcAdapterItem> {
return titles.map { FrpcAdapterItem(it) }.toTypedArray()
}
}
}

View File

@ -0,0 +1,167 @@
package com.idormy.sms.forwarder.adapter.spinner
import android.annotation.SuppressLint
import android.os.Build
import android.text.Html
import android.text.TextUtils
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.STATUS_ON
import com.xuexiang.xui.utils.CollectionUtils
import com.xuexiang.xui.widget.spinner.editspinner.BaseEditSpinnerAdapter
import com.xuexiang.xui.widget.spinner.editspinner.EditSpinnerFilter
import com.xuexiang.xutil.resource.ResUtils.getDrawable
@Suppress("unused", "NAME_SHADOWING", "DEPRECATION")
class FrpcSpinnerAdapter<T> : BaseEditSpinnerAdapter<T>, EditSpinnerFilter {
/**
* 选项的文字颜色
*/
private var mTextColor = 0
/**
* 选项的文字大小
*/
private var mTextSize = 0f
/**
* 背景颜色
*/
private var mBackgroundSelector = 0
/**
* 过滤关键词的选中颜色
*/
private var mFilterColor = "#F15C58"
private var mIsFilterKey = false
/**
* 构造方法
*
* @param data 选项数据
*/
constructor(data: List<T>?) : super(data)
/**
* 构造方法
*
* @param data 选项数据
*/
constructor(data: Array<T>?) : super(data)
override fun getEditSpinnerFilter(): EditSpinnerFilter {
return this
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
var convertView = convertView
val holder: ViewHolder
if (convertView == null) {
convertView = LayoutInflater.from(parent.context).inflate(R.layout.item_spinner_with_icon, parent, false)
holder = ViewHolder(convertView, mTextColor, mTextSize, mBackgroundSelector)
convertView.tag = holder
} else {
holder = convertView.tag as ViewHolder
}
val item = CollectionUtils.getListItem(mDataSource, mIndexs[position]) as FrpcAdapterItem
holder.iconView.setImageDrawable(item.icon)
holder.statusView.setImageDrawable(
getDrawable(
when (item.autorun) {
STATUS_ON -> R.drawable.ic_autorun
else -> R.drawable.ic_manual
}
)
)
//holder.titleView.text = Html.fromHtml(item.toString())
holder.titleView.text = Html.fromHtml(getItem(position))
return convertView
}
override fun onFilter(keyword: String): Boolean {
mDisplayData.clear()
Log.d("FrpcSpinnerAdapter", "keyword = $keyword")
Log.d("FrpcSpinnerAdapter", "mIndexs.indices = ${mIndexs.indices}")
if (TextUtils.isEmpty(keyword)) {
initDisplayData(mDataSource)
for (i in mIndexs.indices) {
mIndexs[i] = i
}
} else {
try {
for (i in mDataSource.indices) {
if (getDataSourceString(i).contains(keyword, ignoreCase = true)) {
mIndexs[mDisplayData.size] = i
if (mIsFilterKey) {
mDisplayData.add(getDataSourceString(i).replaceFirst(keyword.toRegex(), "<font color=\"$mFilterColor\">$keyword</font>"))
} else {
mDisplayData.add(getDataSourceString(i))
}
}
}
} catch (e: Exception) {
e.printStackTrace()
Log.e("FrpcSpinnerAdapter", "onFilter error: ${e.message}")
}
}
Log.d("FrpcSpinnerAdapter", "mDisplayData = $mDisplayData")
notifyDataSetChanged()
return mDisplayData.size > 0
}
fun setTextColor(@ColorInt textColor: Int): FrpcSpinnerAdapter<*> {
mTextColor = textColor
return this
}
fun setTextSize(textSize: Float): FrpcSpinnerAdapter<*> {
mTextSize = textSize
return this
}
fun setBackgroundSelector(@DrawableRes backgroundSelector: Int): FrpcSpinnerAdapter<*> {
mBackgroundSelector = backgroundSelector
return this
}
fun setFilterColor(filterColor: String): FrpcSpinnerAdapter<*> {
mFilterColor = filterColor
return this
}
fun setIsFilterKey(isFilterKey: Boolean): FrpcSpinnerAdapter<*> {
mIsFilterKey = isFilterKey
return this
}
@SuppressLint("ObsoleteSdkInt")
private class ViewHolder(convertView: View, @ColorInt textColor: Int, textSize: Float, @DrawableRes backgroundSelector: Int) {
val iconView: ImageView = convertView.findViewById(R.id.iv_icon)
val statusView: ImageView = convertView.findViewById(R.id.iv_status)
val titleView: TextView = convertView.findViewById(R.id.tv_title)
init {
if (textColor > 0) titleView.setTextColor(textColor)
if (textSize > 0F) titleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
if (backgroundSelector != 0) titleView.setBackgroundResource(backgroundSelector)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val config = convertView.resources.configuration
if (config.layoutDirection == View.LAYOUT_DIRECTION_RTL) {
titleView.textDirection = View.TEXT_DIRECTION_RTL
}
}
}
}
fun getItemSource(position: Int): T {
return mDataSource[mIndexs[position]]
}
}

View File

@ -36,10 +36,12 @@ class RuleAdapterItem(
} }
companion object { companion object {
@JvmStatic
fun of(title: CharSequence): RuleAdapterItem { fun of(title: CharSequence): RuleAdapterItem {
return RuleAdapterItem(title) return RuleAdapterItem(title)
} }
@JvmStatic
fun arrayOf(vararg titles: CharSequence): Array<RuleAdapterItem> { fun arrayOf(vararg titles: CharSequence): Array<RuleAdapterItem> {
return titles.map { RuleAdapterItem(it) }.toTypedArray() return titles.map { RuleAdapterItem(it) }.toTypedArray()
} }

View File

@ -24,6 +24,9 @@ interface FrpcDao {
@Query("DELETE FROM Frpc where uid=:uid") @Query("DELETE FROM Frpc where uid=:uid")
fun delete(uid: String) fun delete(uid: String)
@Query("DELETE FROM Frpc")
fun deleteAll()
@Update @Update
fun update(frpc: Frpc) fun update(frpc: Frpc)
@ -43,10 +46,11 @@ interface FrpcDao {
@Query("SELECT * FROM Frpc ORDER BY time DESC") @Query("SELECT * FROM Frpc ORDER BY time DESC")
fun pagingSource(): PagingSource<Int, Frpc> fun pagingSource(): PagingSource<Int, Frpc>
@Query("SELECT * FROM Frpc ORDER BY time DESC")
fun getAll(): Single<List<Frpc>>
@Transaction @Transaction
@RawQuery(observedEntities = [Frpc::class]) @RawQuery(observedEntities = [Frpc::class])
fun getAllRaw(query: SupportSQLiteQuery): List<Frpc> fun getAllRaw(query: SupportSQLiteQuery): List<Frpc>
@Query("DELETE FROM Frpc")
fun deleteAll()
} }

View File

@ -34,6 +34,16 @@ interface LogsDao {
@Update @Update
fun update(logs: Logs): Completable fun update(logs: Logs): Completable
@Query(
"UPDATE Logs SET forward_status=:status" +
",forward_response=CASE WHEN (trim(forward_response) = '' or trim(forward_response) = 'ok')" +
" THEN :response" +
" ELSE forward_response || '\n--------------------\n' || :response" +
" END" +
" where id=:id"
)
fun updateStatus(id: Long, status: Int, response: String): Int
@Query("SELECT * FROM Logs where id=:id") @Query("SELECT * FROM Logs where id=:id")
fun get(id: Long): Single<Logs> fun get(id: Long): Single<Logs>
@ -48,13 +58,4 @@ 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>
@Query(
"UPDATE Logs SET forward_status=:status" +
",forward_response=CASE WHEN (trim(forward_response) = '' or trim(forward_response) = 'ok')" +
" THEN :response" +
" ELSE forward_response || '\n--------------------\n' || :response" +
" END" +
" where id=:id"
)
fun updateStatus(id: Long, status: Int, response: String): Int
} }

View File

@ -31,6 +31,9 @@ interface RuleDao {
@Update @Update
fun update(rule: Rule) fun update(rule: Rule)
@Query("UPDATE Rule SET status=:status WHERE id IN (:ids)")
fun updateStatusByIds(ids: List<Long>, status: Int)
@Query("SELECT * FROM Rule where id=:id") @Query("SELECT * FROM Rule where id=:id")
fun get(id: Long): Single<Rule> fun get(id: Long): Single<Rule>
@ -54,4 +57,5 @@ interface RuleDao {
@Query("SELECT * FROM Rule ORDER BY id DESC") @Query("SELECT * FROM Rule ORDER BY id DESC")
fun getAll(): Single<List<Rule>> fun getAll(): Single<List<Rule>>
} }

View File

@ -26,9 +26,15 @@ interface SenderDao {
@Query("DELETE FROM Sender where id=:id") @Query("DELETE FROM Sender where id=:id")
fun delete(id: Long) fun delete(id: Long)
@Query("DELETE FROM Sender")
fun deleteAll()
@Update @Update
fun update(sender: Sender) fun update(sender: Sender)
@Query("UPDATE Sender SET status=:status WHERE id IN (:ids)")
fun updateStatusByIds(ids: List<Long>, status: Int)
@Query("SELECT * FROM Sender where id=:id") @Query("SELECT * FROM Sender where id=:id")
fun get(id: Long): Single<Sender> fun get(id: Long): Single<Sender>
@ -54,6 +60,4 @@ interface SenderDao {
@Query("SELECT COUNT(id) FROM Sender WHERE status = 1") @Query("SELECT COUNT(id) FROM Sender WHERE status = 1")
fun getOnCount(): Flow<Long> fun getOnCount(): Flow<Long>
@Query("DELETE FROM Sender")
fun deleteAll()
} }

View File

@ -3,6 +3,7 @@ package com.idormy.sms.forwarder.database.dao
import androidx.paging.PagingSource import androidx.paging.PagingSource
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.RawQuery import androidx.room.RawQuery
import androidx.room.Transaction import androidx.room.Transaction
@ -15,6 +16,24 @@ import java.util.Date
@Dao @Dao
interface TaskDao { interface TaskDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(task: Task): Long
@Query("DELETE FROM Task WHERE id = :taskId")
fun delete(taskId: Long)
@Query("DELETE FROM Task")
fun deleteAll()
@Update
fun update(task: Task)
@Query("UPDATE Task SET last_exec_time = :lastExecTime, next_exec_time = :nextExecTime, status = :status WHERE id = :taskId")
fun updateExecTime(taskId: Long, lastExecTime: Date, nextExecTime: Date, status: Int)
@Query("UPDATE Task SET status = :status WHERE id = :id")
fun updateStatus(id: Long, status: Int)
@Query("SELECT * FROM Task where id=:id") @Query("SELECT * FROM Task where id=:id")
fun get(id: Long): Single<Task> fun get(id: Long): Single<Task>
@ -34,22 +53,4 @@ interface TaskDao {
@Query("SELECT * FROM Task WHERE status = 1 AND type = :taskType") @Query("SELECT * FROM Task WHERE status = 1 AND type = :taskType")
fun getByType(taskType: Int): List<Task> fun getByType(taskType: Int): List<Task>
@Insert
fun insert(task: Task)
@Update
fun update(task: Task)
@Query("UPDATE Task SET last_exec_time = :lastExecTime, next_exec_time = :nextExecTime, status = :status WHERE id = :taskId")
fun updateExecTime(taskId: Long, lastExecTime: Date, nextExecTime: Date, status: Int)
@Query("DELETE FROM Task WHERE id = :taskId")
fun delete(taskId: Long)
@Query("DELETE FROM Task")
fun deleteAll()
@Query("UPDATE Task SET status = :status WHERE id = :id")
fun updateStatus(id: Long, status: Int)
} }

View File

@ -22,6 +22,9 @@ data class Frpc(
@Ignore var connecting: Boolean = false, @Ignore var connecting: Boolean = false,
) : Parcelable { ) : Parcelable {
val imageId: Int
get() = R.drawable.ic_menu_frpc
val autorunImageId: Int val autorunImageId: Int
get() = when (autorun) { get() = when (autorun) {
STATUS_ON -> R.drawable.ic_autorun STATUS_ON -> R.drawable.ic_autorun

View File

@ -4,34 +4,33 @@ import androidx.annotation.WorkerThread
import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.FrpcDao import com.idormy.sms.forwarder.database.dao.FrpcDao
import com.idormy.sms.forwarder.database.entity.Frpc import com.idormy.sms.forwarder.database.entity.Frpc
import io.reactivex.Single
class FrpcRepository( class FrpcRepository(private val frpcDao: FrpcDao) {
private val frpcDao: FrpcDao,
) {
@WorkerThread @WorkerThread
fun insert(frpc: Frpc) { fun insert(frpc: Frpc) = frpcDao.insert(frpc)
frpcDao.insert(frpc)
}
@WorkerThread @WorkerThread
fun delete(uid: String) { fun delete(uid: String) = frpcDao.delete(uid)
frpcDao.delete(uid)
}
@WorkerThread fun deleteAll() = frpcDao.deleteAll()
fun get(uid: String) = frpcDao.get(uid)
@WorkerThread @WorkerThread
fun update(frpc: Frpc) = frpcDao.update(frpc) fun update(frpc: Frpc) = frpcDao.update(frpc)
@WorkerThread
fun get(uid: String) = frpcDao.get(uid)
fun getAllNonCache(): List<Frpc> { fun getAllNonCache(): List<Frpc> {
val query = SimpleSQLiteQuery("SELECT * FROM Frpc ORDER BY time DESC") val query = SimpleSQLiteQuery("SELECT * FROM Frpc ORDER BY time DESC")
return frpcDao.getAllRaw(query) return frpcDao.getAllRaw(query)
} }
fun deleteAll() { fun getAll(): Single<List<Frpc>> = frpcDao.getAll()
frpcDao.deleteAll()
} fun getAutorun(): List<Frpc> = frpcDao.getAutorun()
fun getByUids(uids: List<String>): List<Frpc> = frpcDao.getByUids(uids)
} }

View File

@ -6,26 +6,17 @@ import com.idormy.sms.forwarder.database.entity.Logs
class LogsRepository(private val logsDao: LogsDao) { class LogsRepository(private val logsDao: LogsDao) {
@WorkerThread
fun delete(id: Long) {
logsDao.delete(id)
}
//@WorkerThread
//fun deleteTimeAgo(time: Long) {
// logsDao.deleteTimeAgo(time)
//}
@WorkerThread @WorkerThread
suspend fun insert(logs: Logs): Long = logsDao.insert(logs) suspend fun insert(logs: Logs): Long = logsDao.insert(logs)
@WorkerThread @WorkerThread
fun updateStatus(id: Long, status: Int, response: String): Int = fun delete(id: Long) = logsDao.delete(id)
logsDao.updateStatus(id, status, response)
fun deleteAll() = logsDao.deleteAll()
@WorkerThread
fun updateStatus(id: Long, status: Int, response: String): Int = logsDao.updateStatus(id, status, response)
fun getOne(id: Long) = logsDao.getOne(id) fun getOne(id: Long) = logsDao.getOne(id)
fun deleteAll() {
logsDao.deleteAll()
}
} }

View File

@ -6,21 +6,17 @@ import com.idormy.sms.forwarder.database.entity.Msg
class MsgRepository(private val msgDao: MsgDao) { class MsgRepository(private val msgDao: MsgDao) {
@WorkerThread
fun delete(id: Long) {
msgDao.delete(id)
}
@WorkerThread
fun deleteTimeAgo(time: Long) {
msgDao.deleteTimeAgo(time)
}
@WorkerThread @WorkerThread
suspend fun insert(msg: Msg): Long = msgDao.insert(msg) suspend fun insert(msg: Msg): Long = msgDao.insert(msg)
fun deleteAll() { @WorkerThread
msgDao.deleteAll() fun delete(id: Long) = msgDao.delete(id)
}
fun deleteAll() = msgDao.deleteAll()
fun deleteAll(type: String) = msgDao.deleteAll(type)
@WorkerThread
fun deleteTimeAgo(time: Long) = msgDao.deleteTimeAgo(time)
} }

View File

@ -4,17 +4,14 @@ import androidx.annotation.WorkerThread
import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.RuleDao import com.idormy.sms.forwarder.database.dao.RuleDao
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import io.reactivex.Single
class RuleRepository( class RuleRepository(private val ruleDao: RuleDao) {
private val ruleDao: RuleDao,
) {
private var listener: Listener? = null private var listener: Listener? = null
@WorkerThread @WorkerThread
fun insert(rule: Rule) { fun insert(rule: Rule) = ruleDao.insert(rule)
ruleDao.insert(rule)
}
@WorkerThread @WorkerThread
fun delete(id: Long) { fun delete(id: Long) {
@ -22,23 +19,26 @@ class RuleRepository(
ruleDao.delete(id) ruleDao.delete(id)
} }
fun deleteAll() = ruleDao.deleteAll()
@WorkerThread
fun update(rule: Rule) = ruleDao.update(rule)
fun updateStatusByIds(ids: List<Long>, status: Int) = ruleDao.updateStatusByIds(ids, status)
@WorkerThread @WorkerThread
fun get(id: Long) = ruleDao.get(id) fun get(id: Long) = ruleDao.get(id)
@WorkerThread @WorkerThread
fun getOne(id: Long) = ruleDao.getOne(id) fun getOne(id: Long) = ruleDao.getOne(id)
fun getRuleList(type: String, status: Int, simSlot: String) = ruleDao.getRuleList(type, status, simSlot) fun getAll(): Single<List<Rule>> = ruleDao.getAll()
@WorkerThread
fun update(rule: Rule) = ruleDao.update(rule)
fun getAllNonCache(): List<Rule> { fun getAllNonCache(): List<Rule> {
val query = SimpleSQLiteQuery("SELECT * FROM Rule ORDER BY id ASC") val query = SimpleSQLiteQuery("SELECT * FROM Rule ORDER BY id ASC")
return ruleDao.getAllRaw(query) return ruleDao.getAllRaw(query)
} }
fun deleteAll() { fun getRuleList(type: String, status: Int, simSlot: String) = ruleDao.getRuleList(type, status, simSlot)
ruleDao.deleteAll()
}
} }

View File

@ -4,6 +4,7 @@ import androidx.annotation.WorkerThread
import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.SenderDao import com.idormy.sms.forwarder.database.dao.SenderDao
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import io.reactivex.Single
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
class SenderRepository(private val senderDao: SenderDao) { class SenderRepository(private val senderDao: SenderDao) {
@ -19,22 +20,25 @@ class SenderRepository(private val senderDao: SenderDao) {
senderDao.delete(id) senderDao.delete(id)
} }
fun deleteAll() = senderDao.deleteAll()
fun update(sender: Sender) = senderDao.update(sender)
fun updateStatusByIds(ids: List<Long>, status: Int) = senderDao.updateStatusByIds(ids, status)
fun get(id: Long) = senderDao.get(id) fun get(id: Long) = senderDao.get(id)
fun getOne(id: Long) = senderDao.getOne(id) fun getOne(id: Long) = senderDao.getOne(id)
fun getByIds(ids: List<Long>) = senderDao.getByIds(ids) fun getByIds(ids: List<Long>) = senderDao.getByIds(ids)
fun update(sender: Sender) = senderDao.update(sender)
fun getAllNonCache(): List<Sender> { fun getAllNonCache(): List<Sender> {
val query = SimpleSQLiteQuery("SELECT * FROM Sender ORDER BY id ASC") val query = SimpleSQLiteQuery("SELECT * FROM Sender ORDER BY id ASC")
return senderDao.getAllRaw(query) return senderDao.getAllRaw(query)
} }
fun getAll(): Single<List<Sender>> = senderDao.getAll()
val count: Flow<Long> = senderDao.getOnCount() val count: Flow<Long> = senderDao.getOnCount()
fun deleteAll() {
senderDao.deleteAll()
}
} }

View File

@ -4,27 +4,31 @@ import androidx.annotation.WorkerThread
import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SimpleSQLiteQuery
import com.idormy.sms.forwarder.database.dao.TaskDao import com.idormy.sms.forwarder.database.dao.TaskDao
import com.idormy.sms.forwarder.database.entity.Task import com.idormy.sms.forwarder.database.entity.Task
import java.util.Date
class TaskRepository(private val taskDao: TaskDao) { class TaskRepository(private val taskDao: TaskDao) {
@WorkerThread @WorkerThread
fun insert(task: Task) = taskDao.insert(task) fun insert(task: Task): Long = taskDao.insert(task)
suspend fun getOne(id: Long) = taskDao.getOne(id) @WorkerThread
fun delete(id: Long) = taskDao.delete(id)
fun deleteAll() = taskDao.deleteAll()
fun update(task: Task) = taskDao.update(task) fun update(task: Task) = taskDao.update(task)
fun updateExecTime(taskId: Long, lastExecTime: Date, nextExecTime: Date, status: Int) = taskDao.updateExecTime(taskId, lastExecTime, nextExecTime, status)
fun get(id: Long) = taskDao.get(id)
suspend fun getOne(id: Long) = taskDao.getOne(id)
fun getAllNonCache(): List<Task> { fun getAllNonCache(): List<Task> {
val query = SimpleSQLiteQuery("SELECT * FROM Task ORDER BY id ASC") val query = SimpleSQLiteQuery("SELECT * FROM Task ORDER BY id ASC")
return taskDao.getAllRaw(query) return taskDao.getAllRaw(query)
} }
@WorkerThread fun getByType(type: Int): List<Task> = taskDao.getByType(type)
fun delete(id: Long) {
taskDao.delete(id)
}
fun deleteAll() {
taskDao.deleteAll()
}
} }

View File

@ -26,7 +26,7 @@ class TaskViewModel(private val dao: TaskDao) : ViewModel() {
initialLoadSize = 10 initialLoadSize = 10
) )
) { ) {
//TODO:根据条件查询,不使用 //TODO:根据条件查询,不使用
//dao.pagingSource(type) //dao.pagingSource(type)
if (type == "mine") dao.pagingSourceMine() else dao.pagingSourceFixed() if (type == "mine") dao.pagingSourceMine() else dao.pagingSourceFixed()
}.flow.cachedIn(viewModelScope) }.flow.cachedIn(viewModelScope)

View File

@ -5,6 +5,6 @@ import java.io.Serializable
data class RuleSetting( data class RuleSetting(
var description: String = "", //描述 var description: String = "", //描述
var status: String = "enable", //状态: enable=启用disable=禁 var status: Int = 1, //状态0-禁用1-启
var ruleList: List<Rule>, //转发规则列表 var ruleList: List<Rule>, //转发规则列表
) : Serializable ) : Serializable

View File

@ -5,6 +5,6 @@ import java.io.Serializable
data class SenderSetting( data class SenderSetting(
var description: String = "", //描述 var description: String = "", //描述
var status: String = "enable", //状态: enable=启用disable=禁 var status: Int = 1, //状态0-禁用1-启
var senderList: List<Sender>, //发送通道列表 var senderList: List<Sender>, //发送通道列表
) : Serializable ) : Serializable

View File

@ -13,7 +13,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.adapter.MsgPagingAdapter import com.idormy.sms.forwarder.adapter.MsgPagingAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.LogsDetail import com.idormy.sms.forwarder.database.entity.LogsDetail
import com.idormy.sms.forwarder.database.entity.MsgAndLogs import com.idormy.sms.forwarder.database.entity.MsgAndLogs
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
@ -78,9 +78,7 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
.positiveText(R.string.lab_yes) .positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no) .negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? -> .onPositive { _: MaterialDialog?, _: DialogAction? ->
AppDatabase.getInstance(requireContext()) Core.msg.deleteAll(currentType)
.msgDao()
.deleteAll(currentType)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(object : CompletableObserver { .subscribe(object : CompletableObserver {

View File

@ -16,7 +16,7 @@ import com.idormy.sms.forwarder.adapter.spinner.AppListSpinnerAdapter
import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
@ -405,7 +405,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
//免打扰(禁用转发)时间段 //免打扰(禁用转发)时间段
binding!!.tvSilentPeriod.text = mTimeOption[silentPeriodStart] + " ~ " + mTimeOption[silentPeriodEnd] binding!!.tvSilentPeriod.text = mTimeOption[silentPeriodStart] + " ~ " + mTimeOption[silentPeriodEnd]
AppDatabase.getInstance(requireContext()).senderDao().getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> { Core.sender.getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
@ -568,7 +568,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
//初始化表单 //初始化表单
private fun initForm() { private fun initForm() {
AppDatabase.getInstance(requireContext()).ruleDao().get(ruleId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Rule> { Core.rule.get(ruleId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Rule> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {

View File

@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.* import android.widget.*
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -18,10 +17,8 @@ import com.idormy.sms.forwarder.adapter.ItemMoveCallback
import com.idormy.sms.forwarder.adapter.TaskSettingAdapter import com.idormy.sms.forwarder.adapter.TaskSettingAdapter
import com.idormy.sms.forwarder.adapter.WidgetItemAdapter import com.idormy.sms.forwarder.adapter.WidgetItemAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Task import com.idormy.sms.forwarder.database.entity.Task
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.TaskViewModel
import com.idormy.sms.forwarder.databinding.FragmentTasksEditBinding import com.idormy.sms.forwarder.databinding.FragmentTasksEditBinding
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.condition.CronSetting import com.idormy.sms.forwarder.entity.condition.CronSetting
@ -59,7 +56,6 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
private val TAG: String = TasksEditFragment::class.java.simpleName private val TAG: String = TasksEditFragment::class.java.simpleName
private val that = this private val that = this
private var titleBar: TitleBar? = null private var titleBar: TitleBar? = null
private val viewModel by viewModels<TaskViewModel> { BaseViewModelFactory(context) }
private val dialog: BottomSheetDialog by lazy { BottomSheetDialog(requireContext()) } private val dialog: BottomSheetDialog by lazy { BottomSheetDialog(requireContext()) }
@JvmField @JvmField
@ -345,10 +341,14 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
val taskNew = checkForm() val taskNew = checkForm()
if (isClone) taskNew.id = 0 if (isClone) taskNew.id = 0
Log.d(TAG, taskNew.toString()) Log.d(TAG, taskNew.toString())
//保存任务
if (taskNew.id > 0) {
Core.task.update(taskNew)
} else {
taskNew.id = Core.task.insert(taskNew)
}
//应用任务 //应用任务
applyTask(taskNew) applyTask(taskNew)
//保存任务
viewModel.insertOrUpdate(taskNew)
XToastUtils.success(R.string.tipSaveSuccess) XToastUtils.success(R.string.tipSaveSuccess)
popToBack() popToBack()
return return
@ -363,7 +363,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
//初始化表单 //初始化表单
private fun initForm() { private fun initForm() {
AppDatabase.getInstance(requireContext()).taskDao().get(taskId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Task> { Core.task.get(taskId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Task> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
@ -464,6 +464,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
when (task.type) { when (task.type) {
//定时任务 //定时任务
TASK_CONDITION_CRON -> { TASK_CONDITION_CRON -> {
if (task.id <= 0) return
//取消旧任务的定时器 & 设置新的定时器 //取消旧任务的定时器 & 设置新的定时器
CronJobScheduler.cancelTask(task.id) CronJobScheduler.cancelTask(task.id)
CronJobScheduler.scheduleTask(task) CronJobScheduler.scheduleTask(task)
@ -490,7 +491,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
//必须开启定位服务,才能使用进入地点 或 离开地点 类型条件 //必须开启定位服务,才能使用进入地点 或 离开地点 类型条件
if ((typeCondition == TASK_CONDITION_TO_ADDRESS || typeCondition == TASK_CONDITION_LEAVE_ADDRESS) && !App.LocationClient.isStarted()) { if ((typeCondition == TASK_CONDITION_TO_ADDRESS || typeCondition == TASK_CONDITION_LEAVE_ADDRESS) && !App.LocationClient.isStarted()) {
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext())
.iconRes(R.drawable.icon_location) .iconRes(R.drawable.auto_task_icon_location)
.title(R.string.enable_location) .title(R.string.enable_location)
.content(R.string.enable_location_dialog) .content(R.string.enable_location_dialog)
.cancelable(false) .cancelable(false)

View File

@ -5,9 +5,17 @@ import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.spinner.FrpcAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.FrpcSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Frpc
import com.idormy.sms.forwarder.databinding.FragmentTasksActionFrpcBinding import com.idormy.sms.forwarder.databinding.FragmentTasksActionFrpcBinding
import com.idormy.sms.forwarder.entity.action.FrpcSetting import com.idormy.sms.forwarder.entity.action.FrpcSetting
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
@ -15,6 +23,7 @@ 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_EVENT_DATA_ACTION
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.STATUS_ON
import com.idormy.sms.forwarder.utils.TASK_ACTION_FRPC import com.idormy.sms.forwarder.utils.TASK_ACTION_FRPC
import com.idormy.sms.forwarder.utils.XToastUtils import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus import com.jeremyliao.liveeventbus.LiveEventBus
@ -24,6 +33,11 @@ import com.xuexiang.xrouter.annotation.AutoWired
import com.xuexiang.xrouter.launcher.XRouter import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.utils.CountDownButtonHelper import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.resource.ResUtils.getDrawable
import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
@Page(name = "Frpc") @Page(name = "Frpc")
@Suppress("PrivatePropertyName") @Suppress("PrivatePropertyName")
@ -33,6 +47,16 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
private var titleBar: TitleBar? = null private var titleBar: TitleBar? = null
private var mCountDownHelper: CountDownButtonHelper? = null private var mCountDownHelper: CountDownButtonHelper? = null
//当前发送通道
private var frpcUid = ""
private var frpcListSelected: MutableList<Frpc> = mutableListOf()
private var frpcItemMap = HashMap<String, LinearLayout>(2)
//发送通道列表
private var frpcListAll: MutableList<Frpc> = mutableListOf()
private val frpcSpinnerList = ArrayList<FrpcAdapterItem>()
private lateinit var frpcSpinnerAdapter: FrpcSpinnerAdapter<*>
@JvmField @JvmField
@AutoWired(name = KEY_EVENT_DATA_ACTION) @AutoWired(name = KEY_EVENT_DATA_ACTION)
var eventData: String? = null var eventData: String? = null
@ -69,28 +93,15 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
} }
}) })
binding!!.rgFrpcState.setOnCheckedChangeListener { _, checkedId ->
when (checkedId) {
R.id.rb_start_server -> {
binding!!.layoutStartServer.visibility = View.VISIBLE
binding!!.layoutStopServer.visibility = View.GONE
}
R.id.rb_stop_server -> {
binding!!.layoutStartServer.visibility = View.GONE
binding!!.layoutStopServer.visibility = View.VISIBLE
}
}
}
Log.d(TAG, "initViews eventData:$eventData") Log.d(TAG, "initViews eventData:$eventData")
if (eventData != null) { if (eventData != null) {
val settingVo = Gson().fromJson(eventData, FrpcSetting::class.java) val settingVo = Gson().fromJson(eventData, FrpcSetting::class.java)
binding!!.etStartUid.setText(settingVo.uids)
binding!!.etStopUid.setText(settingVo.uids)
binding!!.rgFrpcState.check(if (settingVo.action == "start") R.id.rb_start_server else R.id.rb_stop_server) binding!!.rgFrpcState.check(if (settingVo.action == "start") R.id.rb_start_server else R.id.rb_stop_server)
Log.d(TAG, "initViews settingVo:$settingVo") Log.d(TAG, "initViews settingVo:$settingVo")
} }
//初始化发送通道下拉框
initFrpcSpinner()
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -151,23 +162,131 @@ class FrpcFragment : BaseFragment<FragmentTasksActionFrpcBinding?>(), View.OnCli
} }
} }
//初始化发送通道下拉框
@SuppressLint("SetTextI18n")
private fun initFrpcSpinner() {
Core.frpc.getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Frpc>> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) {
e.printStackTrace()
Log.e(TAG, "initFrpcSpinner error: ${e.message}")
}
override fun onSuccess(frpcList: List<Frpc>) {
if (frpcList.isEmpty()) {
XToastUtils.error(R.string.add_frpc_first)
return
}
frpcListAll = frpcList as MutableList<Frpc>
for (frpc in frpcList) {
val name = if (frpc.name.length > 20) frpc.name.substring(0, 19) else frpc.name
frpcSpinnerList.add(FrpcAdapterItem(name, getDrawable(R.drawable.auto_task_icon_frpc), frpc.uid, frpc.autorun))
}
frpcSpinnerAdapter = FrpcSpinnerAdapter(frpcSpinnerList)
.setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
binding!!.spFrpc.setAdapter(frpcSpinnerAdapter)
if (frpcListSelected.isNotEmpty()) {
for (frpc in frpcListSelected) {
for (frpcItem in frpcSpinnerList) {
if (frpc.uid == frpcItem.uid) {
addFrpcItemLinearLayout(frpcItemMap, binding!!.layoutFrpcs, frpcItem)
}
}
}
}
}
})
binding!!.spFrpc.setOnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
try {
val frpc = frpcSpinnerAdapter.getItemSource(position) as FrpcAdapterItem
frpcUid = frpc.uid
if (frpcUid.isNotEmpty()) {
frpcListSelected.forEach {
if (frpcUid == it.uid) {
XToastUtils.warning(getString(R.string.frpc_contains_tips))
return@setOnItemClickListener
}
}
frpcListAll.forEach {
if (frpcUid == it.uid) {
frpcListSelected.add(it)
addFrpcItemLinearLayout(frpcItemMap, binding!!.layoutFrpcs, frpc)
}
}
/*if (STATUS_OFF == frpc.status) {
XToastUtils.warning(getString(R.string.frpc_disabled_tips))
}*/
}
} catch (e: Exception) {
XToastUtils.error(e.message.toString())
}
}
}
/**
* 动态增删Frpc
*
* @param frpcItemMap 管理item的map用于删除指定header
* @param layoutFrpcs 需要挂载item的LinearLayout
* @param frpc FrpcAdapterItem
*/
@SuppressLint("SetTextI18n")
private fun addFrpcItemLinearLayout(
frpcItemMap: MutableMap<String, LinearLayout>, layoutFrpcs: LinearLayout, frpc: FrpcAdapterItem
) {
val layoutFrpcItem = View.inflate(requireContext(), R.layout.item_add_frpc, null) as LinearLayout
val ivRemoveFrpc = layoutFrpcItem.findViewById<ImageView>(R.id.iv_remove_frpc)
val ivFrpcImage = layoutFrpcItem.findViewById<ImageView>(R.id.iv_frpc_image)
val ivFrpcStatus = layoutFrpcItem.findViewById<ImageView>(R.id.iv_frpc_status)
val tvFrpcName = layoutFrpcItem.findViewById<TextView>(R.id.tv_frpc_name)
ivFrpcImage.setImageDrawable(frpc.icon)
ivFrpcStatus.setImageDrawable(getDrawable(if (STATUS_ON == frpc.autorun) R.drawable.ic_autorun else R.drawable.ic_manual))
val frpcItemId = frpc.uid
tvFrpcName.text = frpc.title
ivRemoveFrpc.tag = frpcItemId
ivRemoveFrpc.setOnClickListener { view2: View ->
val tagId = view2.tag
layoutFrpcs.removeView(frpcItemMap[tagId])
frpcItemMap.remove(tagId)
//frpcListSelected.removeIf { it.uid == tagId }
for (it in frpcListSelected) {
if (it.uid == tagId) {
frpcListSelected -= it
break
}
}
Log.d(TAG, frpcListSelected.count().toString())
Log.d(TAG, frpcListSelected.toString())
if (frpcListSelected.isEmpty()) frpcUid = ""
}
layoutFrpcs.addView(layoutFrpcItem)
frpcItemMap[frpcItemId] = layoutFrpcItem
}
//检查设置 //检查设置
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun checkSetting(): FrpcSetting { private fun checkSetting(): FrpcSetting {
val startUid = binding!!.etStartUid.text.toString().trim() val description = StringBuilder()
val stopUid = binding!!.etStopUid.text.toString().trim() val action = if (binding!!.rgFrpcState.checkedRadioButtonId == R.id.rb_start_server) {
val description: String description.append(getString(R.string.enable))
val action: String "start"
val uids: String
if (binding!!.rgFrpcState.checkedRadioButtonId == R.id.rb_start_server) {
description = if (startUid == "") "启动全部自启动的Frpc" else "启动UID为${startUid}的Frpc"
action = "start"
uids = startUid
} else { } else {
description = if (stopUid == "") "停止全部自启动的Frpc" else "停止UID为${stopUid}的Frpc" description.append(getString(R.string.disable))
action = "stop" "stop"
uids = stopUid
} }
return FrpcSetting(description, action, uids) if (frpcListSelected.isEmpty()) {
description.append(getString(R.string.all_auto_started_frpc))
} else {
description.append(getString(R.string.specified_frpc)).append(": ")
description.append(frpcListSelected.joinToString(",") { it.name })
}
return FrpcSetting(description.toString(), action, frpcListSelected)
} }
} }

View File

@ -215,10 +215,10 @@ class HttpServerFragment : BaseFragment<FragmentTasksActionHttpServerBinding?>()
val action = if (binding!!.rgHttpServerState.checkedRadioButtonId == R.id.rb_start_server) { val action = if (binding!!.rgHttpServerState.checkedRadioButtonId == R.id.rb_start_server) {
description.append(getString(R.string.start_server)) description.append(getString(R.string.start_server))
if (enableList.isNotEmpty()) { if (enableList.isNotEmpty()) {
description.append(", ").append(getString(R.string.enable_function)).append(": ").append(enableList.joinToString("/")) description.append(", ").append(getString(R.string.enable_function)).append(": ").append(enableList.joinToString(","))
} }
if (disableList.isNotEmpty()) { if (disableList.isNotEmpty()) {
description.append(", ").append(getString(R.string.disable_function)).append(": ").append(disableList.joinToString("/")) description.append(", ").append(getString(R.string.disable_function)).append(": ").append(disableList.joinToString(","))
} }
"start" "start"
} else { } else {

View File

@ -11,7 +11,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.databinding.FragmentTasksActionNotificationBinding import com.idormy.sms.forwarder.databinding.FragmentTasksActionNotificationBinding
@ -268,7 +268,7 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
R.id.btn_save -> { R.id.btn_save -> {
val settingVo = checkSetting() val settingVo = checkSetting()
var description = getString(R.string.select_sender) + ": " var description = getString(R.string.task_notification) + ": "
description += settingVo.senderList.joinToString(",") { it.name } description += settingVo.senderList.joinToString(",") { it.name }
if (settingVo.senderList.size > 1) { if (settingVo.senderList.size > 1) {
description += "; " + getString(R.string.sender_logic) + ": " + when (settingVo.senderLogic) { description += "; " + getString(R.string.sender_logic) + ": " + when (settingVo.senderLogic) {
@ -298,7 +298,7 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
//免打扰(禁用转发)时间段 //免打扰(禁用转发)时间段
binding!!.tvSilentPeriod.text = mTimeOption[silentPeriodStart] + " ~ " + mTimeOption[silentPeriodEnd] binding!!.tvSilentPeriod.text = mTimeOption[silentPeriodStart] + " ~ " + mTimeOption[silentPeriodEnd]
AppDatabase.getInstance(requireContext()).senderDao().getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> { Core.sender.getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {

View File

@ -14,7 +14,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.spinner.RuleAdapterItem import com.idormy.sms.forwarder.adapter.spinner.RuleAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.RuleSpinnerAdapter import com.idormy.sms.forwarder.adapter.spinner.RuleSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.databinding.FragmentTasksActionRuleBinding import com.idormy.sms.forwarder.databinding.FragmentTasksActionRuleBinding
import com.idormy.sms.forwarder.entity.action.RuleSetting import com.idormy.sms.forwarder.entity.action.RuleSetting
@ -24,7 +24,7 @@ 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.KEY_TEST_ACTION
import com.idormy.sms.forwarder.utils.Log import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.STATUS_OFF import com.idormy.sms.forwarder.utils.STATUS_OFF
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDER import com.idormy.sms.forwarder.utils.TASK_ACTION_RULE
import com.idormy.sms.forwarder.utils.XToastUtils import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus import com.jeremyliao.liveeventbus.LiveEventBus
import com.xuexiang.xaop.annotation.SingleClick import com.xuexiang.xaop.annotation.SingleClick
@ -52,7 +52,7 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
private var ruleListSelected: MutableList<Rule> = mutableListOf() private var ruleListSelected: MutableList<Rule> = mutableListOf()
private var ruleItemMap = HashMap<Long, LinearLayout>(2) private var ruleItemMap = HashMap<Long, LinearLayout>(2)
//发送通道列表 //转发规则列表
private var ruleListAll: MutableList<Rule> = mutableListOf() private var ruleListAll: MutableList<Rule> = mutableListOf()
private val ruleSpinnerList = ArrayList<RuleAdapterItem>() private val ruleSpinnerList = ArrayList<RuleAdapterItem>()
private lateinit var ruleSpinnerAdapter: RuleSpinnerAdapter<*> private lateinit var ruleSpinnerAdapter: RuleSpinnerAdapter<*>
@ -96,7 +96,7 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
Log.d(TAG, "initViews eventData:$eventData") Log.d(TAG, "initViews eventData:$eventData")
if (eventData != null) { if (eventData != null) {
val settingVo = Gson().fromJson(eventData, RuleSetting::class.java) val settingVo = Gson().fromJson(eventData, RuleSetting::class.java)
binding!!.rgStatus.check(if (settingVo.status == "enable") R.id.rb_status_enable else R.id.rb_status_disable) binding!!.rgStatus.check(if (settingVo.status == 1) R.id.rb_status_enable else R.id.rb_status_disable)
Log.d(TAG, settingVo.ruleList.toString()) Log.d(TAG, settingVo.ruleList.toString())
settingVo.ruleList.forEach { settingVo.ruleList.forEach {
ruleId = it.id ruleId = it.id
@ -105,7 +105,7 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
Log.d(TAG, "initViews settingVo:$settingVo") Log.d(TAG, "initViews settingVo:$settingVo")
} }
//初始化发送通道下拉框 //初始化转发规则下拉框
initRuleSpinner() initRuleSpinner()
} }
@ -155,7 +155,7 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
val intent = Intent() val intent = Intent()
intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, settingVo.description) intent.putExtra(KEY_BACK_DESCRIPTION_ACTION, settingVo.description)
intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo)) intent.putExtra(KEY_BACK_DATA_ACTION, Gson().toJson(settingVo))
setFragmentResult(TASK_ACTION_SENDER, intent) setFragmentResult(TASK_ACTION_RULE, intent)
popToBack() popToBack()
return return
} }
@ -167,10 +167,10 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
} }
} }
//初始化发送通道下拉框 //初始化转发规则下拉框
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun initRuleSpinner() { private fun initRuleSpinner() {
AppDatabase.getInstance(requireContext()).ruleDao().getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Rule>> { Core.rule.getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Rule>> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
@ -187,7 +187,13 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
ruleListAll = ruleList as MutableList<Rule> ruleListAll = ruleList as MutableList<Rule>
for (rule in ruleList) { for (rule in ruleList) {
val name = if (rule.name.length > 20) rule.name.substring(0, 19) else rule.name val name = if (rule.name.length > 20) rule.name.substring(0, 19) else rule.name
ruleSpinnerList.add(RuleAdapterItem(name, getDrawable(rule.imageId), rule.id, rule.status)) val icon = when (rule.type) {
"sms" -> R.drawable.auto_task_icon_sms
"call" -> R.drawable.auto_task_icon_incall
"app" -> R.drawable.auto_task_icon_start_activity
else -> R.drawable.auto_task_icon_sms
}
ruleSpinnerList.add(RuleAdapterItem(name, getDrawable(icon), rule.id, rule.status))
} }
ruleSpinnerAdapter = RuleSpinnerAdapter(ruleSpinnerList) ruleSpinnerAdapter = RuleSpinnerAdapter(ruleSpinnerList)
.setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg) .setIsFilterKey(true).setFilterColor("#EF5362").setBackgroundSelector(R.drawable.selector_custom_spinner_bg)
@ -222,9 +228,9 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
} }
} }
if (STATUS_OFF == rule.status) { /*if (STATUS_OFF == rule.status) {
XToastUtils.warning(getString(R.string.rule_disabled_tips)) XToastUtils.warning(getString(R.string.rule_disabled_tips))
} }*/
} }
} catch (e: Exception) { } catch (e: Exception) {
XToastUtils.error(e.message.toString()) XToastUtils.error(e.message.toString())
@ -277,21 +283,21 @@ class RuleFragment : BaseFragment<FragmentTasksActionRuleBinding?>(), View.OnCli
//检查设置 //检查设置
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun checkSetting(): RuleSetting { private fun checkSetting(): RuleSetting {
if (ruleListSelected.isEmpty() || ruleId == 0L) {
throw Exception(getString(R.string.new_sender_first))
}
val description = StringBuilder() val description = StringBuilder()
val status: String val status: Int
if (binding!!.rgStatus.checkedRadioButtonId == R.id.rb_status_enable) { if (binding!!.rgStatus.checkedRadioButtonId == R.id.rb_status_enable) {
status = "enable" status = 1
description.append(getString(R.string.enable)) description.append(getString(R.string.enable))
} else { } else {
status = "disable" status = 0
description.append(getString(R.string.disable)) description.append(getString(R.string.disable))
} }
description.append(getString(R.string.menu_rules)) description.append(getString(R.string.menu_rules)).append(", ").append(getString(R.string.specified_rule)).append(": ")
description.append(ruleListSelected.joinToString(",") { it.id.toString() })
if (ruleListSelected.isNotEmpty()) {
description.append(", ").append(getString(R.string.specified_rule)).append(": ")
description.append(ruleListSelected.joinToString("/") { it.id.toString() })
}
return RuleSetting(description.toString(), status, ruleListSelected) return RuleSetting(description.toString(), status, ruleListSelected)
} }

View File

@ -14,7 +14,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem import com.idormy.sms.forwarder.adapter.spinner.SenderAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter import com.idormy.sms.forwarder.adapter.spinner.SenderSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSenderBinding import com.idormy.sms.forwarder.databinding.FragmentTasksActionSenderBinding
import com.idormy.sms.forwarder.entity.action.SenderSetting import com.idormy.sms.forwarder.entity.action.SenderSetting
@ -96,7 +96,7 @@ class SenderFragment : BaseFragment<FragmentTasksActionSenderBinding?>(), View.O
Log.d(TAG, "initViews eventData:$eventData") Log.d(TAG, "initViews eventData:$eventData")
if (eventData != null) { if (eventData != null) {
val settingVo = Gson().fromJson(eventData, SenderSetting::class.java) val settingVo = Gson().fromJson(eventData, SenderSetting::class.java)
binding!!.rgStatus.check(if (settingVo.status == "enable") R.id.rb_status_enable else R.id.rb_status_disable) binding!!.rgStatus.check(if (settingVo.status == 1) R.id.rb_status_enable else R.id.rb_status_disable)
Log.d(TAG, settingVo.senderList.toString()) Log.d(TAG, settingVo.senderList.toString())
settingVo.senderList.forEach { settingVo.senderList.forEach {
senderId = it.id senderId = it.id
@ -170,7 +170,7 @@ class SenderFragment : BaseFragment<FragmentTasksActionSenderBinding?>(), View.O
//初始化发送通道下拉框 //初始化发送通道下拉框
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun initSenderSpinner() { private fun initSenderSpinner() {
AppDatabase.getInstance(requireContext()).senderDao().getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> { Core.sender.getAll().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<List<Sender>> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
@ -222,9 +222,9 @@ class SenderFragment : BaseFragment<FragmentTasksActionSenderBinding?>(), View.O
} }
} }
if (STATUS_OFF == sender.status) { /*if (STATUS_OFF == sender.status) {
XToastUtils.warning(getString(R.string.sender_disabled_tips)) XToastUtils.warning(getString(R.string.sender_disabled_tips))
} }*/
} }
} catch (e: Exception) { } catch (e: Exception) {
XToastUtils.error(e.message.toString()) XToastUtils.error(e.message.toString())
@ -277,21 +277,21 @@ class SenderFragment : BaseFragment<FragmentTasksActionSenderBinding?>(), View.O
//检查设置 //检查设置
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun checkSetting(): SenderSetting { private fun checkSetting(): SenderSetting {
if (senderListSelected.isEmpty() || senderId == 0L) {
throw Exception(getString(R.string.new_sender_first))
}
val description = StringBuilder() val description = StringBuilder()
val status: String val status: Int
if (binding!!.rgStatus.checkedRadioButtonId == R.id.rb_status_enable) { if (binding!!.rgStatus.checkedRadioButtonId == R.id.rb_status_enable) {
status = "enable" status = 1
description.append(getString(R.string.enable)) description.append(getString(R.string.enable))
} else { } else {
status = "disable" status = 0
description.append(getString(R.string.disable)) description.append(getString(R.string.disable))
} }
description.append(getString(R.string.menu_senders)) description.append(getString(R.string.menu_senders)).append(", ").append(getString(R.string.specified_sender)).append(": ")
description.append(senderListSelected.joinToString(",") { it.name })
if (senderListSelected.isNotEmpty()) {
description.append(", ").append(getString(R.string.specified_sender)).append(": ")
description.append(senderListSelected.joinToString("/") { it.name })
}
return SenderSetting(description.toString(), status, senderListSelected) return SenderSetting(description.toString(), status, senderListSelected)
} }

View File

@ -476,10 +476,10 @@ class SettingsFragment : BaseFragment<FragmentTasksActionSettingsBinding?>(), Vi
val description = StringBuilder() val description = StringBuilder()
if (enableList.isNotEmpty()) { if (enableList.isNotEmpty()) {
description.append(" ").append(getString(R.string.enable_function)).append(": ").append(enableList.joinToString("/")) description.append(" ").append(getString(R.string.enable_function)).append(": ").append(enableList.joinToString(","))
} }
if (disableList.isNotEmpty()) { if (disableList.isNotEmpty()) {
description.append(" ").append(getString(R.string.disable_function)).append(": ").append(disableList.joinToString("/")) description.append(" ").append(getString(R.string.disable_function)).append(": ").append(disableList.joinToString(","))
} }
return SettingsSetting(description.toString().trim(), enableSms, enablePhone, enableCallType1, enableCallType2, enableCallType3, enableCallType4, enableCallType5, enableCallType6, enableAppNotify, enableCancelAppNotify, enableNotUserPresent, enableLocation, locationAccuracy, locationPowerRequirement, locationMinInterval, locationMinDistance, enableSmsCommand, smsCommandSafePhone, enableLoadAppList, enableLoadUserAppList, enableLoadSystemAppList, cancelExtraAppNotify, duplicateMessagesLimits) return SettingsSetting(description.toString().trim(), enableSms, enablePhone, enableCallType1, enableCallType2, enableCallType3, enableCallType4, enableCallType5, enableCallType6, enableAppNotify, enableCancelAppNotify, enableNotUserPresent, enableLocation, locationAccuracy, locationPowerRequirement, locationMinInterval, locationMinDistance, enableSmsCommand, smsCommandSafePhone, enableLoadAppList, enableLoadUserAppList, enableLoadSystemAppList, cancelExtraAppNotify, duplicateMessagesLimits)

View File

@ -172,7 +172,7 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
when (v.id) { when (v.id) {
R.id.btn_current_coordinates -> { R.id.btn_current_coordinates -> {
if (!App.LocationClient.isStarted()) { if (!App.LocationClient.isStarted()) {
MaterialDialog.Builder(requireContext()).iconRes(R.drawable.icon_location).title(R.string.enable_location).content(R.string.enable_location_dialog).cancelable(false).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? -> MaterialDialog.Builder(requireContext()).iconRes(R.drawable.auto_task_icon_location).title(R.string.enable_location).content(R.string.enable_location_dialog).cancelable(false).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
SettingUtils.enableLocation = true SettingUtils.enableLocation = true
val serviceIntent = Intent(requireContext(), LocationService::class.java) val serviceIntent = Intent(requireContext(), LocationService::class.java)
serviceIntent.action = "START" serviceIntent.action = "START"

View File

@ -172,7 +172,7 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
when (v.id) { when (v.id) {
R.id.btn_current_coordinates -> { R.id.btn_current_coordinates -> {
if (!App.LocationClient.isStarted()) { if (!App.LocationClient.isStarted()) {
MaterialDialog.Builder(requireContext()).iconRes(R.drawable.icon_location).title(R.string.enable_location).content(R.string.enable_location_dialog).cancelable(false).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? -> MaterialDialog.Builder(requireContext()).iconRes(R.drawable.auto_task_icon_location).title(R.string.enable_location).content(R.string.enable_location_dialog).cancelable(false).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
SettingUtils.enableLocation = true SettingUtils.enableLocation = true
val serviceIntent = Intent(requireContext(), LocationService::class.java) val serviceIntent = Intent(requireContext(), LocationService::class.java)
serviceIntent.action = "START" serviceIntent.action = "START"

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -145,7 +145,7 @@ class BarkFragment : BaseFragment<FragmentSendersBarkBinding?>(), View.OnClickLi
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()).senderDao().get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> { Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {

View File

@ -11,7 +11,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -105,41 +105,36 @@ class DingtalkGroupRobotFragment : BaseFragment<FragmentSendersDingtalkGroupRobo
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkGroupRobotSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etToken.setText(settingVo.token)
binding!!.etSecret.setText(settingVo.secret)
binding!!.sbAtAll.isChecked = settingVo.atAll == true
binding!!.etAtMobiles.setText(settingVo.atMobiles)
binding!!.etAtDingtalkIds.setText(settingVo.atDingtalkIds)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkGroupRobotSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etToken.setText(settingVo.token)
binding!!.etSecret.setText(settingVo.secret)
binding!!.sbAtAll.isChecked = settingVo.atAll == true
binding!!.etAtMobiles.setText(settingVo.atMobiles)
binding!!.etAtDingtalkIds.setText(settingVo.atDingtalkIds)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -220,17 +215,11 @@ class DingtalkGroupRobotFragment : BaseFragment<FragmentSendersDingtalkGroupRobo
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -12,7 +12,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -99,46 +99,41 @@ class DingtalkInnerRobotFragment : BaseFragment<FragmentSendersDingtalkInnerRobo
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkInnerRobotSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etAgentID.setText(settingVo.agentID)
binding!!.etAppKey.setText(settingVo.appKey)
binding!!.etAppSecret.setText(settingVo.appSecret)
binding!!.etUserIds.setText(settingVo.userIds)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
binding!!.etProxyHost.setText(settingVo.proxyHost)
binding!!.etProxyPort.setText(settingVo.proxyPort)
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, DingtalkInnerRobotSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etAgentID.setText(settingVo.agentID)
binding!!.etAppKey.setText(settingVo.appKey)
binding!!.etAppSecret.setText(settingVo.appSecret)
binding!!.etUserIds.setText(settingVo.userIds)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
binding!!.etProxyHost.setText(settingVo.proxyHost)
binding!!.etProxyPort.setText(settingVo.proxyPort)
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -228,17 +223,11 @@ class DingtalkInnerRobotFragment : BaseFragment<FragmentSendersDingtalkInnerRobo
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -121,50 +121,45 @@ class EmailFragment : BaseFragment<FragmentSendersEmailBinding?>(), View.OnClick
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
}
override fun onSuccess(sender: Sender) {
if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard)
} else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
} }
binding!!.etName.setText(sender.name)
override fun onSuccess(sender: Sender) { binding!!.sbEnable.isChecked = sender.status == 1
if (isClone) { val settingVo = Gson().fromJson(sender.jsonSetting, EmailSetting::class.java)
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) Log.d(TAG, settingVo.toString())
binding!!.btnDel.setText(R.string.discard) if (settingVo != null) {
} else { if (!TextUtils.isEmpty(settingVo.mailType)) {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) mailType = settingVo.mailType.toString()
} binding!!.spMailType.setSelectedItem(mailType)
binding!!.etName.setText(sender.name) if (mailType != getString(R.string.other_mail_type)) {
binding!!.sbEnable.isChecked = sender.status == 1 binding!!.layoutServiceSetting.visibility = View.GONE
val settingVo = Gson().fromJson(sender.jsonSetting, EmailSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
if (!TextUtils.isEmpty(settingVo.mailType)) {
mailType = settingVo.mailType.toString()
binding!!.spMailType.setSelectedItem(mailType)
if (mailType != getString(R.string.other_mail_type)) {
binding!!.layoutServiceSetting.visibility = View.GONE
}
} }
binding!!.etFromEmail.setText(settingVo.fromEmail)
binding!!.etPwd.setText(settingVo.pwd)
binding!!.etNickname.setText(settingVo.nickname)
binding!!.etHost.setText(settingVo.host)
binding!!.etPort.setText(settingVo.port)
binding!!.sbSsl.isChecked = settingVo.ssl == true
binding!!.sbStartTls.isChecked = settingVo.startTls == true
binding!!.etToEmail.setText(settingVo.toEmail)
binding!!.etTitleTemplate.setText(settingVo.title)
} }
binding!!.etFromEmail.setText(settingVo.fromEmail)
binding!!.etPwd.setText(settingVo.pwd)
binding!!.etNickname.setText(settingVo.nickname)
binding!!.etHost.setText(settingVo.host)
binding!!.etPort.setText(settingVo.port)
binding!!.sbSsl.isChecked = settingVo.ssl == true
binding!!.sbStartTls.isChecked = settingVo.startTls == true
binding!!.etToEmail.setText(settingVo.toEmail)
binding!!.etTitleTemplate.setText(settingVo.title)
} }
}) }
})
} }
override fun initListeners() { override fun initListeners() {
@ -253,17 +248,11 @@ class EmailFragment : BaseFragment<FragmentSendersEmailBinding?>(), View.OnClick
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -103,9 +103,7 @@ class FeishuAppFragment : BaseFragment<FragmentSendersFeishuAppBinding?>(), View
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId)
.senderDao()
.get(senderId)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> { .subscribe(object : SingleObserver<Sender> {

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -103,38 +103,33 @@ class FeishuFragment : BaseFragment<FragmentSendersFeishuBinding?>(), View.OnCli
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etWebhook.setText(settingVo.webhook)
binding!!.etSecret.setText(settingVo.secret)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, FeishuSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etWebhook.setText(settingVo.webhook)
binding!!.etSecret.setText(settingVo.secret)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -198,17 +193,11 @@ class FeishuFragment : BaseFragment<FragmentSendersFeishuBinding?>(), View.OnCli
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -103,37 +103,32 @@ class GotifyFragment : BaseFragment<FragmentSendersGotifyBinding?>(), View.OnCli
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError $e") Log.e(TAG, "onError $e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, GotifySetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etWebServer.setText(settingVo.webServer)
binding!!.etTitleTemplate.setText(settingVo.title)
binding!!.etPriority.setText(settingVo.priority)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, GotifySetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etWebServer.setText(settingVo.webServer)
binding!!.etTitleTemplate.setText(settingVo.title)
binding!!.etPriority.setText(settingVo.priority)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -197,17 +192,11 @@ class GotifyFragment : BaseFragment<FragmentSendersGotifyBinding?>(), View.OnCli
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -10,7 +10,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -104,47 +104,42 @@ class PushplusFragment : BaseFragment<FragmentSendersPushplusBinding?>(), View.O
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
}
override fun onSuccess(sender: Sender) {
if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard)
} else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
} }
binding!!.etName.setText(sender.name)
override fun onSuccess(sender: Sender) { binding!!.sbEnable.isChecked = sender.status == 1
if (isClone) { val settingVo = Gson().fromJson(sender.jsonSetting, PushplusSetting::class.java)
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) Log.d(TAG, settingVo.toString())
binding!!.btnDel.setText(R.string.discard) if (settingVo != null) {
if (TextUtils.isEmpty(settingVo.website) || settingVo.website == getString(R.string.pushplus_plus)) {
binding!!.rgWebsite.check(R.id.rb_website_plus)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) binding!!.rgWebsite.check(R.id.rb_website_hxtrip)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, PushplusSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
if (TextUtils.isEmpty(settingVo.website) || settingVo.website == getString(R.string.pushplus_plus)) {
binding!!.rgWebsite.check(R.id.rb_website_plus)
} else {
binding!!.rgWebsite.check(R.id.rb_website_hxtrip)
}
binding!!.etToken.setText(settingVo.token)
binding!!.etTopic.setText(settingVo.topic)
binding!!.etTemplate.setText(settingVo.template)
binding!!.etChannel.setText(settingVo.channel)
binding!!.etWebhook.setText(settingVo.webhook)
binding!!.etCallbackUrl.setText(settingVo.callbackUrl)
binding!!.etValidTime.setText(settingVo.validTime)
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
} }
binding!!.etToken.setText(settingVo.token)
binding!!.etTopic.setText(settingVo.topic)
binding!!.etTemplate.setText(settingVo.template)
binding!!.etChannel.setText(settingVo.channel)
binding!!.etWebhook.setText(settingVo.webhook)
binding!!.etCallbackUrl.setText(settingVo.callbackUrl)
binding!!.etValidTime.setText(settingVo.validTime)
binding!!.etTitleTemplate.setText(settingVo.titleTemplate)
} }
}) }
})
} }
override fun initListeners() { override fun initListeners() {
@ -217,17 +212,11 @@ class PushplusFragment : BaseFragment<FragmentSendersPushplusBinding?>(), View.O
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -8,7 +8,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -101,37 +101,32 @@ class ServerchanFragment : BaseFragment<FragmentSendersServerchanBinding?>(), Vi
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, ServerchanSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etSendKey.setText(settingVo.sendKey)
binding!!.etChannel.setText(settingVo.channel)
binding!!.etOpenid.setText(settingVo.openid)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, ServerchanSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etSendKey.setText(settingVo.sendKey)
binding!!.etChannel.setText(settingVo.channel)
binding!!.etOpenid.setText(settingVo.openid)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -170,17 +165,11 @@ class ServerchanFragment : BaseFragment<FragmentSendersServerchanBinding?>(), Vi
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -11,7 +11,7 @@ import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions import com.hjq.permissions.XXPermissions
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -86,27 +86,25 @@ class SmsFragment : BaseFragment<FragmentSendersSmsBinding?>(), View.OnClickList
*/ */
override fun initViews() { override fun initViews() {
//检查发短信权限 //检查发短信权限
XXPermissions.with(this) XXPermissions.with(this).permission(Permission.SEND_SMS).request(object : OnPermissionCallback {
.permission(Permission.SEND_SMS) override fun onGranted(permissions: List<String>, all: Boolean) {
.request(object : OnPermissionCallback { if (!all) {
override fun onGranted(permissions: List<String>, all: Boolean) { XToastUtils.error(R.string.toast_granted_part)
if (!all) {
XToastUtils.error(R.string.toast_granted_part)
HttpServerUtils.enableApiSmsSend = false
}
}
override fun onDenied(permissions: List<String>, never: Boolean) {
HttpServerUtils.enableApiSmsSend = false HttpServerUtils.enableApiSmsSend = false
if (never) {
XToastUtils.error(R.string.toast_denied_never)
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(requireContext(), permissions)
} else {
XToastUtils.error(R.string.toast_denied)
}
} }
}) }
override fun onDenied(permissions: List<String>, never: Boolean) {
HttpServerUtils.enableApiSmsSend = false
if (never) {
XToastUtils.error(R.string.toast_denied_never)
// 如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.startPermissionActivity(requireContext(), permissions)
} else {
XToastUtils.error(R.string.toast_denied)
}
}
})
//测试按钮增加倒计时,避免重复点击 //测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, SettingUtils.requestTimeout) mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, SettingUtils.requestTimeout)
@ -129,37 +127,32 @@ class SmsFragment : BaseFragment<FragmentSendersSmsBinding?>(), View.OnClickList
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, SmsSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.rgSimSlot.check(settingVo.getSmsSimSlotCheckId())
binding!!.etMobiles.setText(settingVo.mobiles)
binding!!.sbOnlyNoNetwork.isChecked = settingVo.onlyNoNetwork == true
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, SmsSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.rgSimSlot.check(settingVo.getSmsSimSlotCheckId())
binding!!.etMobiles.setText(settingVo.mobiles)
binding!!.sbOnlyNoNetwork.isChecked = settingVo.onlyNoNetwork == true
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -204,17 +197,11 @@ class SmsFragment : BaseFragment<FragmentSendersSmsBinding?>(), View.OnClickList
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -9,7 +9,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -103,7 +103,7 @@ class SocketFragment : BaseFragment<FragmentSendersSocketBinding?>(), View.OnCli
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()).senderDao().get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> { Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {} override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {

View File

@ -10,7 +10,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -104,43 +104,38 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, TelegramSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.rgMethod.check(settingVo.getMethodCheckId())
binding!!.etApiToken.setText(settingVo.apiToken)
binding!!.etChatId.setText(settingVo.chatId)
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
binding!!.etProxyHost.setText(settingVo.proxyHost)
binding!!.etProxyPort.setText(settingVo.proxyPort)
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, TelegramSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.rgMethod.check(settingVo.getMethodCheckId())
binding!!.etApiToken.setText(settingVo.apiToken)
binding!!.etChatId.setText(settingVo.chatId)
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
binding!!.etProxyHost.setText(settingVo.proxyHost)
binding!!.etProxyPort.setText(settingVo.proxyPort)
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -196,17 +191,11 @@ class TelegramFragment : BaseFragment<FragmentSendersTelegramBinding?>(), View.O
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -12,7 +12,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -106,35 +106,30 @@ class UrlSchemeFragment : BaseFragment<FragmentSendersUrlSchemeBinding?>(), View
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, UrlSchemeSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etUrlScheme.setText(settingVo.urlScheme)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, UrlSchemeSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etUrlScheme.setText(settingVo.urlScheme)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -173,17 +168,11 @@ class UrlSchemeFragment : BaseFragment<FragmentSendersUrlSchemeBinding?>(), View
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -11,7 +11,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -87,8 +87,7 @@ class WebhookFragment : BaseFragment<FragmentSendersWebhookBinding?>(), View.OnC
override fun initViews() { override fun initViews() {
//测试按钮增加倒计时,避免重复点击 //测试按钮增加倒计时,避免重复点击
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, SettingUtils.requestTimeout) mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, SettingUtils.requestTimeout)
mCountDownHelper!!.setOnCountDownListener(object : mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
CountDownButtonHelper.OnCountDownListener {
override fun onCountDown(time: Int) { override fun onCountDown(time: Int) {
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time) binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
} }
@ -107,50 +106,42 @@ class WebhookFragment : BaseFragment<FragmentSendersWebhookBinding?>(), View.OnC
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
}
override fun onSuccess(sender: Sender) {
if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard)
} else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
} }
binding!!.etName.setText(sender.name)
override fun onSuccess(sender: Sender) { binding!!.sbEnable.isChecked = sender.status == 1
if (isClone) { val settingVo = Gson().fromJson(sender.jsonSetting, WebhookSetting::class.java)
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) Log.d(TAG, settingVo.toString())
binding!!.btnDel.setText(R.string.discard) if (settingVo != null) {
} else { binding!!.rgMethod.check(settingVo.getMethodCheckId())
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) binding!!.etWebServer.setText(settingVo.webServer)
} binding!!.etSecret.setText(settingVo.secret)
binding!!.etName.setText(sender.name) binding!!.etResponse.setText(settingVo.response)
binding!!.sbEnable.isChecked = sender.status == 1 binding!!.etWebParams.setText(settingVo.webParams)
val settingVo = Gson().fromJson(sender.jsonSetting, WebhookSetting::class.java) //set header
Log.d(TAG, settingVo.toString()) if (settingVo.headers != null) {
if (settingVo != null) { for ((key, value) in settingVo.headers) {
binding!!.rgMethod.check(settingVo.getMethodCheckId()) addHeaderItemLinearLayout(
binding!!.etWebServer.setText(settingVo.webServer) headerItemMap, binding!!.layoutHeaders, key, value
binding!!.etSecret.setText(settingVo.secret) )
binding!!.etResponse.setText(settingVo.response)
binding!!.etWebParams.setText(settingVo.webParams)
//set header
if (settingVo.headers != null) {
for ((key, value) in settingVo.headers) {
addHeaderItemLinearLayout(
headerItemMap,
binding!!.layoutHeaders,
key,
value
)
}
} }
} }
} }
}) }
})
} }
override fun initListeners() { override fun initListeners() {
@ -192,17 +183,11 @@ class WebhookFragment : BaseFragment<FragmentSendersWebhookBinding?>(), View.OnC
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }
@ -215,8 +200,7 @@ class WebhookFragment : BaseFragment<FragmentSendersWebhookBinding?>(), View.OnC
val status = if (binding!!.sbEnable.isChecked) 1 else 0 val status = if (binding!!.sbEnable.isChecked) 1 else 0
val settingVo = checkSetting() val settingVo = checkSetting()
if (isClone) senderId = 0 if (isClone) senderId = 0
val senderNew = val senderNew = Sender(senderId, senderType, name, Gson().toJson(settingVo), status)
Sender(senderId, senderType, name, Gson().toJson(settingVo), status)
Log.d(TAG, senderNew.toString()) Log.d(TAG, senderNew.toString())
viewModel.insertOrUpdate(senderNew) viewModel.insertOrUpdate(senderNew)
@ -265,20 +249,13 @@ class WebhookFragment : BaseFragment<FragmentSendersWebhookBinding?>(), View.OnC
* @param value header的value为空则不设置 * @param value header的value为空则不设置
*/ */
private fun addHeaderItemLinearLayout( private fun addHeaderItemLinearLayout(
headerItemMap: MutableMap<Int, LinearLayout>, headerItemMap: MutableMap<Int, LinearLayout>, linearLayoutWebNotifyHeaders: LinearLayout, key: String?, value: String?
linearLayoutWebNotifyHeaders: LinearLayout,
key: String?,
value: String?
) { ) {
val linearLayoutItemAddHeader = val linearLayoutItemAddHeader = View.inflate(requireContext(), R.layout.item_add_header, null) as LinearLayout
View.inflate(requireContext(), R.layout.item_add_header, null) as LinearLayout val imageViewRemoveHeader = linearLayoutItemAddHeader.findViewById<ImageView>(R.id.imageViewRemoveHeader)
val imageViewRemoveHeader =
linearLayoutItemAddHeader.findViewById<ImageView>(R.id.imageViewRemoveHeader)
if (key != null && value != null) { if (key != null && value != null) {
val editTextHeaderKey = val editTextHeaderKey = linearLayoutItemAddHeader.findViewById<EditText>(R.id.editTextHeaderKey)
linearLayoutItemAddHeader.findViewById<EditText>(R.id.editTextHeaderKey) val editTextHeaderValue = linearLayoutItemAddHeader.findViewById<EditText>(R.id.editTextHeaderValue)
val editTextHeaderValue =
linearLayoutItemAddHeader.findViewById<EditText>(R.id.editTextHeaderValue)
editTextHeaderKey.setText(key) editTextHeaderKey.setText(key)
editTextHeaderValue.setText(value) editTextHeaderValue.setText(value)
} }

View File

@ -11,7 +11,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -98,51 +98,46 @@ class WeworkAgentFragment : BaseFragment<FragmentSendersWeworkAgentBinding?>(),
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkAgentSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etCorpID.setText(settingVo.corpID)
binding!!.etAgentID.setText(settingVo.agentID)
binding!!.etSecret.setText(settingVo.secret)
binding!!.sbAtAll.isChecked = settingVo.atAll == true
binding!!.etToUser.setText(settingVo.toUser)
binding!!.etToParty.setText(settingVo.toParty)
binding!!.etToTag.setText(settingVo.toTag)
binding!!.layoutToUser.visibility = if (settingVo.atAll == true) View.GONE else View.VISIBLE
binding!!.layoutToParty.visibility = if (settingVo.atAll == true) View.GONE else View.VISIBLE
binding!!.layoutToTag.visibility = if (settingVo.atAll == true) View.GONE else View.VISIBLE
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
binding!!.etProxyHost.setText(settingVo.proxyHost)
binding!!.etProxyPort.setText(settingVo.proxyPort)
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
binding!!.etCustomizeAPI.setText(settingVo.customizeAPI)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkAgentSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etCorpID.setText(settingVo.corpID)
binding!!.etAgentID.setText(settingVo.agentID)
binding!!.etSecret.setText(settingVo.secret)
binding!!.sbAtAll.isChecked = settingVo.atAll == true
binding!!.etToUser.setText(settingVo.toUser)
binding!!.etToParty.setText(settingVo.toParty)
binding!!.etToTag.setText(settingVo.toTag)
binding!!.layoutToUser.visibility = if (settingVo.atAll == true) View.GONE else View.VISIBLE
binding!!.layoutToParty.visibility = if (settingVo.atAll == true) View.GONE else View.VISIBLE
binding!!.layoutToTag.visibility = if (settingVo.atAll == true) View.GONE else View.VISIBLE
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
binding!!.etProxyHost.setText(settingVo.proxyHost)
binding!!.etProxyPort.setText(settingVo.proxyPort)
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
binding!!.etCustomizeAPI.setText(settingVo.customizeAPI)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -223,17 +218,11 @@ class WeworkAgentFragment : BaseFragment<FragmentSendersWeworkAgentBinding?>(),
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -10,7 +10,7 @@ import androidx.fragment.app.viewModels
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.BaseFragment import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel import com.idormy.sms.forwarder.database.viewmodel.SenderViewModel
@ -104,40 +104,35 @@ class WeworkRobotFragment : BaseFragment<FragmentSendersWeworkRobotBinding?>(),
//编辑 //编辑
binding!!.btnDel.setText(R.string.del) binding!!.btnDel.setText(R.string.del)
AppDatabase.getInstance(requireContext()) Core.sender.get(senderId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<Sender> {
.senderDao() override fun onSubscribe(d: Disposable) {}
.get(senderId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : SingleObserver<Sender> {
override fun onSubscribe(d: Disposable) {}
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
e.printStackTrace() e.printStackTrace()
Log.e(TAG, "onError:$e") Log.e(TAG, "onError:$e")
} }
override fun onSuccess(sender: Sender) { override fun onSuccess(sender: Sender) {
if (isClone) { if (isClone) {
titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.clone_sender) + ": " + sender.name)
binding!!.btnDel.setText(R.string.discard) binding!!.btnDel.setText(R.string.discard)
} else { } else {
titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name) titleBar?.setSubTitle(getString(R.string.edit_sender) + ": " + sender.name)
}
binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkRobotSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etWebHook.setText(settingVo.webHook)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.layoutAt.visibility = if (settingVo.getMsgTypeCheckId() == R.id.rb_msg_type_text) View.VISIBLE else View.GONE
binding!!.sbAtAll.isChecked = settingVo.atAll == true
binding!!.etAtMobiles.setText(settingVo.atMobiles)
binding!!.etAtUserIds.setText(settingVo.atUserIds)
}
} }
}) binding!!.etName.setText(sender.name)
binding!!.sbEnable.isChecked = sender.status == 1
val settingVo = Gson().fromJson(sender.jsonSetting, WeworkRobotSetting::class.java)
Log.d(TAG, settingVo.toString())
if (settingVo != null) {
binding!!.etWebHook.setText(settingVo.webHook)
binding!!.rgMsgType.check(settingVo.getMsgTypeCheckId())
binding!!.layoutAt.visibility = if (settingVo.getMsgTypeCheckId() == R.id.rb_msg_type_text) View.VISIBLE else View.GONE
binding!!.sbAtAll.isChecked = settingVo.atAll == true
binding!!.etAtMobiles.setText(settingVo.atMobiles)
binding!!.etAtUserIds.setText(settingVo.atUserIds)
}
}
})
} }
override fun initListeners() { override fun initListeners() {
@ -193,17 +188,11 @@ class WeworkRobotFragment : BaseFragment<FragmentSendersWeworkRobotBinding?>(),
return return
} }
MaterialDialog.Builder(requireContext()) MaterialDialog.Builder(requireContext()).title(R.string.delete_sender_title).content(R.string.delete_sender_tips).positiveText(R.string.lab_yes).negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
.title(R.string.delete_sender_title) viewModel.delete(senderId)
.content(R.string.delete_sender_tips) XToastUtils.success(R.string.delete_sender_toast)
.positiveText(R.string.lab_yes) popToBack()
.negativeText(R.string.lab_no) }.show()
.onPositive { _: MaterialDialog?, _: DialogAction? ->
viewModel.delete(senderId)
XToastUtils.success(R.string.delete_sender_toast)
popToBack()
}
.show()
return return
} }

View File

@ -16,11 +16,13 @@ import androidx.annotation.RequiresApi
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.workDataOf import androidx.work.workDataOf
import com.idormy.sms.forwarder.utils.DELAY_TIME_AFTER_SIM_READY
import com.idormy.sms.forwarder.utils.Log import com.idormy.sms.forwarder.utils.Log
import com.idormy.sms.forwarder.utils.TASK_CONDITION_NETWORK import com.idormy.sms.forwarder.utils.TASK_CONDITION_NETWORK
import com.idormy.sms.forwarder.utils.TaskWorker import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.task.TaskUtils import com.idormy.sms.forwarder.utils.task.TaskUtils
import com.idormy.sms.forwarder.workers.NetworkWorker import com.idormy.sms.forwarder.workers.NetworkWorker
import java.util.concurrent.TimeUnit
@Suppress("PrivatePropertyName", "DEPRECATION", "UNUSED_PARAMETER") @Suppress("PrivatePropertyName", "DEPRECATION", "UNUSED_PARAMETER")
class NetworkChangeReceiver : BroadcastReceiver() { class NetworkChangeReceiver : BroadcastReceiver() {
@ -84,12 +86,14 @@ class NetworkChangeReceiver : BroadcastReceiver() {
return return
} }
//获取公网IP地址后执行任务 //【注意】延迟5秒给够搜索信号时间才执行任务
val request = OneTimeWorkRequestBuilder<NetworkWorker>().setInputData( val request = OneTimeWorkRequestBuilder<NetworkWorker>()
workDataOf( .setInitialDelay(DELAY_TIME_AFTER_SIM_READY, TimeUnit.MILLISECONDS)
TaskWorker.conditionType to TASK_CONDITION_NETWORK, .setInputData(
) workDataOf(
).build() TaskWorker.conditionType to TASK_CONDITION_NETWORK,
)
).build()
WorkManager.getInstance(context).enqueue(request) WorkManager.getInstance(context).enqueue(request)
} }

View File

@ -12,10 +12,9 @@ import androidx.core.app.NotificationCompat
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.utils.* import com.idormy.sms.forwarder.utils.*
import com.idormy.sms.forwarder.utils.task.CronJobScheduler import com.idormy.sms.forwarder.utils.task.CronJobScheduler
import com.idormy.sms.forwarder.workers.LoadAppListWorker import com.idormy.sms.forwarder.workers.LoadAppListWorker
@ -45,7 +44,7 @@ class ForegroundService : Service() {
if (Frpclib.isRunning(uid)) { if (Frpclib.isRunning(uid)) {
return@Observer return@Observer
} }
AppDatabase.getInstance(App.context).frpcDao().get(uid).flatMap { (uid1, _, config) -> Core.frpc.get(uid).flatMap { (uid1, _, config) ->
val error = Frpclib.runContent(uid1, config) val error = Frpclib.runContent(uid1, config)
Single.just(error) Single.just(error)
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<String> { }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(object : SingleObserver<String> {
@ -130,7 +129,7 @@ class ForegroundService : Service() {
//启动定时任务 //启动定时任务
GlobalScope.async(Dispatchers.IO) { GlobalScope.async(Dispatchers.IO) {
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(TASK_CONDITION_CRON) val taskList = Core.task.getByType(TASK_CONDITION_CRON)
taskList.forEach { task -> taskList.forEach { task ->
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")
CronJobScheduler.cancelTask(task.id) CronJobScheduler.cancelTask(task.id)
@ -150,7 +149,7 @@ class ForegroundService : Service() {
LiveEventBus.get(INTENT_FRPC_APPLY_FILE, String::class.java).observeStickyForever(frpcObserver) LiveEventBus.get(INTENT_FRPC_APPLY_FILE, String::class.java).observeStickyForever(frpcObserver)
//自启动的Frpc //自启动的Frpc
GlobalScope.async(Dispatchers.IO) { GlobalScope.async(Dispatchers.IO) {
val frpcList = AppDatabase.getInstance(App.context).frpcDao().getAutorun() val frpcList = Core.frpc.getAutorun()
if (frpcList.isEmpty()) { if (frpcList.isEmpty()) {
Log.d(TAG, "没有自启动的Frpc") Log.d(TAG, "没有自启动的Frpc")

View File

@ -237,8 +237,8 @@ const val TASK_ACTION_SENDSMS = 2000
const val TASK_ACTION_NOTIFICATION = 2001 const val TASK_ACTION_NOTIFICATION = 2001
const val TASK_ACTION_CLEANER = 2002 const val TASK_ACTION_CLEANER = 2002
const val TASK_ACTION_SETTINGS = 2003 const val TASK_ACTION_SETTINGS = 2003
const val TASK_ACTION_HTTPSERVER = 2004 const val TASK_ACTION_FRPC = 2004
const val TASK_ACTION_FRPC = 2005 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

View File

@ -8,7 +8,7 @@ import android.net.wifi.WifiManager
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.server.model.SmsSendData import com.idormy.sms.forwarder.server.model.SmsSendData
import com.idormy.sms.forwarder.service.HttpServerService import com.idormy.sms.forwarder.service.HttpServerService
import com.xuexiang.xrouter.utils.TextUtils import com.xuexiang.xrouter.utils.TextUtils
@ -50,10 +50,10 @@ class SmsCommandUtils {
GlobalScope.async(Dispatchers.IO) { GlobalScope.async(Dispatchers.IO) {
val frpcList = if (param.isEmpty()) { val frpcList = if (param.isEmpty()) {
AppDatabase.getInstance(App.context).frpcDao().getAutorun() Core.frpc.getAutorun()
} else { } else {
val uids = param.split(",") val uids = param.split(",")
AppDatabase.getInstance(App.context).frpcDao().getByUids(uids) Core.frpc.getByUids(uids)
} }
if (frpcList.isEmpty()) { if (frpcList.isEmpty()) {

View File

@ -43,9 +43,9 @@ class ConditionUtils private constructor() {
return true return true
} }
//注意:触发条件 = SIM卡已准备就绪延迟5秒给够搜索信号时间才执行任务 //注意:触发条件 = SIM卡已准备就绪/网络状态改变延迟5秒给够搜索信号时间才执行任务
val firstCondition = conditionList.firstOrNull() val firstCondition = conditionList.firstOrNull()
val needDelay = firstCondition?.type == TASK_CONDITION_SIM && TaskUtils.simState == 5 val needDelay = (firstCondition?.type == TASK_CONDITION_SIM && TaskUtils.simState == 5) || (firstCondition?.type == TASK_CONDITION_NETWORK && TaskUtils.networkState != 0)
for (i in startIndex until conditionList.size) { for (i in startIndex until conditionList.size) {
val condition = conditionList[i] val condition = conditionList[i]

View File

@ -57,8 +57,8 @@ class TaskUtils private constructor() {
TASK_ACTION_NOTIFICATION -> R.drawable.auto_task_icon_notification TASK_ACTION_NOTIFICATION -> R.drawable.auto_task_icon_notification
TASK_ACTION_CLEANER -> R.drawable.auto_task_icon_cleaner TASK_ACTION_CLEANER -> R.drawable.auto_task_icon_cleaner
TASK_ACTION_SETTINGS -> R.drawable.auto_task_icon_settings TASK_ACTION_SETTINGS -> R.drawable.auto_task_icon_settings
TASK_ACTION_HTTPSERVER -> R.drawable.auto_task_icon_http_server
TASK_ACTION_FRPC -> R.drawable.auto_task_icon_frpc TASK_ACTION_FRPC -> R.drawable.auto_task_icon_frpc
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
else -> R.drawable.auto_task_icon_custom_time else -> R.drawable.auto_task_icon_custom_time
@ -80,8 +80,8 @@ class TaskUtils private constructor() {
TASK_ACTION_NOTIFICATION -> R.drawable.auto_task_icon_notification_grey TASK_ACTION_NOTIFICATION -> R.drawable.auto_task_icon_notification_grey
TASK_ACTION_CLEANER -> R.drawable.auto_task_icon_cleaner_grey TASK_ACTION_CLEANER -> R.drawable.auto_task_icon_cleaner_grey
TASK_ACTION_SETTINGS -> R.drawable.auto_task_icon_settings_grey TASK_ACTION_SETTINGS -> R.drawable.auto_task_icon_settings_grey
TASK_ACTION_HTTPSERVER -> R.drawable.auto_task_icon_http_server_grey
TASK_ACTION_FRPC -> R.drawable.auto_task_icon_frpc_grey TASK_ACTION_FRPC -> R.drawable.auto_task_icon_frpc_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
else -> R.drawable.auto_task_icon_custom_time_grey else -> R.drawable.auto_task_icon_custom_time_grey

View File

@ -13,13 +13,14 @@ import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.Core import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.database.entity.Rule import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
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.RuleSetting
import com.idormy.sms.forwarder.entity.action.SenderSetting
import com.idormy.sms.forwarder.entity.action.SettingsSetting import com.idormy.sms.forwarder.entity.action.SettingsSetting
import com.idormy.sms.forwarder.entity.action.SmsSetting import com.idormy.sms.forwarder.entity.action.SmsSetting
import com.idormy.sms.forwarder.service.HttpServerService import com.idormy.sms.forwarder.service.HttpServerService
@ -39,6 +40,8 @@ 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_RULE
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
import com.idormy.sms.forwarder.utils.TASK_ACTION_SETTINGS import com.idormy.sms.forwarder.utils.TASK_ACTION_SETTINGS
import com.idormy.sms.forwarder.utils.TaskWorker import com.idormy.sms.forwarder.utils.TaskWorker
@ -197,11 +200,8 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
continue continue
} }
val frpcList = if (frpcSetting.uids.isEmpty()) { val frpcList = frpcSetting.frpcList.ifEmpty {
AppDatabase.getInstance(App.context).frpcDao().getAutorun() Core.frpc.getAutorun()
} else {
val uids = frpcSetting.uids.split(",")
AppDatabase.getInstance(App.context).frpcDao().getByUids(uids)
} }
if (frpcList.isEmpty()) { if (frpcList.isEmpty()) {
@ -256,6 +256,38 @@ class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker
writeLog("httpServer success", "SUCCESS") writeLog("httpServer success", "SUCCESS")
} }
TASK_ACTION_RULE -> {
val ruleSetting = Gson().fromJson(action.setting, RuleSetting::class.java)
if (ruleSetting == null) {
writeLog("httpServerSetting is null")
continue
}
val ids = ruleSetting.ruleList.map { it.id }
if (ids.isNotEmpty()) {
Core.rule.updateStatusByIds(ids, ruleSetting.status)
}
successNum++
writeLog("update rule success", "SUCCESS")
}
TASK_ACTION_SENDER -> {
val senderSetting = Gson().fromJson(action.setting, SenderSetting::class.java)
if (senderSetting == null) {
writeLog("senderSetting is null")
continue
}
val ids = senderSetting.senderList.map { it.id }
if (ids.isNotEmpty()) {
Core.sender.updateStatusByIds(ids, senderSetting.status)
}
successNum++
writeLog("update sender success", "SUCCESS")
}
else -> { else -> {
writeLog("action.type is ${action.type}") writeLog("action.type is ${action.type}")
} }

View File

@ -7,8 +7,7 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.condition.BatterySetting import com.idormy.sms.forwarder.entity.condition.BatterySetting
@ -40,7 +39,7 @@ class BatteryWorker(context: Context, params: WorkerParameters) : CoroutineWorke
return Result.failure() return Result.failure()
} }
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")
@ -95,7 +94,7 @@ class BatteryWorker(context: Context, params: WorkerParameters) : CoroutineWorke
return Result.failure() return Result.failure()
} }
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")

View File

@ -7,8 +7,7 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.condition.CronSetting import com.idormy.sms.forwarder.entity.condition.CronSetting
@ -32,7 +31,7 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
return Result.failure() return Result.failure()
} }
val task = AppDatabase.getInstance(App.context).taskDao().getOne(taskId) val task = Core.task.getOne(taskId)
if (task == null || task.status == 0) { if (task == null || task.status == 0) {
Log.d(TAG, "TASK-$taskIdtask is disabled") Log.d(TAG, "TASK-$taskIdtask is disabled")
return Result.success() return Result.success()
@ -77,7 +76,7 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
} }
// 更新任务信息 // 更新任务信息
AppDatabase.getInstance(App.context).taskDao().updateExecTime(task.id, task.lastExecTime, task.nextExecTime, task.status) Core.task.updateExecTime(task.id, task.lastExecTime, task.nextExecTime, task.status)
if (task.status == 0) { if (task.status == 0) {
Log.d(TAG, "TASK-${task.id}task is disabled") Log.d(TAG, "TASK-${task.id}task is disabled")

View File

@ -7,9 +7,8 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.entity.LocationInfo import com.idormy.sms.forwarder.entity.LocationInfo
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
@ -51,7 +50,7 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
//到达地点 //到达地点
TASK_CONDITION_TO_ADDRESS -> { TASK_CONDITION_TO_ADDRESS -> {
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")
@ -114,7 +113,7 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
//离开地点 //离开地点
TASK_CONDITION_LEAVE_ADDRESS -> { TASK_CONDITION_LEAVE_ADDRESS -> {
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")

View File

@ -8,8 +8,7 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.condition.LockScreenSetting import com.idormy.sms.forwarder.entity.condition.LockScreenSetting
@ -29,7 +28,7 @@ class LockScreenWorker(context: Context, params: WorkerParameters) : CoroutineWo
val conditionType = inputData.getInt(TaskWorker.conditionType, -1) val conditionType = inputData.getInt(TaskWorker.conditionType, -1)
val action = inputData.getString(TaskWorker.action) val action = inputData.getString(TaskWorker.action)
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")

View File

@ -9,7 +9,7 @@ import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.condition.NetworkSetting import com.idormy.sms.forwarder.entity.condition.NetworkSetting
@ -34,7 +34,7 @@ class NetworkWorker(context: Context, params: WorkerParameters) : CoroutineWorke
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
try { try {
val conditionType = inputData.getInt(TaskWorker.conditionType, -1) val conditionType = inputData.getInt(TaskWorker.conditionType, -1)
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")
@ -61,7 +61,7 @@ class NetworkWorker(context: Context, params: WorkerParameters) : CoroutineWorke
continue continue
} }
//TODO判断其他条件是否满足 //TODO判断其他条件是否满足注意延迟5秒给够搜索信号时间才执行任务
if (!ConditionUtils.checkCondition(task.id, conditionList)) { if (!ConditionUtils.checkCondition(task.id, conditionList)) {
Log.d(TAG, "TASK-${task.id}other condition is not satisfied") Log.d(TAG, "TASK-${task.id}other condition is not satisfied")
continue continue
@ -92,7 +92,6 @@ class NetworkWorker(context: Context, params: WorkerParameters) : CoroutineWorke
} }
} }
Thread.sleep(1000) //延迟2秒等待获取IP地址
ipv4 = getPublicIP(false) ipv4 = getPublicIP(false)
ipv6 = getPublicIP(true) ipv6 = getPublicIP(true)
} }
@ -106,7 +105,6 @@ class NetworkWorker(context: Context, params: WorkerParameters) : CoroutineWorke
msg.append(getString(R.string.net_wifi)).append("\n") msg.append(getString(R.string.net_wifi)).append("\n")
msg.append(getString(R.string.wifi_ssid)).append(": ").append(TaskUtils.wifiSsid).append("\n") msg.append(getString(R.string.wifi_ssid)).append(": ").append(TaskUtils.wifiSsid).append("\n")
Thread.sleep(2000) //延迟2秒等待获取IP地址
ipv4 = getPublicIP(false) ipv4 = getPublicIP(false)
ipv6 = getPublicIP(true) ipv6 = getPublicIP(true)
} }
@ -154,6 +152,8 @@ class NetworkWorker(context: Context, params: WorkerParameters) : CoroutineWorke
//获取公网IP地址 //获取公网IP地址
private fun getPublicIP(ipv6: Boolean = false): String { private fun getPublicIP(ipv6: Boolean = false): String {
if (TaskUtils.networkState == 0) return ""
return try { return try {
val url = if (ipv6) URL("https://api6.ipify.org/") else URL("https://api.ipify.org/") val url = if (ipv6) URL("https://api6.ipify.org/") else URL("https://api.ipify.org/")
val urlConnection = url.openConnection() as HttpURLConnection val urlConnection = url.openConnection() as HttpURLConnection

View File

@ -10,7 +10,7 @@ import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.TaskSetting import com.idormy.sms.forwarder.entity.TaskSetting
import com.idormy.sms.forwarder.entity.condition.SimSetting import com.idormy.sms.forwarder.entity.condition.SimSetting
@ -31,7 +31,7 @@ class SimWorker(context: Context, params: WorkerParameters) : CoroutineWorker(co
try { try {
val conditionType = inputData.getInt(TaskWorker.conditionType, -1) val conditionType = inputData.getInt(TaskWorker.conditionType, -1)
val simStateStr = inputData.getString(TaskWorker.msg) val simStateStr = inputData.getString(TaskWorker.msg)
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = Core.task.getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<vector android:height="25.0dip" android:width="25.0dip" android:autoMirrored="true" android:viewportWidth="25.0" android:viewportHeight="25.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/color_green_primary_default" 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" />
<path android:fillColor="#ffffffff" android:pathData="M9.372,6.643C9.337,6.583 9.292,6.531 9.238,6.488C9.078,6.322 8.846,6.252 8.622,6.298L8.486,6.314C8.453,6.313 8.427,6.318 8.412,6.321C8.375,6.328 8.344,6.34 8.326,6.348C8.285,6.365 8.24,6.388 8.197,6.412C8.107,6.462 7.991,6.534 7.864,6.615C7.609,6.779 7.295,6.995 7.034,7.186L7.029,7.19L7.025,7.193C6.433,7.657 6.249,8.29 6.29,8.968C6.327,9.585 6.549,10.26 6.823,10.93L6.81,10.951L6.872,11.093C7.346,12.181 8.27,13.582 9.741,15.108L9.738,15.112L9.926,15.3L9.993,15.366L10.009,15.381L10.02,15.392L10.113,15.299L10.114,15.3L10.021,15.394C11.622,16.972 13.094,17.953 14.226,18.447L14.368,18.509L14.389,18.496C15.058,18.77 15.734,18.992 16.351,19.029C17.028,19.07 17.662,18.886 18.126,18.294L18.129,18.29L18.132,18.285C18.323,18.024 18.539,17.71 18.703,17.455C18.785,17.328 18.857,17.212 18.906,17.122C18.931,17.079 18.954,17.034 18.971,16.993C18.979,16.975 18.991,16.944 18.998,16.907C19.001,16.892 19.006,16.866 19.005,16.833L19.02,16.697C19.066,16.473 18.996,16.241 18.831,16.081C18.788,16.028 18.736,15.982 18.676,15.948L18.64,15.92L15.363,14.127L13.785,15.497C13.005,15.085 12.239,14.414 11.574,13.762C10.916,13.093 10.237,12.321 9.822,11.533L11.192,9.955L9.399,6.679L9.372,6.643ZM10.039,15.186L10.039,15.185L10.048,15.176L10.049,15.177C10.059,15.207 10.073,15.237 10.091,15.267L10.09,15.268C10.071,15.244 10.053,15.217 10.039,15.186ZM10.005,14.98L10.02,14.991C10.021,14.98 10.022,14.971 10.024,14.965C10.023,14.965 10.023,14.964 10.022,14.963C10.017,14.968 10.011,14.974 10.005,14.98ZM10.091,15.269L10.092,15.268L10.101,15.281L10.091,15.269ZM10.116,15.298L10.115,15.297L10.234,15.178L10.116,15.298ZM10.431,15.407L10.441,15.398L10.44,15.4L10.431,15.407ZM10.425,15.413L10.428,15.41L10.427,15.411L10.425,15.413ZM10.394,15.435L10.391,15.436L10.403,15.429L10.394,15.435ZM10.408,15.426L10.407,15.427L10.41,15.424L10.408,15.426Z" android:fillType="evenOdd" />
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<vector android:height="25.0dip" android:width="25.0dip" android:autoMirrored="true" android:viewportWidth="25.0" android:viewportHeight="25.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/auto_task_icon_light_blue" 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" />
<path android:fillColor="#ffffffff" android:pathData="M7.984,5.837C8.418,5.586 8.974,5.735 9.224,6.169L9.779,7.13C10.518,6.712 11.372,6.473 12.282,6.473C13.199,6.473 14.06,6.715 14.803,7.14L15.342,6.207C15.592,5.772 16.148,5.623 16.582,5.874C17.017,6.125 17.165,6.68 16.915,7.115L16.212,8.331C16.862,9.121 17.278,10.11 17.355,11.194H7.21C7.287,10.103 7.708,9.107 8.366,8.314L7.651,7.077C7.401,6.643 7.55,6.087 7.984,5.837ZM17.368,12.647H7.198V17.732C7.198,18.535 7.848,19.185 8.651,19.185H15.915C16.718,19.185 17.368,18.535 17.368,17.732V12.647Z" android:fillType="evenOdd" />
</vector>

View File

@ -58,6 +58,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView

View File

@ -150,12 +150,12 @@
style="@style/BarStyle" style="@style/BarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -190,12 +190,12 @@
style="@style/BarStyle" style="@style/BarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView
@ -230,12 +230,12 @@
style="@style/BarStyle" style="@style/BarStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
<TextView <TextView

View File

@ -66,6 +66,7 @@
android:text="@string/forward_sms_tips" android:text="@string/forward_sms_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
@ -928,7 +929,7 @@
style="@style/SwitchButtonStyle" style="@style/SwitchButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck,DuplicateSpeakableTextCheck" />
</LinearLayout> </LinearLayout>
@ -1119,6 +1120,7 @@
android:text="@string/retry_interval_tips" android:text="@string/retry_interval_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -1257,6 +1259,7 @@
android:text="@string/custom_settings_tips" android:text="@string/custom_settings_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -1276,7 +1279,8 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_weight="1" /> android:layout_weight="1"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton <com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/btn_extra_device_mark" android:id="@+id/btn_extra_device_mark"
@ -1292,7 +1296,7 @@
app:sb_ripple_color="@color/white" app:sb_ripple_color="@color/white"
app:sb_ripple_duration="500" app:sb_ripple_duration="500"
app:sb_shape_type="rectangle" app:sb_shape_type="rectangle"
tools:ignore="SmallSp" /> tools:ignore="SmallSp,DuplicateSpeakableTextCheck,TextContrastCheck,TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -1320,6 +1324,7 @@
android:text="@string/carrier_mobile" android:text="@string/carrier_mobile"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText <com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
@ -1337,7 +1342,8 @@
app:met_autoValidate="true" app:met_autoValidate="true"
app:met_errorMessage="@string/tip_number_only_error_message" app:met_errorMessage="@string/tip_number_only_error_message"
app:met_regexp="@string/regexp_number_only" app:met_regexp="@string/regexp_number_only"
app:met_validateOnFocusLost="true" /> app:met_validateOnFocusLost="true"
tools:ignore="DuplicateSpeakableTextCheck,TextContrastCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText <com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_extra_sim1" android:id="@+id/et_extra_sim1"
@ -1347,7 +1353,8 @@
android:layout_weight="3" android:layout_weight="3"
android:hint="@string/custom_settings_tips" android:hint="@string/custom_settings_tips"
android:singleLine="true" android:singleLine="true"
app:met_clearButton="true" /> app:met_clearButton="true"
tools:ignore="DuplicateSpeakableTextCheck,TextContrastCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton <com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/btn_extra_sim1" android:id="@+id/btn_extra_sim1"
@ -1363,7 +1370,7 @@
app:sb_ripple_color="@color/white" app:sb_ripple_color="@color/white"
app:sb_ripple_duration="500" app:sb_ripple_duration="500"
app:sb_shape_type="rectangle" app:sb_shape_type="rectangle"
tools:ignore="SmallSp" /> tools:ignore="SmallSp,TextContrastCheck,TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -1391,6 +1398,7 @@
android:text="@string/carrier_mobile" android:text="@string/carrier_mobile"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText <com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
@ -1408,7 +1416,8 @@
app:met_autoValidate="true" app:met_autoValidate="true"
app:met_errorMessage="@string/tip_number_only_error_message" app:met_errorMessage="@string/tip_number_only_error_message"
app:met_regexp="@string/regexp_number_only" app:met_regexp="@string/regexp_number_only"
app:met_validateOnFocusLost="true" /> app:met_validateOnFocusLost="true"
tools:ignore="TextContrastCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText <com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
android:id="@+id/et_extra_sim2" android:id="@+id/et_extra_sim2"
@ -1418,7 +1427,8 @@
android:layout_weight="3" android:layout_weight="3"
android:hint="@string/custom_settings_tips" android:hint="@string/custom_settings_tips"
android:singleLine="true" android:singleLine="true"
app:met_clearButton="true" /> app:met_clearButton="true"
tools:ignore="TextContrastCheck,TouchTargetSizeCheck" />
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton <com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/btn_extra_sim2" android:id="@+id/btn_extra_sim2"
@ -1434,7 +1444,7 @@
app:sb_ripple_color="@color/white" app:sb_ripple_color="@color/white"
app:sb_ripple_duration="500" app:sb_ripple_duration="500"
app:sb_shape_type="rectangle" app:sb_shape_type="rectangle"
tools:ignore="SmallSp" /> tools:ignore="SmallSp,TextContrastCheck,TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -1457,7 +1467,8 @@
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_weight="1" android:layout_weight="1"
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:minLines="1" /> android:minLines="1"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -1485,13 +1496,15 @@
android:text="@string/enable_custom_templates_tips" android:text="@string/enable_custom_templates_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
android:id="@+id/sb_sms_template" android:id="@+id/sb_sms_template"
style="@style/SwitchButtonStyle" style="@style/SwitchButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
tools:ignore="TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -1533,7 +1546,7 @@
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:minLines="1" android:minLines="1"
android:text="" android:text=""
tools:ignore="RtlHardcoded" /> tools:ignore="RtlHardcoded,SpeakableTextPresentCheck" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -1597,6 +1610,7 @@
android:text="@string/pure_client_mode_tips" android:text="@string/pure_client_mode_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
@ -1631,6 +1645,7 @@
android:text="@string/pure_task_mode_tips" android:text="@string/pure_task_mode_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
@ -1652,12 +1667,36 @@
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical"> android:orientation="vertical">
<TextView <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/debug_mode" android:gravity="center_vertical"
android:textStyle="bold" android:orientation="horizontal">
tools:ignore="RelativeOverlap" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/debug_mode"
android:textStyle="bold"
tools:ignore="RelativeOverlap" />
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
android:id="@+id/btn_export_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:gravity="center"
android:padding="3dp"
android:text="@string/export"
android:textColor="@color/white"
android:textSize="@dimen/text_size_mini"
app:sb_color_unpressed="@color/colorPrimary"
app:sb_ripple_color="@color/white"
app:sb_ripple_duration="500"
app:sb_shape_type="rectangle"
tools:ignore="PrivateResource,SmallSp" />
</LinearLayout>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -1665,22 +1704,8 @@
android:text="@string/debug_mode_tips" android:text="@string/debug_mode_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout>
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton </LinearLayout>
android:id="@+id/btn_export_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:text="@string/export"
android:textColor="@color/white"
android:textSize="@dimen/text_size_small"
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" />
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
android:id="@+id/sb_debug_mode" android:id="@+id/sb_debug_mode"

View File

@ -59,81 +59,54 @@
<RadioGroup <RadioGroup
android:id="@+id/rg_frpc_state" android:id="@+id/rg_frpc_state"
style="@style/rg_style" style="@style/rg_style"
android:orientation="vertical" android:orientation="horizontal"
android:paddingBottom="@dimen/config_padding_5dp"> android:paddingBottom="@dimen/config_padding_5dp">
<RadioButton <RadioButton
android:id="@+id/rb_start_server" android:id="@+id/rb_start_server"
style="@style/rg_rb_style_match" style="@style/rg_rb_style"
android:checked="true" android:checked="true"
android:text="@string/start_server" android:text="@string/start_server"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
<LinearLayout
android:id="@+id/layout_start_server"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/config_margin_10dp"
android:layout_marginEnd="@dimen/config_margin_10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/specified_uid"
android:textStyle="bold" />
<EditText
android:id="@+id/et_start_uid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:hint="@string/specified_uid_hint"
android:importantForAutofill="no"
tools:ignore="TextContrastCheck,TextFields,TouchTargetSizeCheck" />
</LinearLayout>
<RadioButton <RadioButton
android:id="@+id/rb_stop_server" android:id="@+id/rb_stop_server"
style="@style/rg_rb_style_match" style="@style/rg_rb_style"
android:text="@string/stop_server" android:text="@string/stop_server"
tools:ignore="TouchTargetSizeCheck" /> tools:ignore="TouchTargetSizeCheck" />
<LinearLayout
android:id="@+id/layout_stop_server"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/config_margin_10dp"
android:layout_marginEnd="@dimen/config_margin_10dp"
android:orientation="horizontal"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/specified_uid"
android:textStyle="bold" />
<EditText
android:id="@+id/et_stop_uid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:hint="@string/specified_uid_hint"
android:importantForAutofill="no"
tools:ignore="TextContrastCheck,TextFields,TouchTargetSizeCheck" />
</LinearLayout>
</RadioGroup> </RadioGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/specified_uid"
android:textStyle="bold" />
<com.xuexiang.xui.widget.spinner.editspinner.EditSpinner
android:id="@+id/sp_frpc"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_weight="1"
app:es_hint="@string/choose_frpc"
app:es_maxLength="20"
app:es_maxLine="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_frpcs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -60,7 +60,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:id="@+id/layout_Senders" android:id="@+id/layout_senders"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" /> android:orientation="vertical" />

View File

@ -54,7 +54,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
style="@style/BarStyle" style="@style/BarStyle.Switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -69,7 +69,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/forward_sms" android:text="@string/forward_sms"
android:textStyle="bold" android:textStyle="bold"
tools:ignore="RelativeOverlap,TextContrastCheck" /> tools:ignore="RelativeOverlap" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -77,6 +77,7 @@
android:text="@string/forward_sms_tips" android:text="@string/forward_sms_tips"
android:textSize="@dimen/text_size_mini" android:textSize="@dimen/text_size_mini"
tools:ignore="SmallSp" /> tools:ignore="SmallSp" />
</LinearLayout> </LinearLayout>
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
@ -89,7 +90,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
style="@style/BarStyle" style="@style/BarStyle.Switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -260,7 +261,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
style="@style/BarStyle" style="@style/BarStyle.Switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
@ -290,7 +291,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal"
tools:ignore="TextSizeCheck">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -304,7 +306,8 @@
android:id="@+id/scb_cancel_app_notify" android:id="@+id/scb_cancel_app_notify"
android:layout_width="15dp" android:layout_width="15dp"
android:layout_height="15dp" android:layout_height="15dp"
app:scb_color_checked="@color/colorPrimary" /> app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -318,7 +321,8 @@
android:layout_width="15dp" android:layout_width="15dp"
android:layout_height="15dp" android:layout_height="15dp"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
app:scb_color_checked="@color/colorPrimary" /> app:scb_color_checked="@color/colorPrimary"
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" />
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -344,7 +348,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="10dp"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal">
@ -366,7 +370,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
style="@style/BarStyle" style="@style/BarStyle.Switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:gravity="center_vertical"
@ -413,7 +417,7 @@
android:id="@+id/layout_location_setting" android:id="@+id/layout_location_setting"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="5dp" android:layout_marginTop="5dp"
android:orientation="vertical"> android:orientation="vertical">
<View <View
@ -589,7 +593,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
style="@style/BarStyle" style="@style/BarStyle.Switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical"> android:gravity="center_vertical">
@ -618,7 +622,8 @@
android:id="@+id/et_safe_phone" android:id="@+id/et_safe_phone"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/safe_phone_tips" /> android:hint="@string/safe_phone_tips"
tools:ignore="TextContrastCheck,TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -632,7 +637,7 @@
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
style="@style/BarStyle" style="@style/BarStyle.Switch"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">

View File

@ -66,49 +66,56 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/second" /> android:text="@string/second"
android:textSize="@dimen/text_size_mini" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/minute" /> android:text="@string/minute"
android:textSize="@dimen/text_size_mini" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/hour" /> android:text="@string/hour"
android:textSize="@dimen/text_size_mini" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/day" /> android:text="@string/day"
android:textSize="@dimen/text_size_mini" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/month" /> android:text="@string/month"
android:textSize="@dimen/text_size_mini" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/week" /> android:text="@string/week"
android:textSize="@dimen/text_size_mini" />
<TextView <TextView
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/year" /> android:text="@string/year"
android:textSize="@dimen/text_size_mini" />
</LinearLayout> </LinearLayout>
<View <View

View File

@ -0,0 +1,68 @@
<?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="@color/xui_config_color_white"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/xui_config_color_separator_light" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="24dp"
android:layout_height="24dp"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_frpc_image"
android:layout_width="24dp"
android:layout_height="24dp"
tools:ignore="ContentDescription,UseAppTint" />
<ImageView
android:id="@+id/iv_frpc_status"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_marginStart="14dp"
android:layout_marginTop="-10dp"
tools:ignore="ContentDescription" />
</LinearLayout>
<TextView
android:id="@+id/tv_frpc_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:ellipsize="marquee"
android:minHeight="?attr/ms_item_height_size"
android:paddingStart="?attr/ms_padding_left_size"
android:paddingTop="?attr/ms_padding_top_size"
android:paddingEnd="?attr/ms_padding_left_size"
android:paddingBottom="?attr/ms_padding_top_size"
android:singleLine="true"
tools:ignore="PrivateResource" />
<ImageView
android:id="@+id/iv_remove_frpc"
android:layout_width="18dp"
android:layout_height="18dp"
android:contentDescription="@string/frpc_del"
android:src="@drawable/ic_delete"
app:tint="#F15C58" />
</LinearLayout>
</LinearLayout>

View File

@ -28,7 +28,7 @@
android:id="@+id/iv_rule_image" android:id="@+id/iv_rule_image"
android:layout_width="24dp" android:layout_width="24dp"
android:layout_height="24dp" android:layout_height="24dp"
tools:ignore="ContentDescription" /> tools:ignore="ContentDescription,UseAppTint" />
<ImageView <ImageView
android:id="@+id/iv_rule_status" android:id="@+id/iv_rule_status"

View File

@ -21,9 +21,6 @@
<string name="app_browser_name">Universal Browser</string> <string name="app_browser_name">Universal Browser</string>
<string name="description_navigation_main">navigation</string> <string name="description_navigation_main">navigation</string>
<string name="guide_key_sliding_root_navigation">guide_key_sliding_root_navigation</string>
<string name="navigation_drawer_open">Open navigation drawer</string>
<string name="navigation_drawer_close">Close navigation drawer</string>
<string name="menu_logs">Logs</string> <string name="menu_logs">Logs</string>
<string name="menu_senders">Senders</string> <string name="menu_senders">Senders</string>
@ -234,8 +231,11 @@
<string name="delete_rule_tips">Are you sure to delete this rule?</string> <string name="delete_rule_tips">Are you sure to delete this rule?</string>
<string name="delete_rule_toast">The rule has deleted.</string> <string name="delete_rule_toast">The rule has deleted.</string>
<string name="new_sender_first">Please add a new sender and then choose it.</string> <string name="new_sender_first">Please add a new sender and then choose it.</string>
<string name="new_rule_first">Please add a new rule and then choose it.</string>
<string name="new_frpc_first">Please add a new frpc and then choose it.</string>
<string name="add_sender_first">Please add a sender first.</string> <string name="add_sender_first">Please add a sender first.</string>
<string name="add_rule_first">Please add a rule first.</string> <string name="add_rule_first">Please add a rule first.</string>
<string name="add_frpc_first">Please add a frpc first.</string>
<string name="select_sender">Select Sender</string> <string name="select_sender">Select Sender</string>
<string name="rule_tester">Rule tester:</string> <string name="rule_tester">Rule tester:</string>
<string name="test_sim_slot">Test SIM Slot</string> <string name="test_sim_slot">Test SIM Slot</string>
@ -336,7 +336,7 @@
<string name="Customize_API">Customize API</string> <string name="Customize_API">Customize API</string>
<string name="Corp_ID">Corp ID</string> <string name="Corp_ID">Corp ID</string>
<string name="Agent_ID">Agent ID</string> <string name="Agent_ID">Agent ID</string>
<string name="App_Secret">App Secret</string> <string name="App_Secret">Secret</string>
<string name="is_at_all">Is At All</string> <string name="is_at_all">Is At All</string>
<string name="specified_member">Specified Member</string> <string name="specified_member">Specified Member</string>
<string name="at_all">\@all</string> <string name="at_all">\@all</string>
@ -826,6 +826,7 @@
<string name="pushplus_token_hint">Please go to the corresponding official website to obtain</string> <string name="pushplus_token_hint">Please go to the corresponding official website to obtain</string>
<string name="choose_rule">Drop-down selection, keyword fuzzy match</string> <string name="choose_rule">Drop-down selection, keyword fuzzy match</string>
<string name="choose_sender">Drop-down selection, keyword fuzzy match</string> <string name="choose_sender">Drop-down selection, keyword fuzzy match</string>
<string name="choose_frpc">Drop-down selection, keyword fuzzy match</string>
<string name="choose_app">Installed Apps</string> <string name="choose_app">Installed Apps</string>
<string name="extra_app">Extra Apps</string> <string name="extra_app">Extra Apps</string>
<string name="extra_app_hint">One package name per line\nEnable async loading of the App list for selection.</string> <string name="extra_app_hint">One package name per line\nEnable async loading of the App list for selection.</string>
@ -976,6 +977,7 @@
<string name="rule_disabled_tips">[Note] The rule has been disabled, will not be sent even if they match!</string> <string name="rule_disabled_tips">[Note] The rule has been disabled, will not be sent even if they match!</string>
<string name="sender_contains_tips">[Note] The sending channel is already in the list, no need to add it again!</string> <string name="sender_contains_tips">[Note] The sending channel is already in the list, no need to add it again!</string>
<string name="rule_contains_tips">[Note] The rule is already in the list, no need to add it again!</string> <string name="rule_contains_tips">[Note] The rule is already in the list, no need to add it again!</string>
<string name="frpc_contains_tips">[Note] The frpc is already in the list, no need to add it again!</string>
<string name="local_call">Local Call:</string> <string name="local_call">Local Call:</string>
<string name="remote_sms">Remote SMS</string> <string name="remote_sms">Remote SMS</string>
<string name="clear">Clear</string> <string name="clear">Clear</string>
@ -1087,6 +1089,7 @@
<string name="rule_del">Del Rule</string> <string name="rule_del">Del Rule</string>
<string name="sender_del">Del Sender</string> <string name="sender_del">Del Sender</string>
<string name="frpc_del">Del Frpc</string>
<string name="sender_disabled">Sender is disabled</string> <string name="sender_disabled">Sender is disabled</string>
<string name="unknown_sender">Unknown sender</string> <string name="unknown_sender">Unknown sender</string>
<string name="network_type">Network Type</string> <string name="network_type">Network Type</string>
@ -1176,10 +1179,10 @@
<string name="task_lock_screen">Screen Off/On</string> <string name="task_lock_screen">Screen Off/On</string>
<string name="task_lock_screen_tips">Trigger upon screen lock/unlock instantly or after a set time.</string> <string name="task_lock_screen_tips">Trigger upon screen lock/unlock instantly or after a set time.</string>
<string name="task_sendsms">Send Sms</string> <string name="task_sendsms">Send Sms</string>
<string name="task_notification">Notification</string> <string name="task_notification">Notify</string>
<string name="task_frpc">Frpc Setting</string> <string name="task_frpc">Frpc On/Off</string>
<string name="task_frpc_tips">Control the start/stop of FRPC.</string> <string name="task_frpc_tips">Control the start/stop of FRPC.</string>
<string name="task_http_server">Server Setting</string> <string name="task_http_server">Server On/Off</string>
<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>
@ -1314,4 +1317,6 @@
<string name="english">English</string> <string name="english">English</string>
<string name="log_export_failed">Log Export Failed!</string> <string name="log_export_failed">Log Export Failed!</string>
<string name="log_export_success">Log exported successfully! Path:</string> <string name="log_export_success">Log exported successfully! Path:</string>
<string name="all_auto_started_frpc">All auto-started Frpc</string>
<string name="specified_frpc">Specified Frpc</string>
</resources> </resources>

View File

@ -21,9 +21,6 @@
<string name="app_browser_name">通用浏览器</string> <string name="app_browser_name">通用浏览器</string>
<string name="description_navigation_main">导航条</string> <string name="description_navigation_main">导航条</string>
<string name="guide_key_sliding_root_navigation">guide_key_sliding_root_navigation</string>
<string name="navigation_drawer_open">打开导航抽屉</string>
<string name="navigation_drawer_close">关闭导航抽屉</string>
<string name="menu_logs">转发日志</string> <string name="menu_logs">转发日志</string>
<string name="menu_senders">发送通道</string> <string name="menu_senders">发送通道</string>
@ -235,8 +232,11 @@
<string name="delete_rule_tips">删除转发规则后会级联删除其相关的转发日志的所有记录!\n\n确定删除该条规则?</string> <string name="delete_rule_tips">删除转发规则后会级联删除其相关的转发日志的所有记录!\n\n确定删除该条规则?</string>
<string name="delete_rule_toast">该条规则已经删除!</string> <string name="delete_rule_toast">该条规则已经删除!</string>
<string name="new_sender_first">请选择发送通道(若无,请先添加)</string> <string name="new_sender_first">请选择发送通道(若无,请先添加)</string>
<string name="new_rule_first">请选择发送通道(若无,请先添加)</string>
<string name="new_frpc_first">请选择发送通道(若无,请先添加)</string>
<string name="add_sender_first">请先去设置发送通道页面添加</string> <string name="add_sender_first">请先去设置发送通道页面添加</string>
<string name="add_rule_first">请先去设置转发规则页面添加</string> <string name="add_rule_first">请先去设置转发规则页面添加</string>
<string name="add_frpc_first">请先去设置FRPC页面添加</string>
<string name="select_sender">发送通道</string> <string name="select_sender">发送通道</string>
<string name="rule_tester">转发规则测试</string> <string name="rule_tester">转发规则测试</string>
<string name="test_sim_slot">测试模拟的接收卡槽</string> <string name="test_sim_slot">测试模拟的接收卡槽</string>
@ -345,9 +345,9 @@
<string name="touser">指定成员</string> <string name="touser">指定成员</string>
<string name="toparty">指定部门</string> <string name="toparty">指定部门</string>
<string name="totag">指定标签</string> <string name="totag">指定标签</string>
<string name="touser_tips">Tip接收消息的成员ID列表多个接收者用‘|分隔最多支持1000个</string> <string name="touser_tips">Tip接收消息的成员ID列表多个用|分隔最多支持1000个</string>
<string name="toparty_tips">Tip接收消息的部门ID列表多个接收者用‘|分隔最多支持1000个</string> <string name="toparty_tips">Tip接收消息的部门ID列表多个用|分隔最多支持1000个</string>
<string name="totag_tips">Tip接收消息的标签ID列表多个接收者用‘|分隔最多支持1000个</string> <string name="totag_tips">Tip接收消息的标签ID列表多个用|分隔最多支持1000个</string>
<string name="customize_api_tips">Tip通过反向代理(proxy_pass)绕过IP白名单限制</string> <string name="customize_api_tips">Tip通过反向代理(proxy_pass)绕过IP白名单限制</string>
<string name="specified_member_tips2">Tip接收用户的userid每次最多传20个|’分隔)</string> <string name="specified_member_tips2">Tip接收用户的userid每次最多传20个|’分隔)</string>
<string name="server_chan_send_key">SendKey</string> <string name="server_chan_send_key">SendKey</string>
@ -827,6 +827,7 @@
<string name="pushplus_token_hint">请前往对应的官网地址获取</string> <string name="pushplus_token_hint">请前往对应的官网地址获取</string>
<string name="choose_rule">下拉选择,关键字模糊匹配</string> <string name="choose_rule">下拉选择,关键字模糊匹配</string>
<string name="choose_sender">下拉选择,关键字模糊匹配</string> <string name="choose_sender">下拉选择,关键字模糊匹配</string>
<string name="choose_frpc">下拉选择,关键字模糊匹配</string>
<string name="choose_app">已装APP列表</string> <string name="choose_app">已装APP列表</string>
<string name="extra_app">额外消除应用通知</string> <string name="extra_app">额外消除应用通知</string>
<string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string> <string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string>
@ -977,6 +978,7 @@
<string name="rule_disabled_tips">【注意】该转发规则已经禁用,即便匹配上也不会发送!</string> <string name="rule_disabled_tips">【注意】该转发规则已经禁用,即便匹配上也不会发送!</string>
<string name="sender_contains_tips">【注意】该发送通道已经在列表中,无需重复添加!</string> <string name="sender_contains_tips">【注意】该发送通道已经在列表中,无需重复添加!</string>
<string name="rule_contains_tips">【注意】该转发规则已经在列表中,无需重复添加!</string> <string name="rule_contains_tips">【注意】该转发规则已经在列表中,无需重复添加!</string>
<string name="frpc_contains_tips">【注意】该Frpc已经在列表中无需重复添加</string>
<string name="local_call">本地呼叫:</string> <string name="local_call">本地呼叫:</string>
<string name="remote_sms">远程发短信:</string> <string name="remote_sms">远程发短信:</string>
<string name="clear">清除</string> <string name="clear">清除</string>
@ -1088,6 +1090,7 @@
<string name="rule_del">删除转发规则</string> <string name="rule_del">删除转发规则</string>
<string name="sender_del">删除发送通道</string> <string name="sender_del">删除发送通道</string>
<string name="frpc_del">删除Frpc</string>
<string name="sender_disabled">发送通道已禁用</string> <string name="sender_disabled">发送通道已禁用</string>
<string name="unknown_sender">未知发送通道</string> <string name="unknown_sender">未知发送通道</string>
<string name="network_type">网络类型</string> <string name="network_type">网络类型</string>
@ -1178,9 +1181,9 @@
<string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string> <string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string>
<string name="task_sendsms">发送短信</string> <string name="task_sendsms">发送短信</string>
<string name="task_notification">推送通知</string> <string name="task_notification">推送通知</string>
<string name="task_frpc">Frpc设置</string> <string name="task_frpc">启停Frpc</string>
<string name="task_frpc_tips">控制内网穿透·FRPC的启动/停止</string> <string name="task_frpc_tips">控制内网穿透·FRPC的启动/停止</string>
<string name="task_http_server">HttpServer设置</string> <string name="task_http_server">启停HttpServer</string>
<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>
@ -1315,4 +1318,6 @@
<string name="english">English</string> <string name="english">English</string>
<string name="log_export_failed">导出日志失败!</string> <string name="log_export_failed">导出日志失败!</string>
<string name="log_export_success">导出日志成功!存放路径:</string> <string name="log_export_success">导出日志成功!存放路径:</string>
<string name="all_auto_started_frpc">所有自启动的Frpc</string>
<string name="specified_frpc">指定的Frpc</string>
</resources> </resources>

View File

@ -21,9 +21,6 @@
<string name="app_browser_name">通用瀏覽器</string> <string name="app_browser_name">通用瀏覽器</string>
<string name="description_navigation_main">導航列</string> <string name="description_navigation_main">導航列</string>
<string name="guide_key_sliding_root_navigation">guide_key_sliding_root_navigation</string>
<string name="navigation_drawer_open">打開導航抽屜</string>
<string name="navigation_drawer_close">關閉導航抽屜</string>
<string name="menu_logs">轉發日誌</string> <string name="menu_logs">轉發日誌</string>
<string name="menu_senders">發送通道</string> <string name="menu_senders">發送通道</string>
@ -235,8 +232,11 @@
<string name="delete_rule_tips">刪除轉發規則後會級聯刪除其相關的轉發日誌的所有記錄!\n\n確定刪除該條規則?</string> <string name="delete_rule_tips">刪除轉發規則後會級聯刪除其相關的轉發日誌的所有記錄!\n\n確定刪除該條規則?</string>
<string name="delete_rule_toast">該條規則已刪除!</string> <string name="delete_rule_toast">該條規則已刪除!</string>
<string name="new_sender_first">請選擇發送通道(若無,請先添加)</string> <string name="new_sender_first">請選擇發送通道(若無,請先添加)</string>
<string name="new_rule_first">請選擇轉發規則(若無,請先添加)</string>
<string name="new_frpc_first">請選擇FRPC若無請先添加</string>
<string name="add_sender_first">請先去設置發送通道頁面添加</string> <string name="add_sender_first">請先去設置發送通道頁面添加</string>
<string name="add_rule_first">請先去設置轉發規則頁面添加</string> <string name="add_rule_first">請先去設置轉發規則頁面添加</string>
<string name="add_frpc_first">請先去設置FRPC頁面添加</string>
<string name="select_sender">發送通道</string> <string name="select_sender">發送通道</string>
<string name="rule_tester">轉發規則測試</string> <string name="rule_tester">轉發規則測試</string>
<string name="test_sim_slot">測試模擬的接收卡槽</string> <string name="test_sim_slot">測試模擬的接收卡槽</string>
@ -345,9 +345,9 @@
<string name="touser">指定成員</string> <string name="touser">指定成員</string>
<string name="toparty">指定部門</string> <string name="toparty">指定部門</string>
<string name="totag">指定標籤</string> <string name="totag">指定標籤</string>
<string name="touser_tips">Tip接收消息的成員ID列表多個接收者用‘|分隔最多支持1000個</string> <string name="touser_tips">Tip接收消息的成員ID列表多個用|分隔最多支持1000個</string>
<string name="toparty_tips">Tip接收消息的部門ID列表多個接收者用‘|分隔最多支持1000個</string> <string name="toparty_tips">Tip接收消息的部門ID列表多個用|分隔最多支持1000個</string>
<string name="totag_tips">Tip接收消息的標籤ID列表多個接收者用‘|分隔最多支持1000個</string> <string name="totag_tips">Tip接收消息的標籤ID列表多個用|分隔最多支持1000個</string>
<string name="customize_api_tips">Tip通過反向代理(proxy_pass)繞過IP白名單限制</string> <string name="customize_api_tips">Tip通過反向代理(proxy_pass)繞過IP白名單限制</string>
<string name="specified_member_tips2">Tip接收用戶的userid每次最多傳20個|’分隔)</string> <string name="specified_member_tips2">Tip接收用戶的userid每次最多傳20個|’分隔)</string>
<string name="server_chan_send_key">SendKey</string> <string name="server_chan_send_key">SendKey</string>
@ -827,6 +827,7 @@
<string name="pushplus_token_hint">請前往對應的官網地址獲取</string> <string name="pushplus_token_hint">請前往對應的官網地址獲取</string>
<string name="choose_rule">下拉選擇,關鍵字模糊匹配</string> <string name="choose_rule">下拉選擇,關鍵字模糊匹配</string>
<string name="choose_sender">下拉選擇,關鍵字模糊匹配</string> <string name="choose_sender">下拉選擇,關鍵字模糊匹配</string>
<string name="choose_frpc">下拉選擇,關鍵字模糊匹配</string>
<string name="choose_app">已裝APP列表</string> <string name="choose_app">已裝APP列表</string>
<string name="extra_app">額外消除應用通知</string> <string name="extra_app">額外消除應用通知</string>
<string name="extra_app_hint">一行一個包名\n開啟異步加載App列表以便選擇</string> <string name="extra_app_hint">一行一個包名\n開啟異步加載App列表以便選擇</string>
@ -977,6 +978,7 @@
<string name="rule_disabled_tips">【注意】該轉發規則已經禁用,即便匹配上也不會發送!</string> <string name="rule_disabled_tips">【注意】該轉發規則已經禁用,即便匹配上也不會發送!</string>
<string name="sender_contains_tips">【注意】該發送通道已經在列表中,無需重複添加!</string> <string name="sender_contains_tips">【注意】該發送通道已經在列表中,無需重複添加!</string>
<string name="rule_contains_tips">【注意】該轉發規則已經在列表中,無需重複添加!</string> <string name="rule_contains_tips">【注意】該轉發規則已經在列表中,無需重複添加!</string>
<string name="frpc_contains_tips">【注意】該Frpc已經在列表中無需重複添加</string>
<string name="local_call">本地呼叫:</string> <string name="local_call">本地呼叫:</string>
<string name="remote_sms">遠程發簡訊:</string> <string name="remote_sms">遠程發簡訊:</string>
<string name="clear">清除</string> <string name="clear">清除</string>
@ -1088,6 +1090,7 @@
<string name="rule_del">刪除轉發規則</string> <string name="rule_del">刪除轉發規則</string>
<string name="sender_del">刪除發送通道</string> <string name="sender_del">刪除發送通道</string>
<string name="frpc_del">刪除Frpc</string>
<string name="sender_disabled">發送通道已停用</string> <string name="sender_disabled">發送通道已停用</string>
<string name="unknown_sender">未知的發送通道</string> <string name="unknown_sender">未知的發送通道</string>
<string name="network_type">網絡類型</string> <string name="network_type">網絡類型</string>
@ -1178,9 +1181,9 @@
<string name="task_lock_screen_tips">在屏幕鎖定或解鎖後立即或指定時間觸發</string> <string name="task_lock_screen_tips">在屏幕鎖定或解鎖後立即或指定時間觸發</string>
<string name="task_sendsms">發送簡訊</string> <string name="task_sendsms">發送簡訊</string>
<string name="task_notification">推送通知</string> <string name="task_notification">推送通知</string>
<string name="task_frpc">Frpc設置</string> <string name="task_frpc">啟停Frpc</string>
<string name="task_frpc_tips">控制內網穿透·FRPC的啟動/停止</string> <string name="task_frpc_tips">控制內網穿透·FRPC的啟動/停止</string>
<string name="task_http_server">HttpServer設置</string> <string name="task_http_server">啟停HttpServer</string>
<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>
@ -1316,4 +1319,6 @@
<string name="english">English</string> <string name="english">English</string>
<string name="log_export_failed">日誌匯出失敗!</string> <string name="log_export_failed">日誌匯出失敗!</string>
<string name="log_export_success">日誌匯出成功!儲存路徑:</string> <string name="log_export_success">日誌匯出成功!儲存路徑:</string>
<string name="all_auto_started_frpc">所有自動啟動的Frpc</string>
<string name="specified_frpc">特定的Frpc</string>
</resources> </resources>

View File

@ -21,9 +21,6 @@
<string name="app_browser_name">通用浏览器</string> <string name="app_browser_name">通用浏览器</string>
<string name="description_navigation_main">导航条</string> <string name="description_navigation_main">导航条</string>
<string name="guide_key_sliding_root_navigation">guide_key_sliding_root_navigation</string>
<string name="navigation_drawer_open">打开导航抽屉</string>
<string name="navigation_drawer_close">关闭导航抽屉</string>
<string name="menu_logs">转发日志</string> <string name="menu_logs">转发日志</string>
<string name="menu_senders">发送通道</string> <string name="menu_senders">发送通道</string>
@ -235,8 +232,11 @@
<string name="delete_rule_tips">删除转发规则后会级联删除其相关的转发日志的所有记录!\n\n确定删除该条规则?</string> <string name="delete_rule_tips">删除转发规则后会级联删除其相关的转发日志的所有记录!\n\n确定删除该条规则?</string>
<string name="delete_rule_toast">该条规则已经删除!</string> <string name="delete_rule_toast">该条规则已经删除!</string>
<string name="new_sender_first">请选择发送通道(若无,请先添加)</string> <string name="new_sender_first">请选择发送通道(若无,请先添加)</string>
<string name="new_rule_first">请选择转发规则(若无,请先添加)</string>
<string name="new_frpc_first">请选择Frpc若无请先添加</string>
<string name="add_sender_first">请先去设置发送通道页面添加</string> <string name="add_sender_first">请先去设置发送通道页面添加</string>
<string name="add_rule_first">请先去设置转发规则页面添加</string> <string name="add_rule_first">请先去设置转发规则页面添加</string>
<string name="add_frpc_first">请先去设置Frpc页面添加</string>
<string name="select_sender">发送通道</string> <string name="select_sender">发送通道</string>
<string name="rule_tester">转发规则测试</string> <string name="rule_tester">转发规则测试</string>
<string name="test_sim_slot">测试模拟的接收卡槽</string> <string name="test_sim_slot">测试模拟的接收卡槽</string>
@ -345,9 +345,9 @@
<string name="touser">指定成员</string> <string name="touser">指定成员</string>
<string name="toparty">指定部门</string> <string name="toparty">指定部门</string>
<string name="totag">指定标签</string> <string name="totag">指定标签</string>
<string name="touser_tips">Tip接收消息的成员ID列表多个接收者用‘|分隔最多支持1000个</string> <string name="touser_tips">Tip接收消息的成员ID列表多个用|分隔最多支持1000个</string>
<string name="toparty_tips">Tip接收消息的部门ID列表多个接收者用‘|分隔最多支持1000个</string> <string name="toparty_tips">Tip接收消息的部门ID列表多个用|分隔最多支持1000个</string>
<string name="totag_tips">Tip接收消息的标签ID列表多个接收者用‘|分隔最多支持1000个</string> <string name="totag_tips">Tip接收消息的标签ID列表多个用|分隔最多支持1000个</string>
<string name="customize_api_tips">Tip通过反向代理(proxy_pass)绕过IP白名单限制</string> <string name="customize_api_tips">Tip通过反向代理(proxy_pass)绕过IP白名单限制</string>
<string name="specified_member_tips2">Tip接收用户的userid每次最多传20个|’分隔)</string> <string name="specified_member_tips2">Tip接收用户的userid每次最多传20个|’分隔)</string>
<string name="server_chan_send_key">SendKey</string> <string name="server_chan_send_key">SendKey</string>
@ -827,6 +827,7 @@
<string name="pushplus_token_hint">请前往对应的官网地址获取</string> <string name="pushplus_token_hint">请前往对应的官网地址获取</string>
<string name="choose_rule">下拉选择,关键字模糊匹配</string> <string name="choose_rule">下拉选择,关键字模糊匹配</string>
<string name="choose_sender">下拉选择,关键字模糊匹配</string> <string name="choose_sender">下拉选择,关键字模糊匹配</string>
<string name="choose_frpc">下拉选择,关键字模糊匹配</string>
<string name="choose_app">已装APP列表</string> <string name="choose_app">已装APP列表</string>
<string name="extra_app">额外消除应用通知</string> <string name="extra_app">额外消除应用通知</string>
<string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string> <string name="extra_app_hint">一行一个包名\n开启异步加载App列表以便选择</string>
@ -977,6 +978,7 @@
<string name="rule_disabled_tips">【注意】该转发规则已经禁用,即便匹配上也不会发送!</string> <string name="rule_disabled_tips">【注意】该转发规则已经禁用,即便匹配上也不会发送!</string>
<string name="sender_contains_tips">【注意】该发送通道已经在列表中,无需重复添加!</string> <string name="sender_contains_tips">【注意】该发送通道已经在列表中,无需重复添加!</string>
<string name="rule_contains_tips">【注意】该转发规则已经在列表中,无需重复添加!</string> <string name="rule_contains_tips">【注意】该转发规则已经在列表中,无需重复添加!</string>
<string name="frpc_contains_tips">【注意】该Frpc已经在列表中无需重复添加</string>
<string name="local_call">本地呼叫:</string> <string name="local_call">本地呼叫:</string>
<string name="remote_sms">远程发短信:</string> <string name="remote_sms">远程发短信:</string>
<string name="clear">清除</string> <string name="clear">清除</string>
@ -1088,6 +1090,7 @@
<string name="rule_del">删除转发规则</string> <string name="rule_del">删除转发规则</string>
<string name="sender_del">删除发送通道</string> <string name="sender_del">删除发送通道</string>
<string name="frpc_del">删除Frpc</string>
<string name="sender_disabled">发送通道已禁用</string> <string name="sender_disabled">发送通道已禁用</string>
<string name="unknown_sender">未知发送通道</string> <string name="unknown_sender">未知发送通道</string>
<string name="network_type">网络类型</string> <string name="network_type">网络类型</string>
@ -1178,9 +1181,9 @@
<string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string> <string name="task_lock_screen_tips">在屏幕锁定或解锁后立即或指定时间触发</string>
<string name="task_sendsms">发送短信</string> <string name="task_sendsms">发送短信</string>
<string name="task_notification">推送通知</string> <string name="task_notification">推送通知</string>
<string name="task_frpc">Frpc设置</string> <string name="task_frpc">启停Frpc</string>
<string name="task_frpc_tips">控制内网穿透·FRPC的启动/停止</string> <string name="task_frpc_tips">控制内网穿透·FRPC的启动/停止</string>
<string name="task_http_server">HttpServer设置</string> <string name="task_http_server">启停HttpServer</string>
<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>
@ -1315,4 +1318,6 @@
<string name="english">English</string> <string name="english">English</string>
<string name="log_export_failed">导出日志失败!</string> <string name="log_export_failed">导出日志失败!</string>
<string name="log_export_success">导出日志成功!存放路径:</string> <string name="log_export_success">导出日志成功!存放路径:</string>
<string name="all_auto_started_frpc">所有自启动的Frpc</string>
<string name="specified_frpc">指定的Frpc</string>
</resources> </resources>