优化:MainActivity 内容填充方式(避免一次性加载多个Fragment)&& 提升APP启动速度与稳定性

优化:左滑菜单 与 TabBar 美化
精简:界面调整 & 去除不常用资源
整理:code review
pull/408/head
pppscn 6 months ago
parent 70d685ee93
commit 6473b3eb7c

@ -306,6 +306,11 @@ dependencies {
implementation 'gatewayapps.crondroid:crondroid:1.0.0'
//Java Parser For Cron Expressions: https://github.com/grahamar/cron-parser
implementation 'net.redhogs.cronparser:cron-parser-core:3.5'
// https://github.com/yarolegovich/SlidingRootNav
implementation 'com.yarolegovich:sliding-root-nav:1.1.1'
// TabBarhttps://github.com/xuexiangjys/JPTabBar
// implementation 'com.github.xuexiangjys:JPTabBar:1.0.1'
}
//X-Library
apply from: 'x-library.gradle'

@ -298,3 +298,7 @@
-dontwarn javax.lang.model.**
-dontwarn javax.naming.**
-dontwarn javax.naming.directory.**
# This is generated automatically by the Android Gradle plugin.
-dontwarn org.joda.convert.**
-dontwarn org.slf4j.impl.**

@ -16,6 +16,7 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- 授予应用程序访问系统开机事件的权限 -->
<uses-permission
@ -67,12 +68,6 @@
<uses-permission
android:name="android.permission.REBOOT"
tools:ignore="ProtectedPermissions" />
<uses-permission
android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<application
android:name=".App"

@ -74,8 +74,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
/**
* @return 当前app是否是调试开发模式
*/
val isDebug: Boolean
get() = BuildConfig.DEBUG
val isDebug: Boolean = BuildConfig.DEBUG
//Cactus相关
val mEndDate = MutableLiveData<String>() //结束时间

@ -1,77 +1,94 @@
package com.idormy.sms.forwarder.activity
import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.widget.Toolbar
import android.widget.LinearLayout
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager.widget.ViewPager
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.tabs.TabLayout
import com.hjq.permissions.OnPermissionCallback
import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.WidgetItemAdapter
import com.idormy.sms.forwarder.adapter.menu.DrawerAdapter
import com.idormy.sms.forwarder.adapter.menu.DrawerItem
import com.idormy.sms.forwarder.adapter.menu.SimpleItem
import com.idormy.sms.forwarder.adapter.menu.SpaceItem
import com.idormy.sms.forwarder.core.BaseActivity
import com.idormy.sms.forwarder.core.webview.AgentWebActivity
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.databinding.ActivityMainBinding
import com.idormy.sms.forwarder.fragment.*
import com.idormy.sms.forwarder.fragment.AboutFragment
import com.idormy.sms.forwarder.fragment.AppListFragment
import com.idormy.sms.forwarder.fragment.ClientFragment
import com.idormy.sms.forwarder.fragment.FrpcFragment
import com.idormy.sms.forwarder.fragment.LogsFragment
import com.idormy.sms.forwarder.fragment.RulesFragment
import com.idormy.sms.forwarder.fragment.SendersFragment
import com.idormy.sms.forwarder.fragment.ServerFragment
import com.idormy.sms.forwarder.fragment.SettingsFragment
import com.idormy.sms.forwarder.fragment.TasksFragment
import com.idormy.sms.forwarder.service.ForegroundService
import com.idormy.sms.forwarder.utils.*
import com.idormy.sms.forwarder.utils.FRPC_LIB_DOWNLOAD_URL
import com.idormy.sms.forwarder.utils.FRPC_LIB_VERSION
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.XToastUtils
import com.idormy.sms.forwarder.utils.sdkinit.XUpdateInit
import com.idormy.sms.forwarder.widget.GuideTipsDialog.Companion.showTips
import com.idormy.sms.forwarder.widget.GuideTipsDialog.Companion.showTipsForce
import com.idormy.sms.forwarder.workers.LoadAppListWorker
import com.jeremyliao.liveeventbus.LiveEventBus
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xhttp2.XHttp
import com.xuexiang.xhttp2.callback.DownloadProgressCallBack
import com.xuexiang.xhttp2.exception.ApiException
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.core.PageOption
import com.xuexiang.xpage.model.PageInfo
import com.xuexiang.xui.adapter.FragmentAdapter
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
import com.xuexiang.xui.utils.DensityUtils
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.utils.ThemeUtils
import com.xuexiang.xui.utils.ViewUtils
import com.xuexiang.xui.utils.WidgetUtils
import com.xuexiang.xui.widget.alpha.XUIAlphaTextView
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.GravityEnum
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.file.FileUtils
import com.xuexiang.xutil.net.NetworkUtils
import com.yarolegovich.slidingrootnav.SlideGravity
import com.yarolegovich.slidingrootnav.SlidingRootNav
import com.yarolegovich.slidingrootnav.SlidingRootNavBuilder
import com.yarolegovich.slidingrootnav.callback.DragStateListener
import frpclib.Frpclib
import io.reactivex.CompletableObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.File
@Suppress("DEPRECATION", "PrivatePropertyName")
class MainActivity : BaseActivity<ActivityMainBinding?>(),
View.OnClickListener,
BottomNavigationView.OnNavigationItemSelectedListener,
Toolbar.OnMenuItemClickListener,
RecyclerViewHolder.OnItemClickListener<PageInfo> {
@Suppress("PrivatePropertyName", "unused", "DEPRECATION")
class MainActivity : BaseActivity<ActivityMainBinding?>(), DrawerAdapter.OnItemSelectedListener {
private val TAG: String = MainActivity::class.java.simpleName
private lateinit var mTitles: Array<String>
private var logsType: String = "sms"
private var ruleType: String = "sms"
//private lateinit var mTitles: Array<String>
//private var logsType: String = "sms"
//private var ruleType: String = "sms"
private val POS_LOG = 0
private val POS_RULE = 1
private val POS_SENDER = 2
private val POS_SETTING = 3
private val POS_TASK = 5 //4为空行
private val POS_SERVER = 6
private val POS_CLIENT = 7
private val POS_FRPC = 8
private val POS_APPS = 9
private val POS_HELP = 11 //10为空行
private val POS_ABOUT = 12
private lateinit var mTabLayout: TabLayout
private lateinit var mSlidingRootNav: SlidingRootNav
private lateinit var mLLMenu: LinearLayout
private lateinit var mMenuTitles: Array<String>
private lateinit var mMenuIcons: Array<Drawable>
private lateinit var mAdapter: DrawerAdapter
override fun viewBindingInflate(inflater: LayoutInflater?): ActivityMainBinding {
return ActivityMainBinding.inflate(inflater!!)
@ -79,9 +96,10 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(),
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initViews()
initData()
initListeners()
initViews()
initSlidingMenu(savedInstanceState)
//不在最近任务列表中显示
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && SettingUtils.enableExcludeFromRecents) {
@ -95,26 +113,23 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(),
}
//检查通知权限是否获取
XXPermissions.with(this)
.permission(Permission.NOTIFICATION_SERVICE)
.permission(Permission.POST_NOTIFICATIONS)
.request(OnPermissionCallback { _, allGranted ->
if (!allGranted) {
XToastUtils.error(R.string.tips_notification)
return@OnPermissionCallback
}
XXPermissions.with(this).permission(Permission.NOTIFICATION_SERVICE).permission(Permission.POST_NOTIFICATIONS).request(OnPermissionCallback { _, allGranted ->
if (!allGranted) {
XToastUtils.error(R.string.tips_notification)
return@OnPermissionCallback
}
//启动前台服务
if (!ForegroundService.isRunning) {
val serviceIntent = Intent(this, ForegroundService::class.java)
serviceIntent.action = "START"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
} else {
startService(serviceIntent)
}
//启动前台服务
if (!ForegroundService.isRunning) {
val serviceIntent = Intent(this, ForegroundService::class.java)
serviceIntent.action = "START"
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent)
} else {
startService(serviceIntent)
}
})
}
})
}
override val isSupportSlideBack: Boolean
@ -122,24 +137,37 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(),
private fun initViews() {
WidgetUtils.clearActivityBackground(this)
mTitles = ResUtils.getStringArray(R.array.home_titles)
binding!!.includeMain.toolbar.title = mTitles[0]
binding!!.includeMain.toolbar.inflateMenu(R.menu.menu_logs)
binding!!.includeMain.toolbar.setOnMenuItemClickListener(this)
//主页内容填充
val fragments = arrayOf(
LogsFragment(),
RulesFragment(),
SendersFragment(),
SettingsFragment()
)
val adapter = FragmentAdapter(supportFragmentManager, fragments)
binding!!.includeMain.viewPager.offscreenPageLimit = mTitles.size - 1
binding!!.includeMain.viewPager.adapter = adapter
initTab()
}
private fun initTab() {
mTabLayout = binding!!.tabs
WidgetUtils.addTabWithoutRipple(mTabLayout, getString(R.string.menu_logs), R.drawable.selector_icon_tabbar_logs)
WidgetUtils.addTabWithoutRipple(mTabLayout, getString(R.string.menu_rules), R.drawable.selector_icon_tabbar_rules)
WidgetUtils.addTabWithoutRipple(mTabLayout, getString(R.string.menu_senders), R.drawable.selector_icon_tabbar_senders)
WidgetUtils.addTabWithoutRipple(mTabLayout, getString(R.string.menu_settings), R.drawable.selector_icon_tabbar_settings)
WidgetUtils.setTabLayoutTextFont(mTabLayout)
switchPage(LogsFragment::class.java)
mTabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
mAdapter.setSelected(tab.position)
when (tab.position) {
POS_LOG -> switchPage(LogsFragment::class.java)
POS_RULE -> switchPage(RulesFragment::class.java)
POS_SENDER -> switchPage(SendersFragment::class.java)
POS_SETTING -> switchPage(SettingsFragment::class.java)
}
}
override fun onTabUnselected(tab: TabLayout.Tab) {}
override fun onTabReselected(tab: TabLayout.Tab) {}
})
}
private fun initData() {
mMenuTitles = ResUtils.getStringArray(this, R.array.menu_titles)
mMenuIcons = ResUtils.getDrawableArray(this, R.array.menu_icons)
//仅当开启自动检查且有网络时自动检查更新/获取提示
if (SettingUtils.autoCheckUpdate && NetworkUtils.isHaveInternet()) {
showTips(this)
@ -147,264 +175,144 @@ class MainActivity : BaseActivity<ActivityMainBinding?>(),
}
}
fun initListeners() {
val toggle = ActionBarDrawerToggle(
this,
binding!!.drawerLayout,
binding!!.includeMain.toolbar,
R.string.navigation_drawer_open,
R.string.navigation_drawer_close
)
binding!!.drawerLayout.addDrawerListener(toggle)
toggle.syncState()
//侧边栏点击事件
binding!!.navView.setNavigationItemSelectedListener { menuItem: MenuItem ->
if (menuItem.isCheckable) {
binding!!.drawerLayout.closeDrawers()
return@setNavigationItemSelectedListener handleNavigationItemSelected(menuItem)
} else {
when (menuItem.itemId) {
R.id.nav_task -> openNewPage(TasksFragment::class.java)
R.id.nav_server -> openNewPage(ServerFragment::class.java)
R.id.nav_client -> openNewPage(ClientFragment::class.java)
R.id.nav_frpc -> {
if (!FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) {
MaterialDialog.Builder(this)
.title(
String.format(
getString(R.string.frpclib_download_title),
FRPC_LIB_VERSION
)
)
.content(R.string.download_frpc_tips)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
downloadFrpcLib()
}
.show()
return@setNavigationItemSelectedListener false
}
if (FRPC_LIB_VERSION == Frpclib.getVersion()) {
openNewPage(FrpcFragment::class.java)
} else {
MaterialDialog.Builder(this)
.title(R.string.frpclib_version_mismatch)
.content(R.string.download_frpc_tips)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
downloadFrpcLib()
}
.show()
}
}
R.id.nav_app_list -> {
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
XToastUtils.info(getString(R.string.loading_app_list))
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
WorkManager.getInstance(this).enqueue(request)
Thread.sleep(2000)
}
openNewPage(AppListFragment::class.java)
}
//R.id.nav_logcat -> openNewPage(LogcatFragment::class.java)
R.id.nav_help -> AgentWebActivity.goWeb(this, getString(R.string.url_help))
R.id.nav_about -> openNewPage(AboutFragment::class.java)
else -> XToastUtils.toast("Click:" + menuItem.title)
}
}
true
}
//主页事件监听
binding!!.includeMain.viewPager.addOnPageChangeListener(object :
ViewPager.OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int,
) {
}
//按返回键不退出回到桌面
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
val intent = Intent(Intent.ACTION_MAIN)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addCategory(Intent.CATEGORY_HOME)
startActivity(intent)
}
override fun onPageSelected(position: Int) {
val item = binding!!.includeMain.bottomNavigation.menu.getItem(position)
binding!!.includeMain.toolbar.title = item.title
binding!!.includeMain.toolbar.menu.clear()
when (item.title) {
getString(R.string.menu_rules) -> binding!!.includeMain.toolbar.inflateMenu(
R.menu.menu_rules
)
fun openMenu() {
mSlidingRootNav.openMenu()
}
getString(R.string.menu_senders) -> binding!!.includeMain.toolbar.inflateMenu(
R.menu.menu_senders
)
fun closeMenu() {
mSlidingRootNav.closeMenu()
}
getString(R.string.menu_settings) -> binding!!.includeMain.toolbar.inflateMenu(
R.menu.menu_settings
)
fun isMenuOpen(): Boolean {
return mSlidingRootNav.isMenuOpened
}
else -> binding!!.includeMain.toolbar.inflateMenu(R.menu.menu_logs)
}
item.isChecked = true
updateSideNavStatus(item)
private fun initSlidingMenu(savedInstanceState: Bundle?) {
mSlidingRootNav = SlidingRootNavBuilder(this).withGravity(if (ResUtils.isRtl(this)) SlideGravity.RIGHT else SlideGravity.LEFT).withMenuOpened(false).withContentClickableWhenMenuOpened(false).withSavedState(savedInstanceState).withMenuLayout(R.layout.menu_left_drawer).inject()
mLLMenu = mSlidingRootNav.layout.findViewById(R.id.ll_menu)
//val ivQrcode = mSlidingRootNav.layout.findViewById<AppCompatImageView>(R.id.iv_qrcode)
//ivQrcode.setOnClickListener { openNewPage(SettingsFragment::class.java) }
//val ivSetting = mSlidingRootNav.layout.findViewById<AppCompatImageView>(R.id.iv_setting)
//ivSetting.setOnClickListener { openNewPage(SettingsFragment::class.java) }
ViewUtils.setVisibility(mLLMenu, false)
mAdapter = DrawerAdapter(
mutableListOf(
createItemFor(POS_LOG).setChecked(true),
createItemFor(POS_RULE),
createItemFor(POS_SENDER),
createItemFor(POS_SETTING),
SpaceItem(15),
createItemFor(POS_TASK),
createItemFor(POS_SERVER),
createItemFor(POS_CLIENT),
createItemFor(POS_FRPC),
createItemFor(POS_APPS),
SpaceItem(15),
createItemFor(POS_HELP),
createItemFor(POS_ABOUT),
)
)
mAdapter.setListener(this)
val list: RecyclerView = findViewById(R.id.list)
list.isNestedScrollingEnabled = false
list.layoutManager = LinearLayoutManager(this)
list.adapter = mAdapter
mAdapter.setSelected(POS_LOG)
mSlidingRootNav.isMenuLocked = false
mSlidingRootNav.layout.addDragStateListener(object : DragStateListener {
override fun onDragStart() {
ViewUtils.setVisibility(mLLMenu, true)
}
override fun onPageScrollStateChanged(state: Int) {}
override fun onDragEnd(isMenuOpened: Boolean) {
ViewUtils.setVisibility(mLLMenu, isMenuOpened)
/*if (isMenuOpened) {
if (!GuideCaseView.isShowOnce(this@MainActivity, getString(R.string.guide_key_sliding_root_navigation))) {
val guideStep1 = GuideCaseView.Builder(this@MainActivity)
.title("点击进入,可切换主题样式哦~~")
.titleSize(18, TypedValue.COMPLEX_UNIT_SP)
.focusOn(ivSetting)
.build()
val guideStep2 = GuideCaseView.Builder(this@MainActivity)
.title("点击进入,扫码关注哦~~")
.titleSize(18, TypedValue.COMPLEX_UNIT_SP)
.focusOn(ivQrcode)
.build()
GuideCaseQueue()
.add(guideStep1)
.add(guideStep2)
.show()
GuideCaseView.setShowOnce(this@MainActivity, getString(R.string.guide_key_sliding_root_navigation))
}
}*/
}
})
binding!!.includeMain.bottomNavigation.setOnNavigationItemSelectedListener(this)
//tabBar分类切换
LiveEventBus.get(EVENT_UPDATE_LOGS_TYPE, String::class.java).observe(this) { type: String ->
logsType = type
}
LiveEventBus.get(EVENT_UPDATE_RULE_TYPE, String::class.java).observe(this) { type: String ->
ruleType = type
}
}
/**
* 处理侧边栏点击事件
*
* @param menuItem
* @return
*/
private fun handleNavigationItemSelected(menuItem: MenuItem): Boolean {
for (index in mTitles.indices) {
if (mTitles[index] == menuItem.title) {
binding!!.includeMain.toolbar.title = menuItem.title
binding!!.includeMain.viewPager.setCurrentItem(index, false)
return true
override fun onItemSelected(position: Int) {
when (position) {
POS_LOG, POS_RULE, POS_SENDER, POS_SETTING -> {
val tab = mTabLayout.getTabAt(position)
tab?.select()
mSlidingRootNav.closeMenu()
}
}
return false
}
@SuppressLint("InflateParams")
override fun onMenuItemClick(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_notifications -> {
showTipsForce(this)
}
POS_TASK -> openNewPage(TasksFragment::class.java)
POS_SERVER -> openNewPage(ServerFragment::class.java)
POS_CLIENT -> openNewPage(ClientFragment::class.java)
POS_FRPC -> {
if (FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so") && FRPC_LIB_VERSION == Frpclib.getVersion()) {
openNewPage(FrpcFragment::class.java)
return
}
val title = if (!FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) {
String.format(getString(R.string.frpclib_download_title), FRPC_LIB_VERSION)
} else {
getString(R.string.frpclib_version_mismatch)
}
R.id.action_clear_logs -> {
MaterialDialog.Builder(this)
.content(R.string.delete_type_log_tips)
.title(title)
.content(R.string.download_frpc_tips)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
AppDatabase.getInstance(this)
.msgDao()
.deleteAll(logsType)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : CompletableObserver {
override fun onSubscribe(d: Disposable) {}
override fun onComplete() {
XToastUtils.success(R.string.delete_type_log_toast)
}
override fun onError(e: Throwable) {
e.message?.let { XToastUtils.error(it) }
}
})
downloadFrpcLib()
}
.show()
}
R.id.action_add_sender -> {
val dialog = BottomSheetDialog(this)
val view: View =
LayoutInflater.from(this).inflate(R.layout.dialog_sender_bottom_sheet, null)
val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
WidgetUtils.initGridRecyclerView(recyclerView, 4, DensityUtils.dp2px(1f))
val widgetItemAdapter = WidgetItemAdapter(SENDER_FRAGMENT_LIST)
widgetItemAdapter.setOnItemClickListener(this)
recyclerView.adapter = widgetItemAdapter
val bottomSheetCloseButton: XUIAlphaTextView = view.findViewById(R.id.bottom_sheet_close_button)
bottomSheetCloseButton.setOnClickListener { dialog.dismiss() }
dialog.setContentView(view)
dialog.setCancelable(true)
dialog.setCanceledOnTouchOutside(true)
dialog.show()
WidgetUtils.transparentBottomSheetDialogBackground(dialog)
}
R.id.action_add_rule -> {
PageOption.to(RulesEditFragment::class.java)
.putString(KEY_RULE_TYPE, ruleType)
.setNewActivity(true)
.open(this)
}
/*R.id.action_restore_settings -> {
XToastUtils.success(logsType)
}*/
}
return false
}
@SingleClick
override fun onClick(v: View) {
}
//================Navigation================//
/**
* 底部导航栏点击事件
*
* @param menuItem
* @return
*/
override fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
for (index in mTitles.indices) {
if (mTitles[index] == menuItem.title) {
binding!!.includeMain.toolbar.title = menuItem.title
binding!!.includeMain.viewPager.setCurrentItem(index, false)
updateSideNavStatus(menuItem)
return true
POS_APPS -> {
if (App.UserAppList.isEmpty() && App.SystemAppList.isEmpty()) {
XToastUtils.info(getString(R.string.loading_app_list))
val request = OneTimeWorkRequestBuilder<LoadAppListWorker>().build()
WorkManager.getInstance(this).enqueue(request)
return
}
openNewPage(AppListFragment::class.java)
}
}
return false
}
/**
* 更新侧边栏菜单选中状态
*
* @param menuItem
*/
private fun updateSideNavStatus(menuItem: MenuItem) {
val side = binding!!.navView.menu.findItem(menuItem.itemId)
if (side != null) {
side.isChecked = true
POS_HELP -> AgentWebActivity.goWeb(this, getString(R.string.url_help))
POS_ABOUT -> openNewPage(AboutFragment::class.java)
}
}
//按返回键不退出回到桌面
@Deprecated("Deprecated in Java")
override fun onBackPressed() {
val intent = Intent(Intent.ACTION_MAIN)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
intent.addCategory(Intent.CATEGORY_HOME)
startActivity(intent)
}
@SingleClick
override fun onItemClick(itemView: View, widgetInfo: PageInfo, pos: Int) {
try {
@Suppress("UNCHECKED_CAST")
PageOption.to(Class.forName(widgetInfo.classPath) as Class<XPageFragment>) //跳转的fragment
.setNewActivity(true)
.putInt(KEY_SENDER_TYPE, pos) //注意:目前刚好是这个顺序而已
.open(this)
} catch (e: Exception) {
e.printStackTrace()
XToastUtils.error(e.message.toString())
}
private fun createItemFor(position: Int): DrawerItem<*> {
return SimpleItem(mMenuIcons[position], mMenuTitles[position])
.withIconTint(ThemeUtils.resolveColor(this, R.attr.xui_config_color_content_text))
.withTextTint(ThemeUtils.resolveColor(this, R.attr.xui_config_color_content_text))
.withSelectedIconTint(ThemeUtils.getMainThemeColor(this))
.withSelectedTextTint(ThemeUtils.getMainThemeColor(this))
}
//动态加载FrpcLib

@ -15,6 +15,7 @@ import com.idormy.sms.forwarder.databinding.AdapterFrpcsCardViewListItemBinding
import com.xuexiang.xutil.resource.ResUtils.getColors
import frpclib.Frpclib
@Suppress("EmptyMethod", "unused")
class FrpcPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Frpc, MyViewHolder>(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

@ -12,7 +12,6 @@ import com.idormy.sms.forwarder.database.entity.LogsAndRuleAndSender
import com.idormy.sms.forwarder.databinding.AdapterLogsCardViewListItemBinding
import com.xuexiang.xutil.data.DateUtils
@Suppress("unused")
class LogsPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<LogsAndRuleAndSender, MyViewHolder>(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

@ -18,6 +18,7 @@ import com.idormy.sms.forwarder.database.entity.MsgAndLogs
import com.idormy.sms.forwarder.databinding.AdapterLogsCardViewListItemBinding
import com.xuexiang.xutil.data.DateUtils
@Suppress("EmptyMethod", "unused")
class MsgPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<MsgAndLogs, MyViewHolder>(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

@ -16,6 +16,7 @@ import com.idormy.sms.forwarder.adapter.RulePagingAdapter.MyViewHolder
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.databinding.AdapterRulesCardViewListItemBinding
@Suppress("EmptyMethod", "unused")
class RulePagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Rule, MyViewHolder>(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

@ -11,6 +11,7 @@ import com.idormy.sms.forwarder.adapter.SenderPagingAdapter.MyViewHolder
import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.databinding.AdapterSendersCardViewListItemBinding
@Suppress("EmptyMethod", "unused")
class SenderPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Sender, MyViewHolder>(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

@ -18,6 +18,7 @@ import com.idormy.sms.forwarder.databinding.AdapterTasksCardViewListItemBinding
import com.idormy.sms.forwarder.entity.TaskSetting
import com.xuexiang.xutil.data.DateUtils
@Suppress("EmptyMethod", "unused")
class TaskPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Task, MyViewHolder>(diffCallback) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {

@ -1,5 +1,3 @@
@file:Suppress("DEPRECATION")
package com.idormy.sms.forwarder.adapter
import android.annotation.SuppressLint
@ -14,6 +12,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.entity.TaskSetting
@Suppress("DEPRECATION", "unused")
class TaskSettingAdapter(
val itemList: MutableList<TaskSetting>,
private val editClickListener: (Int) -> Unit,
@ -90,11 +89,10 @@ class TaskSettingAdapter(
notifyItemMoved(fromPosition, toPosition)
}
override fun onDragFinished() {
TODO("Not yet implemented")
}
override fun onDragFinished() {}
}
@Suppress("DEPRECATION")
class ItemMoveCallback(private val listener: Listener) : ItemTouchHelper.Callback() {
interface Listener {

@ -12,6 +12,7 @@ import me.samlss.broccoli.Broccoli
* @author XUE
* @since 2019/4/8 16:33
*/
@Suppress("unused")
abstract class BroccoliRecyclerAdapter<T>(collection: Collection<T>?) :
BaseRecyclerAdapter<T>(collection) {
/**

@ -15,6 +15,7 @@ import me.samlss.broccoli.Broccoli
* @author xuexiang
* @since 2021/1/9 4:52 PM
*/
@Suppress("unused")
abstract class BroccoliSimpleDelegateAdapter<T> : SimpleDelegateAdapter<T> {
/**
* 是否已经加载成功

@ -9,6 +9,7 @@ import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
* @author xuexiang
* @since 2020/3/20 12:44 AM
*/
@Suppress("unused")
abstract class BaseDelegateAdapter<T> : XDelegateAdapter<T, RecyclerViewHolder> {
constructor() : super()
constructor(list: Collection<T>?) : super(list)

@ -0,0 +1,83 @@
package com.idormy.sms.forwarder.adapter.menu
import android.util.SparseArray
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
@Suppress("LeakingThis", "UNCHECKED_CAST")
class DrawerAdapter(private val items: List<DrawerItem<out ViewHolder>>) : RecyclerView.Adapter<DrawerAdapter.ViewHolder>() {
private val viewTypes: MutableMap<Class<out DrawerItem<*>>, Int> = HashMap()
private val holderFactories = SparseArray<DrawerItem<*>>()
private var listener: OnItemSelectedListener? = null
init {
processViewTypes()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val holder = holderFactories.get(viewType).createViewHolder(parent)
holder.adapter = this
return holder
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
(items[position] as DrawerItem<ViewHolder>).bindViewHolder(holder)
}
override fun getItemCount(): Int = items.size
override fun getItemViewType(position: Int): Int = viewTypes[items[position]::class.java] ?: -1
private fun processViewTypes() {
var type = 0
items.forEach { item ->
if (!viewTypes.containsKey(item::class.java)) {
viewTypes[item::class.java] = type
holderFactories.put(type, item)
type++
}
}
}
fun setSelected(position: Int) {
val newChecked = items[position]
if (!newChecked.isSelectable()) return
items.forEachIndexed { index, item ->
if (item.isChecked()) {
item.setChecked(false)
notifyItemChanged(index)
return@forEachIndexed
}
}
newChecked.setChecked(true)
notifyItemChanged(position)
listener?.onItemSelected(position)
}
fun setListener(listener: OnItemSelectedListener?) {
this.listener = listener
}
@Suppress("DEPRECATION")
abstract class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
var adapter: DrawerAdapter? = null
init {
itemView.setOnClickListener(this)
}
override fun onClick(v: View) {
adapter?.setSelected(adapterPosition)
}
}
interface OnItemSelectedListener {
fun onItemSelected(position: Int)
}
}

@ -0,0 +1,19 @@
package com.idormy.sms.forwarder.adapter.menu
import android.view.ViewGroup
abstract class DrawerItem<T : DrawerAdapter.ViewHolder> {
private var isChecked = false
abstract fun createViewHolder(parent: ViewGroup): T
abstract fun bindViewHolder(holder: T)
fun setChecked(checked: Boolean): DrawerItem<T> {
isChecked = checked
return this
}
fun isChecked(): Boolean = isChecked
open fun isSelectable(): Boolean = true
}

@ -0,0 +1,54 @@
package com.idormy.sms.forwarder.adapter.menu
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.idormy.sms.forwarder.R
class SimpleItem(
private val icon: Drawable,
private val title: String,
private var selectedItemIconTint: Int = 0,
private var selectedItemTextTint: Int = 0,
private var normalItemIconTint: Int = 0,
private var normalItemTextTint: Int = 0
) : DrawerItem<SimpleItem.ViewHolder>() {
override fun createViewHolder(parent: ViewGroup): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.menu_item_option, parent, false)
return ViewHolder(v)
}
override fun bindViewHolder(holder: ViewHolder) {
holder.title.text = title
holder.icon.setImageDrawable(icon)
holder.title.setTextColor(if (isChecked()) selectedItemTextTint else normalItemTextTint)
holder.icon.setColorFilter(if (isChecked()) selectedItemIconTint else normalItemIconTint)
}
fun withSelectedIconTint(selectedItemIconTint: Int): SimpleItem = apply {
this.selectedItemIconTint = selectedItemIconTint
}
fun withSelectedTextTint(selectedItemTextTint: Int): SimpleItem = apply {
this.selectedItemTextTint = selectedItemTextTint
}
fun withIconTint(normalItemIconTint: Int): SimpleItem = apply {
this.normalItemIconTint = normalItemIconTint
}
fun withTextTint(normalItemTextTint: Int): SimpleItem = apply {
this.normalItemTextTint = normalItemTextTint
}
class ViewHolder(itemView: View) : DrawerAdapter.ViewHolder(itemView) {
val icon: ImageView = itemView.findViewById(R.id.icon)
val title: TextView = itemView.findViewById(R.id.title)
}
}

@ -0,0 +1,24 @@
package com.idormy.sms.forwarder.adapter.menu
import android.content.Context
import android.view.View
import android.view.ViewGroup
class SpaceItem(private val spaceDp: Int) : DrawerItem<SpaceItem.ViewHolder>() {
override fun createViewHolder(parent: ViewGroup): ViewHolder {
val context: Context = parent.context
val view = View(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, (context.resources.displayMetrics.density * spaceDp).toInt()
)
}
return ViewHolder(view)
}
override fun bindViewHolder(holder: ViewHolder) {}
override fun isSelectable(): Boolean = false
class ViewHolder(itemView: View) : DrawerAdapter.ViewHolder(itemView)
}

@ -76,8 +76,8 @@ class SenderSpinnerAdapter<T> : BaseEditSpinnerAdapter<T>, EditSpinnerFilter {
holder.statusView.setImageDrawable(
ResUtils.getDrawable(
when (item.status) {
STATUS_OFF -> R.drawable.icon_off
else -> R.drawable.icon_on
STATUS_OFF -> R.drawable.ic_stop
else -> R.drawable.ic_start
}
)
)

@ -26,7 +26,7 @@ import io.github.inflationx.viewpump.ViewPumpContextWrapper
* @author XUE
* @since 2019/3/22 11:21
*/
@Suppress("MemberVisibilityCanBePrivate", "UNCHECKED_CAST", "DEPRECATION")
@Suppress("MemberVisibilityCanBePrivate", "UNCHECKED_CAST", "DEPRECATION", "EmptyMethod")
open class BaseActivity<Binding : ViewBinding?> : XPageActivity() {
/**
* 获取Binding

@ -16,7 +16,7 @@ import com.xuexiang.xui.widget.actionbar.TitleUtils
* @author xuexiang
* @since 2018/11/22 上午11:26
*/
@Suppress("unused", "UNUSED_PARAMETER")
@Suppress("UNUSED_PARAMETER", "unused")
abstract class BaseContainerFragment : XPageContainerListFragment() {
override fun initPage() {
initTitle()

@ -35,7 +35,7 @@ import java.lang.reflect.Type
* @author xuexiang
* @since 2018/5/25 下午3:44
*/
@Suppress("MemberVisibilityCanBePrivate")
@Suppress("MemberVisibilityCanBePrivate", "EmptyMethod")
abstract class BaseFragment<Binding : ViewBinding?> : XPageFragment() {
private var mIProgressLoader: IProgressLoader? = null
@ -204,27 +204,35 @@ abstract class BaseFragment<Binding : ViewBinding?> : XPageFragment() {
is Int -> {
option.putInt(key, value)
}
is Float -> {
option.putFloat(key, value)
}
is String -> {
option.putString(key, value)
}
is Boolean -> {
option.putBoolean(key, value)
}
is Long -> {
option.putLong(key, value)
}
is Double -> {
option.putDouble(key, value)
}
is Parcelable -> {
option.putParcelable(key, value)
}
is Serializable -> {
option.putSerializable(key, value)
}
else -> {
option.putString(key, serializeObject(value))
}

@ -5,10 +5,14 @@ import android.util.Log
import androidx.work.Configuration
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.BuildConfig
import com.idormy.sms.forwarder.database.repository.*
import com.idormy.sms.forwarder.database.repository.FrpcRepository
import com.idormy.sms.forwarder.database.repository.LogsRepository
import com.idormy.sms.forwarder.database.repository.MsgRepository
import com.idormy.sms.forwarder.database.repository.RuleRepository
import com.idormy.sms.forwarder.database.repository.SenderRepository
import com.idormy.sms.forwarder.database.repository.TaskRepository
import kotlinx.coroutines.launch
@Suppress("unused")
object Core : Configuration.Provider {
lateinit var app: Application
val frpc: FrpcRepository by lazy { (app as App).frpcRepository }

@ -13,6 +13,7 @@ import com.xuexiang.xutil.common.StringUtils
* @author xuexiang
* @since 2018/12/19 上午12:19
*/
@Suppress("unused")
class SimpleListAdapter(context: Context?, data: List<Map<String?, String?>?>?) :
BaseListAdapter<Map<String?, String?>, SimpleListAdapter.ViewHolder>(context, data) {
override fun newViewHolder(convertView: View): ViewHolder {

@ -11,7 +11,6 @@ import com.just.agentweb.core.AgentWeb
* @author xuexiang
* @since 2019/5/28 10:22
*/
@Suppress("unused")
abstract class BaseWebViewFragment : BaseFragment<ViewBinding?>() {
private var mAgentWeb: AgentWeb? = null

@ -11,7 +11,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.core.webview.WebViewInterceptDialog.Companion.show
import com.just.agentweb.core.client.MiddlewareWebClientBase
import com.xuexiang.xui.utils.ResUtils
import java.util.*
import java.util.Locale
/**
* 网络请求加载
@ -47,7 +47,7 @@ import java.util.*
*
* 这里主要是做去广告的工作
*/
@Suppress("UNUSED_PARAMETER", "DEPRECATION", "OVERRIDE_DEPRECATION")
@Suppress("UNUSED_PARAMETER", "DEPRECATION", "OVERRIDE_DEPRECATION", "unused")
open class MiddlewareWebViewClient : MiddlewareWebClientBase() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {

@ -108,8 +108,8 @@ data class Rule(
val statusImageId: Int
get() = when (status) {
STATUS_OFF -> R.drawable.icon_off
else -> R.drawable.icon_on
STATUS_OFF -> R.drawable.ic_stop
else -> R.drawable.ic_start
}
fun getSenderLogicCheckId(): Int {

@ -60,8 +60,8 @@ data class Sender(
val statusImageId: Int
get() = when (status) {
STATUS_OFF -> R.drawable.icon_off
else -> R.drawable.icon_on
STATUS_OFF -> R.drawable.ic_stop
else -> R.drawable.ic_start
}
}

@ -32,8 +32,8 @@ data class Task(
val statusImageId: Int
get() = when (status) {
STATUS_OFF -> R.drawable.icon_off
else -> R.drawable.icon_on
STATUS_OFF -> R.drawable.ic_stop
else -> R.drawable.ic_start
}
}

@ -3,7 +3,6 @@ package com.idormy.sms.forwarder.database.ext
import androidx.room.TypeConverter
import java.util.Date
@Suppress("unused")
class ConvertersDate {
@TypeConverter
fun fromTimestamp(value: Long?): Date? {

@ -4,7 +4,6 @@ import androidx.room.TypeConverter
import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.entity.Sender
@Suppress("unused")
class ConvertersSenderList {
@TypeConverter

@ -4,6 +4,5 @@ import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
@Suppress("unused")
fun <T> LifecycleOwner.observe(liveData: LiveData<T>?, observer: (T) -> Unit) =
liveData?.observe(this, Observer(observer))

@ -7,6 +7,7 @@ import com.xuexiang.xui.utils.ResUtils.getString
import java.io.Serializable
import java.util.*
@Suppress("DEPRECATION")
data class ContactInfo(
val name: String = "",
@SerializedName("phone_number")

@ -4,6 +4,7 @@ import com.idormy.sms.forwarder.R
import com.xuexiang.xui.utils.ResUtils
import java.io.Serializable
@Suppress("DEPRECATION")
data class LocationInfo(
var longitude: Double = 0.0,
var latitude: Double = 0.0,

@ -6,7 +6,7 @@ import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xutil.resource.ResUtils.getString
import java.io.Serializable
@Suppress("DEPRECATION", "unused")
@Suppress("DEPRECATION")
data class ChargeSetting(
var description: String = "", //描述
var status: Int = BatteryManager.BATTERY_STATUS_UNKNOWN, //状态

@ -31,7 +31,7 @@ import com.xuexiang.xui.utils.WidgetUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xutil.XUtil
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
@Page(name = "应用列表")
class AppListFragment : BaseFragment<FragmentAppListBinding?>() {

@ -45,7 +45,7 @@ import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.data.ConvertTools
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
@Page(name = "主动控制·客户端")
class ClientFragment : BaseFragment<FragmentClientBinding?>(), View.OnClickListener, RecyclerViewHolder.OnItemClickListener<PageInfo> {

@ -11,8 +11,10 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
import com.alibaba.android.vlayout.VirtualLayoutManager
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.adapter.MsgPagingAdapter
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.database.entity.LogsDetail
import com.idormy.sms.forwarder.database.entity.MsgAndLogs
import com.idormy.sms.forwarder.database.entity.Rule
@ -25,12 +27,17 @@ import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import com.xuexiang.xutil.data.DateUtils
import io.reactivex.CompletableObserver
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
@ -41,6 +48,7 @@ import java.util.*
class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnItemClickListener {
private val TAG: String = LogsFragment::class.java.simpleName
private var titleBar: TitleBar? = null
private var adapter = MsgPagingAdapter(this)
private val viewModel by viewModels<MsgViewModel> { BaseViewModelFactory(context) }
private var currentType: String = "sms"
@ -52,11 +60,49 @@ class LogsFragment : BaseFragment<FragmentLogsBinding?>(), MsgPagingAdapter.OnIt
return FragmentLogsBinding.inflate(inflater, container, false)
}
/**
* @return 返回为 null意为不需要导航栏
*/
override fun initTitle(): TitleBar? {
return null
titleBar = super.initTitle()!!.setImmersive(false)
titleBar!!.setLeftImageResource(R.drawable.ic_action_menu)
titleBar!!.setTitle(R.string.menu_logs)
titleBar!!.setLeftClickListener { getContainer()?.openMenu() }
/*titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_menu_notifications_white) {
@SingleClick
override fun performAction(view: View) {
showTipsForce(requireContext())
}
})*/
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_delete) {
@SingleClick
override fun performAction(view: View) {
MaterialDialog.Builder(requireContext())
.content(R.string.delete_type_log_tips)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
AppDatabase.getInstance(requireContext())
.msgDao()
.deleteAll(currentType)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : CompletableObserver {
override fun onSubscribe(d: Disposable) {}
override fun onComplete() {
XToastUtils.success(R.string.delete_type_log_toast)
}
override fun onError(e: Throwable) {
e.message?.let { XToastUtils.error(it) }
}
})
}
.show()
}
})
return titleBar
}
private fun getContainer(): MainActivity? {
return activity as MainActivity?
}
/**

@ -474,7 +474,7 @@ class RulesEditFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnClic
val tvSenderName = layoutSenderItem.findViewById<TextView>(R.id.tv_sender_name)
ivSenderImage.setImageDrawable(sender.icon)
ivSenderStatus.setImageDrawable(ResUtils.getDrawable(if (STATUS_OFF == sender.status) R.drawable.icon_off else R.drawable.icon_on))
ivSenderStatus.setImageDrawable(ResUtils.getDrawable(if (STATUS_OFF == sender.status) R.drawable.ic_stop else R.drawable.ic_start))
val senderItemId = sender.id as Long
tvSenderName.text = "ID-$senderItemId${sender.title}"

@ -8,6 +8,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
import com.alibaba.android.vlayout.VirtualLayoutManager
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.adapter.RulePagingAdapter
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.entity.Rule
@ -21,6 +22,7 @@ import com.idormy.sms.forwarder.utils.KEY_RULE_TYPE
import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xpage.core.PageOption
import com.xuexiang.xui.utils.ResUtils
@ -35,7 +37,9 @@ import kotlinx.coroutines.launch
class RulesFragment : BaseFragment<FragmentRulesBinding?>(), RulePagingAdapter.OnItemClickListener {
//private val TAG: String = RulesFragment::class.java.simpleName
private val that = this
private var adapter = RulePagingAdapter(this)
private var titleBar: TitleBar? = null
private val viewModel by viewModels<RuleViewModel> { BaseViewModelFactory(context) }
private var currentType: String = "sms"
@ -46,11 +50,25 @@ class RulesFragment : BaseFragment<FragmentRulesBinding?>(), RulePagingAdapter.O
return FragmentRulesBinding.inflate(inflater, container, false)
}
/**
* @return 返回为 null意为不需要导航栏
*/
override fun initTitle(): TitleBar? {
return null
titleBar = super.initTitle()!!.setImmersive(false)
titleBar!!.setLeftImageResource(R.drawable.ic_action_menu)
titleBar!!.setTitle(R.string.menu_rules)
titleBar!!.setLeftClickListener { getContainer()?.openMenu() }
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_add) {
@SingleClick
override fun performAction(view: View) {
PageOption.to(RulesEditFragment::class.java)
.putString(KEY_RULE_TYPE, currentType)
.setNewActivity(true)
.open(that)
}
})
return titleBar
}
private fun getContainer(): MainActivity? {
return activity as MainActivity?
}
/**
@ -132,5 +150,4 @@ class RulesFragment : BaseFragment<FragmentRulesBinding?>(), RulePagingAdapter.O
}
override fun onItemRemove(view: View?, id: Int) {}
}

@ -1,15 +1,20 @@
package com.idormy.sms.forwarder.fragment
import android.annotation.SuppressLint
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.RecycledViewPool
import com.alibaba.android.vlayout.VirtualLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.adapter.SenderPagingAdapter
import com.idormy.sms.forwarder.adapter.WidgetItemAdapter
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.database.entity.Sender
import com.idormy.sms.forwarder.database.viewmodel.BaseViewModelFactory
@ -34,6 +39,7 @@ import com.idormy.sms.forwarder.fragment.senders.WeworkRobotFragment
import com.idormy.sms.forwarder.utils.KEY_SENDER_CLONE
import com.idormy.sms.forwarder.utils.KEY_SENDER_ID
import com.idormy.sms.forwarder.utils.KEY_SENDER_TYPE
import com.idormy.sms.forwarder.utils.SENDER_FRAGMENT_LIST
import com.idormy.sms.forwarder.utils.TYPE_BARK
import com.idormy.sms.forwarder.utils.TYPE_DINGTALK_GROUP_ROBOT
import com.idormy.sms.forwarder.utils.TYPE_DINGTALK_INNER_ROBOT
@ -52,10 +58,17 @@ import com.idormy.sms.forwarder.utils.TYPE_WEWORK_AGENT
import com.idormy.sms.forwarder.utils.TYPE_WEWORK_ROBOT
import com.idormy.sms.forwarder.utils.XToastUtils
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.core.PageOption
import com.xuexiang.xpage.model.PageInfo
import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
import com.xuexiang.xui.utils.DensityUtils
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xui.utils.WidgetUtils
import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.alpha.XUIAlphaTextView
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import kotlinx.coroutines.flow.collectLatest
@ -63,11 +76,16 @@ import kotlinx.coroutines.launch
@Suppress("PrivatePropertyName", "DEPRECATION")
@Page(name = "发送通道")
class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAdapter.OnItemClickListener {
class SendersFragment : BaseFragment<FragmentSendersBinding?>(),
SenderPagingAdapter.OnItemClickListener,
RecyclerViewHolder.OnItemClickListener<PageInfo> {
private val TAG: String = SendersFragment::class.java.simpleName
private val that = this
private var titleBar: TitleBar? = null
private var adapter = SenderPagingAdapter(this)
private val viewModel by viewModels<SenderViewModel> { BaseViewModelFactory(context) }
private val dialog: BottomSheetDialog by lazy { BottomSheetDialog(requireContext()) }
private var currentStatus: Int = 1
//private val statusValueArray = ResUtils.getIntArray(R.array.status_param_value)
@ -78,11 +96,38 @@ class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAda
return FragmentSendersBinding.inflate(inflater, container, false)
}
/**
* @return 返回为 null意为不需要导航栏
*/
override fun initTitle(): TitleBar? {
return null
titleBar = super.initTitle()!!.setImmersive(false)
titleBar!!.setLeftImageResource(R.drawable.ic_action_menu)
titleBar!!.setTitle(R.string.menu_senders)
titleBar!!.setLeftClickListener { getContainer()?.openMenu() }
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_add) {
@SuppressLint("InflateParams")
@SingleClick
override fun performAction(view: View) {
val bottomSheet: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_sender_bottom_sheet, null)
val recyclerView: RecyclerView = bottomSheet.findViewById(R.id.recyclerView)
WidgetUtils.initGridRecyclerView(recyclerView, 4, DensityUtils.dp2px(1f))
val widgetItemAdapter = WidgetItemAdapter(SENDER_FRAGMENT_LIST)
widgetItemAdapter.setOnItemClickListener(that)
recyclerView.adapter = widgetItemAdapter
val bottomSheetCloseButton: XUIAlphaTextView = bottomSheet.findViewById(R.id.bottom_sheet_close_button)
bottomSheetCloseButton.setOnClickListener { dialog.dismiss() }
dialog.setContentView(bottomSheet)
dialog.setCancelable(true)
dialog.setCanceledOnTouchOutside(true)
dialog.show()
WidgetUtils.transparentBottomSheetDialogBackground(dialog)
}
})
return titleBar
}
private fun getContainer(): MainActivity? {
return activity as MainActivity?
}
/**
@ -127,27 +172,8 @@ class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAda
Log.e(TAG, item.toString())
when (view?.id) {
R.id.iv_copy -> {
PageOption.to(
when (item.type) {
TYPE_DINGTALK_GROUP_ROBOT -> DingtalkGroupRobotFragment::class.java
TYPE_EMAIL -> EmailFragment::class.java
TYPE_BARK -> BarkFragment::class.java
TYPE_WEBHOOK -> WebhookFragment::class.java
TYPE_WEWORK_ROBOT -> WeworkRobotFragment::class.java
TYPE_WEWORK_AGENT -> WeworkAgentFragment::class.java
TYPE_SERVERCHAN -> ServerchanFragment::class.java
TYPE_TELEGRAM -> TelegramFragment::class.java
TYPE_SMS -> SmsFragment::class.java
TYPE_FEISHU -> FeishuFragment::class.java
TYPE_PUSHPLUS -> PushplusFragment::class.java
TYPE_GOTIFY -> GotifyFragment::class.java
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
TYPE_URL_SCHEME -> UrlSchemeFragment::class.java
TYPE_SOCKET -> SocketFragment::class.java
else -> DingtalkGroupRobotFragment::class.java
}
).setNewActivity(true)
PageOption.to(getFragment(item.type))
.setNewActivity(true)
.putLong(KEY_SENDER_ID, item.id)
.putInt(KEY_SENDER_TYPE, item.type)
.putBoolean(KEY_SENDER_CLONE, true)
@ -155,27 +181,8 @@ class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAda
}
R.id.iv_edit -> {
PageOption.to(
when (item.type) {
TYPE_DINGTALK_GROUP_ROBOT -> DingtalkGroupRobotFragment::class.java
TYPE_EMAIL -> EmailFragment::class.java
TYPE_BARK -> BarkFragment::class.java
TYPE_WEBHOOK -> WebhookFragment::class.java
TYPE_WEWORK_ROBOT -> WeworkRobotFragment::class.java
TYPE_WEWORK_AGENT -> WeworkAgentFragment::class.java
TYPE_SERVERCHAN -> ServerchanFragment::class.java
TYPE_TELEGRAM -> TelegramFragment::class.java
TYPE_SMS -> SmsFragment::class.java
TYPE_FEISHU -> FeishuFragment::class.java
TYPE_PUSHPLUS -> PushplusFragment::class.java
TYPE_GOTIFY -> GotifyFragment::class.java
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
TYPE_URL_SCHEME -> UrlSchemeFragment::class.java
TYPE_SOCKET -> SocketFragment::class.java
else -> DingtalkGroupRobotFragment::class.java
}
).setNewActivity(true)
PageOption.to(getFragment(item.type))
.setNewActivity(true)
.putLong(KEY_SENDER_ID, item.id)
.putInt(KEY_SENDER_TYPE, item.type)
.open(this)
@ -200,4 +207,40 @@ class SendersFragment : BaseFragment<FragmentSendersBinding?>(), SenderPagingAda
override fun onItemRemove(view: View?, id: Int) {}
@SingleClick
override fun onItemClick(itemView: View, widgetInfo: PageInfo, pos: Int) {
try {
@Suppress("UNCHECKED_CAST")
PageOption.to(Class.forName(widgetInfo.classPath) as Class<XPageFragment>) //跳转的fragment
.setNewActivity(true)
.putInt(KEY_SENDER_TYPE, pos) //注意:目前刚好是这个顺序而已
.open(this)
} catch (e: Exception) {
e.printStackTrace()
XToastUtils.error(e.message.toString())
}
}
private fun getFragment(type: Int): Class<out XPageFragment> {
return when (type) {
TYPE_DINGTALK_GROUP_ROBOT -> DingtalkGroupRobotFragment::class.java
TYPE_EMAIL -> EmailFragment::class.java
TYPE_BARK -> BarkFragment::class.java
TYPE_WEBHOOK -> WebhookFragment::class.java
TYPE_WEWORK_ROBOT -> WeworkRobotFragment::class.java
TYPE_WEWORK_AGENT -> WeworkAgentFragment::class.java
TYPE_SERVERCHAN -> ServerchanFragment::class.java
TYPE_TELEGRAM -> TelegramFragment::class.java
TYPE_SMS -> SmsFragment::class.java
TYPE_FEISHU -> FeishuFragment::class.java
TYPE_PUSHPLUS -> PushplusFragment::class.java
TYPE_GOTIFY -> GotifyFragment::class.java
TYPE_DINGTALK_INNER_ROBOT -> DingtalkInnerRobotFragment::class.java
TYPE_FEISHU_APP -> FeishuAppFragment::class.java
TYPE_URL_SCHEME -> UrlSchemeFragment::class.java
TYPE_SOCKET -> SocketFragment::class.java
else -> DingtalkGroupRobotFragment::class.java
}
}
}

@ -28,6 +28,7 @@ import com.hjq.permissions.Permission
import com.hjq.permissions.XXPermissions
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.activity.MainActivity
import com.idormy.sms.forwarder.adapter.spinner.AppListAdapterItem
import com.idormy.sms.forwarder.adapter.spinner.AppListSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment
@ -37,6 +38,7 @@ import com.idormy.sms.forwarder.receiver.BootCompletedReceiver
import com.idormy.sms.forwarder.service.ForegroundService
import com.idormy.sms.forwarder.service.LocationService
import com.idormy.sms.forwarder.utils.*
import com.idormy.sms.forwarder.widget.GuideTipsDialog
import com.idormy.sms.forwarder.workers.LoadAppListWorker
import com.jeremyliao.liveeventbus.LiveEventBus
import com.xuexiang.xaop.annotation.SingleClick
@ -60,6 +62,7 @@ import java.util.*
class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickListener {
private val TAG: String = SettingsFragment::class.java.simpleName
private var titleBar: TitleBar? = null
private val mTimeOption = DataProvider.timePeriodOption
//已安装App信息列表
@ -77,15 +80,38 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
return FragmentSettingsBinding.inflate(inflater, container, false)
}
/**
* @return 返回为 null意为不需要导航栏
*/
override fun initTitle(): TitleBar? {
return null
titleBar = super.initTitle()!!.setImmersive(false)
titleBar!!.setLeftImageResource(R.drawable.ic_action_menu)
titleBar!!.setTitle(R.string.menu_settings)
titleBar!!.setLeftClickListener { getContainer()?.openMenu() }
titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_menu_notifications_white) {
@SingleClick
override fun performAction(view: View) {
GuideTipsDialog.showTipsForce(requireContext())
}
})/*titleBar!!.addAction(object : TitleBar.ImageAction(R.drawable.ic_restore) {
@SingleClick
override fun performAction(view: View) {
MaterialDialog.Builder(requireContext())
.content(R.string.delete_type_log_tips)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no)
.onPositive { _: MaterialDialog?, _: DialogAction? ->
}
.show()
}
})*/
return titleBar
}
private fun getContainer(): MainActivity? {
return activity as MainActivity?
}
@SuppressLint("NewApi", "SetTextI18n")
override fun initViews() {
//转发短信广播
switchEnableSms(binding!!.sbEnableSms)
//转发通话记录
@ -94,7 +120,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
switchEnableAppNotify(binding!!.sbEnableAppNotify, binding!!.scbCancelAppNotify, binding!!.scbNotUserPresent)
//启用GPS定位功能
switchEnableLocation(binding!!.sbEnableLocation, binding!!.layoutLocationSetting, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.xsbMinInterval, binding!!.xsbMinDistance)
switchEnableLocation(binding!!.sbEnableLocation, binding!!.layoutLocationSetting, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.etMinInterval, binding!!.etMinDistance)
//短信指令
switchEnableSmsCommand(binding!!.sbEnableSmsCommand, binding!!.etSafePhone)
//启动时异步获取已安装App信息
@ -140,6 +166,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
switchDirectlyToClient(binding!!.sbDirectlyToClient)
//纯自动任务模式
switchDirectlyToTask(binding!!.sbDirectlyToTask)
}
override fun onResume() {
@ -456,7 +483,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
}
//启用定位功能
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocation: SwitchButton, layoutLocationSetting: LinearLayout, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, xsbMinInterval: XSeekBar, xsbMinDistance: XSeekBar) {
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocation: SwitchButton, layoutLocationSetting: LinearLayout, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, etMinInterval: EditText, etMinDistance: EditText) {
//是否启用定位功能
switchEnableLocation.isChecked = SettingUtils.enableLocation
layoutLocationSetting.visibility = if (SettingUtils.enableLocation) View.VISIBLE else View.GONE
@ -486,6 +513,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
}
layoutLocationSetting.visibility = if (isChecked) View.VISIBLE else View.GONE
}
//设置位置精度:高精度(默认)
rgAccuracy.check(
when (SettingUtils.locationAccuracy) {
@ -502,9 +530,9 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
R.id.rb_accuracy_no_requirement -> Criteria.NO_REQUIREMENT
else -> Criteria.ACCURACY_FINE
}
//TODO: MainActivity.kt 中压入 FragmentManager 时会导致定位服务重启,暂时注释掉
//restartLocationService()
restartLocationService("rgAccuracy")
}
//设置电量消耗:低电耗(默认)
rgPowerRequirement.check(
when (SettingUtils.locationPowerRequirement) {
@ -523,23 +551,42 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
R.id.rb_power_requirement_no_requirement -> Criteria.NO_REQUIREMENT
else -> Criteria.POWER_LOW
}
//TODO: MainActivity.kt 中压入 FragmentManager 时会导致定位服务重启,暂时注释掉
//restartLocationService()
restartLocationService("rgPowerRequirement")
}
//设置位置更新最小时间间隔(单位:毫秒); 默认间隔10000毫秒最小间隔1000毫秒
xsbMinInterval.setDefaultValue((SettingUtils.locationMinInterval / 1000).toInt())
xsbMinInterval.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
SettingUtils.locationMinInterval = newValue * 1000L
//TODO: MainActivity.kt 中压入 FragmentManager 时会导致定位服务重启,暂时注释掉
//restartLocationService()
}
etMinInterval.setText((SettingUtils.locationMinInterval / 1000).toString())
etMinInterval.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
val changedText = s.toString()
if (changedText.isEmpty() || changedText == "0") {
etMinInterval.setText("1")
etMinInterval.setSelection(etMinInterval.text.length) // 将光标移至文本末尾
return
}
SettingUtils.locationMinInterval = changedText.toLong() * 1000
restartLocationService()
}
})
//设置位置更新最小距离单位默认距离0米
xsbMinDistance.setDefaultValue(SettingUtils.locationMinDistance)
xsbMinDistance.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
SettingUtils.locationMinDistance = newValue
//TODO: MainActivity.kt 中压入 FragmentManager 时会导致定位服务重启,暂时注释掉
//restartLocationService()
}
etMinDistance.setText(SettingUtils.locationMinDistance.toString())
etMinDistance.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable) {
val changedText = s.toString()
if (changedText.isEmpty()) {
etMinDistance.setText("0")
etMinDistance.setSelection(etMinInterval.text.length) // 将光标移至文本末尾
return
}
SettingUtils.locationMinDistance = changedText.toInt()
restartLocationService()
}
})
}
//重启定位服务
@ -772,6 +819,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
xsbRetryTimes.setDefaultValue(SettingUtils.requestRetryTimes)
xsbRetryTimes.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
SettingUtils.requestRetryTimes = newValue
binding!!.layoutDelayTime.visibility = if (newValue > 0) View.VISIBLE else View.GONE
}
xsbDelayTime.setDefaultValue(SettingUtils.requestDelayTime)
xsbDelayTime.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->

@ -53,16 +53,14 @@ import java.util.*
@Page(name = "自动任务·编辑器")
@Suppress("PrivatePropertyName", "unused", "DEPRECATION", "UNUSED_PARAMETER")
@Suppress("PrivatePropertyName", "DEPRECATION", "UNUSED_PARAMETER", "EmptyMethod", "unused")
class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClickListener, RecyclerViewHolder.OnItemClickListener<PageInfo> {
private val TAG: String = TasksEditFragment::class.java.simpleName
private val that = this
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
@AutoWired(name = KEY_TASK_ID)
@ -170,20 +168,20 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
try {
when (v.id) {
R.id.layout_add_condition -> {
val view: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_task_condition_bottom_sheet, null)
val tvTitle: TextView = view.findViewById(R.id.tv_title)
val bottomSheet: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_task_condition_bottom_sheet, null)
val tvTitle: TextView = bottomSheet.findViewById(R.id.tv_title)
tvTitle.text = if (itemListConditions.isEmpty()) getString(R.string.select_task_trigger) else getString(R.string.select_task_condition)
val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
val recyclerView: RecyclerView = bottomSheet.findViewById(R.id.recyclerView)
WidgetUtils.initGridRecyclerView(recyclerView, 4, DensityUtils.dp2px(1f))
val widgetItemAdapter = WidgetItemAdapter(TASK_CONDITION_FRAGMENT_LIST)
widgetItemAdapter.setOnItemClickListener(that)
recyclerView.adapter = widgetItemAdapter
val bottomSheetCloseButton: XUIAlphaTextView = view.findViewById(R.id.bottom_sheet_close_button)
val bottomSheetCloseButton: XUIAlphaTextView = bottomSheet.findViewById(R.id.bottom_sheet_close_button)
bottomSheetCloseButton.setOnClickListener { dialog.dismiss() }
dialog.setContentView(view)
dialog.setContentView(bottomSheet)
dialog.setCancelable(true)
dialog.setCanceledOnTouchOutside(true)
dialog.show()
@ -191,18 +189,18 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
}
R.id.layout_add_action -> {
val view: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_task_action_bottom_sheet, null)
val recyclerView: RecyclerView = view.findViewById(R.id.recyclerView)
val bottomSheet: View = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_task_action_bottom_sheet, null)
val recyclerView: RecyclerView = bottomSheet.findViewById(R.id.recyclerView)
WidgetUtils.initGridRecyclerView(recyclerView, 4, DensityUtils.dp2px(1f))
val widgetItemAdapter = WidgetItemAdapter(TASK_ACTION_FRAGMENT_LIST)
widgetItemAdapter.setOnItemClickListener(that)
recyclerView.adapter = widgetItemAdapter
val bottomSheetCloseButton: XUIAlphaTextView = view.findViewById(R.id.bottom_sheet_close_button)
val bottomSheetCloseButton: XUIAlphaTextView = bottomSheet.findViewById(R.id.bottom_sheet_close_button)
bottomSheetCloseButton.setOnClickListener { dialog.dismiss() }
dialog.setContentView(view)
dialog.setContentView(bottomSheet)
dialog.setCancelable(true)
dialog.setCanceledOnTouchOutside(true)
dialog.show()

@ -378,7 +378,7 @@ class NotificationFragment : BaseFragment<FragmentTasksActionNotificationBinding
val tvSenderName = layoutSenderItem.findViewById<TextView>(R.id.tv_sender_name)
ivSenderImage.setImageDrawable(sender.icon)
ivSenderStatus.setImageDrawable(ResUtils.getDrawable(if (STATUS_OFF == sender.status) R.drawable.icon_off else R.drawable.icon_on))
ivSenderStatus.setImageDrawable(ResUtils.getDrawable(if (STATUS_OFF == sender.status) R.drawable.ic_stop else R.drawable.ic_start))
val senderItemId = sender.id as Long
tvSenderName.text = "ID-$senderItemId${sender.title}"

@ -134,9 +134,6 @@ class CallQueryFragment : BaseFragment<FragmentClientCallQueryBinding?>() {
.addPlaceholder(PlaceholderHelper.getParameter(holder.findView(R.id.iv_reply)))
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
TODO("Not yet implemented")
}
}
val delegateAdapter = DelegateAdapter(virtualLayoutManager)

@ -125,9 +125,6 @@ class ContactQueryFragment : BaseFragment<FragmentClientContactQueryBinding?>()
.addPlaceholder(PlaceholderHelper.getParameter(holder.findView(R.id.iv_reply)))
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
TODO("Not yet implemented")
}
}
val delegateAdapter = DelegateAdapter(virtualLayoutManager)

@ -122,10 +122,6 @@ class SmsQueryFragment : BaseFragment<FragmentClientSmsQueryBinding?>() {
.addPlaceholder(PlaceholderHelper.getParameter(holder.findView(R.id.iv_reply)))
}
override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
TODO("Not yet implemented")
}
}
val delegateAdapter = DelegateAdapter(virtualLayoutManager)

@ -24,7 +24,7 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.widget.actionbar.TitleBar
@Page(name = "Battery")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class BatteryFragment : BaseFragment<FragmentTasksConditionBatteryBinding?>(), View.OnClickListener {
private val TAG: String = BatteryFragment::class.java.simpleName

@ -23,7 +23,7 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.widget.actionbar.TitleBar
@Page(name = "Charge")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class ChargeFragment : BaseFragment<FragmentTasksConditionChargeBinding?>(), View.OnClickListener {
private val TAG: String = ChargeFragment::class.java.simpleName

@ -31,7 +31,7 @@ import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
@Page(name = "LeaveAddress")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBinding?>(), View.OnClickListener {
private val TAG: String = LeaveAddressFragment::class.java.simpleName
@ -78,17 +78,18 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
}
}
Log.d(TAG, "initViews eventData:$eventData")
var settingVo = LocationSetting(getString(R.string.task_leave_address_tips), "leave")
if (eventData != null) {
val settingVo = Gson().fromJson(eventData, LocationSetting::class.java)
Log.d(TAG, "initViews settingVo:$settingVo")
binding!!.tvDescription.text = settingVo.description
binding!!.etLongitude.setText(settingVo.longitude.toString())
binding!!.etLatitude.setText(settingVo.latitude.toString())
binding!!.etDistance.setText(settingVo.distance.toString())
binding!!.etAddress.setText(settingVo.address)
binding!!.rgCalcType.check(settingVo.getCalcTypeCheckId())
Log.d(TAG, "initViews eventData:$eventData")
settingVo = Gson().fromJson(eventData, LocationSetting::class.java)
}
Log.d(TAG, "initViews settingVo:$settingVo")
binding!!.tvDescription.text = settingVo.description
binding!!.etLongitude.setText(settingVo.longitude.toString())
binding!!.etLatitude.setText(settingVo.latitude.toString())
binding!!.etDistance.setText(settingVo.distance.toString())
binding!!.etAddress.setText(settingVo.address)
binding!!.rgCalcType.check(settingVo.getCalcTypeCheckId())
}
@SuppressLint("SetTextI18n")
@ -220,7 +221,7 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
if (latitude.isNaN() || longitude.isNaN() || distance.isNaN()) {
throw Exception(getString(R.string.calc_type_distance_error))
}
description = String.format(getString(R.string.to_address_distance_description), longitude, latitude, distance)
description = String.format(getString(R.string.leave_address_distance_description), longitude, latitude, distance)
"distance"
}
@ -228,7 +229,7 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
if (address.isEmpty()) {
throw Exception(getString(R.string.calc_type_address_error))
}
description = String.format(getString(R.string.to_address_keyword_description), address)
description = String.format(getString(R.string.leave_address_keyword_description), address)
"address"
}
}

@ -23,7 +23,7 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.widget.actionbar.TitleBar
@Page(name = "LockScreen")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class LockScreenFragment : BaseFragment<FragmentTasksConditionLockScreenBinding?>(), View.OnClickListener {
private val TAG: String = LockScreenFragment::class.java.simpleName

@ -25,7 +25,7 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.widget.actionbar.TitleBar
@Page(name = "Network")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class NetworkFragment : BaseFragment<FragmentTasksConditionNetworkBinding?>(), View.OnClickListener {
private val TAG: String = NetworkFragment::class.java.simpleName

@ -23,7 +23,7 @@ import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.widget.actionbar.TitleBar
@Page(name = "Sim")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class SimFragment : BaseFragment<FragmentTasksConditionSimBinding?>(), View.OnClickListener {
private val TAG: String = SimFragment::class.java.simpleName

@ -31,7 +31,7 @@ import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
@Page(name = "ToAddress")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameParameterValue")
class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(), View.OnClickListener {
private val TAG: String = ToAddressFragment::class.java.simpleName
@ -78,17 +78,18 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
}
}
Log.d(TAG, "initViews eventData:$eventData")
var settingVo = LocationSetting(getString(R.string.task_leave_address_tips), "to")
if (eventData != null) {
val settingVo = Gson().fromJson(eventData, LocationSetting::class.java)
Log.d(TAG, "initViews settingVo:$settingVo")
binding!!.tvDescription.text = settingVo.description
binding!!.etLongitude.setText(settingVo.longitude.toString())
binding!!.etLatitude.setText(settingVo.latitude.toString())
binding!!.etDistance.setText(settingVo.distance.toString())
binding!!.etAddress.setText(settingVo.address)
binding!!.rgCalcType.check(settingVo.getCalcTypeCheckId())
Log.d(TAG, "initViews eventData:$eventData")
settingVo = Gson().fromJson(eventData, LocationSetting::class.java)
}
Log.d(TAG, "initViews settingVo:$settingVo")
binding!!.tvDescription.text = settingVo.description
binding!!.etLongitude.setText(settingVo.longitude.toString())
binding!!.etLatitude.setText(settingVo.latitude.toString())
binding!!.etDistance.setText(settingVo.distance.toString())
binding!!.etAddress.setText(settingVo.address)
binding!!.rgCalcType.check(settingVo.getCalcTypeCheckId())
}
@SuppressLint("SetTextI18n")

@ -44,7 +44,7 @@ import io.reactivex.schedulers.Schedulers
import java.util.Date
@Page(name = "Email")
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
class EmailFragment : BaseFragment<FragmentSendersEmailBinding?>(), View.OnClickListener {
private val TAG: String = EmailFragment::class.java.simpleName

@ -157,15 +157,9 @@ class WebhookFragment : BaseFragment<FragmentSendersWebhookBinding?>(), View.OnC
binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this)
binding!!.btnAddHeader.setOnClickListener {
addHeaderItemLinearLayout(
headerItemMap,
binding!!.layoutHeaders,
null,
null
)
addHeaderItemLinearLayout(headerItemMap, binding!!.layoutHeaders, null, null)
}
LiveEventBus.get(KEY_SENDER_TEST, String::class.java)
.observe(this) { mCountDownHelper?.finish() }
LiveEventBus.get(KEY_SENDER_TEST, String::class.java).observe(this) { mCountDownHelper?.finish() }
}
@SingleClick

@ -22,7 +22,7 @@ import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.task.TaskUtils
import com.idormy.sms.forwarder.workers.NetworkWorker
@Suppress("PrivatePropertyName", "DEPRECATION", "UNUSED_PARAMETER")
@Suppress("PrivatePropertyName", "DEPRECATION", "UNUSED_PARAMETER", "unused")
class NetworkChangeReceiver : BroadcastReceiver() {
private val TAG: String = NetworkChangeReceiver::class.java.simpleName

@ -6,9 +6,9 @@ import android.content.Intent
import android.telephony.TelephonyManager
import android.util.Log
import com.idormy.sms.forwarder.utils.SettingUtils
import java.util.*
import java.util.Date
@Suppress("DEPRECATION")
@Suppress("DEPRECATION", "unused")
abstract class PhoneStateReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@ -70,6 +70,7 @@ abstract class PhoneStateReceiver : BroadcastReceiver() {
onIncomingCallReceived(context, number, callStartTime)
}
TelephonyManager.CALL_STATE_OFFHOOK ->
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if (lastState != TelephonyManager.CALL_STATE_RINGING) {
@ -83,6 +84,7 @@ abstract class PhoneStateReceiver : BroadcastReceiver() {
onIncomingCallAnswered(context, savedNumber, callStartTime)
}
TelephonyManager.CALL_STATE_IDLE ->
//Went to idle- this is the end of a call. What type depends on previous state(s)
if (lastState == TelephonyManager.CALL_STATE_RINGING) {

@ -20,7 +20,7 @@ import com.xuexiang.xrouter.utils.TextUtils
import java.util.Date
//短信广播
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "unused", "UNUSED_PARAMETER")
class SmsReceiver : BroadcastReceiver() {
private var TAG = SmsReceiver::class.java.simpleName

@ -13,7 +13,7 @@ import com.yanzhenjie.andserver.http.HttpMethod
import com.yanzhenjie.andserver.http.HttpRequest
import com.yanzhenjie.andserver.http.HttpResponse
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "DEPRECATION")
@Interceptor
class LoggerInterceptor : HandlerInterceptor {

@ -9,7 +9,6 @@ import com.yanzhenjie.andserver.http.HttpRequest
import com.yanzhenjie.andserver.http.HttpResponse
//@Interceptor
@Suppress("unused")
class LoginInterceptor : HandlerInterceptor {
override fun onIntercept(
request: HttpRequest,

@ -12,7 +12,7 @@ import com.xuexiang.xutil.XUtil.getContentResolver
import com.yanzhenjie.andserver.annotation.*
@Suppress("PrivatePropertyName")
@Suppress("PrivatePropertyName", "SameReturnValue")
@RestController
@RequestMapping(path = ["/contact"])
class ContactController {

@ -13,7 +13,7 @@ import kotlin.reflect.KProperty
* @author pppscn
* @since 2022年5月9日
*/
@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused")
@Suppress("UNCHECKED_CAST", "unused")
class HistoryUtils<T>(private val name: String, private val default: T) : ReadWriteProperty<Any?, T> {
companion object {

@ -11,7 +11,6 @@ import javax.crypto.Cipher
/**
* 非对称加密RSA加密和解密
*/
@Suppress("unused")
object RSACrypt {
private const val transformation = "RSA"

@ -12,7 +12,6 @@ import com.xuexiang.xui.widget.toast.XToast
* @author xuexiang
* @since 2019-06-30 19:04
*/
@Suppress("unused")
class XToastUtils private constructor() {
@SuppressLint("CheckResult")
companion object {

@ -41,7 +41,7 @@ class UMengInit private constructor() {
return
}
UMConfigure.setLogEnabled(false)
UMConfigure.preInit(application, BuildConfig.APP_ID_UMENG, getChannel()) //getChannel(application)
UMConfigure.preInit(application, BuildConfig.APP_ID_UMENG, DEFAULT_CHANNEL_ID) //getChannel(application)
// 用户同意了隐私协议
if (isAgreePrivacy) {
realInit(application)
@ -62,7 +62,7 @@ class UMengInit private constructor() {
UMConfigure.init(
application,
BuildConfig.APP_ID_UMENG,
getChannel(), //getChannel(application)
DEFAULT_CHANNEL_ID, //getChannel(application)
UMConfigure.DEVICE_TYPE_PHONE,
""
)
@ -75,10 +75,9 @@ class UMengInit private constructor() {
/**
* 获取渠道信息
*/
private fun getChannel(): String { //context: Context?
//return WalleChannelReader.getChannel(context!!, DEFAULT_CHANNEL_ID)
return DEFAULT_CHANNEL_ID
}
//private fun getChannel(context: Context?): String {
// return WalleChannelReader.getChannel(context!!, DEFAULT_CHANNEL_ID)
//}
}
init {

@ -18,7 +18,7 @@ import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
@Suppress("unused", "RegExpRedundantEscape")
@Suppress("RegExpRedundantEscape")
class BarkUtils {
companion object {

@ -25,6 +25,7 @@ import com.zzhoujay.richtext.RichText
* @author xuexiang
* @since 2019-08-22 17:02
*/
@Suppress("SameReturnValue")
class GuideTipsDialog(context: Context?, tips: List<TipInfo>) :
BaseDialog(context, R.layout.dialog_guide_tips), View.OnClickListener,
CompoundButton.OnCheckedChangeListener {
@ -85,10 +86,12 @@ class GuideTipsDialog(context: Context?, tips: List<TipInfo>) :
mTvPrevious!!.isEnabled = false
mTvNext!!.isEnabled = true
}
mTips!!.size - 1 -> {
mTvPrevious!!.isEnabled = true
mTvNext!!.isEnabled = false
}
else -> {
mTvPrevious!!.isEnabled = true
mTvNext!!.isEnabled = true

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorAccent" android:state_pressed="true" />
<item android:color="?attr/colorAccent" android:state_selected="true" />
<item android:color="@color/xui_btn_disable_color" android:state_enabled="false" />
<item android:color="?attr/colorAccent" />
</selector>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 xuexiangjys(xuexiangjys@163.com)
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="?attr/colorAccent" />
<item android:state_selected="true" android:color="?attr/colorAccent" />
<item android:color="@color/xui_config_color_gray_6" />
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M11.67,3.87L9.9,2.1 0,12l9.9,9.9 1.77,-1.77L3.54,12z"/>
</vector>

@ -0,0 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="M895.11,191.93 L381.96,191.93c-35.15,0 -63.64,28.49 -63.64,63.64 0,35.15 28.49,63.64 63.64,63.64l513.15,0c35.15,0 63.64,-28.49 63.64,-63.64C958.75,220.43 930.26,191.93 895.11,191.93z" />
<path
android:fillColor="#ffffff"
android:pathData="M895.11,449.81 L381.96,449.81c-35.15,0 -63.64,28.49 -63.64,63.64 0,35.15 28.49,63.64 63.64,63.64l513.15,0c35.15,0 63.64,-28.49 63.64,-63.64C958.75,478.3 930.26,449.81 895.11,449.81z" />
<path
android:fillColor="#ffffff"
android:pathData="M893.06,703.59 L379.91,703.59c-35.15,0 -63.64,28.49 -63.64,63.64 0,35.15 28.49,63.64 63.64,63.64l513.15,0c35.15,0 63.64,-28.49 63.64,-63.64C956.7,732.08 928.21,703.59 893.06,703.59z" />
<path
android:fillColor="#ffffff"
android:pathData="M130.65,257.03m-61.4,0a60,60 0,1 0,122.8 0,60 60,0 1,0 -122.8,0Z" />
<path
android:fillColor="#ffffff"
android:pathData="M124.51,514.9m-61.4,0a60,60 0,1 0,122.8 0,60 60,0 1,0 -122.8,0Z" />
<path
android:fillColor="#ffffff"
android:pathData="M126.55,766.63m-61.4,0a60,60 0,1 0,122.8 0,60 60,0 1,0 -122.8,0Z" />
</vector>

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 414 B

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

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

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

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

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

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorAccent"
android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM7.68,14.98H6V9h1.71c1.28,0 1.71,1.03 1.71,1.71l0,2.56C9.42,13.95 9,14.98 7.68,14.98zM12.38,11.46v1.07h-1.18v1.39h1.93v1.07h-2.25c-0.4,0.01 -0.74,-0.31 -0.75,-0.71V9.75c-0.01,-0.4 0.31,-0.74 0.71,-0.75h2.28l0,1.07h-1.92v1.39H12.38zM16.88,14.23c-0.48,1.11 -1.33,0.89 -1.71,0L13.77,9h1.18l1.07,4.11L17.09,9h1.18L16.88,14.23z" />
<path
android:fillColor="?attr/colorAccent"
android:pathData="M7.77,10.12H7.14v3.77h0.63c0.14,0 0.28,-0.05 0.42,-0.16c0.14,-0.1 0.21,-0.26 0.21,-0.47v-2.52c0,-0.21 -0.07,-0.37 -0.21,-0.47C8.05,10.17 7.91,10.12 7.77,10.12z" />
</vector>

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

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

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

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorAccent"
android:pathData="M16.54,11L13,7.46l1.41,-1.41l2.12,2.12l4.24,-4.24l1.41,1.41L16.54,11zM11,7H2v2h9V7zM21,13.41L19.59,12L17,14.59L14.41,12L13,13.41L15.59,16L13,18.59L14.41,20L17,17.41L19.59,20L21,18.59L18.41,16L21,13.41zM11,15H2v2h9V15z" />
</vector>

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

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorAccent"
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z" />
</vector>

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

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

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

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

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save