feat: stealth mode indicator

This commit is contained in:
rhunk
2024-01-17 14:53:15 +01:00
parent 8c71e4af27
commit 93490c323c
5 changed files with 89 additions and 0 deletions

View File

@ -340,6 +340,10 @@
"name": "Fidelius Indicator", "name": "Fidelius Indicator",
"description": "Adds a green circle next to messages that have been sent only to you" "description": "Adds a green circle next to messages that have been sent only to you"
}, },
"stealth_mode_indicator": {
"name": "Stealth Mode Indicator",
"description": "Adds a \uD83D\uDC7B emoji next to conversations in stealth mode"
},
"edit_text_override": { "edit_text_override": {
"name": "Edit Text Override", "name": "Edit Text Override",
"description": "Overrides text field behavior" "description": "Overrides text field behavior"

View File

@ -49,6 +49,7 @@ class UserInterfaceTweaks : ConfigContainer() {
val hideSettingsGear = boolean("hide_settings_gear") { requireRestart() } val hideSettingsGear = boolean("hide_settings_gear") { requireRestart() }
val verticalStoryViewer = boolean("vertical_story_viewer") { requireRestart() } val verticalStoryViewer = boolean("vertical_story_viewer") { requireRestart() }
val fideliusIndicator = boolean("fidelius_indicator") { requireRestart() } val fideliusIndicator = boolean("fidelius_indicator") { requireRestart() }
val stealthModeIndicator = boolean("stealth_mode_indicator") { requireRestart() }
val editTextOverride = multiple("edit_text_override", "multi_line_chat_input", "bypass_text_input_limit") { val editTextOverride = multiple("edit_text_override", "multi_line_chat_input", "bypass_text_input_limit") {
requireRestart(); addNotices(FeatureNotice.BAN_RISK, FeatureNotice.INTERNAL_BEHAVIOR) requireRestart(); addNotices(FeatureNotice.BAN_RISK, FeatureNotice.INTERNAL_BEHAVIOR)
} }

View File

@ -4,6 +4,11 @@ import me.rhunk.snapenhance.common.data.MessagingRuleType
import me.rhunk.snapenhance.common.data.RuleState import me.rhunk.snapenhance.common.data.RuleState
abstract class MessagingRuleFeature(name: String, val ruleType: MessagingRuleType, loadParams: Int = 0) : Feature(name, loadParams) { abstract class MessagingRuleFeature(name: String, val ruleType: MessagingRuleType, loadParams: Int = 0) : Feature(name, loadParams) {
private val listeners = mutableListOf<(String, Boolean) -> Unit>()
fun addStateListener(listener: (conversationId: String, newState: Boolean) -> Unit) {
listeners.add(listener)
}
open fun getRuleState() = context.config.rules.getRuleState(ruleType) open fun getRuleState() = context.config.rules.getRuleState(ruleType)
@ -13,6 +18,7 @@ abstract class MessagingRuleFeature(name: String, val ruleType: MessagingRuleTyp
ruleType, ruleType,
state state
) )
listeners.forEach { it(conversationId, state) }
} }
fun getState(conversationId: String) = fun getState(conversationId: String) =

View File

@ -0,0 +1,77 @@
package me.rhunk.snapenhance.core.features.impl.ui
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.Shape
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.rhunk.snapenhance.core.event.events.impl.BindViewEvent
import me.rhunk.snapenhance.core.features.Feature
import me.rhunk.snapenhance.core.features.FeatureLoadParams
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
import me.rhunk.snapenhance.core.ui.addForegroundDrawable
import me.rhunk.snapenhance.core.ui.removeForegroundDrawable
import me.rhunk.snapenhance.core.util.EvictingMap
import me.rhunk.snapenhance.core.util.ktx.getDimens
import me.rhunk.snapenhance.core.util.ktx.getIdentifier
class StealthModeIndicator : Feature("StealthModeIndicator", loadParams = FeatureLoadParams.ACTIVITY_CREATE_SYNC) {
private val stealthMode by lazy { context.feature(StealthMode::class) }
private val listeners = EvictingMap<String, (Boolean) -> Unit>(100)
private fun fetchStealthState(conversationId: String, result: (Boolean) -> Unit) {
context.coroutineScope.launch {
val isStealth = stealthMode.getState(conversationId)
withContext(Dispatchers.Main) {
result(isStealth)
}
}
}
override fun onActivityCreate() {
if (!context.config.userInterface.stealthModeIndicator.get()) return
val secondaryTextSize = context.resources.getDimens("ff_feed_cell_secondary_text_size").toFloat()
val sigColorTextPrimary = context.mainActivity!!.obtainStyledAttributes(
intArrayOf(context.resources.getIdentifier("sigColorTextPrimary", "attr"))
).use { it.getColor(0, 0) }
stealthMode.addStateListener { conversationId, state ->
runCatching {
listeners[conversationId]?.invoke(state)
}.onFailure {
context.log.error("Failed to update stealth mode indicator", it)
}
}
context.event.subscribe(BindViewEvent::class) { event ->
fun updateStealthIndicator(isStealth: Boolean = true) {
event.view.removeForegroundDrawable("stealthModeIndicator")
if (!isStealth || !event.view.isAttachedToWindow) return
event.view.addForegroundDrawable("stealthModeIndicator", ShapeDrawable(object : Shape() {
override fun draw(canvas: Canvas, paint: Paint) {
paint.textSize = secondaryTextSize
paint.color = sigColorTextPrimary
canvas.drawText(
"\uD83D\uDC7B",
0f,
canvas.height.toFloat() - secondaryTextSize / 2,
paint
)
}
}))
}
event.friendFeedItem { conversationId ->
listeners[conversationId] = addStateListener@{ stealth ->
updateStealthIndicator(stealth)
}
fetchStealthState(conversationId) { isStealth ->
updateStealthIndicator(isStealth)
}
}
}
}
}

View File

@ -116,6 +116,7 @@ class FeatureManager(
ConversationToolbox(), ConversationToolbox(),
SpotlightCommentsUsername(), SpotlightCommentsUsername(),
OperaViewerParamsOverride(), OperaViewerParamsOverride(),
StealthModeIndicator(),
) )
initializeFeatures() initializeFeatures()