feat(app/ui): home section redesign
This commit is contained in:
@@ -65,7 +65,7 @@ class Navigation(
|
||||
val currentSection = getCurrentSection(currentDestination)
|
||||
|
||||
TopAppBar(title = {
|
||||
Text(text = currentSection.sectionTopBarName())
|
||||
currentSection.Title()
|
||||
}, navigationIcon = {
|
||||
val backButtonAnimation by animateFloatAsState(if (currentSection.canGoBack()) 1f else 0f,
|
||||
label = "backButtonAnimation"
|
||||
|
||||
@@ -3,6 +3,7 @@ package me.rhunk.snapenhance.ui.manager
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.navigation.NavController
|
||||
@@ -70,6 +71,9 @@ open class Section {
|
||||
open fun sectionTopBarName(): String = context.translation["manager.routes.${enumSection.route}"]
|
||||
open fun canGoBack(): Boolean = false
|
||||
|
||||
@Composable
|
||||
open fun Title() { Text(text = sectionTopBarName()) }
|
||||
|
||||
@Composable
|
||||
open fun Content() { NotImplemented() }
|
||||
|
||||
|
||||
@@ -4,16 +4,15 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material.icons.filled.BugReport
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.scale
|
||||
@@ -21,7 +20,11 @@ import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -30,12 +33,11 @@ import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navigation
|
||||
import kotlinx.coroutines.launch
|
||||
import me.rhunk.snapenhance.R
|
||||
import me.rhunk.snapenhance.common.BuildConfig
|
||||
import me.rhunk.snapenhance.ui.manager.Section
|
||||
import me.rhunk.snapenhance.ui.manager.data.InstallationSummary
|
||||
import me.rhunk.snapenhance.ui.manager.data.Updater
|
||||
import me.rhunk.snapenhance.ui.setup.Requirements
|
||||
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
||||
import me.rhunk.snapenhance.ui.util.saveFile
|
||||
import java.util.Locale
|
||||
|
||||
class HomeSection : Section() {
|
||||
@@ -56,31 +58,6 @@ class HomeSection : Section() {
|
||||
activityLauncherHelper = ActivityLauncherHelper(context.activity!!)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SummaryCardRow(icon: ImageVector? = null, title: String, action: @Composable () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier.padding(all = 16.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
icon?.let {
|
||||
Icon(
|
||||
imageVector = it,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = 10.dp)
|
||||
.align(Alignment.CenterVertically)
|
||||
)
|
||||
}
|
||||
Text(text = title, modifier = Modifier
|
||||
.weight(1f)
|
||||
.align(Alignment.CenterVertically)
|
||||
)
|
||||
Column {
|
||||
action()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SummaryCards(installationSummary: InstallationSummary) {
|
||||
val summaryInfo = remember {
|
||||
@@ -130,35 +107,6 @@ class HomeSection : Section() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutlinedCard(
|
||||
modifier = Modifier
|
||||
.padding(all = cardMargin)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
SummaryCardRow(
|
||||
icon = Icons.Filled.Map,
|
||||
title = if (installationSummary.modInfo == null || installationSummary.modInfo.mappingsOutdated == true) {
|
||||
"Mappings ${if (installationSummary.modInfo == null) "not generated" else "outdated"}"
|
||||
} else {
|
||||
"Mappings are up-to-date"
|
||||
}
|
||||
) {
|
||||
Button(onClick = {
|
||||
context.checkForRequirements(Requirements.MAPPINGS)
|
||||
}, modifier = Modifier.height(40.dp)) {
|
||||
Icon(Icons.Filled.Refresh, contentDescription = null)
|
||||
}
|
||||
}
|
||||
|
||||
SummaryCardRow(icon = Icons.Filled.Language, title = userLocale ?: "Unknown") {
|
||||
Button(onClick = {
|
||||
context.checkForRequirements(Requirements.LANGUAGE)
|
||||
}, modifier = Modifier.height(40.dp)) {
|
||||
Icon(Icons.Filled.OpenInNew, contentDescription = null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResumed() {
|
||||
@@ -173,7 +121,9 @@ class HomeSection : Section() {
|
||||
context.longToast("SnapEnhance failed to load installation summary: ${it.message}")
|
||||
}
|
||||
runCatching {
|
||||
latestUpdate = Updater.checkForLatestRelease()
|
||||
if (!BuildConfig.DEBUG) {
|
||||
latestUpdate = Updater.checkForLatestRelease()
|
||||
}
|
||||
}.onFailure {
|
||||
context.longToast("SnapEnhance failed to check for updates: ${it.message}")
|
||||
}
|
||||
@@ -211,48 +161,7 @@ class HomeSection : Section() {
|
||||
}
|
||||
}
|
||||
LOGS_SECTION_ROUTE -> {
|
||||
var showDropDown by remember { mutableStateOf(false) }
|
||||
|
||||
IconButton(onClick = {
|
||||
showDropDown = true
|
||||
}) {
|
||||
Icon(Icons.Filled.MoreVert, contentDescription = null)
|
||||
}
|
||||
|
||||
DropdownMenu(
|
||||
expanded = showDropDown,
|
||||
onDismissRequest = { showDropDown = false },
|
||||
modifier = Modifier.align(Alignment.CenterVertically)
|
||||
) {
|
||||
DropdownMenuItem(onClick = {
|
||||
context.log.clearLogs()
|
||||
navController.navigate(LOGS_SECTION_ROUTE)
|
||||
showDropDown = false
|
||||
}, text = {
|
||||
Text(
|
||||
text = context.translation["manager.sections.home.logs.clear_logs_button"]
|
||||
)
|
||||
})
|
||||
|
||||
DropdownMenuItem(onClick = {
|
||||
activityLauncherHelper.saveFile("snapenhance-logs-${System.currentTimeMillis()}.zip", "application/zip") { uri ->
|
||||
context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use {
|
||||
runCatching {
|
||||
context.log.exportLogsToZip(it)
|
||||
context.longToast("Saved logs to $uri")
|
||||
}.onFailure {
|
||||
context.longToast("Failed to save logs to $uri!")
|
||||
context.log.error("Failed to save logs to $uri!", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
showDropDown = false
|
||||
}, text = {
|
||||
Text(
|
||||
text = context.translation["manager.sections.home.logs.export_logs_button"]
|
||||
)
|
||||
})
|
||||
}
|
||||
homeSubSection.LogsTopBarButtons(activityLauncherHelper, navController, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,30 +188,84 @@ class HomeSection : Section() {
|
||||
@Composable
|
||||
@Preview
|
||||
override fun Content() {
|
||||
val avenirNextFontFamily = remember {
|
||||
FontFamily(
|
||||
Font(R.font.avenir_next_medium, FontWeight.Medium)
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(ScrollState(0))
|
||||
) {
|
||||
Column(
|
||||
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.launcher_icon_monochrome),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary),
|
||||
contentScale = ContentScale.FillHeight,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.scale(1.8f)
|
||||
.height(90.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = arrayOf("\u0020", "\u0065", "\u0063", "\u006e", "\u0061", "\u0068", "\u006e", "\u0045", "\u0070", "\u0061", "\u006e", "\u0053").reversed().joinToString(""),
|
||||
fontSize = 30.sp,
|
||||
fontFamily = avenirNextFontFamily,
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "v" + BuildConfig.VERSION_NAME + " \u00b7 by rhunk",
|
||||
fontSize = 12.sp,
|
||||
fontFamily = avenirNextFontFamily,
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "An Xposed module made to enhance your Snapchat experience",
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(15.dp, Alignment.CenterHorizontally),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 10.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.launcher_icon_monochrome),
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = R.drawable.ic_github),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary),
|
||||
contentScale = ContentScale.FillHeight,
|
||||
modifier = Modifier
|
||||
.height(120.dp)
|
||||
.scale(1.75f)
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(32.dp).clickable {
|
||||
context.activity?.startActivity(
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = Uri.parse("https://github.com/rhunk/SnapEnhance")
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
Text(
|
||||
text = arrayOf("\u0065", "\u0063", "\u006e", "\u0061", "\u0068", "\u006e", "\u0045", "\u0070", "\u0061", "\u006e", "\u0053").reversed().joinToString(""),
|
||||
fontSize = 30.sp,
|
||||
modifier = Modifier.padding(16.dp),
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(id = R.drawable.ic_telegram),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(32.dp).clickable {
|
||||
context.activity?.startActivity(
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = Uri.parse("https://t.me/snapenhance")
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
|
||||
if (latestUpdate != null) {
|
||||
OutlinedCard(
|
||||
@@ -345,11 +308,6 @@ class HomeSection : Section() {
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "An Xposed module made to enhance your Snapchat experience",
|
||||
modifier = Modifier.padding(16.dp)
|
||||
)
|
||||
|
||||
SummaryCards(installationSummary = installationSummary ?: return)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.rhunk.snapenhance.ui.manager.sections.home
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.compose.foundation.ScrollState
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
@@ -10,14 +11,12 @@ import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.KeyboardDoubleArrowDown
|
||||
import androidx.compose.material.icons.filled.KeyboardDoubleArrowUp
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.outlined.BugReport
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material.icons.outlined.Report
|
||||
import androidx.compose.material.icons.outlined.Warning
|
||||
import androidx.compose.material3.FilledIconButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -28,6 +27,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavController
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -36,8 +36,10 @@ import me.rhunk.snapenhance.LogReader
|
||||
import me.rhunk.snapenhance.RemoteSideContext
|
||||
import me.rhunk.snapenhance.common.logger.LogChannel
|
||||
import me.rhunk.snapenhance.common.logger.LogLevel
|
||||
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
||||
import me.rhunk.snapenhance.ui.util.pullrefresh.PullRefreshIndicator
|
||||
import me.rhunk.snapenhance.ui.util.pullrefresh.rememberPullRefreshState
|
||||
import me.rhunk.snapenhance.ui.util.saveFile
|
||||
|
||||
class HomeSubSection(
|
||||
private val context: RemoteSideContext
|
||||
@@ -170,6 +172,54 @@ class HomeSubSection(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LogsTopBarButtons(activityLauncherHelper: ActivityLauncherHelper, navController: NavController, rowScope: RowScope) {
|
||||
var showDropDown by remember { mutableStateOf(false) }
|
||||
|
||||
IconButton(onClick = {
|
||||
showDropDown = true
|
||||
}) {
|
||||
Icon(Icons.Filled.MoreVert, contentDescription = null)
|
||||
}
|
||||
|
||||
rowScope.apply {
|
||||
DropdownMenu(
|
||||
expanded = showDropDown,
|
||||
onDismissRequest = { showDropDown = false },
|
||||
modifier = Modifier.align(Alignment.CenterVertically)
|
||||
) {
|
||||
DropdownMenuItem(onClick = {
|
||||
context.log.clearLogs()
|
||||
navController.navigate(HomeSection.LOGS_SECTION_ROUTE)
|
||||
showDropDown = false
|
||||
}, text = {
|
||||
Text(
|
||||
text = context.translation["manager.sections.home.logs.clear_logs_button"]
|
||||
)
|
||||
})
|
||||
|
||||
DropdownMenuItem(onClick = {
|
||||
activityLauncherHelper.saveFile("snapenhance-logs-${System.currentTimeMillis()}.zip", "application/zip") { uri ->
|
||||
context.androidContext.contentResolver.openOutputStream(Uri.parse(uri))?.use {
|
||||
runCatching {
|
||||
context.log.exportLogsToZip(it)
|
||||
context.longToast("Saved logs to $uri")
|
||||
}.onFailure {
|
||||
context.longToast("Failed to save logs to $uri!")
|
||||
context.log.error("Failed to save logs to $uri!", it)
|
||||
}
|
||||
}
|
||||
}
|
||||
showDropDown = false
|
||||
}, text = {
|
||||
Text(
|
||||
text = context.translation["manager.sections.home.logs.export_logs_button"]
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LogsActionButtons() {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
@@ -21,6 +21,7 @@ import me.rhunk.snapenhance.common.Constants
|
||||
import me.rhunk.snapenhance.common.action.EnumAction
|
||||
import me.rhunk.snapenhance.common.bridge.types.BridgeFileType
|
||||
import me.rhunk.snapenhance.ui.manager.Section
|
||||
import me.rhunk.snapenhance.ui.setup.Requirements
|
||||
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
||||
import me.rhunk.snapenhance.ui.util.AlertDialogs
|
||||
import me.rhunk.snapenhance.ui.util.saveFile
|
||||
@@ -63,7 +64,7 @@ class SettingsSection(
|
||||
ShiftedRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(65.dp)
|
||||
.height(55.dp)
|
||||
.clickable {
|
||||
takeAction()
|
||||
},
|
||||
@@ -116,6 +117,12 @@ class SettingsSection(
|
||||
launchActionIntent(enumAction)
|
||||
}
|
||||
}
|
||||
RowAction(title = "Regenerate Mappings") {
|
||||
context.checkForRequirements(Requirements.MAPPINGS)
|
||||
}
|
||||
RowAction(title = "Change Language") {
|
||||
context.checkForRequirements(Requirements.LANGUAGE)
|
||||
}
|
||||
RowTitle(title = "Message Logger")
|
||||
ShiftedRow {
|
||||
Column(
|
||||
@@ -227,6 +234,7 @@ class SettingsSection(
|
||||
Text(text = "Clear")
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(50.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
11
app/src/main/res/drawable/ic_github.xml
Normal file
11
app/src/main/res/drawable/ic_github.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,0c-6.626,0 -12,5.373 -12,12 0,5.302 3.438,9.8 8.207,11.387 0.599,0.111 0.793,-0.261 0.793,-0.577v-2.234c-3.338,0.726 -4.033,-1.416 -4.033,-1.416 -0.546,-1.387 -1.333,-1.756 -1.333,-1.756 -1.089,-0.745 0.083,-0.729 0.083,-0.729 1.205,0.084 1.839,1.237 1.839,1.237 1.07,1.834 2.807,1.304 3.492,0.997 0.107,-0.775 0.418,-1.305 0.762,-1.604 -2.665,-0.305 -5.467,-1.334 -5.467,-5.931 0,-1.311 0.469,-2.381 1.236,-3.221 -0.124,-0.303 -0.535,-1.524 0.117,-3.176 0,0 1.008,-0.322 3.301,1.23 0.957,-0.266 1.983,-0.399 3.003,-0.404 1.02,0.005 2.047,0.138 3.006,0.404 2.291,-1.552 3.297,-1.23 3.297,-1.23 0.653,1.653 0.242,2.874 0.118,3.176 0.77,0.84 1.235,1.911 1.235,3.221 0,4.609 -2.807,5.624 -5.479,5.921 0.43,0.372 0.823,1.102 0.823,2.222v3.293c0,0.319 0.192,0.694 0.801,0.576 4.765,-1.589 8.199,-6.086 8.199,-11.386 0,-6.627 -5.373,-12 -12,-12z"
|
||||
tools:ignore="VectorPath" />
|
||||
</vector>
|
||||
4
app/src/main/res/drawable/ic_telegram.xml
Normal file
4
app/src/main/res/drawable/ic_telegram.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<vector android:height="24dp" android:viewportHeight="32"
|
||||
android:viewportWidth="32" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="m16,0.5c-8.563,0 -15.5,6.938 -15.5,15.5s6.938,15.5 15.5,15.5c8.563,0 15.5,-6.938 15.5,-15.5s-6.938,-15.5 -15.5,-15.5zM23.613,11.119 L21.069,23.107c-0.188,0.85 -0.694,1.056 -1.4,0.656l-3.875,-2.856 -1.869,1.8c-0.206,0.206 -0.381,0.381 -0.781,0.381l0.275,-3.944 7.181,-6.488c0.313,-0.275 -0.069,-0.431 -0.482,-0.156l-8.875,5.587 -3.825,-1.194c-0.831,-0.262 -0.85,-0.831 0.175,-1.231l14.944,-5.763c0.694,-0.25 1.3,0.169 1.075,1.219z"/>
|
||||
</vector>
|
||||
@@ -7,10 +7,10 @@ enum class EnumAction(
|
||||
val exitOnFinish: Boolean = false,
|
||||
val isCritical: Boolean = false,
|
||||
) {
|
||||
CLEAN_CACHE("clean_snapchat_cache", exitOnFinish = true),
|
||||
EXPORT_CHAT_MESSAGES("export_chat_messages"),
|
||||
EXPORT_MEMORIES("export_memories"),
|
||||
BULK_MESSAGING_ACTION("bulk_messaging_action");
|
||||
BULK_MESSAGING_ACTION("bulk_messaging_action"),
|
||||
CLEAN_CACHE("clean_snapchat_cache", exitOnFinish = true);
|
||||
|
||||
companion object {
|
||||
const val ACTION_PARAMETER = "se_action"
|
||||
|
||||
Reference in New Issue
Block a user