Updated superuser fragment to new arch
Fixed theme issues along the way
This commit is contained in:
parent
8a8441c875
commit
bcd1064e94
@ -10,4 +10,5 @@ val applicationModule = module {
|
||||
single { RxBus() }
|
||||
single { get<Context>().resources }
|
||||
single { get<Context>() as App }
|
||||
single { get<Context>().packageManager }
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.topjohnwu.magisk.di
|
||||
|
||||
import com.topjohnwu.magisk.App
|
||||
import org.koin.dsl.module
|
||||
|
||||
|
||||
val databaseModule = module {}
|
||||
val databaseModule = module {
|
||||
single { get<App>().DB }
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package com.topjohnwu.magisk.di
|
||||
|
||||
import com.topjohnwu.magisk.ui.MainViewModel
|
||||
import com.topjohnwu.magisk.ui.home.HomeViewModel
|
||||
import com.topjohnwu.magisk.ui.superuser.SuperuserViewModel
|
||||
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
@ -9,4 +10,5 @@ import org.koin.dsl.module
|
||||
val viewModelModules = module {
|
||||
viewModel { MainViewModel() }
|
||||
viewModel { HomeViewModel(get(), get()) }
|
||||
viewModel { SuperuserViewModel(get(), get(), get()) }
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package com.topjohnwu.magisk.model.entity.recycler
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import com.skoumal.teanity.databinding.ComparableRvItem
|
||||
import com.skoumal.teanity.util.KObservableField
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.model.entity.Policy
|
||||
import com.topjohnwu.magisk.utils.toggle
|
||||
|
||||
class PolicyRvItem(val item: Policy, val icon: Drawable) : ComparableRvItem<PolicyRvItem>() {
|
||||
|
||||
override val layoutRes: Int = R.layout.item_policy
|
||||
|
||||
val isExpanded = KObservableField(false)
|
||||
val isEnabled = KObservableField(item.policy == Policy.ALLOW)
|
||||
val shouldNotify = KObservableField(item.notification)
|
||||
val shouldLog = KObservableField(item.logging)
|
||||
|
||||
fun toggle() = isExpanded.toggle()
|
||||
|
||||
override fun contentSameAs(other: PolicyRvItem): Boolean = itemSameAs(other)
|
||||
override fun itemSameAs(other: PolicyRvItem): Boolean = item.uid == other.item.uid
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.topjohnwu.magisk.model.events
|
||||
|
||||
import android.app.Activity
|
||||
import com.skoumal.teanity.viewevents.ViewEvent
|
||||
|
||||
|
||||
@ -15,3 +16,5 @@ class UninstallEvent : ViewEvent()
|
||||
class EnvFixEvent : ViewEvent()
|
||||
|
||||
class UpdateSafetyNetEvent : ViewEvent()
|
||||
|
||||
class ViewActionEvent(val action: Activity.() -> Unit) : ViewEvent()
|
@ -11,6 +11,7 @@ import com.ncapdevi.fragnav.FragNavController
|
||||
import com.ncapdevi.fragnav.FragNavTransactionOptions
|
||||
import com.skoumal.teanity.viewevents.ViewEvent
|
||||
import com.topjohnwu.magisk.Config
|
||||
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
||||
import com.topjohnwu.magisk.model.navigation.MagiskAnimBuilder
|
||||
import com.topjohnwu.magisk.model.navigation.MagiskNavigationEvent
|
||||
import com.topjohnwu.magisk.model.navigation.Navigator
|
||||
@ -62,6 +63,7 @@ abstract class MagiskActivity<ViewModel : MagiskViewModel, Binding : ViewDataBin
|
||||
super.onEventDispatched(event)
|
||||
when (event) {
|
||||
is MagiskNavigationEvent -> navigateTo(event)
|
||||
is ViewActionEvent -> event.action(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import androidx.databinding.ViewDataBinding
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.skoumal.teanity.view.TeanityFragment
|
||||
import com.skoumal.teanity.viewevents.ViewEvent
|
||||
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
||||
import com.topjohnwu.magisk.model.navigation.MagiskNavigationEvent
|
||||
import com.topjohnwu.magisk.model.navigation.Navigator
|
||||
import kotlin.reflect.KClass
|
||||
@ -25,6 +26,7 @@ abstract class MagiskFragment<ViewModel : MagiskViewModel, Binding : ViewDataBin
|
||||
super.onEventDispatched(event)
|
||||
when (event) {
|
||||
is MagiskNavigationEvent -> navigateTo(event)
|
||||
is ViewActionEvent -> event.action(requireActivity())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.topjohnwu.magisk.ui.base
|
||||
|
||||
import android.app.Activity
|
||||
import com.skoumal.teanity.viewmodel.LoadingViewModel
|
||||
import com.topjohnwu.magisk.model.events.ViewActionEvent
|
||||
import com.topjohnwu.magisk.utils.Event
|
||||
import timber.log.Timber
|
||||
|
||||
@ -10,4 +12,8 @@ abstract class MagiskViewModel : LoadingViewModel(), Event.AutoListener {
|
||||
override fun onEvent(event: Int) = Timber.i("Event of $event was not handled")
|
||||
override fun getListeningEvents(): IntArray = intArrayOf()
|
||||
|
||||
fun withView(action: Activity.() -> Unit) {
|
||||
ViewActionEvent(action).publish()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,63 +0,0 @@
|
||||
package com.topjohnwu.magisk.ui.superuser;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.topjohnwu.magisk.R;
|
||||
import com.topjohnwu.magisk.model.adapters.PolicyAdapter;
|
||||
import com.topjohnwu.magisk.model.entity.Policy;
|
||||
import com.topjohnwu.magisk.ui.base.BaseFragment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import butterknife.BindView;
|
||||
|
||||
public class SuperuserFragment extends BaseFragment {
|
||||
|
||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||
@BindView(R.id.empty_rv) TextView emptyRv;
|
||||
|
||||
private PackageManager pm;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_superuser, container, false);
|
||||
unbinder = new SuperuserFragment_ViewBinding(this, view);
|
||||
|
||||
pm = requireActivity().getPackageManager();
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
requireActivity().setTitle(getString(R.string.superuser));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
displayPolicyList();
|
||||
}
|
||||
|
||||
private void displayPolicyList() {
|
||||
List<Policy> policyList = app.getDB().getPolicyList();
|
||||
|
||||
if (policyList.size() == 0) {
|
||||
emptyRv.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
recyclerView.setAdapter(new PolicyAdapter(policyList, app.getDB(), pm));
|
||||
emptyRv.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.topjohnwu.magisk.ui.superuser
|
||||
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.FragmentSuperuserBinding
|
||||
import com.topjohnwu.magisk.ui.base.MagiskFragment
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class SuperuserFragment :
|
||||
MagiskFragment<SuperuserViewModel, FragmentSuperuserBinding>() {
|
||||
|
||||
override val layoutRes: Int = R.layout.fragment_superuser
|
||||
override val viewModel: SuperuserViewModel by viewModel()
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
magiskActivity.supportActionBar?.title = getString(R.string.superuser)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
viewModel.updatePolicies()
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
package com.topjohnwu.magisk.ui.superuser
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import com.skoumal.teanity.databinding.ComparableRvItem
|
||||
import com.skoumal.teanity.extensions.addOnPropertyChangedCallback
|
||||
import com.skoumal.teanity.extensions.applySchedulers
|
||||
import com.skoumal.teanity.util.DiffObservableList
|
||||
import com.skoumal.teanity.viewevents.SnackbarEvent
|
||||
import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.data.database.MagiskDB
|
||||
import com.topjohnwu.magisk.model.entity.Policy
|
||||
import com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem
|
||||
import com.topjohnwu.magisk.ui.base.MagiskViewModel
|
||||
import com.topjohnwu.magisk.utils.FingerprintHelper
|
||||
import com.topjohnwu.magisk.utils.toggle
|
||||
import com.topjohnwu.magisk.view.dialogs.CustomAlertDialog
|
||||
import com.topjohnwu.magisk.view.dialogs.FingerprintAuthDialog
|
||||
import io.reactivex.Single
|
||||
import me.tatarka.bindingcollectionadapter2.ItemBinding
|
||||
import timber.log.Timber
|
||||
|
||||
class SuperuserViewModel(
|
||||
private val database: MagiskDB,
|
||||
private val packageManager: PackageManager,
|
||||
private val resources: Resources
|
||||
) : MagiskViewModel() {
|
||||
|
||||
val items = DiffObservableList(ComparableRvItem.callback)
|
||||
val itemBinding = ItemBinding.of<ComparableRvItem<*>> { itemBinding, _, item ->
|
||||
item.bind(itemBinding)
|
||||
itemBinding.bindExtra(BR.viewModel, this@SuperuserViewModel)
|
||||
}
|
||||
|
||||
private var ignoreNext: PolicyRvItem? = null
|
||||
|
||||
init {
|
||||
updatePolicies()
|
||||
}
|
||||
|
||||
fun updatePolicies() {
|
||||
Single.fromCallable { database.policyList }
|
||||
.flattenAsFlowable { it }
|
||||
.map { PolicyRvItem(it, it.info.loadIcon(packageManager)).setListeners() }
|
||||
.toList()
|
||||
.applySchedulers()
|
||||
.applyViewModel(this)
|
||||
.subscribe({
|
||||
items.update(it)
|
||||
}, Timber::e)
|
||||
.add()
|
||||
}
|
||||
|
||||
fun deletePressed(item: PolicyRvItem) {
|
||||
fun updateState() = deletePolicy(item.item)
|
||||
.subscribe({
|
||||
items.remove(item)
|
||||
}, Timber::e)
|
||||
.add()
|
||||
|
||||
withView {
|
||||
if (FingerprintHelper.useFingerprint()) {
|
||||
FingerprintAuthDialog(this) { updateState() }.show()
|
||||
} else {
|
||||
CustomAlertDialog(this)
|
||||
.setTitle(R.string.su_revoke_title)
|
||||
.setMessage(getString(R.string.su_revoke_msg, item.item.appName))
|
||||
.setPositiveButton(R.string.yes) { _, _ -> updateState() }
|
||||
.setNegativeButton(R.string.no_thanks, null)
|
||||
.setCancelable(true)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun PolicyRvItem.setListeners() = apply {
|
||||
isEnabled.addOnPropertyChangedCallback {
|
||||
it ?: return@addOnPropertyChangedCallback
|
||||
|
||||
if (ignoreNext == this) {
|
||||
ignoreNext = null
|
||||
return@addOnPropertyChangedCallback
|
||||
}
|
||||
|
||||
fun updateState() {
|
||||
item.policy = if (it) Policy.ALLOW else Policy.DENY
|
||||
|
||||
updatePolicy(item)
|
||||
.map { it.policy == Policy.ALLOW }
|
||||
.subscribe({
|
||||
val textId = if (it) R.string.su_snack_grant else R.string.su_snack_deny
|
||||
val text = resources.getString(textId).format(item.appName)
|
||||
SnackbarEvent(text).publish()
|
||||
}, Timber::e)
|
||||
.add()
|
||||
}
|
||||
|
||||
if (FingerprintHelper.useFingerprint()) {
|
||||
withView {
|
||||
FingerprintAuthDialog(this, { updateState() }, {
|
||||
ignoreNext = this@setListeners
|
||||
isEnabled.toggle()
|
||||
}).show()
|
||||
}
|
||||
} else {
|
||||
updateState()
|
||||
}
|
||||
}
|
||||
shouldNotify.addOnPropertyChangedCallback {
|
||||
it ?: return@addOnPropertyChangedCallback
|
||||
item.notification = it
|
||||
|
||||
updatePolicy(item)
|
||||
.map { it.notification }
|
||||
.subscribe({
|
||||
val textId = if (it) R.string.su_snack_notif_on else R.string.su_snack_notif_off
|
||||
val text = resources.getString(textId).format(item.appName)
|
||||
SnackbarEvent(text).publish()
|
||||
}, Timber::e)
|
||||
.add()
|
||||
}
|
||||
shouldLog.addOnPropertyChangedCallback {
|
||||
it ?: return@addOnPropertyChangedCallback
|
||||
item.logging = it
|
||||
|
||||
updatePolicy(item)
|
||||
.map { it.logging }
|
||||
.subscribe({
|
||||
val textId = if (it) R.string.su_snack_log_on else R.string.su_snack_log_off
|
||||
val text = resources.getString(textId).format(item.appName)
|
||||
SnackbarEvent(text).publish()
|
||||
}, Timber::e)
|
||||
.add()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePolicy(policy: Policy) =
|
||||
Single.fromCallable { database.updatePolicy(policy); policy }
|
||||
.applySchedulers()
|
||||
|
||||
private fun deletePolicy(policy: Policy) =
|
||||
Single.fromCallable { database.deletePolicy(policy); policy }
|
||||
.applySchedulers()
|
||||
|
||||
}
|
@ -1,26 +1,53 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/empty_rv"
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.topjohnwu.magisk.ui.superuser.SuperuserViewModel" />
|
||||
|
||||
</data>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:gravity="center"
|
||||
android:text="@string/no_apps_found"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="italic"
|
||||
android:visibility="gone" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:dividerHeight="@dimen/card_divider_space"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/superuser_content"
|
||||
dividerColor="@{@android:color/transparent}"
|
||||
dividerSize="@{@dimen/margin_generic}"
|
||||
gone="@{!viewModel.loaded}"
|
||||
itemBinding="@{viewModel.itemBinding}"
|
||||
items="@{viewModel.items}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/margin_generic"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_policy" />
|
||||
|
||||
<ProgressBar
|
||||
style="@style/Widget.Progress"
|
||||
gone="@{!viewModel.loading}"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/superuser_empty"
|
||||
gone="@{!viewModel.loaded || viewModel.items.size > 0}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:gravity="center"
|
||||
android:text="@string/no_apps_found"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="italic" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
||||
</layout>
|
||||
|
||||
</LinearLayout>
|
||||
|
213
app/src/main/res/layout/item_policy.xml
Normal file
213
app/src/main/res/layout/item_policy.xml
Normal file
@ -0,0 +1,213 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout 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">
|
||||
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="item"
|
||||
type="com.topjohnwu.magisk.model.entity.recycler.PolicyRvItem" />
|
||||
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="com.topjohnwu.magisk.ui.superuser.SuperuserViewModel" />
|
||||
|
||||
</data>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/Widget.Card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:foreground="?attr/selectableItemBackground"
|
||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||
android:onClick="@{() -> item.toggle()}"
|
||||
app:cardCornerRadius="@dimen/radius_generic"
|
||||
app:cardElevation="2dp"
|
||||
app:cardPreventCornerOverlap="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="@dimen/margin_generic_half">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:gravity="end"
|
||||
android:src="@{item.icon}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/app_name"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:srcCompat="@drawable/ic_logo" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/margin_generic"
|
||||
android:layout_marginRight="@dimen/margin_generic"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{item.item.appName}"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toTopOf="@+id/package_name"
|
||||
app:layout_constraintEnd_toStartOf="@+id/master_switch"
|
||||
app:layout_constraintStart_toEndOf="@+id/app_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="@string/app_name" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@{item.item.packageName}"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@android:color/tertiary_text_dark"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@id/app_name"
|
||||
app:layout_constraintStart_toStartOf="@id/app_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/app_name"
|
||||
tools:text="com.topjohnwu.magisk" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/master_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:checked="@={item.isEnabled}"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/app_name"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/expand_layout"
|
||||
gone="@{!item.isExpanded}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_generic_half"
|
||||
android:paddingTop="@dimen/margin_generic_half"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/package_name">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/bell"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:tint="@color/icon_grey"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/notification_switch"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_notifications" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/notification_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:checked="@={item.shouldNotify}"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline"
|
||||
app:layout_constraintStart_toEndOf="@+id/bell"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.4" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/bug"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:tint="@color/icon_grey"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/logging_switch"
|
||||
app:layout_constraintStart_toStartOf="@+id/guideline"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_bug_report" />
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/logging_switch"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:checked="@={item.shouldLog}"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline2"
|
||||
app:layout_constraintStart_toEndOf="@+id/bug"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline2"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.8" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/more_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:tint="@color/icon_grey"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/delete"
|
||||
app:layout_constraintStart_toStartOf="@id/guideline2"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_more" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/delete"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:onClick="@{() -> viewModel.deletePressed(item)}"
|
||||
android:tint="@color/icon_grey"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/more_info"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:srcCompat="@drawable/ic_delete" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</layout>
|
@ -9,6 +9,7 @@
|
||||
<item name="imageColorTint">@color/dark_secondary_text</item>
|
||||
<item name="colorControl">?android:attr/textColorSecondary</item>
|
||||
<item name="colorAccentFallback">@color/accentFallback</item>
|
||||
<item name="android:windowBackground">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -10,6 +10,7 @@
|
||||
<item name="colorAccent">@color/colorSecondary</item>
|
||||
<item name="colorSecondary">@color/colorSecondary</item>
|
||||
<item name="colorSecondaryVariant">@color/colorSecondaryDark</item>
|
||||
<item name="android:windowBackground">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeFoundation.Colored.ExtraProps" />
|
||||
|
Loading…
Reference in New Issue
Block a user