mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-29 13:00:17 +02:00
feat: partial scope content
This commit is contained in:
parent
31570694a0
commit
16a16df51a
@ -33,13 +33,23 @@ class BridgeService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun triggerFriendSync(friendId: String) {
|
fun triggerFriendSync(friendId: String) {
|
||||||
SerializableDataObject.fromJson<FriendInfo>(syncCallback.syncFriend(friendId)).let {
|
val syncedFriend = syncCallback.syncFriend(friendId)
|
||||||
|
if (syncedFriend == null) {
|
||||||
|
Logger.error("Failed to sync friend $friendId")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
SerializableDataObject.fromJson<FriendInfo>(syncedFriend).let {
|
||||||
remoteSideContext.modDatabase.syncFriend(it)
|
remoteSideContext.modDatabase.syncFriend(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun triggerGroupSync(groupId: String) {
|
fun triggerGroupSync(groupId: String) {
|
||||||
SerializableDataObject.fromJson<MessagingGroupInfo>(syncCallback.syncGroup(groupId)).let {
|
val syncedGroup = syncCallback.syncGroup(groupId)
|
||||||
|
if (syncedGroup == null) {
|
||||||
|
Logger.error("Failed to sync group $groupId")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
SerializableDataObject.fromJson<MessagingGroupInfo>(syncedGroup).let {
|
||||||
remoteSideContext.modDatabase.syncGroupInfo(it)
|
remoteSideContext.modDatabase.syncGroupInfo(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,13 @@ class ModDatabase(
|
|||||||
var receiveMessagingDataCallback: (friends: List<MessagingFriendInfo>, groups: List<MessagingGroupInfo>) -> Unit = { _, _ -> }
|
var receiveMessagingDataCallback: (friends: List<MessagingFriendInfo>, groups: List<MessagingGroupInfo>) -> Unit = { _, _ -> }
|
||||||
|
|
||||||
fun executeAsync(block: () -> Unit) {
|
fun executeAsync(block: () -> Unit) {
|
||||||
executor.execute(block)
|
executor.execute {
|
||||||
|
runCatching {
|
||||||
|
block()
|
||||||
|
}.onFailure {
|
||||||
|
Logger.error("Failed to execute async block", it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
@ -56,7 +62,7 @@ class ModDatabase(
|
|||||||
"userId VARCHAR PRIMARY KEY",
|
"userId VARCHAR PRIMARY KEY",
|
||||||
"notify BOOLEAN",
|
"notify BOOLEAN",
|
||||||
"expirationTimestamp BIGINT",
|
"expirationTimestamp BIGINT",
|
||||||
"count INTEGER"
|
"length INTEGER"
|
||||||
),
|
),
|
||||||
"analytics_config" to listOf(
|
"analytics_config" to listOf(
|
||||||
"userId VARCHAR PRIMARY KEY",
|
"userId VARCHAR PRIMARY KEY",
|
||||||
@ -137,7 +143,7 @@ class ModDatabase(
|
|||||||
)
|
)
|
||||||
//sync streaks
|
//sync streaks
|
||||||
if (friend.streakLength > 0) {
|
if (friend.streakLength > 0) {
|
||||||
database.execSQL("INSERT OR REPLACE INTO streaks (userId, expirationTimestamp, count) VALUES (?, ?, ?)", arrayOf(
|
database.execSQL("INSERT OR REPLACE INTO streaks (userId, expirationTimestamp, length) VALUES (?, ?, ?)", arrayOf(
|
||||||
friend.userId,
|
friend.userId,
|
||||||
friend.streakExpirationTimestamp,
|
friend.streakExpirationTimestamp,
|
||||||
friend.streakLength
|
friend.streakLength
|
||||||
@ -227,8 +233,17 @@ class ModDatabase(
|
|||||||
userId = cursor.getStringOrNull("userId")!!,
|
userId = cursor.getStringOrNull("userId")!!,
|
||||||
notify = cursor.getInteger("notify") == 1,
|
notify = cursor.getInteger("notify") == 1,
|
||||||
expirationTimestamp = cursor.getLongOrNull("expirationTimestamp") ?: 0L,
|
expirationTimestamp = cursor.getLongOrNull("expirationTimestamp") ?: 0L,
|
||||||
count = cursor.getInteger("count")
|
length = cursor.getInteger("length")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setFriendStreaksNotify(userId: String, notify: Boolean) {
|
||||||
|
executeAsync {
|
||||||
|
database.execSQL("UPDATE streaks SET notify = ? WHERE userId = ?", arrayOf(
|
||||||
|
if (notify) 1 else 0,
|
||||||
|
userId
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -44,7 +44,8 @@ class MainActivity : ComponentActivity() {
|
|||||||
Scaffold(
|
Scaffold(
|
||||||
containerColor = MaterialTheme.colorScheme.background,
|
containerColor = MaterialTheme.colorScheme.background,
|
||||||
topBar = { navigation.TopBar() },
|
topBar = { navigation.TopBar() },
|
||||||
bottomBar = { navigation.NavBar() }
|
bottomBar = { navigation.NavBar() },
|
||||||
|
floatingActionButton = { navigation.Fab() }
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
navigation.NavigationHost(
|
navigation.NavigationHost(
|
||||||
innerPadding = innerPadding,
|
innerPadding = innerPadding,
|
||||||
|
@ -100,6 +100,15 @@ class Navigation(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Fab() {
|
||||||
|
val navBackStackEntry by navHostController.currentBackStackEntryAsState()
|
||||||
|
val currentDestination = navBackStackEntry?.destination ?: return
|
||||||
|
val currentSection = getCurrentSection(currentDestination)
|
||||||
|
|
||||||
|
currentSection.FloatingActionButton()
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun NavBar() {
|
fun NavBar() {
|
||||||
NavigationBar {
|
NavigationBar {
|
||||||
|
@ -76,6 +76,9 @@ open class Section {
|
|||||||
@Composable
|
@Composable
|
||||||
open fun TopBarActions(rowScope: RowScope) {}
|
open fun TopBarActions(rowScope: RowScope) {}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
open fun FloatingActionButton() {}
|
||||||
|
|
||||||
open fun build(navGraphBuilder: NavGraphBuilder) {
|
open fun build(navGraphBuilder: NavGraphBuilder) {
|
||||||
navGraphBuilder.composable(enumSection.route) {
|
navGraphBuilder.composable(enumSection.route) {
|
||||||
Content()
|
Content()
|
||||||
|
@ -30,6 +30,7 @@ import androidx.compose.material.icons.filled.FolderOpen
|
|||||||
import androidx.compose.material.icons.filled.OpenInNew
|
import androidx.compose.material.icons.filled.OpenInNew
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.icons.rounded.Save
|
import androidx.compose.material.icons.rounded.Save
|
||||||
|
import androidx.compose.material3.BottomSheetScaffoldState
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FilledIconButton
|
import androidx.compose.material3.FilledIconButton
|
||||||
@ -77,6 +78,7 @@ import me.rhunk.snapenhance.core.config.PropertyValue
|
|||||||
import me.rhunk.snapenhance.ui.manager.Section
|
import me.rhunk.snapenhance.ui.manager.Section
|
||||||
import me.rhunk.snapenhance.ui.util.ChooseFolderHelper
|
import me.rhunk.snapenhance.ui.util.ChooseFolderHelper
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
class FeaturesSection : Section() {
|
class FeaturesSection : Section() {
|
||||||
private val dialogs by lazy { Dialogs(context.translation) }
|
private val dialogs by lazy { Dialogs(context.translation) }
|
||||||
|
|
||||||
@ -91,6 +93,8 @@ class FeaturesSection : Section() {
|
|||||||
|
|
||||||
private val featuresRouteName by lazy { context.translation["manager.routes.features"] }
|
private val featuresRouteName by lazy { context.translation["manager.routes.features"] }
|
||||||
|
|
||||||
|
private lateinit var rememberScaffoldState: BottomSheetScaffoldState
|
||||||
|
|
||||||
private val allContainers by lazy {
|
private val allContainers by lazy {
|
||||||
val containers = mutableMapOf<String, PropertyPair<*>>()
|
val containers = mutableMapOf<String, PropertyPair<*>>()
|
||||||
fun queryContainerRecursive(container: ConfigContainer) {
|
fun queryContainerRecursive(container: ConfigContainer) {
|
||||||
@ -458,35 +462,14 @@ class FeaturesSection : Section() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun PropertiesView(
|
private fun PropertiesView(
|
||||||
properties: List<PropertyPair<*>>
|
properties: List<PropertyPair<*>>
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
rememberScaffoldState = rememberBottomSheetScaffoldState()
|
||||||
val scaffoldState = rememberBottomSheetScaffoldState()
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(scaffoldState.snackbarHostState) },
|
snackbarHost = { SnackbarHost(rememberScaffoldState.snackbarHostState) },
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
floatingActionButton = {
|
|
||||||
FloatingActionButton(
|
|
||||||
onClick = {
|
|
||||||
context.config.writeConfig()
|
|
||||||
scope.launch {
|
|
||||||
scaffoldState.snackbarHostState.showSnackbar("Saved")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(10.dp),
|
|
||||||
containerColor = MaterialTheme.colorScheme.primary,
|
|
||||||
contentColor = MaterialTheme.colorScheme.onPrimary,
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Rounded.Save,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
content = { innerPadding ->
|
content = { innerPadding ->
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -494,7 +477,7 @@ class FeaturesSection : Section() {
|
|||||||
.padding(innerPadding),
|
.padding(innerPadding),
|
||||||
//save button space
|
//save button space
|
||||||
contentPadding = PaddingValues(top = 10.dp, bottom = 110.dp),
|
contentPadding = PaddingValues(top = 10.dp, bottom = 110.dp),
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Top
|
||||||
) {
|
) {
|
||||||
items(properties) {
|
items(properties) {
|
||||||
PropertyCard(it)
|
PropertyCard(it)
|
||||||
@ -504,6 +487,28 @@ class FeaturesSection : Section() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun FloatingActionButton() {
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
FloatingActionButton(
|
||||||
|
onClick = {
|
||||||
|
context.config.writeConfig()
|
||||||
|
scope.launch {
|
||||||
|
rememberScaffoldState.snackbarHostState.showSnackbar("Saved")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifier = Modifier.padding(10.dp),
|
||||||
|
containerColor = MaterialTheme.colorScheme.primary,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.Save,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Container(
|
private fun Container(
|
||||||
|
@ -3,7 +3,13 @@ package me.rhunk.snapenhance.ui.manager.sections.social
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.offset
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@ -13,13 +19,18 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.rhunk.snapenhance.RemoteSideContext
|
import me.rhunk.snapenhance.RemoteSideContext
|
||||||
import me.rhunk.snapenhance.core.messaging.MessagingRuleType
|
import me.rhunk.snapenhance.core.messaging.MessagingRuleType
|
||||||
import me.rhunk.snapenhance.core.messaging.SocialScope
|
import me.rhunk.snapenhance.core.messaging.SocialScope
|
||||||
|
import me.rhunk.snapenhance.ui.util.BitmojiImage
|
||||||
|
import me.rhunk.snapenhance.util.snap.BitmojiSelfie
|
||||||
|
|
||||||
class ScopeContent(
|
class ScopeContent(
|
||||||
private val context: RemoteSideContext,
|
private val context: RemoteSideContext,
|
||||||
@ -28,7 +39,6 @@ class ScopeContent(
|
|||||||
private val scope: SocialScope,
|
private val scope: SocialScope,
|
||||||
private val id: String
|
private val id: String
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DeleteScopeEntityButton() {
|
private fun DeleteScopeEntityButton() {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
@ -40,7 +50,7 @@ class ScopeContent(
|
|||||||
context.modDatabase.executeAsync {
|
context.modDatabase.executeAsync {
|
||||||
coroutineScope.launch {
|
coroutineScope.launch {
|
||||||
section.onResumed()
|
section.onResumed()
|
||||||
navController.popBackStack()
|
navController.navigate(SocialSection.MAIN_ROUTE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
@ -50,7 +60,10 @@ class ScopeContent(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Content() {
|
fun Content() {
|
||||||
Column {
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
when (scope) {
|
when (scope) {
|
||||||
SocialScope.FRIEND -> Friend()
|
SocialScope.FRIEND -> Friend()
|
||||||
SocialScope.GROUP -> Group()
|
SocialScope.GROUP -> Group()
|
||||||
@ -60,26 +73,87 @@ class ScopeContent(
|
|||||||
|
|
||||||
val scopeRules = context.modDatabase.getRulesFromId(scope, id)
|
val scopeRules = context.modDatabase.getRulesFromId(scope, id)
|
||||||
|
|
||||||
Text(text = "Rules", maxLines = 1)
|
SectionTitle("Rules")
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
//manager anti features etc
|
ContentCard {
|
||||||
MessagingRuleType.values().forEach { feature ->
|
//manager anti features etc
|
||||||
var featureEnabled by remember {
|
MessagingRuleType.values().forEach { feature ->
|
||||||
mutableStateOf(scopeRules.any { it.subject == feature.key })
|
var featureEnabled by remember {
|
||||||
}
|
mutableStateOf(scopeRules.any { it.subject == feature.key })
|
||||||
val featureEnabledText = if (featureEnabled) "Enabled" else "Disabled"
|
}
|
||||||
Row {
|
val featureEnabledText = if (featureEnabled) "Enabled" else "Disabled"
|
||||||
Text(text = "${feature.key}: $featureEnabledText", maxLines = 1)
|
|
||||||
Switch(checked = featureEnabled, onCheckedChange = {
|
Row {
|
||||||
context.modDatabase.toggleRuleFor(scope, id, feature.key, it)
|
Text(text = "${feature.key}: $featureEnabledText", maxLines = 1)
|
||||||
featureEnabled = it
|
Switch(checked = featureEnabled, onCheckedChange = {
|
||||||
})
|
context.modDatabase.toggleRuleFor(scope, id, feature.key, it)
|
||||||
|
featureEnabled = it
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ContentCard(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp)
|
||||||
|
.fillMaxWidth()
|
||||||
|
.then(modifier)
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun SectionTitle(title: String) {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
maxLines = 1,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier
|
||||||
|
.offset(x = 20.dp)
|
||||||
|
.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
//need to display all units?
|
||||||
|
private fun computeStreakETA(timestamp: Long): String {
|
||||||
|
val now = System.currentTimeMillis()
|
||||||
|
val stringBuilder = StringBuilder()
|
||||||
|
val diff = timestamp - now
|
||||||
|
val seconds = diff / 1000
|
||||||
|
val minutes = seconds / 60
|
||||||
|
val hours = minutes / 60
|
||||||
|
val days = hours / 24
|
||||||
|
if (days > 0) {
|
||||||
|
stringBuilder.append("$days days ")
|
||||||
|
return stringBuilder.toString()
|
||||||
|
}
|
||||||
|
if (hours > 0) {
|
||||||
|
stringBuilder.append("$hours hours ")
|
||||||
|
return stringBuilder.toString()
|
||||||
|
}
|
||||||
|
if (minutes > 0) {
|
||||||
|
stringBuilder.append("$minutes minutes ")
|
||||||
|
return stringBuilder.toString()
|
||||||
|
}
|
||||||
|
if (seconds > 0) {
|
||||||
|
stringBuilder.append("$seconds seconds ")
|
||||||
|
return stringBuilder.toString()
|
||||||
|
}
|
||||||
|
return "Expired"
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Friend() {
|
private fun Friend() {
|
||||||
//fetch the friend from the database
|
//fetch the friend from the database
|
||||||
@ -87,15 +161,74 @@ class ScopeContent(
|
|||||||
Text(text = "Friend not found")
|
Text(text = "Friend not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Column {
|
|
||||||
Text(text = friend.displayName ?: "No display name", maxLines = 1)
|
|
||||||
Text(text = "bitmojiId: ${friend.bitmojiId ?: "No bitmojiId"}", maxLines = 1)
|
|
||||||
Text(text = "selfieId: ${friend.selfieId ?: "No selfieId"}", maxLines = 1)
|
|
||||||
|
|
||||||
|
val streaks = remember {
|
||||||
|
context.modDatabase.getFriendStreaks(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(10.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
val bitmojiUrl = (friend.selfieId to friend.bitmojiId).let { (selfieId, bitmojiId) ->
|
||||||
|
if (selfieId == null || bitmojiId == null) return@let null
|
||||||
|
BitmojiSelfie.getBitmojiSelfie(
|
||||||
|
selfieId,
|
||||||
|
bitmojiId,
|
||||||
|
BitmojiSelfie.BitmojiSelfieType.THREE_D
|
||||||
|
)
|
||||||
|
}
|
||||||
|
BitmojiImage(context = context, url = bitmojiUrl, size = 100)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Text(
|
||||||
|
text = friend.displayName ?: friend.mutableUsername,
|
||||||
|
maxLines = 1,
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(5.dp))
|
||||||
|
Text(
|
||||||
|
text = friend.mutableUsername,
|
||||||
|
maxLines = 1,
|
||||||
|
fontSize = 12.sp,
|
||||||
|
fontWeight = FontWeight.Light
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
DeleteScopeEntityButton()
|
DeleteScopeEntityButton()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
Column {
|
||||||
|
//streaks
|
||||||
|
streaks?.let {
|
||||||
|
var shouldNotify by remember { mutableStateOf(it.notify) }
|
||||||
|
SectionTitle("Streaks")
|
||||||
|
ContentCard {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
) {
|
||||||
|
Text(text = "Count: ${streaks.length}", maxLines = 1)
|
||||||
|
Text(text = "Expires in: ${computeStreakETA(streaks.expirationTimestamp)}", maxLines = 1)
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(text = "Notify Expiration", maxLines = 1)
|
||||||
|
Switch(checked = shouldNotify, onCheckedChange = {
|
||||||
|
context.modDatabase.setFriendStreaksNotify(id, it)
|
||||||
|
shouldNotify = it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -26,7 +26,6 @@ import androidx.compose.material3.TabRowDefaults
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
@ -147,7 +146,7 @@ class SocialSection : Section() {
|
|||||||
) {
|
) {
|
||||||
val bitmojiUrl = (friend.selfieId to friend.bitmojiId).let { (selfieId, bitmojiId) ->
|
val bitmojiUrl = (friend.selfieId to friend.bitmojiId).let { (selfieId, bitmojiId) ->
|
||||||
if (selfieId == null || bitmojiId == null) return@let null
|
if (selfieId == null || bitmojiId == null) return@let null
|
||||||
BitmojiSelfie.getBitmojiSelfie(selfieId, bitmojiId, BitmojiSelfie.BitmojiSelfieType.STANDARD)
|
BitmojiSelfie.getBitmojiSelfie(selfieId, bitmojiId, BitmojiSelfie.BitmojiSelfieType.THREE_D)
|
||||||
}
|
}
|
||||||
BitmojiImage(context = context, url = bitmojiUrl)
|
BitmojiImage(context = context, url = bitmojiUrl)
|
||||||
Column(
|
Column(
|
||||||
|
@ -6,12 +6,12 @@ interface SyncCallback {
|
|||||||
* @param uuid The uuid of the friend to sync
|
* @param uuid The uuid of the friend to sync
|
||||||
* @return The serialized friend data
|
* @return The serialized friend data
|
||||||
*/
|
*/
|
||||||
String syncFriend(String uuid);
|
@nullable String syncFriend(String uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the conversation data has been synced
|
* Called when the conversation data has been synced
|
||||||
* @param uuid The uuid of the conversation to sync
|
* @param uuid The uuid of the conversation to sync
|
||||||
* @return The serialized conversation data
|
* @return The serialized conversation data
|
||||||
*/
|
*/
|
||||||
String syncGroup(String uuid);
|
@nullable String syncGroup(String uuid);
|
||||||
}
|
}
|
@ -89,6 +89,7 @@ class SnapEnhance {
|
|||||||
|
|
||||||
Logger.debug("Reloading config")
|
Logger.debug("Reloading config")
|
||||||
appContext.reloadConfig()
|
appContext.reloadConfig()
|
||||||
|
syncRemote()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +132,7 @@ class SnapEnhance {
|
|||||||
val database = appContext.database
|
val database = appContext.database
|
||||||
|
|
||||||
appContext.executeAsync {
|
appContext.executeAsync {
|
||||||
|
Logger.debug("request remote sync")
|
||||||
appContext.bridgeClient.sync(object : SyncCallback.Stub() {
|
appContext.bridgeClient.sync(object : SyncCallback.Stub() {
|
||||||
override fun syncFriend(uuid: String): String? {
|
override fun syncFriend(uuid: String): String? {
|
||||||
return database.getFriendInfo(uuid)?.toJson()
|
return database.getFriendInfo(uuid)?.toJson()
|
||||||
|
@ -29,7 +29,7 @@ data class FriendStreaks(
|
|||||||
val userId: String,
|
val userId: String,
|
||||||
val notify: Boolean,
|
val notify: Boolean,
|
||||||
val expirationTimestamp: Long,
|
val expirationTimestamp: Long,
|
||||||
val count: Int
|
val length: Int
|
||||||
) : SerializableDataObject()
|
) : SerializableDataObject()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user