Skip to content

Commit de90622

Browse files
authored
Merge pull request #1661 from DimensionDev/feature/appstore_review
Feature/appstore review
2 parents 6a3c6c3 + 9ddd124 commit de90622

File tree

125 files changed

+5757
-4814
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+5757
-4814
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ plugins {
1717
// END Non-FOSS component
1818
alias(libs.plugins.compose.compiler)
1919
id("kotlin-parcelize")
20+
alias(libs.plugins.stability.analyzer)
2021
}
2122

2223
// START Non-FOSS component

app/src/main/java/dev/dimension/flare/common/PodcastManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.ComponentName
44
import android.content.Context
55
import android.content.Intent
66
import androidx.annotation.OptIn
7+
import androidx.compose.runtime.Stable
78
import androidx.core.net.toUri
89
import androidx.media3.common.util.UnstableApi
910
import androidx.media3.datasource.DefaultHttpDataSource
@@ -20,6 +21,7 @@ import kotlinx.coroutines.flow.Flow
2021
import kotlinx.coroutines.flow.MutableStateFlow
2122
import kotlinx.coroutines.flow.asSharedFlow
2223

24+
@Stable
2325
internal class PodcastManager(
2426
private val context: Context,
2527
) : AutoCloseable {

app/src/main/java/dev/dimension/flare/common/VideoDownloadHelper.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import android.content.IntentFilter
88
import android.os.Environment
99
import android.util.Log
1010
import android.webkit.MimeTypeMap
11+
import androidx.compose.runtime.Stable
1112
import androidx.core.content.ContextCompat
1213
import androidx.core.net.toUri
1314

1415
/**
1516
* Download Manager Helper - Simplified Version
1617
* Encapsulates Android's DownloadManager, provides simple video download functionality
1718
*/
19+
@Stable
1820
internal class VideoDownloadHelper(
1921
private val context: Context,
2022
) {

app/src/main/java/dev/dimension/flare/ui/common/OnNewIntent.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,11 @@ private fun Context.getActivity(): Activity {
1717

1818
@Composable
1919
fun OnNewIntent(
20-
key1: Any? = null,
21-
key2: Any? = null,
22-
key3: Any? = null,
2320
withOnCreateIntent: Boolean = false,
2421
onNewIntent: (Intent) -> Unit,
2522
) {
2623
val context = LocalContext.current
27-
DisposableEffect(key1 = key1, key2 = key2, key3 = key3) {
24+
DisposableEffect(Unit) {
2825
val activity = (context.getActivity() as ComponentActivity)
2926
val listener =
3027
Consumer<Intent> {

app/src/main/java/dev/dimension/flare/ui/component/RssRichText.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ import com.halilibo.richtext.ui.string.RichTextString
3737
import com.halilibo.richtext.ui.string.RichTextStringStyle
3838
import com.halilibo.richtext.ui.string.Text
3939
import com.halilibo.richtext.ui.string.withFormat
40-
import dev.dimension.flare.common.AppDeepLink
40+
import dev.dimension.flare.ui.route.DeeplinkRoute
41+
import dev.dimension.flare.ui.route.toUri
4142
import kotlinx.collections.immutable.ImmutableMap
4243

4344
private val lightLinkColor = Color(0xff0066cc)
@@ -85,7 +86,7 @@ fun RssRichText(
8586
imageHeader = imageHeader,
8687
onMediaClick = {
8788
uriHandler.openUri(
88-
AppDeepLink.RawImage(it),
89+
DeeplinkRoute.Media.Image(it, previewUrl = null).toUri(),
8990
)
9091
},
9192
)

app/src/main/java/dev/dimension/flare/ui/route/Route.kt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.dimension.flare.ui.route
22

3+
import androidx.compose.runtime.Immutable
34
import androidx.navigation3.runtime.NavKey
45
import dev.dimension.flare.data.model.TimelineTabItem
56
import dev.dimension.flare.model.AccountType
@@ -8,6 +9,7 @@ import kotlinx.collections.immutable.ImmutableMap
89
import kotlinx.collections.immutable.toImmutableMap
910
import kotlinx.serialization.Serializable
1011

12+
@Immutable
1113
@Serializable
1214
internal sealed interface Route : NavKey {
1315
@Serializable
@@ -412,6 +414,24 @@ internal sealed interface Route : NavKey {
412414
val data: ImmutableMap<MicroBlogKey, Route>,
413415
) : Route
414416

417+
@Serializable
418+
public data class BlockUser(
419+
val accountType: AccountType?,
420+
val userKey: MicroBlogKey,
421+
) : Route
422+
423+
@Serializable
424+
public data class MuteUser(
425+
val accountType: AccountType?,
426+
val userKey: MicroBlogKey,
427+
) : Route
428+
429+
@Serializable
430+
public data class ReportUser(
431+
val accountType: AccountType?,
432+
val userKey: MicroBlogKey,
433+
) : Route
434+
415435
companion object {
416436
public fun parse(url: String): Route? {
417437
val deeplinkRoute = DeeplinkRoute.parse(url) ?: return null
@@ -554,6 +574,32 @@ internal sealed interface Route : NavKey {
554574
statusKey = deeplinkRoute.statusKey,
555575
accountType = deeplinkRoute.accountType,
556576
)
577+
578+
is DeeplinkRoute.BlockUser ->
579+
Route.BlockUser(
580+
accountType = deeplinkRoute.accountKey?.let { AccountType.Specific(it) },
581+
userKey = deeplinkRoute.userKey,
582+
)
583+
is DeeplinkRoute.DirectMessage ->
584+
DM.UserConversation(
585+
accountType = AccountType.Specific(deeplinkRoute.accountKey),
586+
userKey = deeplinkRoute.userKey,
587+
)
588+
is DeeplinkRoute.EditUserList ->
589+
Lists.EditAccountList(
590+
accountType = AccountType.Specific(deeplinkRoute.accountKey),
591+
userKey = deeplinkRoute.userKey,
592+
)
593+
is DeeplinkRoute.MuteUser ->
594+
Route.MuteUser(
595+
accountType = deeplinkRoute.accountKey?.let { AccountType.Specific(it) },
596+
userKey = deeplinkRoute.userKey,
597+
)
598+
is DeeplinkRoute.ReportUser ->
599+
Route.ReportUser(
600+
accountType = deeplinkRoute.accountKey?.let { AccountType.Specific(it) },
601+
userKey = deeplinkRoute.userKey,
602+
)
557603
}
558604
}
559605
}

app/src/main/java/dev/dimension/flare/ui/route/Router.kt

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable
99
import androidx.compose.runtime.CompositionLocalProvider
1010
import androidx.compose.runtime.getValue
1111
import androidx.compose.runtime.remember
12+
import androidx.compose.runtime.snapshots.SnapshotStateList
1213
import androidx.compose.ui.platform.LocalUriHandler
1314
import androidx.compose.ui.platform.UriHandler
1415
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
@@ -19,7 +20,6 @@ import androidx.navigation3.scene.DialogSceneStrategy
1920
import androidx.navigation3.ui.NavDisplay
2021
import dev.dimension.flare.ui.common.OnNewIntent
2122
import dev.dimension.flare.ui.component.BottomSheetSceneStrategy
22-
import dev.dimension.flare.ui.component.TopLevelBackStack
2323
import dev.dimension.flare.ui.component.platform.isBigScreen
2424
import dev.dimension.flare.ui.presenter.home.DeepLinkPresenter
2525
import dev.dimension.flare.ui.presenter.invoke
@@ -49,20 +49,14 @@ import soup.compose.material.motion.animation.translateXOut
4949
@OptIn(ExperimentalMaterial3AdaptiveApi::class, ExperimentalSharedTransitionApi::class)
5050
@Composable
5151
internal fun Router(
52-
topLevelBackStack: TopLevelBackStack<Route>,
52+
backStack: SnapshotStateList<Route>,
53+
navigate: (Route) -> Unit,
54+
onBack: () -> Unit,
5355
navigationState: NavigationState,
5456
openDrawer: () -> Unit,
5557
) {
5658
val listDetailStrategy = rememberListDetailSceneStrategy<NavKey>()
5759

58-
fun navigate(route: Route) {
59-
topLevelBackStack.add(route)
60-
}
61-
62-
fun onBack() {
63-
topLevelBackStack.removeLast()
64-
}
65-
6660
val isBigScreen = isBigScreen()
6761

6862
val uriHandler = LocalUriHandler.current
@@ -110,7 +104,7 @@ internal fun Router(
110104
rememberSaveableStateHolderNavEntryDecorator(),
111105
rememberViewModelStoreNavEntryDecorator(),
112106
),
113-
backStack = topLevelBackStack.backStack,
107+
backStack = backStack,
114108
onBack = { onBack() },
115109
transitionSpec = {
116110
if (isBigScreen) {
@@ -138,18 +132,18 @@ internal fun Router(
138132
},
139133
entryProvider =
140134
entryProvider {
141-
homeEntryBuilder(::navigate, ::onBack, openDrawer, uriHandler = proxyUriHandler)
142-
blueskyEntryBuilder(::navigate, ::onBack)
143-
composeEntryBuilder(::navigate, ::onBack)
144-
dmEntryBuilder(::navigate, ::onBack, navigationState)
145-
listEntryBuilder(::navigate, ::onBack)
146-
mediaEntryBuilder(::navigate, ::onBack, uriHandler = proxyUriHandler)
147-
profileEntryBuilder(::navigate, ::onBack)
148-
rssEntryBuilder(::navigate, ::onBack)
149-
serviceSelectEntryBuilder(::navigate, ::onBack)
150-
settingsSelectEntryBuilder(::navigate, ::onBack)
151-
statusEntryBuilder(::navigate, ::onBack)
152-
misskeyEntryBuilder(::navigate, ::onBack)
135+
homeEntryBuilder(navigate, onBack, openDrawer, uriHandler = proxyUriHandler)
136+
blueskyEntryBuilder(navigate, onBack)
137+
composeEntryBuilder(navigate, onBack)
138+
dmEntryBuilder(navigate, onBack, navigationState)
139+
listEntryBuilder(navigate, onBack)
140+
mediaEntryBuilder(navigate, onBack, uriHandler = proxyUriHandler)
141+
profileEntryBuilder(navigate, onBack)
142+
rssEntryBuilder(navigate, onBack)
143+
serviceSelectEntryBuilder(navigate, onBack)
144+
settingsSelectEntryBuilder(navigate, onBack)
145+
statusEntryBuilder(navigate, onBack)
146+
misskeyEntryBuilder(navigate, onBack)
153147
},
154148
)
155149
}

app/src/main/java/dev/dimension/flare/ui/screen/compose/ComposeScreen.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import androidx.compose.material3.TopAppBarDefaults
5959
import androidx.compose.material3.surfaceColorAtElevation
6060
import androidx.compose.runtime.Composable
6161
import androidx.compose.runtime.CompositionLocalProvider
62+
import androidx.compose.runtime.Immutable
6263
import androidx.compose.runtime.LaunchedEffect
6364
import androidx.compose.runtime.getValue
6465
import androidx.compose.runtime.mutableStateOf
@@ -387,10 +388,10 @@ internal fun ComposeScreen(
387388
.horizontalScroll(rememberScrollState()),
388389
horizontalArrangement = Arrangement.spacedBy(8.dp),
389390
) {
390-
mediaState.medias.forEach { (uri, altTextState) ->
391+
mediaState.medias.forEach { media ->
391392
Box {
392393
NetworkImage(
393-
model = uri,
394+
model = media.url,
394395
contentDescription = null,
395396
modifier =
396397
Modifier
@@ -438,7 +439,7 @@ internal fun ComposeScreen(
438439
},
439440
icon = {
440441
NetworkImage(
441-
model = uri,
442+
model = media.url,
442443
contentDescription = null,
443444
modifier =
444445
Modifier
@@ -451,10 +452,10 @@ internal fun ComposeScreen(
451452
},
452453
text = {
453454
OutlinedTextField(
454-
altTextState,
455+
media.textState,
455456
trailingIcon = {
456457
val remainingLength =
457-
mediaState.altTextMaxLength - altTextState.text.length
458+
mediaState.altTextMaxLength - media.textState.text.length
458459
Text(
459460
remainingLength.toString(),
460461
color =
@@ -473,7 +474,7 @@ internal fun ComposeScreen(
473474
}
474475
IconButton(
475476
onClick = {
476-
mediaState.removeMedia(uri)
477+
mediaState.removeMedia(media.uri)
477478
},
478479
colors =
479480
IconButtonDefaults.iconButtonColors(
@@ -1147,10 +1148,13 @@ private fun mediaPresenter(
11471148
}
11481149
}
11491150

1151+
@Immutable
11501152
private data class MediaData(
11511153
val uri: Uri,
11521154
val textState: TextFieldState = TextFieldState(),
1153-
)
1155+
) {
1156+
val url = uri.toString()
1157+
}
11541158

11551159
@Composable
11561160
private fun pollPresenter(config: ComposeConfig.Poll) =

app/src/main/java/dev/dimension/flare/ui/screen/home/ChangeLogState.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package dev.dimension.flare.ui.screen.home
22

33
import android.content.Context
44
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.Immutable
56
import androidx.compose.runtime.getValue
67
import androidx.compose.runtime.remember
78
import androidx.compose.runtime.rememberCoroutineScope
@@ -54,6 +55,7 @@ internal fun changeLogPresenter(
5455
}
5556
}
5657

58+
@Immutable
5759
interface ChangeLogState {
5860
val shouldShowChangeLog: UiState<Boolean>
5961
val changeLog: AnnotatedString?

app/src/main/java/dev/dimension/flare/ui/screen/home/HomeScreen.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,13 +292,19 @@ internal fun HomeScreen(afterInit: () -> Unit) {
292292
LocalScrollToTopRegistry provides state.scrollToTopRegistry,
293293
) {
294294
Router(
295-
topLevelBackStack = topLevelBackStack,
295+
backStack = topLevelBackStack.backStack,
296296
navigationState = state.navigationState,
297297
openDrawer = {
298298
scope.launch {
299299
wideNavigationRailState.toggle()
300300
}
301301
},
302+
navigate = {
303+
topLevelBackStack.add(it)
304+
},
305+
onBack = {
306+
topLevelBackStack.removeLast()
307+
},
302308
)
303309
}
304310
}

0 commit comments

Comments
 (0)