Skip to content

Commit

Permalink
[app] add launchOtherAppRules
Browse files Browse the repository at this point in the history
  • Loading branch information
Tornaco committed Mar 8, 2024
1 parent 549f24e commit 5d8958d
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package github.tornaco.android.thanos.core.app.activity;

import android.content.ComponentName;
import android.os.RemoteException;

import java.util.List;

Expand Down Expand Up @@ -175,4 +176,19 @@ public boolean isLaunchOtherAppBlockerEnabled() {
public void setLaunchOtherAppBlockerEnabled(boolean enable) {
supervisor.setLaunchOtherAppBlockerEnabled(enable);
}

@SneakyThrows
public void addLaunchOtherAppRule(String rule) throws RemoteException {
supervisor.addLaunchOtherAppRule(rule);
}

@SneakyThrows
public void deleteLaunchOtherAppRule(String rule) throws RemoteException {
supervisor.deleteLaunchOtherAppRule(rule);
}

@SneakyThrows
public String[] getAllLaunchOtherAppRules() throws RemoteException {
return supervisor.getAllLaunchOtherAppRules();
}
}
3 changes: 3 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@
<activity
android:name="now.fortuitous.thanos.launchother.LaunchOtherAppListActivity"
android:exported="false" />
<activity
android:name="now.fortuitous.thanos.launchother.LaunchOtherAppRuleActivity"
android:exported="false" />

<meta-data
android:name="xposedmodule"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.util.List;
import java.util.stream.Collectors;

import github.tornaco.android.thanos.R;
import github.tornaco.android.thanos.common.AppItemClickListener;
import github.tornaco.android.thanos.common.AppListItemDescriptionComposer;
import github.tornaco.android.thanos.common.AppListModel;
Expand Down Expand Up @@ -263,6 +264,10 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
.setPositiveButton(android.R.string.ok, (dialog, which) -> selectAll(ActivityStackSupervisor.LaunchOtherAppPkgSetting.IGNORE)).show();
return true;
}
if (R.id.action_rule == item.getItemId()) {
LaunchOtherAppRuleActivity.start(thisActivity());
return true;
}

return super.onOptionsItemSelected(item);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package now.fortuitous.thanos.launchother

import android.content.Context
import android.content.Intent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.hilt.navigation.compose.hiltViewModel
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.SwipeRefreshIndicator
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import dagger.hilt.android.AndroidEntryPoint
import github.tornaco.android.thanos.module.compose.common.ComposeThemeActivity
import github.tornaco.android.thanos.module.compose.common.DisposableEffectWithLifeCycle
import github.tornaco.android.thanos.module.compose.common.theme.TypographyDefaults
import github.tornaco.android.thanos.module.compose.common.widget.ListItem
import github.tornaco.android.thanos.module.compose.common.widget.TextInputDialog
import github.tornaco.android.thanos.module.compose.common.widget.ThanoxSmallAppBarScaffold
import github.tornaco.android.thanos.module.compose.common.widget.rememberTextInputState

@AndroidEntryPoint
class LaunchOtherAppRuleActivity : ComposeThemeActivity() {
companion object {
@JvmStatic
fun start(context: Context) {
val starter = Intent(context, LaunchOtherAppRuleActivity::class.java)
context.startActivity(starter)
}
}

@Composable
override fun Content() {
val viewModel = hiltViewModel<LaunchOtherAppRuleViewModel>()
val state by viewModel.state.collectAsState()

val inputDialog = rememberTextInputState(
title = stringResource(id = github.tornaco.android.thanos.R.string.menu_title_rules),
message = ""
) {
viewModel.add(it)
}
TextInputDialog(state = inputDialog)

ThanoxSmallAppBarScaffold(
title = {
Text(
text = stringResource(id = github.tornaco.android.thanos.R.string.menu_title_rules),
style = TypographyDefaults.appBarTitleTextStyle()
)
},
onBackPressed = {
thisActivity().finish()
},
actions = {
IconButton(onClick = {
inputDialog.show()
}) {
Icon(
painter = painterResource(id = github.tornaco.android.thanos.R.drawable.ic_add_fill),
contentDescription = "Add"
)
}
}
) { paddings ->

DisposableEffectWithLifeCycle(onResume = {
viewModel.refresh()
})

LaunchedEffect(viewModel) {
viewModel.refresh()
}

SwipeRefresh(
state = rememberSwipeRefreshState(state.isLoading),
onRefresh = { viewModel.refresh() },
indicatorPadding = paddings,
clipIndicatorToPadding = false,
indicator = { state, refreshTriggerDistance ->
SwipeRefreshIndicator(
state = state,
refreshTriggerDistance = refreshTriggerDistance,
scale = true,
arrowEnabled = false,
contentColor = MaterialTheme.colorScheme.primary
)
}
) {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(paddings)
) {
items(state.ruleItems) {
ListItem(modifier = Modifier, title = it.rule,
action1 = {
IconButton(onClick = {
viewModel.remove(it.rule)
}) {
Icon(
painter = painterResource(id = github.tornaco.android.thanos.R.drawable.ic_delete_bin_2_fill),
contentDescription = "Delete"
)
}
})
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package now.fortuitous.thanos.launchother

import android.annotation.SuppressLint
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import github.tornaco.android.thanos.core.app.ThanosManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject

data class RuleItem(val rule: String)

data class OpsState(
val isLoading: Boolean,
val ruleItems: List<RuleItem>
)

@SuppressLint("StaticFieldLeak")
@HiltViewModel
class LaunchOtherAppRuleViewModel @Inject constructor(@ApplicationContext private val context: Context) :
ViewModel() {

private val _state =
MutableStateFlow(
OpsState(
isLoading = true,
ruleItems = emptyList()
)
)
val state = _state.asStateFlow()

private val thanos by lazy { ThanosManager.from(context) }
private val supervisor by lazy { thanos.activityStackSupervisor }

fun refresh() {
_state.value = _state.value.copy(isLoading = true)
viewModelScope.launch {
val rules = withContext(Dispatchers.IO) {
supervisor.allLaunchOtherAppRules.map { RuleItem(it) }
}
_state.value = _state.value.copy(ruleItems = rules, isLoading = false)
}
}

fun add(rule: String) {
supervisor.addLaunchOtherAppRule(rule)
refresh()
}

fun remove(rule: String) {
supervisor.deleteLaunchOtherAppRule(rule)
refresh()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,9 @@
android:title="@string/module_ops_mode_ignore_all"
app:showAsAction="never" />

<item
android:id="@+id/action_rule"
android:title="@string/menu_title_rules"
app:showAsAction="never" />

</menu>

0 comments on commit 5d8958d

Please sign in to comment.