Skip to content

Commit c4f30f3

Browse files
authored
Merge pull request #314 from tuuhin/feature/assets-options
feat: Added asset selection for multiple installer variants (#293)
2 parents ccc7dfb + 73768f5 commit c4f30f3

File tree

10 files changed

+1020
-596
lines changed

10 files changed

+1020
-596
lines changed

core/presentation/src/commonMain/composeResources/values/strings.xml

Lines changed: 457 additions & 496 deletions
Large diffs are not rendered by default.

feature/details/presentation/src/commonMain/kotlin/zed/rainxch/details/presentation/DetailsAction.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package zed.rainxch.details.presentation
22

33
import org.jetbrains.compose.resources.StringResource
4+
import zed.rainxch.core.domain.model.GithubAsset
45
import zed.rainxch.core.domain.model.GithubRelease
56
import zed.rainxch.details.domain.model.ReleaseCategory
67
import zed.rainxch.details.presentation.model.TranslationTarget
@@ -50,4 +51,8 @@ sealed interface DetailsAction {
5051
data object ToggleWhatsNewTranslation : DetailsAction
5152
data class ShowLanguagePicker(val target: TranslationTarget) : DetailsAction
5253
data object DismissLanguagePicker : DetailsAction
54+
55+
// show release asset picker
56+
data class SelectDownloadAsset(val release: GithubAsset) : DetailsAction
57+
data object ToggleReleaseAssetsPicker : DetailsAction
5358
}

feature/details/presentation/src/commonMain/kotlin/zed/rainxch/details/presentation/DetailsState.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package zed.rainxch.details.presentation
22

3-
import zed.rainxch.core.domain.model.SystemArchitecture
4-
import zed.rainxch.core.domain.model.GithubRepoSummary
5-
import zed.rainxch.core.domain.model.GithubRelease
63
import zed.rainxch.core.domain.model.GithubAsset
4+
import zed.rainxch.core.domain.model.GithubRelease
5+
import zed.rainxch.core.domain.model.GithubRepoSummary
76
import zed.rainxch.core.domain.model.GithubUserProfile
87
import zed.rainxch.core.domain.model.InstalledApp
8+
import zed.rainxch.core.domain.model.SystemArchitecture
99
import zed.rainxch.details.domain.model.ReleaseCategory
1010
import zed.rainxch.details.domain.model.RepoStats
1111
import zed.rainxch.details.presentation.model.DowngradeWarning
@@ -18,13 +18,18 @@ data class DetailsState(
1818
val isLoading: Boolean = true,
1919
val errorMessage: String? = null,
2020

21+
val userProfile: GithubUserProfile? = null,
2122
val repository: GithubRepoSummary? = null,
22-
val selectedRelease: GithubRelease? = null,
23-
val installableAssets: List<GithubAsset> = emptyList(),
23+
24+
// state for assets
2425
val primaryAsset: GithubAsset? = null,
25-
val userProfile: GithubUserProfile? = null,
26+
val installableAssets: List<GithubAsset> = emptyList(),
2627

28+
// state for releases
29+
val selectedRelease: GithubRelease? = null,
2730
val allReleases: List<GithubRelease> = emptyList(),
31+
val isReleaseSelectorVisible: Boolean = false,
32+
2833
val selectedReleaseCategory: ReleaseCategory = ReleaseCategory.STABLE,
2934
val isVersionPickerVisible: Boolean = false,
3035

feature/details/presentation/src/commonMain/kotlin/zed/rainxch/details/presentation/DetailsViewModel.kt

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package zed.rainxch.details.presentation
22

33
import androidx.lifecycle.ViewModel
44
import androidx.lifecycle.viewModelScope
5-
import zed.rainxch.githubstore.core.presentation.res.*
65
import kotlinx.coroutines.Job
76
import kotlinx.coroutines.NonCancellable
87
import kotlinx.coroutines.async
@@ -46,8 +45,19 @@ import zed.rainxch.details.presentation.model.DowngradeWarning
4645
import zed.rainxch.details.presentation.model.DownloadStage
4746
import zed.rainxch.details.presentation.model.InstallLogItem
4847
import zed.rainxch.details.presentation.model.LogResult
48+
import zed.rainxch.details.presentation.model.LogResult.Error
4949
import zed.rainxch.details.presentation.model.SupportedLanguages
5050
import zed.rainxch.details.presentation.model.TranslationState
51+
import zed.rainxch.githubstore.core.presentation.res.Res
52+
import zed.rainxch.githubstore.core.presentation.res.added_to_favourites
53+
import zed.rainxch.githubstore.core.presentation.res.failed_to_open_app
54+
import zed.rainxch.githubstore.core.presentation.res.failed_to_share_link
55+
import zed.rainxch.githubstore.core.presentation.res.failed_to_uninstall
56+
import zed.rainxch.githubstore.core.presentation.res.installer_saved_downloads
57+
import zed.rainxch.githubstore.core.presentation.res.link_copied_to_clipboard
58+
import zed.rainxch.githubstore.core.presentation.res.rate_limit_exceeded
59+
import zed.rainxch.githubstore.core.presentation.res.removed_from_favourites
60+
import zed.rainxch.githubstore.core.presentation.res.translation_failed
5161
import java.util.concurrent.atomic.AtomicBoolean
5262
import kotlin.coroutines.cancellation.CancellationException
5363
import kotlin.time.Clock.System
@@ -857,7 +867,7 @@ class DetailsViewModel(
857867
assetName = asset.name,
858868
size = asset.size,
859869
tag = release.tagName,
860-
result = LogResult.Error(t.message)
870+
result = Error(t.message)
861871
)
862872
}
863873
}
@@ -887,6 +897,15 @@ class DetailsViewModel(
887897
is DetailsAction.OnMessage -> {
888898
// Handled in composable
889899
}
900+
901+
is DetailsAction.SelectDownloadAsset -> {
902+
_state.update { state -> state.copy(primaryAsset = action.release) }
903+
}
904+
905+
DetailsAction.ToggleReleaseAssetsPicker -> {
906+
_state.update { state -> state.copy(isReleaseSelectorVisible = !state.isReleaseSelectorVisible) }
907+
}
908+
890909
}
891910
}
892911

feature/details/presentation/src/commonMain/kotlin/zed/rainxch/details/presentation/components/AppHeader.kt

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ import androidx.compose.material3.MaterialTheme
3030
import androidx.compose.material3.Surface
3131
import androidx.compose.material3.Text
3232
import androidx.compose.runtime.Composable
33+
import androidx.compose.runtime.derivedStateOf
3334
import androidx.compose.runtime.getValue
35+
import androidx.compose.runtime.remember
3436
import androidx.compose.ui.Alignment
3537
import androidx.compose.ui.Modifier
3638
import androidx.compose.ui.draw.clip
3739
import androidx.compose.ui.graphics.StrokeCap
3840
import androidx.compose.ui.text.font.FontWeight
3941
import androidx.compose.ui.unit.dp
4042
import com.skydoves.landscapist.coil3.CoilImage
41-
import zed.rainxch.githubstore.core.presentation.res.*
4243
import org.jetbrains.compose.resources.stringResource
4344
import zed.rainxch.core.domain.model.GithubRelease
4445
import zed.rainxch.core.domain.model.GithubRepoSummary
@@ -48,6 +49,13 @@ import zed.rainxch.core.presentation.components.ForkBadge
4849
import zed.rainxch.core.presentation.components.PlatformChip
4950
import zed.rainxch.core.presentation.utils.formatReleasedAt
5051
import zed.rainxch.details.presentation.model.DownloadStage
52+
import zed.rainxch.githubstore.core.presentation.res.Res
53+
import zed.rainxch.githubstore.core.presentation.res.by_author
54+
import zed.rainxch.githubstore.core.presentation.res.installed
55+
import zed.rainxch.githubstore.core.presentation.res.installed_version
56+
import zed.rainxch.githubstore.core.presentation.res.no_description
57+
import zed.rainxch.githubstore.core.presentation.res.pending_install
58+
import zed.rainxch.githubstore.core.presentation.res.update_available
5159

5260
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalLayoutApi::class)
5361
@Composable
@@ -66,6 +74,12 @@ fun AppHeader(
6674
label = "avatar_progress_animation"
6775
)
6876

77+
val supportedPlatforms by remember(release?.assets) {
78+
derivedStateOf {
79+
derivePlatformsFromAssets(release)
80+
}
81+
}
82+
6983
Column(
7084
modifier = modifier.fillMaxWidth()
7185
) {
@@ -128,7 +142,7 @@ fun AppHeader(
128142
)
129143
}
130144

131-
else -> { }
145+
else -> {}
132146
}
133147
}
134148
}
@@ -151,16 +165,17 @@ fun AppHeader(
151165
modifier = Modifier.weight(1f, fill = false)
152166
)
153167

154-
if (repository.isFork) {
155-
ForkBadge()
156-
}
157-
}
158-
159-
Text(
160-
text = stringResource(Res.string.by_author, author?.login.toString()),
161-
style = MaterialTheme.typography.bodyMedium,
162-
color = MaterialTheme.colorScheme.primary,
163-
)
168+
if (repository.isFork) {
169+
ForkBadge()
170+
}
171+
}
172+
author?.login?.let{ author ->
173+
Text(
174+
text = stringResource(Res.string.by_author, author),
175+
style = MaterialTheme.typography.bodyMedium,
176+
color = MaterialTheme.colorScheme.primary,
177+
)
178+
}
164179

165180
Spacer(Modifier.height(8.dp))
166181

@@ -208,15 +223,14 @@ fun AppHeader(
208223
}
209224
}
210225

211-
val platforms = derivePlatformsFromAssets(release)
212-
if (platforms.isNotEmpty()) {
226+
if (supportedPlatforms.isNotEmpty()) {
213227
Spacer(Modifier.height(12.dp))
214228

215229
FlowRow(
216230
horizontalArrangement = Arrangement.spacedBy(6.dp),
217231
verticalArrangement = Arrangement.spacedBy(6.dp)
218232
) {
219-
platforms.forEach { platform ->
233+
supportedPlatforms.forEach { platform ->
220234
PlatformChip(platform = platform)
221235
}
222236
}
@@ -235,12 +249,18 @@ fun AppHeader(
235249
private fun derivePlatformsFromAssets(release: GithubRelease?): List<String> {
236250
if (release == null) return emptyList()
237251
val names = release.assets.map { it.name.lowercase() }
238-
val platforms = mutableListOf<String>()
239-
if (names.any { it.endsWith(".apk") }) platforms.add("Android")
240-
if (names.any { it.endsWith(".exe") || it.endsWith(".msi") }) platforms.add("Windows")
241-
if (names.any { it.endsWith(".dmg") || it.endsWith(".pkg") }) platforms.add("macOS")
242-
if (names.any { it.endsWith(".appimage") || it.endsWith(".deb") || it.endsWith(".rpm") }) platforms.add("Linux")
243-
return platforms
252+
return buildList {
253+
when {
254+
names.any { it.endsWith(".apk") } -> add("Android")
255+
names.any { it.endsWith(".exe") || it.endsWith(".msi") } -> add("Windows")
256+
names.any { it.endsWith(".dmg") || it.endsWith(".pkg") } -> add("macOS")
257+
names.any {
258+
it.endsWith(".appimage") ||
259+
it.endsWith(".deb") ||
260+
it.endsWith(".rpm")
261+
} -> add("Linux")
262+
}
263+
}
244264
}
245265

246266
@Composable

0 commit comments

Comments
 (0)