mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-11 00:12:24 +01:00
intro: only after an update, never on a new install; recommend Organic Maps before Vela and ViVi Music before Metrolist; the thanks page links the list of cars that work
This commit is contained in:
1 parent
cd7b13c88e
commit
76955669f5
2 files changed
+57
-25
No files matched your search
@@ -97,8 +97,8 @@ import kotlin.random.Random
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The release intro: a few tap-through screens shown once after each new release (and on a new
|
* The release intro: a few screens shown once after updating to a new release, before setup. New
|
||||||
* install), before setup. Its look follows the 0.3 mockup: Material shapes in the phone's own colours,
|
* installs skip it. Its look follows the 0.3 mockup: Material shapes in the phone's own colours,
|
||||||
* with every size taken from the screen's width so it scales from small phones to tablets.
|
* with every size taken from the screen's width so it scales from small phones to tablets.
|
||||||
*/
|
*/
|
||||||
object Intro {
|
object Intro {
|
||||||
@@ -108,8 +108,19 @@ object Intro {
|
|||||||
/** "0.3" from "0.3.00-alpha": the intro belongs to a release, not to each patch. */
|
/** "0.3" from "0.3.00-alpha": the intro belongs to a release, not to each patch. */
|
||||||
val release: String = BuildConfig.VERSION_NAME.split('.').take(2).joinToString(".")
|
val release: String = BuildConfig.VERSION_NAME.split('.').take(2).joinToString(".")
|
||||||
|
|
||||||
fun due(context: Context): Boolean =
|
/**
|
||||||
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).getString(KEY_SEEN, null) != release
|
* True once per release for people who updated. A new install gets the setup guide instead:
|
||||||
|
* there's nothing "new" yet, so this release counts as seen and the next one shows.
|
||||||
|
*/
|
||||||
|
fun due(context: Context): Boolean {
|
||||||
|
if (context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).getString(KEY_SEEN, null) == release) return false
|
||||||
|
val info = runCatching { context.packageManager.getPackageInfo(context.packageName, 0) }.getOrNull()
|
||||||
|
if (info != null && info.firstInstallTime == info.lastUpdateTime) {
|
||||||
|
markSeen(context)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fun markSeen(context: Context) {
|
fun markSeen(context: Context) {
|
||||||
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit().putString(KEY_SEEN, release).apply()
|
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE).edit().putString(KEY_SEEN, release).apply()
|
||||||
@@ -187,7 +198,10 @@ fun IntroScreen(onDone: () -> Unit) {
|
|||||||
) { ShieldIcon(c.onSecondaryC, c.secondaryC) }
|
) { ShieldIcon(c.onSecondaryC, c.secondaryC) }
|
||||||
IntroStep.THANKS -> BadgeStep(c, ::cq, ::cqSp, c.tertiaryC, "Thank you.",
|
IntroStep.THANKS -> BadgeStep(c, ::cq, ::cqSp, c.tertiaryC, "Thank you.",
|
||||||
"Thanks to your usage notes, Gearslip is confirmed to work in cars newer than 2020. " +
|
"Thanks to your usage notes, Gearslip is confirmed to work in cars newer than 2020. " +
|
||||||
"Each note shows which cars work and which still fail, so I know what to fix next.", step) { HeartIcon(c.onTertiaryC) }
|
"Each note shows which cars work and which still fail, so I know what to fix next.", step,
|
||||||
|
action = "See which cars work" to { GearslipLinks.open(context, GearslipLinks.CARS) },
|
||||||
|
outlined = true,
|
||||||
|
) { HeartIcon(c.onTertiaryC) }
|
||||||
IntroStep.CHAT -> BadgeStep(c, ::cq, ::cqSp, c.primaryC, "Come say hi.",
|
IntroStep.CHAT -> BadgeStep(c, ::cq, ::cqSp, c.primaryC, "Come say hi.",
|
||||||
"Gearslip has a chat room on Matrix. Talk with other drivers about cars, apps, and " +
|
"Gearslip has a chat room on Matrix. Talk with other drivers about cars, apps, and " +
|
||||||
"where Gearslip is headed.", step,
|
"where Gearslip is headed.", step,
|
||||||
@@ -195,7 +209,7 @@ fun IntroScreen(onDone: () -> Unit) {
|
|||||||
outlined = true,
|
outlined = true,
|
||||||
) { ChatIcon(c.onPrimaryC, c.primaryC) }
|
) { ChatIcon(c.onPrimaryC, c.primaryC) }
|
||||||
IntroStep.APPS -> BadgeStep(c, ::cq, ::cqSp, c.secondaryC, "Good company.",
|
IntroStep.APPS -> BadgeStep(c, ::cq, ::cqSp, c.secondaryC, "Good company.",
|
||||||
"Free, open-source apps that work well in the car. Tap one to see it on GitHub.", step,
|
"Free, open-source apps that work well in the car. The first in each row works best. Tap one to see it on GitHub.", step,
|
||||||
extra = { AppPicks(c, ::cq, ::cqSp, step) }) { StarIcon(c.onSecondaryC) }
|
extra = { AppPicks(c, ::cq, ::cqSp, step) }) { StarIcon(c.onSecondaryC) }
|
||||||
IntroStep.THEME -> BadgeStep(c, ::cq, ::cqSp, c.tertiaryC, "Your buttons.",
|
IntroStep.THEME -> BadgeStep(c, ::cq, ::cqSp, c.tertiaryC, "Your buttons.",
|
||||||
"Pick how the car's buttons look. Change it any time in the car's settings.", step,
|
"Pick how the car's buttons look. Change it any time in the car's settings.", step,
|
||||||
@@ -489,38 +503,56 @@ private fun CommandDrift(c: IntroColors, cq: (Float) -> Dp, cqSp: (Float) -> Tex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Each kind of app with its picks, the first recommended most. */
|
||||||
private val APP_PICKS = listOf(
|
private val APP_PICKS = listOf(
|
||||||
Triple("Music", "Metrolist", "https://github.com/MetrolistGroup/Metrolist"),
|
"Maps" to listOf(
|
||||||
Triple("Maps", "Vela", "https://github.com/PimpinPumpkin/Vela"),
|
"Organic Maps" to "https://github.com/organicmaps/organicmaps",
|
||||||
Triple("Podcasts", "AntennaPod", "https://github.com/AntennaPod/AntennaPod"),
|
"Vela" to "https://github.com/PimpinPumpkin/Vela",
|
||||||
|
),
|
||||||
|
"Music" to listOf(
|
||||||
|
"ViVi Music" to "https://github.com/vivizzz007/vivi-music",
|
||||||
|
"Metrolist" to "https://github.com/MetrolistGroup/Metrolist",
|
||||||
|
),
|
||||||
|
"Podcasts" to listOf(
|
||||||
|
"AntennaPod" to "https://github.com/AntennaPod/AntennaPod",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
/** One row per pick, each opening the app's GitHub page; they arrive one after another. */
|
/** One row per kind, with a chip per app opening its GitHub page; the rows arrive one after another. */
|
||||||
@Composable
|
@Composable
|
||||||
private fun AppPicks(c: IntroColors, cq: (Float) -> Dp, cqSp: (Float) -> TextUnit, key: IntroStep) {
|
private fun AppPicks(c: IntroColors, cq: (Float) -> Dp, cqSp: (Float) -> TextUnit, key: IntroStep) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
Column(Modifier.padding(top = cq(6f)), verticalArrangement = Arrangement.spacedBy(cq(2.6f))) {
|
Column(Modifier.padding(top = cq(6f)), verticalArrangement = Arrangement.spacedBy(cq(2.6f))) {
|
||||||
APP_PICKS.forEachIndexed { i, (kind, name, url) ->
|
APP_PICKS.forEachIndexed { i, (kind, apps) ->
|
||||||
Row(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.up(entrance(key, 500 + i * 120, 700), cq(7f))
|
.up(entrance(key, 500 + i * 120, 700), cq(7f))
|
||||||
.clip(RoundedCornerShape(cq(5f)))
|
.clip(RoundedCornerShape(cq(5f)))
|
||||||
.background(c.secondaryC)
|
.background(c.secondaryC)
|
||||||
.clickable {
|
.padding(horizontal = cq(4f), vertical = cq(3f)),
|
||||||
runCatching {
|
|
||||||
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(horizontal = cq(5f), vertical = cq(3.4f)),
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
) {
|
) {
|
||||||
Column(Modifier.weight(1f)) {
|
Text(kind.uppercase(), color = c.onSecondaryC.copy(alpha = 0.7f),
|
||||||
Text(kind.uppercase(), color = c.onSecondaryC.copy(alpha = 0.7f),
|
style = TextStyle(fontSize = cqSp(3.2f), fontWeight = FontWeight.Bold, letterSpacing = cqSp(0.3f)),
|
||||||
style = TextStyle(fontSize = cqSp(3.2f), fontWeight = FontWeight.Bold, letterSpacing = cqSp(0.3f)))
|
modifier = Modifier.padding(start = cq(1f), bottom = cq(1.6f)))
|
||||||
Text(name, color = c.onSecondaryC, style = TextStyle(fontSize = cqSp(5.2f), fontWeight = FontWeight.ExtraBold))
|
Row(horizontalArrangement = Arrangement.spacedBy(cq(2f))) {
|
||||||
|
apps.forEach { (name, url) ->
|
||||||
|
Text(
|
||||||
|
"$name ↗", color = c.onSecondaryC,
|
||||||
|
style = TextStyle(fontSize = cqSp(4.4f), fontWeight = FontWeight.ExtraBold),
|
||||||
|
maxLines = 1,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(RoundedCornerShape(50))
|
||||||
|
.border(BorderStroke(1.5.dp, c.onSecondaryC.copy(alpha = 0.35f)), RoundedCornerShape(50))
|
||||||
|
.clickable {
|
||||||
|
runCatching {
|
||||||
|
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(horizontal = cq(3.6f), vertical = cq(2f)),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Text("GitHub ↗", color = c.onSecondaryC, style = TextStyle(fontSize = cqSp(3.8f), fontWeight = FontWeight.SemiBold))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ private class RecommendedApp(val name: String, val packageName: String, val url:
|
|||||||
|
|
||||||
private val recommended = listOf(
|
private val recommended = listOf(
|
||||||
"Maps" to listOf(
|
"Maps" to listOf(
|
||||||
RecommendedApp("Vela Maps", "app.vela", "https://github.com/PimpinPumpkin/Vela", "Turn-by-turn navigation without Google."),
|
|
||||||
RecommendedApp("Organic Maps", "app.organicmaps", "https://github.com/organicmaps/organicmaps", "Offline maps and routing."),
|
RecommendedApp("Organic Maps", "app.organicmaps", "https://github.com/organicmaps/organicmaps", "Offline maps and routing."),
|
||||||
|
RecommendedApp("Vela Maps", "app.vela", "https://github.com/PimpinPumpkin/Vela", "Turn-by-turn navigation without Google."),
|
||||||
),
|
),
|
||||||
"Music" to listOf(
|
"Music" to listOf(
|
||||||
RecommendedApp("ViVi Music", "com.vivi.vivimusic", "https://github.com/vivizzz007/vivi-music", "A YouTube Music player."),
|
RecommendedApp("ViVi Music", "com.vivi.vivimusic", "https://github.com/vivizzz007/vivi-music", "A YouTube Music player."),
|
||||||
|
|||||||
Reference in new issue
Block a user