redesign: PurrAura Indicator(thanks to RSR)

This commit is contained in:
particle-box
2026-01-26 13:37:27 +05:30
parent 1401aa90cc
commit 296769af49
30 changed files with 243 additions and 58 deletions

View File

@@ -148,6 +148,10 @@
"clear_history": "অনুসন্ধানের তথ্য মুছে ফেলুন",
"subtitle": "অনুসন্ধান ও পরিচালনা করুন"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "নিষ্ক্রিয়",
"disable_state_subtext": "কোন বন্ধু/ কোরোর প্রভাবিত হবে না",

View File

@@ -148,6 +148,10 @@
"clear_history": "Ryd søgehistorik",
"subtitle": "Søg og administrere funktioner"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Deaktiveret",
"disable_state_subtext": "Ingen venner / grupper vil blive påvirket",

View File

@@ -148,6 +148,10 @@
"clear_history": "Suchverlauf löschen",
"subtitle": "Funktionen suchen und verwalten"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Behinderte",
"disable_state_subtext": "Keine Freunde / Gruppen betroffen",

View File

@@ -148,6 +148,10 @@
"clear_history": "Clear search history",
"subtitle": "Search and manage features"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Disabled",
"disable_state_subtext": "No friends/groups will be affected",

View File

@@ -148,6 +148,10 @@
"clear_history": "Clear search history",
"subtitle": "Search and manage features"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Disabled",
"disable_state_subtext": "No friends/groups will be affected",

View File

@@ -148,6 +148,10 @@
"clear_history": "Historial de búsqueda clara",
"subtitle": "Buscar y gestionar características"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Discapacitados",
"disable_state_subtext": "Ningún amigo/grupos será afectado",

View File

@@ -148,6 +148,10 @@
"clear_history": "Tyhjennä hakuhistoria",
"subtitle": "Etsi ja hallitse ominaisuuksia"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Ei käytössä",
"disable_state_subtext": "Ystäviä tai ryhmiä ei muuteta",

View File

@@ -148,6 +148,10 @@
"clear_history": "Effacer l'historique de la recherche",
"subtitle": "Recherche et gestion des fonctionnalités"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Handicapés",
"disable_state_subtext": "Aucun ami/groupe ne sera affecté",

View File

@@ -148,6 +148,10 @@
"clear_history": "खोज इतिहास साफ़ करें",
"subtitle": "सुविधाओं को खोजें और प्रबंधित करें"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "विकलांग",
"disable_state_subtext": "कोई मित्र/समूह प्रभावित नहीं होंगे",

View File

@@ -148,6 +148,10 @@
"clear_history": "A keresési előzmények törlése",
"subtitle": "Keresési és kezelési funkciók"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Fogyatékos",
"disable_state_subtext": "Nem lesz hatással a barátok / csoportok",

View File

@@ -148,6 +148,10 @@
"clear_history": "Bersihkan riwayat pencarian",
"subtitle": "Cari dan kelola fitur"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Dinonaktifkan",
"disable_state_subtext": "Tidak ada teman / kelompok yang akan terpengaruh",

View File

@@ -148,6 +148,10 @@
"clear_history": "Cancella la cronologia di ricerca",
"subtitle": "Ricerca e gestione delle funzionalità"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Disabili",
"disable_state_subtext": "Nessun amico/gruppo sarà interessato",

View File

@@ -148,6 +148,10 @@
"clear_history": "明確な検索履歴",
"subtitle": "機能の検索と管理"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "バリアフリー",
"disable_state_subtext": "友だち/グループが影響しません",

View File

@@ -148,6 +148,10 @@
"clear_history": "자주 묻는 질문",
"subtitle": "검색 및 관리 기능"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "지원하다",
"disable_state_subtext": "친구 / 그룹은 영향을받지 않습니다",

View File

@@ -148,6 +148,10 @@
"clear_history": "پاککردنەوەی مێژووی گەڕان",
"subtitle": "گەڕان و بەڕێوەبردنی تایبەتمەندییەکان"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "ناچالاک کراوە",
"disable_state_subtext": "هیچ هاوڕێ/گرووپێک کاریگەر نابێت",

View File

@@ -148,6 +148,10 @@
"clear_history": "Tīrīt meklēšanas vēsturi",
"subtitle": "Meklēt un pārvaldīt funkcijas"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Atslēgts",
"disable_state_subtext": "Nekādi draugi/grupas netiks ietekmēti",

View File

@@ -148,6 +148,10 @@
"clear_history": "Tøm søkehistorikken",
"subtitle": "Søk og administrere funksjoner"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Deaktivert",
"disable_state_subtext": "Ingen venner/grupper vil bli berørt",

View File

@@ -148,6 +148,10 @@
"clear_history": "Zoekgeschiedenis wissen",
"subtitle": "Functies zoeken en beheren"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Uitgeschakeld",
"disable_state_subtext": "Geen vrienden/groepen worden beïnvloed",

View File

@@ -148,6 +148,10 @@
"clear_history": "Wyczyść historię wyszukiwania",
"subtitle": "Funkcja wyszukiwania i zarządzania"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Wyłączone",
"disable_state_subtext": "Nie wpłynie to na przyjaciół / grupy",

View File

@@ -148,6 +148,10 @@
"clear_history": "Limpar o histórico de pesquisa",
"subtitle": "Procurar e gerenciar recursos"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Desactivado",
"disable_state_subtext": "Nenhum amigo/grupo será afetado",

View File

@@ -148,6 +148,10 @@
"clear_history": "Șterge istoricul căutării",
"subtitle": "Caută și gestionează caracteristicile"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Dezactivat",
"disable_state_subtext": "Niciun prieten/grup nu va fi afectat",

View File

@@ -148,6 +148,10 @@
"clear_history": "Ясная история поиска",
"subtitle": "Поиск и управление функциями"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Инвалид",
"disable_state_subtext": "Друзья/группы не будут затронуты",

View File

@@ -148,6 +148,10 @@
"clear_history": "Počisti zgodovino iskanja",
"subtitle": "Iskanje in upravljanje funkcij"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Onemogočeno",
"disable_state_subtext": "Na prijatelje/skupine ne bo vpliva",

View File

@@ -148,6 +148,10 @@
"clear_history": "Tydlig sökhistoria",
"subtitle": "Sök och hantera funktioner"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Inaktiverad",
"disable_state_subtext": "Inga vänner/grupper kommer att påverkas",

View File

@@ -148,6 +148,10 @@
"clear_history": "Arama geçmişini temizle",
"subtitle": "Özellikleri ara ve yönet"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Devre Dışı",
"disable_state_subtext": "Hiçbir arkadaş/grup etkilenmeyecek",

View File

@@ -148,6 +148,10 @@
"clear_history": "Історія пошуку",
"subtitle": "Пошук і управління функціями"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "Вимкнено",
"disable_state_subtext": "Ніяких друзів/груп",

View File

@@ -148,6 +148,10 @@
"clear_history": "清除搜索历史",
"subtitle": "搜索和管理特性"
},
"bypass_status": {
"active": "PurrAura Active",
"inactive": "PurrAura Inactive"
},
"manage_rule_feature": {
"disable_state_option": "已禁用",
"disable_state_subtext": "没有朋友或团体受到影响",

View File

@@ -1,24 +1,8 @@
package me.eternal.purrfectsnap.core.features.impl.global
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.delay
import me.eternal.purrfectsnap.core.features.Feature
import me.eternal.purrfectsnap.core.event.events.impl.NetworkApiRequestEvent
import me.eternal.purrfectsnap.core.event.events.impl.UnaryCallEvent
import me.eternal.purrfectsnap.core.ui.CustomComposable
import me.eternal.purrfectsnap.core.util.dataBuilder
import me.eternal.purrfectsnap.core.util.hook.HookStage
import me.eternal.purrfectsnap.core.util.hook.hook
@@ -32,47 +16,6 @@ class EndpointsBlocker : Feature("EndpointsBlocker") {
@Volatile
private var isInLoginSignup = false
private fun showBypassStatusIndicator(isWorking: Boolean) {
if (context.bridgeClient.getDebugProp("disable_bypass_indicator", "false") == "true") {
return
}
lateinit var composable: CustomComposable
composable = {
Row(
modifier = Modifier
.padding(16.dp)
.align(Alignment.TopCenter)
.background(
color = Color.Black.copy(alpha = 0.8f),
shape = RoundedCornerShape(8.dp)
)
.padding(horizontal = 12.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = if (isWorking) Icons.Filled.Check else Icons.Filled.Close,
contentDescription = null,
tint = if (isWorking) Color.Green else Color.Red,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "PurrAura",
color = Color.White,
fontSize = 14.sp
)
}
LaunchedEffect(Unit) {
delay(3000)
context.inAppOverlay.removeCustomComposable(composable)
}
}
context.inAppOverlay.addCustomComposable(composable)
}
override fun init() {
val bypassToggleEnabled = context.bridgeClient.getDebugProp("test_mode", "false") == "true"
@@ -101,7 +44,7 @@ class EndpointsBlocker : Feature("EndpointsBlocker") {
context.log.warn("EndpointsBlocker: native self-test failed, indicator set to inactive")
context.log.warn("EndpointsBlocker: Possible causes - config not loaded or self-test logic failed")
}
showBypassStatusIndicator(healthy)
context.inAppOverlay.showBypassStatusIndicator(healthy)
} else {
context.native.setTestMode(false)
}

View File

@@ -6,6 +6,7 @@ import android.widget.FrameLayout
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.rememberSplineBasedDecay
import androidx.compose.foundation.BorderStroke
@@ -20,6 +21,8 @@ import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.outlined.Warning
import androidx.compose.material3.*
import androidx.compose.runtime.*
@@ -33,6 +36,7 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
@@ -378,4 +382,134 @@ class InAppOverlay(
durationMs = durationMs
))
}
private enum class BypassAnimation { SLIDE_DOWN, ZOOM_IN }
fun showBypassStatusIndicator(isWorking: Boolean) {
if (context.bridgeClient.getDebugProp("disable_bypass_indicator", "false") == "true") {
return
}
val animationType = BypassAnimation.entries.random()
lateinit var composable: CustomComposable
composable = {
var visible by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
visible = true
delay(3000)
visible = false
delay(400)
context.inAppOverlay.removeCustomComposable(composable)
}
val progress by animateFloatAsState(
targetValue = if (visible) 1f else 0f,
animationSpec = spring(
dampingRatio = 0.7f,
stiffness = 70f
),
label = "progress"
)
val (offsetX, offsetY, scale) = when (animationType) {
BypassAnimation.SLIDE_DOWN -> Triple(0f, -80f * (1f - progress), 1f)
BypassAnimation.ZOOM_IN -> Triple(0f, 0f, progress)
}
Box(
modifier = Modifier
.align(Alignment.TopCenter)
.padding(top = 16.dp)
.graphicsLayer {
translationX = offsetX
translationY = offsetY
scaleX = scale
scaleY = scale
alpha = progress
}
) {
// Use PurrfectSnap UI colors - gradient for active, red tint for inactive
val backgroundColor = if (isWorking) {
Brush.linearGradient(
listOf(
PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.85f),
PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.75f)
)
)
} else {
Brush.linearGradient(
listOf(
Color(0xFFB71C1C).copy(alpha = 0.85f),
Color(0xFFD32F2F).copy(alpha = 0.75f)
)
)
}
val shape = RoundedCornerShape(24.dp)
Surface(
modifier = Modifier
.shadow(
elevation = 12.dp,
shape = shape,
spotColor = if (isWorking) PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.3f) else Color(0xFFB71C1C).copy(alpha = 0.25f),
ambientColor = if (isWorking) PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.2f) else Color(0xFFD32F2F).copy(alpha = 0.18f)
)
.clip(shape)
.background(backgroundColor, shape)
.border(
BorderStroke(
1.dp,
if (isWorking) {
Brush.linearGradient(
listOf(
PurrfectOverlayPalette.glowPrimary.copy(alpha = 0.7f),
PurrfectOverlayPalette.glowSecondary.copy(alpha = 0.6f)
)
)
} else {
Brush.linearGradient(
listOf(
Color(0xFFB71C1C).copy(alpha = 0.7f),
Color(0xFFD32F2F).copy(alpha = 0.6f)
)
)
}
),
shape
),
color = Color.Transparent,
tonalElevation = 0.dp,
shadowElevation = 0.dp
) {
Row(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(
imageVector = if (isWorking) Icons.Filled.Check else Icons.Filled.Close,
contentDescription = null,
tint = Color.White,
modifier = Modifier.size(18.dp)
)
Text(
text = if (isWorking)
context.translation.getOrNull("manager.sections.bypass_status.active") ?: "Bypass Active"
else
context.translation.getOrNull("manager.sections.bypass_status.inactive") ?: "Bypass Inactive",
color = Color.White,
fontSize = 14.sp,
fontWeight = FontWeight.Medium
)
}
}
}
}
context.mainActivity?.let { injectOverlay(it) }
customComposables.add(composable)
}
}