feat: changelog system
Signed-off-by: Infi <wingit@geist.ga>
This commit is contained in:
parent
3a5098ecf1
commit
e625297718
|
|
@ -0,0 +1,90 @@
|
|||
# 
|
||||
|
||||
## Welcome Beta Ring II 🎉
|
||||
|
||||
For many of you, this is the first time you're seeing this app. Welcome to the second beta ring!
|
||||
You'll be helping us test the app and find bugs before we release it to the general public. Everyone
|
||||
is so excited to have you here!
|
||||
|
||||
Crashes are expected, and we're working hard to fix them. If you find a crash, it will be reported
|
||||
automatically. If you have anything else to say, use the **channels on Jenvolt** or the **Feedback**
|
||||
button in settings.
|
||||
|
||||
## Server Identities are here
|
||||
|
||||
Server identities and role colours will now be shown across the app. This should help make the app
|
||||
feel a lot more like the web client, which is our compatibility target. Servers look a lot closer
|
||||
now!
|
||||
|
||||
We'll still exploring how to best show these identities in user sheets, but for now, they're only
|
||||
shown inline in chat and in the member list.
|
||||
|
||||
## Changelogs
|
||||
|
||||
You're reading one right now! New releases will now come with changelogs, so you can see what's
|
||||
been cooking in the kitchen. We'll also be posting these on the website after general availability,
|
||||
so feel free to check them out there too.
|
||||
|
||||
## Updated to Android 14 SDK
|
||||
|
||||
We've updated the app to use the latest Android SDK, which is Android 14. This means we're now
|
||||
ahead of the actual Android release schedule! 14 is still in beta, but the SDK is stable by now.
|
||||
|
||||
This will help us keep the
|
||||
app [in the Play Store](https://support.google.com/googleplay/android-developer/answer/11926878?hl=en)
|
||||
for longer, and it also means we can use the latest and greatest APIs. As always, the app's aim is
|
||||
to make use of the Android platform as much as possible, and being on the newest SDK helps us do
|
||||
that.
|
||||
|
||||
## Extended Markdown in Bios and Changelogs
|
||||
|
||||
There is now a separate **web-based** Markdown renderer, currently in use on user bios and
|
||||
changelogs.
|
||||
This renderer is more powerful than the one we use in chat, and it's also more accurate to the web
|
||||
client. It is a little slower, but we're working on that. The aim will be to instantly render
|
||||
Markdown in it, however the current placeholder implementation works alright. Look forward to KaTeX
|
||||
and more!
|
||||
|
||||
Now, our focus will go back to the native chat Markdown renderer. It is quite a bit behind in terms
|
||||
of feature support. Some features (such as KaTeX) will be impossible to implement natively, so we
|
||||
will be looking at ways to fuse the two renderers together on-demand. As always, this is a long-term
|
||||
goal, but we're getting there.
|
||||
|
||||
## Member List
|
||||
|
||||
Here it is, the member list sheet! This is equivalent to the right sidebar on the web client. It
|
||||
shows all the members of the server, sorted by role and position, along with the correct role colour
|
||||
and identity.
|
||||
|
||||
In the future, you will be able to filter this list by role, and search for members. For now, it's
|
||||
just a list.
|
||||
|
||||
## The Small Things
|
||||
|
||||
- Latest and greatest dependency versions are now used, including Kotlin 1.9.10 and Compose 1.5.3.
|
||||
- Audio player gained a "share URL" menu item.
|
||||
- Message timestamps now use native time formatting APIs, which means they'll be formatted
|
||||
correctly for your locale and will stay accurate in all cases.
|
||||
- The disconnected/reconnected/connected banner is now using Material You colouring if your theme is
|
||||
set to that.
|
||||
- Roles in the user sheet are now sorted by position.
|
||||
- If a users' profile is empty or fails to load, the fallback messages are now clearly
|
||||
distinguishable as such.
|
||||
- Debug builds now have "+debug" appended to their version string, an app ID of "chat.revolt.debug",
|
||||
and a different name. This allows you to install the debug build alongside the release build.
|
||||
|
||||
## Squished Bug Showcase
|
||||
|
||||
- Fixed a crash when opening the user sheet for a user that has blocked you.
|
||||
- Fixed a condition in which messages from yesterday would be shown as "Today" in the chat.
|
||||
- Fixed a condition in which GIFs would not play in the chat.
|
||||
- Fixed a condition in which animated WebP images would not play in the chat.
|
||||
- Fixed a condition in which users were eagerly shown as offline when they were actually online.
|
||||
- Fixed a condition in which the ripple area for server icons would be too small compared to the
|
||||
icon.
|
||||
|
||||
## 🫡✨
|
||||
|
||||
That's all for now! We hope you enjoy this release, and we're looking forward to your feedback.
|
||||
Please report any bugs you find, and let us know what you think of the app so far. Thank you for
|
||||
testing!
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"list": {
|
||||
"6000": {
|
||||
"summary": "Beta Ring II, Server Identities, Changelogs, SDK34",
|
||||
"version": "0.6.0",
|
||||
"date": "2023-09-08"
|
||||
}
|
||||
},
|
||||
"latest": "6000"
|
||||
}
|
||||
|
|
@ -62,11 +62,8 @@
|
|||
<script src="https://cdn.jsdelivr.net/npm/showdown@2.1.0/dist/showdown.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.5/dist/purify.min.js"></script>
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
const style = document.querySelector("style")
|
||||
style.innerHTML = style.innerHTML
|
||||
.replaceAll("{content}", Bridge.getContentColour())
|
||||
.replaceAll("{primary}", Bridge.getPrimaryColour())
|
||||
const renderMarkdown = () => {
|
||||
const markdown = document.querySelector("#markdown")
|
||||
|
||||
const converter = new showdown.Converter()
|
||||
|
||||
|
|
@ -75,14 +72,22 @@
|
|||
converter.setOption("emoji", true)
|
||||
converter.setOption("disableForced4SpacesIndentedSublists", true)
|
||||
converter.setOption("noHeaderId", true)
|
||||
converter.setOption("simpleLineBreaks", true)
|
||||
converter.setOption("simpleLineBreaks", Bridge.shouldUseSimpleLineBreaks())
|
||||
converter.setOption("strikethrough", true)
|
||||
converter.setOption("tasklists", true)
|
||||
|
||||
const markdown = document.querySelector("#markdown")
|
||||
const html = converter.makeHtml(Bridge.getMarkdown())
|
||||
markdown.innerHTML = DOMPurify.sanitize(html)
|
||||
}
|
||||
window.renderMarkdown = renderMarkdown
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
const style = document.querySelector("style")
|
||||
style.innerHTML = style.innerHTML
|
||||
.replaceAll("{content}", Bridge.getContentColour())
|
||||
.replaceAll("{primary}", Bridge.getPrimaryColour())
|
||||
|
||||
renderMarkdown()
|
||||
Bridge.onLoaded()
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import chat.revolt.screens.register.RegisterDetailsScreen
|
|||
import chat.revolt.screens.register.RegisterGreetingScreen
|
||||
import chat.revolt.screens.register.RegisterVerifyScreen
|
||||
import chat.revolt.screens.settings.AppearanceSettingsScreen
|
||||
import chat.revolt.screens.settings.ChangelogsSettingsScreen
|
||||
import chat.revolt.screens.settings.ClosedBetaUpdaterScreen
|
||||
import chat.revolt.screens.settings.DebugSettingsScreen
|
||||
import chat.revolt.screens.settings.SettingsScreen
|
||||
|
|
@ -137,6 +138,7 @@ fun AppEntrypoint(windowSizeClass: WindowSizeClass) {
|
|||
composable("settings/appearance") { AppearanceSettingsScreen(navController) }
|
||||
composable("settings/debug") { DebugSettingsScreen(navController) }
|
||||
composable("settings/updater") { ClosedBetaUpdaterScreen(navController) }
|
||||
composable("settings/changelogs") { ChangelogsSettingsScreen(navController) }
|
||||
dialog("settings/feedback") { FeedbackDialog(navController) }
|
||||
|
||||
composable("about") { AboutScreen(navController) }
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ private fun argbAsCssColour(argb: Int): String {
|
|||
fun WebMarkdown(
|
||||
text: String,
|
||||
maskLoading: Boolean = false,
|
||||
simpleLineBreaks: Boolean = true,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val contentColour = LocalContentColor.current
|
||||
|
|
@ -128,7 +129,7 @@ fun WebMarkdown(
|
|||
}
|
||||
|
||||
loadUrl(
|
||||
"https://app.revolt.chat/_android_assets/webmarkdown/renderer.html",
|
||||
"$REVOLT_APP/_android_assets/webmarkdown/renderer.html",
|
||||
)
|
||||
|
||||
settings.apply {
|
||||
|
|
@ -164,6 +165,11 @@ fun WebMarkdown(
|
|||
fun getPrimaryColour(): String {
|
||||
return argbAsCssColour(materialColourScheme.primary.toArgb())
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
fun shouldUseSimpleLineBreaks(): Boolean {
|
||||
return simpleLineBreaks
|
||||
}
|
||||
},
|
||||
"Bridge"
|
||||
)
|
||||
|
|
@ -174,6 +180,9 @@ fun WebMarkdown(
|
|||
LayoutParams.WRAP_CONTENT
|
||||
)
|
||||
}
|
||||
},
|
||||
update = {
|
||||
it.evaluateJavascript("renderMarkdown()", null)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package chat.revolt.internals
|
||||
|
||||
import android.content.Context
|
||||
import chat.revolt.api.RevoltJson
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class Changelog(
|
||||
val summary: String,
|
||||
val version: String,
|
||||
val date: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ChangelogIndex(
|
||||
val list: Map<String, Changelog>,
|
||||
val latest: String
|
||||
)
|
||||
|
||||
class Changelogs(val context: Context, val kvStorage: KVStorage? = null) {
|
||||
val index = context.assets.open("changelogs/index.json").use {
|
||||
it.reader().readText()
|
||||
}.let {
|
||||
RevoltJson.decodeFromString(ChangelogIndex.serializer(), it)
|
||||
}
|
||||
|
||||
fun getChangelog(version: String): String {
|
||||
return context.assets.open("changelogs/${version}.md").use {
|
||||
it.reader().readText()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun hasSeenLatest(): Boolean {
|
||||
if (kvStorage == null) throw IllegalStateException("Not supported for non-KVStorage instances of Changelogs")
|
||||
|
||||
return kvStorage.get("latestChangelogRead") == index.latest
|
||||
}
|
||||
|
||||
suspend fun markAsSeen() {
|
||||
if (kvStorage == null) throw IllegalStateException("Not supported for non-KVStorage instances of Changelogs")
|
||||
|
||||
kvStorage.set("latestChangelogRead", index.latest)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package chat.revolt.screens.chat
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.Crossfade
|
||||
|
|
@ -73,12 +75,14 @@ import chat.revolt.components.screens.chat.drawer.channel.ChannelList
|
|||
import chat.revolt.components.screens.chat.drawer.server.DrawerServer
|
||||
import chat.revolt.components.screens.chat.drawer.server.DrawerServerlikeIcon
|
||||
import chat.revolt.components.screens.chat.drawer.server.ServerDrawerSeparator
|
||||
import chat.revolt.internals.Changelogs
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog
|
||||
import chat.revolt.screens.chat.views.HomeScreen
|
||||
import chat.revolt.screens.chat.views.NoCurrentChannelScreen
|
||||
import chat.revolt.screens.chat.views.channel.ChannelScreen
|
||||
import chat.revolt.sheets.AddServerSheet
|
||||
import chat.revolt.sheets.ChangelogSheet
|
||||
import chat.revolt.sheets.ServerContextSheet
|
||||
import chat.revolt.sheets.StatusSheet
|
||||
import chat.revolt.sheets.UserContextSheet
|
||||
|
|
@ -88,27 +92,41 @@ import com.airbnb.lottie.compose.LottieCompositionSpec
|
|||
import com.airbnb.lottie.compose.animateLottieCompositionAsState
|
||||
import com.airbnb.lottie.compose.rememberLottieComposition
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
class ChatRouterViewModel @Inject constructor(
|
||||
private val kvStorage: KVStorage
|
||||
private val kvStorage: KVStorage,
|
||||
@ApplicationContext val context: Context
|
||||
) : ViewModel() {
|
||||
var currentServer by mutableStateOf("home")
|
||||
var currentChannel by mutableStateOf<String?>(null)
|
||||
var sidebarSparkDisplayed by mutableStateOf(true)
|
||||
var latestChangelogRead by mutableStateOf(true)
|
||||
var latestChangelog by mutableStateOf("")
|
||||
|
||||
private val changelogs = Changelogs(context, kvStorage)
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
currentServer = kvStorage.get("currentServer") ?: "home"
|
||||
currentChannel = kvStorage.get("currentChannel")
|
||||
|
||||
sidebarSparkDisplayed = if (kvStorage.getBoolean("sidebarSpark") == null) {
|
||||
false
|
||||
} else {
|
||||
kvStorage.getBoolean("sidebarSpark")!!
|
||||
}
|
||||
|
||||
latestChangelogRead = changelogs.hasSeenLatest()
|
||||
latestChangelog = changelogs.index.latest
|
||||
if (!latestChangelogRead) {
|
||||
changelogs.markAsSeen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -291,6 +309,22 @@ fun ChatRouterScreen(
|
|||
}
|
||||
}
|
||||
|
||||
if (!viewModel.latestChangelogRead) {
|
||||
val changelogSheetState = rememberModalBottomSheetState()
|
||||
|
||||
ModalBottomSheet(
|
||||
sheetState = changelogSheetState,
|
||||
onDismissRequest = {
|
||||
viewModel.latestChangelogRead = true
|
||||
},
|
||||
) {
|
||||
ChangelogSheet(
|
||||
version = viewModel.latestChangelog,
|
||||
new = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (showSidebarSpark.value) {
|
||||
AlertDialog(
|
||||
onDismissRequest = {},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
package chat.revolt.screens.settings
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheet
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.navigation.NavController
|
||||
import chat.revolt.R
|
||||
import chat.revolt.components.generic.PageHeader
|
||||
import chat.revolt.internals.Changelogs
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import chat.revolt.sheets.ChangelogSheet
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ChangelogsSettingsScreenViewModel @Inject constructor(
|
||||
kvStorage: KVStorage,
|
||||
@ApplicationContext context: Context
|
||||
) : ViewModel() {
|
||||
val index = Changelogs(context, kvStorage).index
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ChangelogsSettingsScreen(
|
||||
navController: NavController,
|
||||
viewModel: ChangelogsSettingsScreenViewModel = hiltViewModel()
|
||||
) {
|
||||
var currentChangelog by remember { mutableStateOf(viewModel.index.latest) }
|
||||
var sheetOpen by remember { mutableStateOf(false) }
|
||||
|
||||
if (sheetOpen) {
|
||||
val sheetState = rememberModalBottomSheetState()
|
||||
|
||||
ModalBottomSheet(
|
||||
sheetState = sheetState,
|
||||
onDismissRequest = {
|
||||
sheetOpen = false
|
||||
}
|
||||
) {
|
||||
ChangelogSheet(version = currentChangelog)
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.safeDrawingPadding()
|
||||
) {
|
||||
PageHeader(
|
||||
text = stringResource(R.string.settings_changelogs),
|
||||
showBackButton = true,
|
||||
onBackButtonClicked = {
|
||||
navController.popBackStack()
|
||||
})
|
||||
|
||||
LazyColumn {
|
||||
items(
|
||||
viewModel.index.list.size,
|
||||
key = { viewModel.index.list.keys.elementAt(it) }
|
||||
) { index ->
|
||||
val version = viewModel.index.list.keys.elementAt(index)
|
||||
val changelog = viewModel.index.list[version]!!
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
currentChangelog = version
|
||||
sheetOpen = true
|
||||
}
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
Text(
|
||||
text = changelog.version,
|
||||
style = MaterialTheme.typography.headlineSmall
|
||||
)
|
||||
Text(
|
||||
text = changelog.summary,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,12 @@ class DebugSettingsScreenViewModel @Inject constructor(
|
|||
fun forgetAllSparks() {
|
||||
this.forgetSidebarSparkShown()
|
||||
}
|
||||
|
||||
fun forgetLatestChangelog() {
|
||||
viewModelScope.launch {
|
||||
kvStorage.remove("latestChangelogRead")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -79,6 +85,19 @@ fun DebugSettingsScreen(
|
|||
Text("Forget all sparks")
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "Changelogs",
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
modifier = Modifier.padding(bottom = 10.dp)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.horizontalScroll(rememberScrollState())
|
||||
) {
|
||||
ElevatedButton(onClick = { viewModel.forgetLatestChangelog() }) {
|
||||
Text("Mark latest changelog as unread")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import androidx.compose.foundation.verticalScroll
|
|||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.DateRange
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
|
|
@ -154,6 +155,25 @@ fun SettingsScreen(
|
|||
modifier = Modifier.padding(bottom = 10.dp, start = 10.dp, top = 20.dp)
|
||||
)
|
||||
|
||||
SheetClickable(
|
||||
icon = { modifier ->
|
||||
Icon(
|
||||
imageVector = Icons.Default.DateRange,
|
||||
contentDescription = stringResource(id = R.string.settings_changelogs),
|
||||
modifier = modifier
|
||||
)
|
||||
},
|
||||
label = { textStyle ->
|
||||
Text(
|
||||
text = stringResource(id = R.string.settings_changelogs),
|
||||
style = textStyle
|
||||
)
|
||||
},
|
||||
modifier = Modifier.testTag("settings_view_changelogs")
|
||||
) {
|
||||
navController.navigate("settings/changelogs")
|
||||
}
|
||||
|
||||
SheetClickable(
|
||||
icon = { modifier ->
|
||||
Icon(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
package chat.revolt.sheets
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import chat.revolt.R
|
||||
import chat.revolt.components.generic.PageHeader
|
||||
import chat.revolt.components.generic.WebMarkdown
|
||||
import chat.revolt.internals.Changelog
|
||||
import chat.revolt.internals.Changelogs
|
||||
import chat.revolt.persistence.KVStorage
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
class ChangelogSheetViewModel @Inject constructor(
|
||||
val kvStorage: KVStorage,
|
||||
@ApplicationContext val context: Context
|
||||
) : ViewModel() {
|
||||
private val changelogs = Changelogs(context, kvStorage)
|
||||
var changelogContents by mutableStateOf(null as String?)
|
||||
var changelog by mutableStateOf(null as Changelog?)
|
||||
|
||||
private fun getContents(version: String): String {
|
||||
return changelogs.getChangelog(version)
|
||||
}
|
||||
|
||||
private fun getChangelog(version: String): Changelog {
|
||||
return changelogs.index.list[version] ?: throw IllegalStateException("Changelog not found")
|
||||
}
|
||||
|
||||
fun populate(version: String) {
|
||||
changelogContents = getContents(version)
|
||||
changelog = getChangelog(version)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChangelogSheet(
|
||||
version: String,
|
||||
new: Boolean = false,
|
||||
viewModel: ChangelogSheetViewModel = hiltViewModel()
|
||||
) {
|
||||
LaunchedEffect(version) {
|
||||
viewModel.populate(version)
|
||||
}
|
||||
|
||||
Column {
|
||||
PageHeader(
|
||||
if (new) {
|
||||
stringResource(R.string.settings_changelogs_new_header)
|
||||
} else {
|
||||
stringResource(
|
||||
R.string.settings_changelogs_historical_version_header,
|
||||
viewModel.changelog?.version
|
||||
?: stringResource(R.string.settings_changelogs_historical_version_header_placeholder)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
if (viewModel.changelogContents == null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(200.dp)
|
||||
) {
|
||||
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
|
||||
}
|
||||
}
|
||||
|
||||
key(viewModel.changelogContents) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
WebMarkdown(
|
||||
text = viewModel.changelogContents ?: "",
|
||||
maskLoading = true,
|
||||
simpleLineBreaks = false
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -359,4 +359,9 @@
|
|||
|
||||
<string name="settings_feedback_disabled_title">Feedback unavailable</string>
|
||||
<string name="settings_feedback_disabled_message">Feedback is not available on this build of Revolt. Support for this build is limited. (Build: %1$s %2$s)</string>
|
||||
|
||||
<string name="settings_changelogs">Changelogs</string>
|
||||
<string name="settings_changelogs_new_header">What\'s been cooking ✨</string>
|
||||
<string name="settings_changelogs_historical_version_header">Changelog for %1$s</string>
|
||||
<string name="settings_changelogs_historical_version_header_placeholder">that version</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in New Issue