Rebrand app to ShiggyCord and update launcher icon

Replace Aliucord branding with ShiggyCord throughout the app. Update
launcher icon and background to use Shiggy yellow (#FFCB82). Remove
unused assets and update contributor/lead developer roles. Adjust
notification and patching references to match new branding.
This commit is contained in:
kmmiio99o 2025-10-14 00:31:30 +02:00
parent e925c83dac
commit 343fb7e9b1
31 changed files with 542 additions and 474 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 KiB

View file

@ -23,55 +23,124 @@ import dev.shiggy.manager.R
@Composable
fun ContributorCommitsItem(
user: Contributor,
modifier: Modifier = Modifier,
user: Contributor,
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier = modifier
.clickable { uriHandler.openUri("https://github.com/${user.username}") }
.padding(horizontal = 16.dp, vertical = 8.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(16.dp),
modifier =
modifier
.clickable { uriHandler.openUri("https://github.com/${user.username}") }
.padding(horizontal = 16.dp, vertical = 8.dp)
.fillMaxWidth(),
) {
SubcomposeAsyncImage(
model = user.avatarUrl,
contentDescription = user.username,
error = {
Surface(
content = {},
tonalElevation = 2.dp,
modifier = Modifier
.fillMaxSize()
.shimmer(),
)
},
modifier = Modifier
.padding(top = 6.dp)
.size(45.dp)
.clip(CircleShape)
model = user.avatarUrl,
contentDescription = user.username,
error = {
Surface(
content = {},
tonalElevation = 2.dp,
modifier = Modifier.fillMaxSize().shimmer(),
)
},
modifier = Modifier.padding(top = 6.dp).size(45.dp).clip(CircleShape)
)
Column {
Text(
text = user.username,
style = MaterialTheme.typography.bodyLarge
)
Text(
text = stringResource(R.string.contributors_contributions, user.commits),
style = MaterialTheme.typography.bodyMedium.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
)
Text(text = user.username, style = MaterialTheme.typography.bodyLarge)
Text(
text = user.repositories.joinToString { it.name },
fontStyle = FontStyle.Italic,
style = MaterialTheme.typography.bodySmall
.copy(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)),
modifier = Modifier.padding(top = 4.dp),
)
// Local role overrides for selected contributors to mimic LeadContributor two-line
// style
val roleOverrides =
mapOf(
"maisymoe" to "Creator - Vendetta",
"rushiiMachine" to "Manager - Creator"
)
val role = roleOverrides[user.username]
if (role != null) {
val roleParts = role.split(Regex("\\s*-\\s*"), limit = 2)
// Primary role line (muted)
Text(
text = roleParts[0],
style =
MaterialTheme.typography.bodyMedium.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
)
)
// Secondary affiliation/role line (smaller, muted) if present
if (roleParts.size == 2) {
Text(
text = roleParts[1],
style =
MaterialTheme.typography.bodySmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
),
modifier = Modifier.padding(top = 2.dp)
)
}
// Keep contribution count below the role lines
Text(
text = stringResource(R.string.contributors_contributions, user.commits),
style =
MaterialTheme.typography.bodySmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
),
modifier = Modifier.padding(top = 6.dp)
)
// Show repositories (italic) as before
Text(
text = user.repositories.joinToString { it.name },
fontStyle = FontStyle.Italic,
style =
MaterialTheme.typography.bodySmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
),
modifier = Modifier.padding(top = 4.dp),
)
} else {
// Fallback: original layout (contributions + repos)
Text(
text = stringResource(R.string.contributors_contributions, user.commits),
style =
MaterialTheme.typography.bodyMedium.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
)
)
Text(
text = user.repositories.joinToString { it.name },
fontStyle = FontStyle.Italic,
style =
MaterialTheme.typography.bodySmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
),
modifier = Modifier.padding(top = 4.dp),
)
}
}
}
}

View file

@ -21,45 +21,44 @@ import androidx.core.graphics.drawable.toDrawable
import com.aliucord.manager.ui.screens.patchopts.PatchOptions.IconReplacement
import dev.shiggy.manager.R
// Sizing information is obtained from here: https://medium.com/google-design/designing-adaptive-icons-515af294c783
// Sizing information is obtained from here:
// https://medium.com/google-design/designing-adaptive-icons-515af294c783
@Composable
fun discordIconDrawable(
backgroundColor: Color,
oldLogo: Boolean = false,
size: Dp = 24.dp,
backgroundColor: Color,
oldLogo: Boolean = false,
size: Dp = 24.dp,
): Drawable {
val density = LocalDensity.current
val context = LocalContext.current
val size = with(density) { size.roundToPx() }
val sizePx = with(density) { size.roundToPx() }
val drawable = remember(context, oldLogo) {
val drawableId = when (oldLogo) {
false -> R.drawable.ic_discord
true -> R.drawable.ic_discord_old
}
val drawable =
remember(context, oldLogo) {
val drawableId =
when (oldLogo) {
false -> R.drawable.ic_discord
true -> R.drawable.ic_discord_old
}
InsetDrawable(
/* drawable = */ ContextCompat.getDrawable(context, drawableId)!!,
/* inset = */ (size * .17f).toInt(),
).apply {
setTint(Color.White.toArgb())
}
}
InsetDrawable(
/* drawable = */ ContextCompat.getDrawable(context, drawableId)!!,
/* inset = */ (sizePx * .17f).toInt(),
)
.apply { setTint(Color.White.toArgb()) }
}
val bitmap = remember(size) { createBitmap(size, size) }
DisposableEffect(size) {
onDispose {
bitmap.recycle()
}
}
val bitmap = remember(sizePx) { createBitmap(sizePx, sizePx) }
DisposableEffect(sizePx) { onDispose { bitmap.recycle() } }
DisposableEffect(backgroundColor, bitmap, drawable) {
bitmap.applyCanvas {
val paint = Paint().apply {
style = Paint.Style.FILL
setColor(backgroundColor.toArgb())
}
val paint =
Paint().apply {
style = Paint.Style.FILL
setColor(backgroundColor.toArgb())
}
drawRect(Rect(0, 0, width, height), paint)
drawable.setBounds(0, 0, width, height)
@ -69,43 +68,36 @@ fun discordIconDrawable(
onDispose {}
}
return remember(context, bitmap) {
bitmap.toDrawable(context.resources)
}
return remember(context, bitmap) { bitmap.toDrawable(context.resources) }
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun customIconDrawable(
foregroundIcon: ByteArray,
backgroundColor: Color = IconReplacement.BlurpleColor,
foregroundIcon: ByteArray,
backgroundColor: Color = IconReplacement.BlurpleColor,
): Drawable {
val context = LocalContext.current
return remember(context, foregroundIcon) {
val foregroundIconBitmap = BitmapFactory.decodeByteArray(foregroundIcon, 0, foregroundIcon.size)
val foregroundIconBitmap =
BitmapFactory.decodeByteArray(foregroundIcon, 0, foregroundIcon.size)
AdaptiveIconDrawable(
/* backgroundDrawable = */ backgroundColor.toArgb().toDrawable(),
/* foregroundDrawable = */ foregroundIconBitmap.toDrawable(context.resources),
/* backgroundDrawable = */ backgroundColor.toArgb().toDrawable(),
/* foregroundDrawable = */ foregroundIconBitmap.toDrawable(context.resources),
)
}
}
@Composable
fun Drawable(
drawable: Drawable,
modifier: Modifier = Modifier,
drawable: Drawable,
modifier: Modifier = Modifier,
) {
AndroidView(
factory = { context ->
ImageView(context).apply {
setImageDrawable(drawable)
}
},
update = { imageView ->
imageView.setImageDrawable(drawable)
},
modifier = modifier,
factory = { context -> ImageView(context).apply { setImageDrawable(drawable) } },
update = { imageView -> imageView.setImageDrawable(drawable) },
modifier = modifier,
)
}

View file

@ -12,61 +12,67 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import dev.shiggy.manager.BuildConfig
import dev.shiggy.manager.R
@Composable
fun ProjectHeader(
aliucord: Boolean = false,
modifier: Modifier = Modifier,
aliucord: Boolean = false,
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(6.dp),
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(6.dp),
modifier = modifier,
) {
Image(
painter = painterResource(if (aliucord) R.drawable.ic_aliucord_logo else R.drawable.ic_rounded_shiggy),
contentDescription = null,
modifier = Modifier
.padding(bottom = 6.dp)
.size(88.dp),
painter =
painterResource(
if (aliucord) R.drawable.ic_aliucord_logo
else R.drawable.ic_rounded_shiggy
),
contentDescription = null,
modifier = Modifier.padding(bottom = 6.dp).size(88.dp),
)
Text(
text = stringResource(if (aliucord) R.string.aliucord else R.string.shiggy),
style = MaterialTheme.typography.titleMedium.copy(fontSize = 26.sp)
text = stringResource(if (aliucord) R.string.aliucord else R.string.shiggy),
style = MaterialTheme.typography.titleMedium.copy(fontSize = 26.sp)
)
Text(
text = stringResource(if (aliucord) R.string.aliucord_description else R.string.app_description),
style = MaterialTheme.typography.titleSmall.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = .6f)
),
textAlign = TextAlign.Center,
text =
stringResource(
if (aliucord) R.string.aliucord_description
else R.string.app_description
),
style =
MaterialTheme.typography.titleSmall.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = .6f)
),
textAlign = TextAlign.Center,
)
Row(
horizontalArrangement = Arrangement.Center,
horizontalArrangement = Arrangement.Center,
) {
TextButton(onClick = { uriHandler.openUri("https://github.com/${if (aliucord) "Aliucord" else BuildConfig.GITHUB_ORG}") }) {
TextButton(
onClick = { uriHandler.openUri("https://github.com/kmmiio99o/ShiggyCord") }
) {
Icon(
painter = painterResource(R.drawable.ic_account_github_white_24dp),
contentDescription = null,
modifier = Modifier.padding(end = ButtonDefaults.IconSpacing),
painter = painterResource(R.drawable.ic_account_github_white_24dp),
contentDescription = null,
modifier = Modifier.padding(end = ButtonDefaults.IconSpacing),
)
Text(text = stringResource(R.string.github))
}
TextButton(onClick = { uriHandler.openUri("https://discord.gg/${if (aliucord) "EsNDvBaHVU" else BuildConfig.SUPPORT_SERVER}") }) {
TextButton(onClick = { uriHandler.openUri("https://discord.gg/nQykFF9Ud6") }) {
Icon(
painter = painterResource(R.drawable.ic_discord),
contentDescription = stringResource(R.string.support_server),
modifier = Modifier
.padding(end = ButtonDefaults.IconSpacing)
.size(22.dp),
painter = painterResource(R.drawable.ic_discord),
contentDescription = stringResource(R.string.support_server),
modifier = Modifier.padding(end = ButtonDefaults.IconSpacing).size(22.dp),
)
Text(text = stringResource(R.string.discord))
}

View file

@ -10,7 +10,6 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
@ -89,7 +88,7 @@ fun AboutScreenContent(state: State<AboutScreenState>) {
}
}
item(key = "PROJECT_HEADER") { ProjectHeader(aliucord = true) }
item(key = "PROJECT_HEADER") { ProjectHeader() }
item(key = "HEADER_DIVIDER") {
TextDivider(
@ -104,9 +103,9 @@ fun AboutScreenContent(state: State<AboutScreenState>) {
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
LeadContributor("C0C0B01", "Creator of Kettu")
LeadContributor("kmmiio99o", "Creator of ShiggyCord")
LeadContributor("pylixonly", "Creator of Bunny")
LeadContributor("C0C0B01", stringResource(R.string.lead_role_kettu))
LeadContributor("kmmiio99o", stringResource(R.string.lead_role_shiggycord))
LeadContributor("pylixonly", stringResource(R.string.lead_role_bunny))
}
}
@ -131,8 +130,16 @@ fun AboutScreenContent(state: State<AboutScreenState>) {
LoadFailure(modifier = Modifier.fillMaxSize().padding(vertical = 38.dp))
}
is AboutScreenState.Loaded -> {
items(state.contributors, key = { it.username }) { user ->
ContributorCommitsItem(user)
// Render the two requested contributors as LeadContributor entries
item(key = "SELECTED_CONTRIBUTORS") {
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
LeadContributor("maisymoe", "Creator - Vendetta")
LeadContributor("rushiiMachine", "Manager - Creator")
}
}
}
}

View file

@ -18,57 +18,77 @@ import com.valentinilk.shimmer.shimmer
@Composable
fun LeadContributor(
name: String,
roles: String,
username: String = name,
modifier: Modifier = Modifier,
name: String,
roles: String,
username: String = name,
modifier: Modifier = Modifier,
) {
val uriHandler = LocalUriHandler.current
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier = modifier
.clickable(
onClick = { uriHandler.openUri("https://github.com/$username") },
indication = ripple(bounded = false, radius = 90.dp),
interactionSource = remember(::MutableInteractionSource)
)
.widthIn(min = 100.dp)
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp),
modifier =
modifier.clickable(
onClick = {
uriHandler.openUri("https://github.com/$username")
},
indication = ripple(bounded = false, radius = 90.dp),
interactionSource = remember(::MutableInteractionSource)
)
.widthIn(min = 100.dp)
) {
SubcomposeAsyncImage(
model = "https://github.com/$username.png",
contentDescription = username,
error = {
Surface(
content = {},
tonalElevation = 2.dp,
modifier = Modifier
.fillMaxSize()
.shimmer(),
)
},
modifier = Modifier
.size(80.dp)
.clip(CircleShape),
model = "https://github.com/$username.png",
contentDescription = username,
error = {
Surface(
content = {},
tonalElevation = 2.dp,
modifier = Modifier.fillMaxSize().shimmer(),
)
},
modifier = Modifier.size(80.dp).clip(CircleShape),
)
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = name,
style = MaterialTheme.typography.titleMedium.copy(
fontSize = 18.sp
)
)
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(text = name, style = MaterialTheme.typography.titleMedium.copy(fontSize = 18.sp))
Text(
text = roles,
style = MaterialTheme.typography.titleSmall.copy(
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
val roleParts = roles.split(Regex("\\s*-\\s*"), limit = 2)
if (roleParts.size == 2) {
// Render left and right parts on two separate lines, removing the dash
Text(
text = roleParts[0],
style =
MaterialTheme.typography.titleSmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
)
)
)
Text(
text = roleParts[1],
style =
MaterialTheme.typography.bodySmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
)
)
} else {
Text(
text = roles,
style =
MaterialTheme.typography.titleSmall.copy(
color =
MaterialTheme.colorScheme.onSurface.copy(
alpha = 0.6f
)
)
)
}
}
}
}

View file

@ -40,7 +40,6 @@ import com.aliucord.manager.ui.util.spacedByLastAtBottom
import com.aliucord.manager.ui.util.thenIf
import com.aliucord.manager.util.back
import com.aliucord.manager.util.isIgnoringBatteryOptimizations
import dev.shiggy.manager.BuildConfig
import dev.shiggy.manager.R
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.filter
@ -52,8 +51,7 @@ val VERTICAL_PADDING: Dp = 18.dp
@Parcelize
class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
@IgnoredOnParcel
override val key = "Patching"
@IgnoredOnParcel override val key = "Patching"
@Composable
override fun Content() {
@ -66,7 +64,8 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
val showMinimizationWarning = rememberSaveable { !context.isIgnoringBatteryOptimizations() }
// Exit warning dialog (dismiss itself if install process state changes, esp. for Success)
var showAbortWarning by rememberSaveable(model.state.collectAsState().value) { mutableStateOf(false) }
var showAbortWarning by
rememberSaveable(model.state.collectAsState().value) { mutableStateOf(false) }
// The currently expanded step group on this screen
var expandedGroup by rememberSaveable { mutableStateOf<StepGroup?>(StepGroup.Prepare) }
@ -94,14 +93,14 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
LaunchedEffect(state) {
when (state) {
// Go home directly if screen model mandates so (usually caused by cancelled PackageInstaller dialog)
// Go home directly if screen model mandates so (usually caused by cancelled
// PackageInstaller dialog)
PatchingScreenState.CloseScreen -> navigator.popUntilRoot()
// Close all groups when successfully finished everything
PatchingScreenState.Success -> {
expandedGroup = null
}
else -> {}
}
@ -110,58 +109,55 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
if (showAbortWarning) {
InstallerAbortDialog(
onDismiss = { showAbortWarning = false },
onConfirm = {
navigator.back(currentActivity = null)
model.cancelInstall()
},
onDismiss = { showAbortWarning = false },
onConfirm = {
navigator.back(currentActivity = null)
model.cancelInstall()
},
)
} else {
BackHandler(onBack = onTryExit)
}
Scaffold(
topBar = { PatchingAppBar(onTryExit) },
topBar = { PatchingAppBar(onTryExit) },
) { paddingValues ->
Column(
verticalArrangement = Arrangement.spacedBy(VERTICAL_PADDING),
modifier = Modifier
.padding(paddingValues.exclude(PaddingValuesSides.Bottom)),
verticalArrangement = Arrangement.spacedBy(VERTICAL_PADDING),
modifier = Modifier.padding(paddingValues.exclude(PaddingValuesSides.Bottom)),
) {
if (state == PatchingScreenState.Working) {
LinearProgressIndicator(
modifier = Modifier
.height(4.dp)
.fillMaxWidth()
)
LinearProgressIndicator(modifier = Modifier.height(4.dp).fillMaxWidth())
} else {
HorizontalDivider(
thickness = 2.dp,
modifier = Modifier.fillMaxWidth(),
thickness = 2.dp,
modifier = Modifier.fillMaxWidth(),
)
}
LazyColumn(
state = listState,
verticalArrangement = Arrangement.spacedByLastAtBottom(0.dp),
contentPadding = paddingValues
.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top)
.add(PaddingValues(bottom = 25.dp)),
modifier = Modifier
.padding(horizontal = 16.dp)
.fillMaxSize(),
state = listState,
verticalArrangement = Arrangement.spacedByLastAtBottom(0.dp),
contentPadding =
paddingValues
.exclude(
PaddingValuesSides.Horizontal +
PaddingValuesSides.Top
)
.add(PaddingValues(bottom = 25.dp)),
modifier = Modifier.padding(horizontal = 16.dp).fillMaxSize(),
) {
item(key = "MINIMIZATION_WARNING") {
BannerSection(visible = showMinimizationWarning && !state.isFinished) {
TextBanner(
text = stringResource(R.string.installer_banner_minimization),
icon = painterResource(R.drawable.ic_warning),
iconColor = MaterialTheme.customColors.onWarningContainer,
outlineColor = MaterialTheme.customColors.warning,
containerColor = MaterialTheme.customColors.warningContainer,
modifier = Modifier
.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth(),
text = stringResource(R.string.installer_banner_minimization),
icon = painterResource(R.drawable.ic_warning),
iconColor = MaterialTheme.customColors.onWarningContainer,
outlineColor = MaterialTheme.customColors.warning,
containerColor = MaterialTheme.customColors.warningContainer,
modifier =
Modifier.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth(),
)
}
}
@ -171,15 +167,15 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
val handler = LocalUriHandler.current
TextBanner(
text = stringResource(R.string.installer_banner_failure),
icon = painterResource(R.drawable.ic_warning),
iconColor = MaterialTheme.colorScheme.error,
outlineColor = null,
containerColor = MaterialTheme.colorScheme.errorContainer,
onClick = { handler.openUri("https://discord.gg/${BuildConfig.SUPPORT_SERVER}") },
modifier = Modifier
.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth(),
text = stringResource(R.string.installer_banner_failure),
icon = painterResource(R.drawable.ic_warning),
iconColor = MaterialTheme.colorScheme.error,
outlineColor = null,
containerColor = MaterialTheme.colorScheme.errorContainer,
onClick = { handler.openUri("https://discord.gg/nQykFF9Ud6") },
modifier =
Modifier.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth(),
)
}
}
@ -187,14 +183,14 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
item(key = "INSTALLED_BANNER") {
BannerSection(visible = state is PatchingScreenState.Success) {
TextBanner(
text = stringResource(R.string.installer_banner_success),
icon = painterResource(R.drawable.ic_check_circle),
iconColor = Color(0xFF59B463),
outlineColor = MaterialTheme.colorScheme.surfaceVariant,
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
modifier = Modifier
.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth(),
text = stringResource(R.string.installer_banner_success),
icon = painterResource(R.drawable.ic_check_circle),
iconColor = Color(0xFF59B463),
outlineColor = MaterialTheme.colorScheme.surfaceVariant,
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
modifier =
Modifier.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth(),
)
}
}
@ -202,75 +198,91 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
for ((group, steps) in model.steps?.entries ?: persistentListOf()) {
item(key = System.identityHashCode(group)) {
StepGroupCard(
name = stringResource(group.localizedName),
subSteps = steps,
isExpanded = expandedGroup == group,
onExpand = { expandedGroup = group },
modifier = Modifier
.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth()
.thenIf(state is PatchingScreenState.Success) { alpha(.5f) }
name = stringResource(group.localizedName),
subSteps = steps,
isExpanded = expandedGroup == group,
onExpand = { expandedGroup = group },
modifier =
Modifier.padding(bottom = VERTICAL_PADDING)
.fillMaxWidth()
.thenIf(state is PatchingScreenState.Success) {
alpha(.5f)
}
)
}
}
item(key = "BUTTONS") {
var cacheCleared by rememberSaveable { mutableStateOf(false) }
val filteredState by remember { model.state.filter { it.isProgressChange } }
.collectAsState(initial = PatchingScreenState.Working)
val filteredState by
remember { model.state.filter { it.isProgressChange } }
.collectAsState(initial = PatchingScreenState.Working)
AnimatedVisibility(
visible = filteredState != PatchingScreenState.Working,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically { it * -2 },
visible = filteredState != PatchingScreenState.Working,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically { it * -2 },
) {
Column(
verticalArrangement = Arrangement.spacedBy(VERTICAL_PADDING / 2),
verticalArrangement =
Arrangement.spacedBy(VERTICAL_PADDING / 2),
) {
HorizontalDivider(
thickness = 1.dp,
modifier = Modifier
.padding(bottom = VERTICAL_PADDING / 2)
thickness = 1.dp,
modifier = Modifier.padding(bottom = VERTICAL_PADDING / 2)
)
when (filteredState) {
PatchingScreenState.Working -> {}
PatchingScreenState.CloseScreen -> error("unreachable")
PatchingScreenState.Success -> {
MainActionButton(
text = stringResource(R.string.action_launch),
icon = painterResource(R.drawable.ic_launch),
onClick = model::launchApp,
text = stringResource(R.string.action_launch),
icon = painterResource(R.drawable.ic_launch),
onClick = model::launchApp,
)
}
is PatchingScreenState.Failed -> {
MainActionButton(
text = stringResource(R.string.action_retry_install),
icon = painterResource(R.drawable.ic_refresh),
onClick = model::install,
text =
stringResource(
R.string.action_retry_install
),
icon = painterResource(R.drawable.ic_refresh),
onClick = model::install,
)
MainActionButton(
text = stringResource(R.string.action_open_error_log),
icon = painterResource(R.drawable.ic_launch),
onClick = { navigator.push(LogScreen(installId = model.getCurrentInstallId()!!)) },
text =
stringResource(
R.string.action_open_error_log
),
icon = painterResource(R.drawable.ic_launch),
onClick = {
navigator.push(
LogScreen(
installId =
model.getCurrentInstallId()!!
)
)
},
)
}
}
MainActionButton(
text = stringResource(R.string.settings_clear_cache),
icon = painterResource(R.drawable.ic_delete_forever),
enabled = !cacheCleared,
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = MaterialTheme.colorScheme.error,
),
onClick = {
cacheCleared = true
model.clearCache()
},
text = stringResource(R.string.settings_clear_cache),
icon = painterResource(R.drawable.ic_delete_forever),
enabled = !cacheCleared,
colors =
IconButtonDefaults.filledTonalIconButtonColors(
containerColor =
MaterialTheme.colorScheme.error,
),
onClick = {
cacheCleared = true
model.clearCache()
},
)
}
}
@ -278,8 +290,8 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
item(key = "FUN_FACT") {
FunFact(
text = stringResource(model.funFact),
state = state,
text = stringResource(model.funFact),
state = state,
)
}
}
@ -290,23 +302,22 @@ class PatchingScreen(private val data: PatchOptions) : Screen, Parcelable {
@Composable
private fun BannerSection(
visible: Boolean,
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
visible: Boolean,
modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
AnimatedVisibility(
visible = visible,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically(),
modifier = modifier
.padding(bottom = VERTICAL_PADDING),
visible = visible,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically(),
modifier = modifier.padding(bottom = VERTICAL_PADDING),
) {
Column {
content()
HorizontalDivider(
thickness = 1.dp,
modifier = Modifier.padding(vertical = 4.dp),
thickness = 1.dp,
modifier = Modifier.padding(vertical = 4.dp),
)
}
}

View file

@ -14,50 +14,38 @@ enum class VersionPreference {
Stable,
Beta,
Alpha,
Custom;
Custom
}
@Immutable
@Parcelize
@Serializable
data class PatchOptions(
/**
* The app name that's user-facing in launchers.
*/
val appName: String,
/** The app name that's user-facing in launchers. */
val appName: String,
/**
* Changes the installation package name.
*/
val packageName: String,
/** Changes the installation package name. */
val packageName: String,
/**
* Adding the debuggable APK flag.
*/
val debuggable: Boolean,
/** Adding the debuggable APK flag. */
val debuggable: Boolean,
/**
* Replacement of the user-facing launcher icon.
*/
val iconReplacement: IconReplacement,
/** Replacement of the user-facing launcher icon. */
val iconReplacement: IconReplacement,
/**
* Version preference to fetch and install
*/
val versionPreference: VersionPreference,
/** Version preference to fetch and install */
val versionPreference: VersionPreference,
/**
* Version to fetch and install when versionPreference is set to VersionPreference.Custom.
*/
val customVersionCode: String,
/**
* Version to fetch and install when versionPreference is set to VersionPreference.Custom.
*/
val customVersionCode: String,
) : Parcelable {
@Immutable
@Parcelize
@Serializable
sealed interface IconReplacement : Parcelable {
/**
* Keeps the original icons that are present in the APK.
*/
/** Keeps the original icons that are present in the APK. */
@Immutable
@Parcelize
@Serializable
@ -65,8 +53,8 @@ data class PatchOptions(
data object Original : IconReplacement
/**
* Changes the foreground logo to Discord's old logo and the
* background color to old blurple, like prior to early 2021.
* Changes the foreground logo to Discord's old logo and the background color to old
* blurple, like prior to early 2021.
*/
@Immutable
@Parcelize
@ -75,22 +63,22 @@ data class PatchOptions(
data object OldDiscord : IconReplacement
/**
* Changes the background of the icon to a specific color without
* altering the foreground or monochrome variants.
* Changes the background of the icon to a specific color without altering the foreground or
* monochrome variants.
*/
@Immutable
@Parcelize
@Serializable
@SerialName("color")
data class CustomColor(
@TypeParceler<Color, ColorParceler>
@Serializable(ColorSerializer::class)
val color: Color,
@TypeParceler<Color, ColorParceler>
@Serializable(ColorSerializer::class)
val color: Color,
) : IconReplacement
/**
* Replaces the foreground image of the icon entirely and sets the background to transparent.
* This does not affect the monochrome icon.
* Replaces the foreground image of the icon entirely and sets the background to
* transparent. This does not affect the monochrome icon.
*/
@Immutable
@Parcelize
@ -98,41 +86,39 @@ data class PatchOptions(
@SerialName("image")
data class CustomImage(val imageBytes: ByteArray) : IconReplacement {
override fun hashCode() = imageBytes.contentHashCode()
override fun equals(other: Any?) = this === other
|| (javaClass == other?.javaClass && imageBytes.contentEquals((other as CustomImage).imageBytes))
override fun equals(other: Any?) =
this === other ||
(javaClass == other?.javaClass &&
imageBytes.contentEquals((other as CustomImage).imageBytes))
}
companion object {
/**
* The default Aliucord background color.
*/
/** The default Aliucord background color. */
val AliucordColor = Color(0xFF00C853)
/**
* The default Shiggy background color.
* The default Shiggy background color. Updated to the requested hex #ffcb82 (ARGB
* 0xFFFFCB82).
*/
val ShiggyColor = Color(0xFF133E87)
val ShiggyColor = Color(0xFFFFCB82)
/**
* The new Discord blurple used in icons.
*/
/** The new Discord blurple used in icons. */
val BlurpleColor = Color(0xFF5865F2)
/**
* The old Discord icon color (before the accessibility redesign).
*/
/** The old Discord icon color (before the accessibility redesign). */
val OldBlurpleColor = Color(0xFF7289DA)
}
}
companion object {
val Default = PatchOptions(
appName = "Shiggy",
packageName = "dev.shiggy.app",
debuggable = false,
iconReplacement = IconReplacement.CustomColor(IconReplacement.ShiggyColor),
versionPreference = VersionPreference.Stable,
customVersionCode = "",
)
val Default =
PatchOptions(
appName = "ShiggyCord",
packageName = "dev.shiggy.cord",
debuggable = false,
iconReplacement = IconReplacement.CustomColor(IconReplacement.ShiggyColor),
versionPreference = VersionPreference.Stable,
customVersionCode = "",
)
}
}

View file

@ -19,48 +19,52 @@ object InstallNotifications {
private const val CHANNEL_ID = "installation"
/**
* Creates or replaces a notification with id [id] that brings
* up the existing [MainActivity] when clicked upon.
* Creates or replaces a notification with id [id] that brings up the existing [MainActivity]
* when clicked upon.
*
* @param id A unique notification ID for different notifications
* @param title Main notification title
* @param description Notification description
*/
fun createNotification(
context: Context,
id: Int,
@StringRes title: Int,
@StringRes description: Int,
context: Context,
id: Int,
@StringRes title: Int,
@StringRes description: Int,
) {
val manager = NotificationManagerCompat.from(context)
// Create the target notification channel
if (Build.VERSION.SDK_INT >= 26 && manager.getNotificationChannel(CHANNEL_ID) == null) {
val channel = NotificationChannelCompat.Builder(CHANNEL_ID, NotificationManager.IMPORTANCE_HIGH)
.setName(context.getString(R.string.notif_group_install_title))
.setDescription(context.getString(R.string.notif_group_install_desc))
.build()
val channel =
NotificationChannelCompat.Builder(
CHANNEL_ID,
NotificationManager.IMPORTANCE_HIGH
)
.setName(context.getString(R.string.notif_group_install_title))
.setDescription(context.getString(R.string.notif_group_install_desc))
.build()
manager.createNotificationChannel(channel)
}
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setDefaults(Notification.DEFAULT_LIGHTS or Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_aliucord_logo)
.setContentTitle(context.getString(title))
.setContentText(context.getString(description))
.setContentIntent(
PendingIntent.getActivity(
/* context = */ context,
/* requestCode = */ 0,
/* intent = */
Intent(context, MainActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT),
/* flags = */ PendingIntent.FLAG_IMMUTABLE,
)
)
.build()
val notification =
NotificationCompat.Builder(context, CHANNEL_ID)
.setDefaults(Notification.DEFAULT_LIGHTS or Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_rounded_shiggy)
.setContentTitle(context.getString(title))
.setContentText(context.getString(description))
.setContentIntent(
PendingIntent.getActivity(
/* context = */ context,
/* requestCode = */ 0,
/* intent = */ Intent(context, MainActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT),
/* flags = */ PendingIntent.FLAG_IMMUTABLE,
)
)
.build()
try {
manager.notify(id, notification)
@ -69,20 +73,19 @@ object InstallNotifications {
}
}
/**
* Request the `POST_NOTIFICATIONS` permission if needed.
*/
/** Request the `POST_NOTIFICATIONS` permission if needed. */
fun requestPermissions(context: Context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
val granted = ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS)
val granted =
ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS)
val activity = context.findActivity() ?: return
if (granted != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
0,
activity,
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
0,
)
}
}

View file

@ -1,16 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#33FF88"
android:pathData="M15.672,16.224c-1.333,3.194 -6.808,2.414 -6.808,-0.36l0,-7.961c0,-2.87 5.403,-3.53 7.048,-0.648l4.995,-1.921c-1.945,-4.119 -5.536,-5.319 -8.513,-5.319c-4.851,0 -9.642,2.678 -9.642,7.901l0,7.961c0,5.259 4.791,7.901 9.546,7.901c3.038,0 6.7,-1.441 8.718,-5.187L15.672,16.224z" />
<path
android:fillColor="#00C853"
android:fillType="evenOdd"
android:pathData="M9.08,0.59l5.644,0L23.477,24.005l-6.652,0l-1.597,-4.695l-6.544,0L7.17,24.005l-6.652,0l3.638,-9.954l5.92,0l3.674,0l-1.693,-6.844l-0.168,0l-1.057,4.011l-4.167,-3.999L9.08,0.59z" />
<path
android:fillColor="#33FF88"
android:pathData="M21.015,18.578l-5.331,-2.353c-0.612,1.813 -1.561,2.39 -3.71,3.074l4.479,3.566C18.217,22.072 19.874,20.691 21.015,18.578z" />
</vector>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Redirect the old Aliucord logo drawable to use the project's Shiggy rounded logo.
This keeps a single source of truth for the Shiggy image and avoids duplicating vector paths. -->
<item android:drawable="@drawable/ic_rounded_shiggy" />
</layer-list>

View file

@ -0,0 +1,17 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="256"
android:viewportHeight="256"
>
<!-- Solid circular background (Discord blurple) -->
<path android:fillColor="#5865F2" android:pathData="M256,128 A128,128 0 1,1 0,128 A128,128 0 1,1 256,128 Z" />
<!-- White Discord mark (borrowed path scaled by viewport) -->
<path
android:fillColor="#FFFFFFFF"
android:pathData="M216.86,45.1C200.29,37.34 182.57,31.71 164.04,28.5C161.77,32.61 159.11,38.15 157.28,42.55C137.58,39.58 118.07,39.58 98.74,42.55C96.91,38.15 94.19,32.61 91.9,28.5C73.35,31.71 55.61,37.36 39.04,45.14C5.62,95.65 -3.44,144.9 1.09,193.46C23.26,210.01 44.74,220.07 65.86,226.65C71.08,219.47 75.73,211.84 79.74,203.8C72.1,200.9 64.79,197.32 57.89,193.17C59.72,191.81 61.51,190.39 63.24,188.93C105.37,208.63 151.13,208.63 192.75,188.93C194.51,190.39 196.3,191.81 198.11,193.17C191.18,197.34 183.85,200.92 176.22,203.82C180.23,211.84 184.86,219.49 190.1,226.67C211.24,220.09 232.74,210.03 254.91,193.46C260.23,137.17 245.83,88.37 216.86,45.1ZM85.47,163.59C72.83,163.59 62.46,151.79 62.46,137.41C62.46,123.04 72.61,111.21 85.47,111.21C98.34,111.21 108.71,123.02 108.49,137.41C108.51,151.79 98.34,163.59 85.47,163.59ZM170.53,163.59C157.88,163.59 147.51,151.79 147.51,137.41C147.51,123.04 157.66,111.21 170.53,111.21C183.39,111.21 193.76,123.02 193.54,137.41C193.54,151.79 183.39,163.59 170.53,163.59Z"
/>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

@ -1,27 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M0,0H108V108H0V0Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="110.3"
android:startY="-93.78"
android:endX="-29.87"
android:endY="-44.09"
android:type="linear">
<item
android:offset="0"
android:color="#FF608BC1" />
<item
android:offset="0.32"
android:color="#FF3E69A7" />
<item
android:offset="1"
android:color="#FF133E87" />
</gradient>
</aapt:attr>
</path>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
>
<!-- Flat background color for launcher adaptive icon -->
<path android:pathData="M0,0H108V108H0Z" android:fillColor="#FFFFCB82" />
</vector>

View file

@ -1,10 +1 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:pathData="M53.59,30C52.49,30 51.6,30.89 51.6,31.99V37.3L46.98,34.58C45.98,34 44.72,34.34 44.15,35.34C43.58,36.34 43.92,37.63 44.92,38.22L51.6,42.15V51.14L42.83,46.97L42.16,39.21C42.06,38.06 41.06,37.21 39.93,37.31C38.8,37.41 37.96,38.42 38.06,39.57L38.52,44.93L33.95,42.76C32.91,42.26 31.67,42.71 31.19,43.76C30.71,44.81 31.17,46.06 32.21,46.56L36.78,48.73L32.45,51.81C31.53,52.48 31.31,53.78 31.96,54.73C32.61,55.68 33.89,55.91 34.82,55.25L41.09,50.78L48.05,54.08L32.21,61.61C31.17,62.1 30.71,63.35 31.19,64.4C31.67,65.45 32.91,65.9 33.95,65.41L38.52,63.24L38.06,68.6C37.96,69.74 38.8,70.76 39.93,70.86C41.06,70.96 42.06,70.11 42.16,68.96L42.83,61.19L51.6,57.02V65.04L44.97,68.94C43.97,69.53 43.63,70.81 44.19,71.82C44.76,72.82 46.03,73.16 47.03,72.57L51.6,69.88V75.17C51.6,76.27 52.49,77.16 53.59,77.16C54.68,77.16 55.57,76.27 55.57,75.17V69.84L60.23,72.57C61.22,73.16 62.49,72.82 63.06,71.82C63.63,70.81 63.28,69.53 62.29,68.94L55.57,64.99V56.96L64.35,61.13L65.02,68.9C65.12,70.05 66.12,70.9 67.25,70.8C68.39,70.7 69.22,69.69 69.13,68.54L68.67,63.18L73.23,65.35C74.28,65.85 75.51,65.4 75.99,64.35C76.47,63.3 76.02,62.04 74.97,61.55L70.41,59.38L74.73,56.3C75.66,55.64 75.88,54.33 75.22,53.38C74.57,52.43 73.29,52.2 72.37,52.86L66.1,57.33L59.14,54.03L74.97,46.51C76.01,46.01 76.47,44.76 75.99,43.71C75.51,42.66 74.27,42.21 73.23,42.7L68.66,44.87L69.12,39.52C69.22,38.37 68.38,37.36 67.25,37.26C66.12,37.16 65.12,38 65.02,39.15L64.35,46.92L55.57,51.09V42.14L62.24,38.22C63.24,37.63 63.58,36.35 63.01,35.34C62.44,34.34 61.18,34 60.18,34.58L55.57,37.3V31.99C55.57,30.89 54.68,30 53.59,30Z"
android:fillColor="#F3F3E0"
android:fillType="evenOdd" />
</vector>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/ic_launcher" android:gravity="center" />

View file

@ -0,0 +1,19 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="256"
android:viewportHeight="256"
>
<!-- Solid circular background (Shiggy yellow) -->
<path android:fillColor="#fcc680" android:pathData="M256,128 A128,128 0 1,1 0,128 A128,128 0 1,1 256,128 Z" />
<!-- White Discord mark (scaled down and centered) -->
<group android:scaleX="0.7" android:scaleY="0.7" android:translateX="38.4" android:translateY="38.4">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M216.86,45.1C200.29,37.34 182.57,31.71 164.04,28.5C161.77,32.61 159.11,38.15 157.28,42.55C137.58,39.58 118.07,39.58 98.74,42.55C96.91,38.15 94.19,32.61 91.9,28.5C73.35,31.71 55.61,37.36 39.04,45.14C5.62,95.65 -3.44,144.9 1.09,193.46C23.26,210.01 44.74,220.07 65.86,226.65C71.08,219.47 75.73,211.84 79.74,203.8C72.1,200.9 64.79,197.32 57.89,193.17C59.72,191.81 61.51,190.39 63.24,188.93C105.37,208.63 151.13,208.63 192.75,188.93C194.51,190.39 196.3,191.81 198.11,193.17C191.18,197.34 183.85,200.92 176.22,203.82C180.23,211.84 184.86,219.49 190.1,226.67C211.24,220.09 232.74,210.03 254.91,193.46C260.23,137.17 245.83,88.37 216.86,45.1ZM85.47,163.59C72.83,163.59 62.46,151.79 62.46,137.41C62.46,123.04 72.61,111.21 85.47,111.21C98.34,111.21 108.71,123.02 108.49,137.41C108.51,151.79 98.34,163.59 85.47,163.59ZM170.53,163.59C157.88,163.59 147.51,151.79 147.51,137.41C147.51,123.04 157.66,111.21 170.53,111.21C183.39,111.21 193.76,123.02 193.54,137.41C193.54,151.79 183.39,163.59 170.53,163.59Z"
/>
</group>
</vector>

View file

@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:pathData="M0,12C0,5.373 5.373,0 12,0V0C18.627,0 24,5.373 24,12V12C24,18.627 18.627,24 12,24V24C5.373,24 0,18.627 0,12V12Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="24.51"
android:startY="-20.84"
android:endX="-6.637"
android:endY="-9.798"
android:type="linear">
<item
android:offset="0"
android:color="#FF608BC1" />
<item
android:offset="0.322"
android:color="#FF3E69A7" />
<item
android:offset="1"
android:color="#FF133E87" />
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M12.057,4.8C12.392,4.8 12.663,5.072 12.663,5.406V7.028L14.072,6.199C14.375,6.021 14.762,6.125 14.935,6.431C15.109,6.737 15.003,7.13 14.7,7.309L12.663,8.508V11.24L15.344,9.966L15.549,7.594C15.579,7.244 15.884,6.985 16.229,7.016C16.575,7.047 16.832,7.356 16.802,7.706L16.66,9.341L18.055,8.679C18.374,8.528 18.751,8.665 18.898,8.986C19.045,9.306 18.905,9.689 18.587,9.84L13.752,12.136L15.878,13.146L17.792,11.781C18.074,11.579 18.466,11.651 18.665,11.941C18.864,12.23 18.796,12.629 18.513,12.83L17.193,13.771L18.588,14.434C18.906,14.585 19.045,14.968 18.898,15.288C18.751,15.609 18.375,15.746 18.056,15.595L16.661,14.932L16.802,16.569C16.831,16.919 16.576,17.228 16.23,17.259C15.884,17.29 15.579,17.03 15.549,16.68L15.344,14.307L12.664,13.033V15.485L14.715,16.691C15.018,16.869 15.124,17.263 14.95,17.569C14.776,17.876 14.389,17.979 14.086,17.801L12.664,16.964V18.594C12.664,18.929 12.392,19.2 12.057,19.2C11.722,19.2 11.451,18.929 11.451,18.594V16.979L10.053,17.801C9.75,17.979 9.363,17.876 9.189,17.569C9.015,17.263 9.121,16.87 9.425,16.692L11.451,15.499V13.052L8.77,14.324L8.568,16.698C8.538,17.048 8.232,17.306 7.886,17.276C7.541,17.245 7.285,16.936 7.315,16.586L7.455,14.949L6.061,15.613C5.743,15.764 5.365,15.626 5.218,15.306C5.072,14.985 5.211,14.603 5.529,14.451L10.365,12.153L8.241,11.144L6.326,12.511C6.043,12.713 5.652,12.641 5.453,12.352C5.254,12.062 5.321,11.663 5.604,11.461L6.925,10.519L5.53,9.857C5.212,9.705 5.073,9.323 5.219,9.002C5.366,8.682 5.743,8.544 6.061,8.696L7.455,9.358L7.315,7.723C7.285,7.372 7.541,7.063 7.887,7.032C8.233,7.002 8.538,7.261 8.568,7.612L8.771,9.983L11.451,11.256V8.509L9.41,7.309C9.106,7.13 9.001,6.737 9.175,6.431C9.348,6.125 9.735,6.021 10.039,6.199L11.451,7.029V5.406C11.451,5.072 11.722,4.8 12.057,4.8Z"
android:fillColor="#F3F3E0" />
</vector>

View file

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<!-- Adaptive icon updated to use Shiggy flat background and provided foreground image -->
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8" ?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View file

@ -2,13 +2,13 @@
<string name="app_name">Shiggy Manager</string>
<string name="app_description">A Discord mod built with simplicity and a seamless experience in mind.</string>
<string name="aliucord" translatable="false">Aliucord</string>
<string name="aliucord" translatable="false">ShiggyCord</string>
<string name="discord" translatable="false">Discord</string>
<string name="github" translatable="false">GitHub</string>
<string name="support_server">Support Server</string>
<string name="installer">Installer</string>
<string name="shiggy" translatable="false">Shiggy</string>
<string name="shiggy" translatable="false">Shiggy Manager</string>
<string name="aliucord_description">A mod for the Discord Android App</string>
<string name="action_cancel">Cancel</string>
@ -65,7 +65,7 @@
<string
name="about_manager_credit_disclaimer_notice"
>This manager is a fork of the original Aliucord Manager project, adapted for use with Shiggy. All credit goes to the Aliucord team for their foundational work.</string>
>This manager is a fork of the original Aliucord Manager project, Which was a forked by wintry, and now rebranded as Shiggy Manager. Credit to the original project\'s maintainers for the foundational work; continued development and branding are by the Shiggy team.</string>
<string name="theme_system">System</string>
<string name="theme_dark">Dark</string>
@ -85,8 +85,13 @@
<string name="navigation_logs">Open logs</string>
<string name="navigation_settings">Settings</string>
<string name="contributors_lead">Lead</string>
<string name="contributors">Contributors</string>
<string name="contributors_lead">Lead Developers</string>
<string name="lead_role_kettu">Kettu - Creator</string>
<string name="lead_role_shiggycord">ShiggyCord - Creator</string>
<string name="lead_role_bunny">Bunny - Creator</string>
<string name="role_creator_vendetta">Creator of Vendetta</string>
<string name="role_original_manager_creator">Original Manager Creator</string>
<string name="contributors">Other Developers</string>
<string name="contributors_contributions">%s contributions</string>
<string name="network_load_fail">Failed to load</string>
@ -105,7 +110,6 @@
<string name="version_load_fail">Failed to retrieve version</string>
<string name="version_invalid_code">Invalid version code format</string>
<string name="installer_file_save_success">Saved to %s</string>
<string name="installer_file_save_failed">Failed to save %s</string>
<string name="installer_install_success">Successfully installed Shiggy</string>
@ -142,14 +146,14 @@
<string name="patch_step_restore_cache">Restoring from cache</string>
<string name="patch_step_dl_kt_apk">Downloading Discord APK</string>
<string name="patch_step_dl_kotlin">Downloading Kotlin library</string>
<string name="patch_step_dl_injector">Downloading Aliucord Injector</string>
<string name="patch_step_dl_aliuhook">Downloading Aliuhook library</string>
<string name="patch_step_dl_injector">Downloading ShiggyCord Injector</string>
<string name="patch_step_dl_aliuhook">Downloading ShiggyHook library</string>
<string name="patch_step_dl_smali">Downloading smali patches</string>
<string name="patch_step_copy_deps">Copying dependencies</string>
<string name="patch_step_patch_manifests">Patching APK manifest</string>
<string name="patch_step_patch_icon">Patching app icon</string>
<string name="patch_step_add_injector">Adding Aliucord injector</string>
<string name="patch_step_add_aliuhook">Adding Aliuhook library</string>
<string name="patch_step_add_injector">Adding ShiggyCord injector</string>
<string name="patch_step_add_aliuhook">Adding ShiggyHook library</string>
<string name="patch_step_patch_smali">Applying smali patches</string>
<string name="patch_step_reorganize_dex">Adding .dex files to APK</string>
<string name="patch_step_save_metadata">Store metadata</string>
@ -211,7 +215,7 @@
<string name="patchopts_divider_advanced">Advanced</string>
<string name="patchopts_warning_invalid_iconopts">The selected icon options are invalid!</string>
<string name="patchopts_verchannel_title">Version channel</string>
<string name="patchopts_verchannel_desc">Select the release channel to install from, or choose \'Custom\' to enter a specific version code.</string>
<string name="patchopts_verchannel_desc">Select the release channel to install from, or choose Custom to enter a specific version code.</string>
<string name="patchopts_vercode_title">Custom Version Code</string>
<string name="patchopts_vercode_desc">Manually enter a Discord version code to fetch and install.</string>
@ -221,8 +225,8 @@
<string name="iconopts_variant_title_color">Custom Color</string>
<string name="iconopts_variant_title_image">Custom Image</string>
<string name="iconopts_variant_desc_discord">Does not alter the original icon, instead only adding the missing monochrome icon to the APK.</string>
<string name="iconopts_variant_desc_aliucord">Changes the original icon color to Aliucord\'s branding.</string>
<string name="iconopts_variant_desc_Shiggy">Changes the original icon color to Shiggy\'s branding.</string>
<string name="iconopts_variant_desc_aliucord">Changes the original icon color to Shiggy\'s branding.</string>
<string name="iconopts_variant_desc_shiggy">Changes the original icon color to Shiggy\'s branding.</string>
<string name="iconopts_variant_desc_color">Select a custom icon background color.</string>
<string
name="iconopts_variant_desc_image"
@ -237,13 +241,13 @@
<string name="iconopts_failed_image_too_big">Image size exceeds maximum of 256KiB</string>
<string name="iconopts_btn_open_selection">Select Image</string>
<string name="iconopts_btn_open_example_image">Example image</string>
<string name="iconopts_image_preview_none">No image selected</string>
<string name="iconopts_image_preview_desc">A full, uncropped preview of the selected image.</string>
<string name="iconopts_image_preview_title">Preview</string>
<string name="iconopts_icon_preview_title">Icon Preview</string>
<string
name="iconopts_icon_preview_desc"
>A preview of the selected options, cropped and scaled to show how the icon will appear on your device</string>
<string name="iconopts_image_preview_title">Preview</string>
<string name="iconopts_image_preview_desc">A full, uncropped preview of the selected image.</string>
<string name="iconopts_image_preview_none">No image selected</string>
<string name="log_title">Log</string>
<string name="log_section_install_info">Installation Info</string>
@ -264,14 +268,14 @@
<string name="notif_group_install_title">Active installation</string>
<string name="notif_group_install_desc">Progress notifications sent during a minimized installation</string>
<string name="notif_install_ready_title">Shiggy installation ready!</string>
<string name="notif_install_ready_desc">Click to install…</string>
<string name="notif_install_ready_desc">Click to install...</string>
<string name="notif_install_fail_title">Shiggy failed to install</string>
<string name="notif_install_fail_desc">Click to view more info…</string>
<string name="notif_install_fail_desc">Click to view more info...</string>
<string name="play_protect_warning_title">Play Protect</string>
<string
name="play_protect_warning_desc"
>Google Play Protect appears to be enabled on your device. It may attempt to interfere with a new installation due to the usage of a unique signing key. You can disable it in Play Protect\'s settings.\n\nIf it does show a warning dialog, press\n\"More Details\" -> \"Install anyway\"</string>
>Google Play Protect appears to be enabled on your device. It may attempt to interfere with a new installation due to the usage of a unique signing key. You can disable it in Play Protect\'s settings. If it does show a warning dialog, press &quot;More Details&quot; -&gt; &quot;Install anyway&quot;</string>
<string name="play_protect_warning_ok">Continue</string>
<string name="play_protect_warning_open_gpp">Open Play Protect</string>
<string name="play_protect_warning_disable">Don\'t show this again</string>
@ -280,17 +284,17 @@
<string name="custom_component_picker_desc">A custom local version for a patching component (%s) has been found. Would you like to use it?</string>
<string name="fun_fact_prefix">Fun Fact: %s</string>
<string name="fun_fact_1">Did you know that Google Play Protect is useless?</string>
<string name="fun_fact_2">Did you know Aliucord with 150+ plugins somehow runs better than Discord\'s new app?</string>
<string name="fun_fact_3">Did you know Aliucord has over 200 available plugins?</string>
<string name="fun_fact_4">i am in your walls</string>
<string name="fun_fact_5">Did you know AliucordRN spawned Enmity and Vendetta?</string>
<string name="fun_fact_6">Having issues? Visit the #support channel in our Discord!</string>
<string name="fun_fact_7">The IWillCrashYourDiscord plugin crashes your discord.</string>
<string name="fun_fact_8" translatable="false">\"@Vendicated my bad.\"</string>
<string name="fun_fact_9">Aliucord can run on WearOS</string>
<string name="fun_fact_10">Aliucord uses the *real* old UI, from mid-2022!</string>
<string name="fun_fact_11">There was an attempt to make Aliucord run on iOS…</string>
<string name="fun_fact_12" translatable="false">veeeee 😭</string>
<string name="fun_fact_1">ShiggyCord on first release was meant to be custom Kettu build!</string>
<string name="fun_fact_2">The refreshed UI inside the settings was made from developer boredom</string>
<string name="fun_fact_3">ShiggyCord as first vendetta like client used to show users the built in plugins and even add extra ones!</string>
<string name="fun_fact_4">You love boys, don\'t you?</string>
<string name="fun_fact_5">Aliucord is the best client with old discord UI</string>
<string name="fun_fact_6">We love you cocobo and pylix!</string>
<string name="fun_fact_7">The Vendetta react native part was a total dogshit</string>
<string name="fun_fact_8">Vencord and Equicord are not the same.</string>
<string name="fun_fact_9">This client can be run on a android TV!</string>
<string name="fun_fact_10">The Main Developer one and half a year ago didn\'t even know how to code</string>
<string name="fun_fact_11">This client does not support iOS!</string>
<string name="fun_fact_12">Boom!</string>
</resources>