diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index a8d957b92..b195fafdb 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -32,7 +32,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 17 + java-version: 21 - name: Setup Android SDK uses: android-actions/setup-android@v2 diff --git a/app/build.gradle.kts b/app/build.gradle.kts index dfa8e0580..b7ae94453 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,7 +117,8 @@ dependencies { implementation(libs.bundles.koin) implementation(libs.ktorfit.lib) ksp(libs.ktorfit.ksp) - implementation(libs.bundles.coil) + implementation(libs.bundles.coil3) + implementation(libs.bundles.coil3.extensions) implementation(libs.bundles.ktor) implementation(libs.molecule.runtime) implementation(libs.ksoup) @@ -145,6 +146,8 @@ dependencies { implementation(libs.colorpicker.compose) implementation(libs.material.motion.compose) implementation(libs.nestedScrollView) + implementation(libs.precompose.molecule) + implementation(libs.compose.placeholder.material3) if (project.file("google-services.json").exists()) { implementation(platform(libs.firebase.bom)) diff --git a/app/src/main/java/dev/dimension/flare/App.kt b/app/src/main/java/dev/dimension/flare/App.kt index 4f07adf85..6f051720f 100644 --- a/app/src/main/java/dev/dimension/flare/App.kt +++ b/app/src/main/java/dev/dimension/flare/App.kt @@ -2,11 +2,13 @@ package dev.dimension.flare import android.app.Application import android.os.Build -import coil.ImageLoader -import coil.ImageLoaderFactory -import coil.decode.GifDecoder -import coil.decode.ImageDecoderDecoder -import coil.decode.SvgDecoder +import coil3.ImageLoader +import coil3.PlatformContext +import coil3.SingletonImageLoader +import coil3.gif.AnimatedImageDecoder +import coil3.gif.GifDecoder +import coil3.request.crossfade +import coil3.svg.SvgDecoder import dev.dimension.flare.common.AnimatedPngDecoder import dev.dimension.flare.common.AnimatedWebPDecoder import dev.dimension.flare.di.androidModule @@ -16,7 +18,7 @@ import org.koin.core.context.startKoin class App : Application(), - ImageLoaderFactory { + SingletonImageLoader.Factory { override fun onCreate() { super.onCreate() startKoin { @@ -25,12 +27,12 @@ class App : } } - override fun newImageLoader(): ImageLoader = + override fun newImageLoader(context: PlatformContext): ImageLoader = ImageLoader .Builder(this) .components { if (Build.VERSION.SDK_INT >= 28) { - add(ImageDecoderDecoder.Factory()) + add(factory = AnimatedImageDecoder.Factory()) } else { add(GifDecoder.Factory()) } diff --git a/app/src/main/java/dev/dimension/flare/common/AnimatedPngDecoder.kt b/app/src/main/java/dev/dimension/flare/common/AnimatedPngDecoder.kt index c46e56acb..7492dfd3f 100644 --- a/app/src/main/java/dev/dimension/flare/common/AnimatedPngDecoder.kt +++ b/app/src/main/java/dev/dimension/flare/common/AnimatedPngDecoder.kt @@ -1,12 +1,13 @@ package dev.dimension.flare.common -import coil.ImageLoader -import coil.annotation.ExperimentalCoilApi -import coil.decode.DecodeResult -import coil.decode.Decoder -import coil.decode.ImageSource -import coil.fetch.SourceResult -import coil.request.Options +import coil3.ImageLoader +import coil3.annotation.ExperimentalCoilApi +import coil3.asImage +import coil3.decode.DecodeResult +import coil3.decode.Decoder +import coil3.decode.ImageSource +import coil3.fetch.SourceFetchResult +import coil3.request.Options import com.github.penfeizhou.animation.apng.APNGDrawable import com.github.penfeizhou.animation.apng.decode.APNGParser @@ -16,13 +17,13 @@ internal class AnimatedPngDecoder( @OptIn(ExperimentalCoilApi::class) override suspend fun decode(): DecodeResult = DecodeResult( - drawable = APNGDrawable.fromFile(source.file().toString()), + image = APNGDrawable.fromFile(source.file().toString()).asImage(), isSampled = false, ) class Factory : Decoder.Factory { override fun create( - result: SourceResult, + result: SourceFetchResult, options: Options, imageLoader: ImageLoader, ): Decoder? = diff --git a/app/src/main/java/dev/dimension/flare/common/AnimatedWebPDecoder.kt b/app/src/main/java/dev/dimension/flare/common/AnimatedWebPDecoder.kt index e1e0f5431..669535430 100644 --- a/app/src/main/java/dev/dimension/flare/common/AnimatedWebPDecoder.kt +++ b/app/src/main/java/dev/dimension/flare/common/AnimatedWebPDecoder.kt @@ -1,26 +1,29 @@ package dev.dimension.flare.common -import coil.ImageLoader -import coil.decode.DecodeResult -import coil.decode.Decoder -import coil.decode.ImageSource -import coil.fetch.SourceResult -import coil.request.Options +import coil3.ImageLoader +import coil3.annotation.ExperimentalCoilApi +import coil3.asImage +import coil3.decode.DecodeResult +import coil3.decode.Decoder +import coil3.decode.ImageSource +import coil3.fetch.SourceFetchResult +import coil3.request.Options import com.github.penfeizhou.animation.webp.WebPDrawable import com.github.penfeizhou.animation.webp.decode.WebPParser internal class AnimatedWebPDecoder( private val source: ImageSource, ) : Decoder { + @OptIn(ExperimentalCoilApi::class) override suspend fun decode(): DecodeResult = DecodeResult( - drawable = WebPDrawable.fromFile(source.file().toString()), + image = WebPDrawable.fromFile(source.file().toString()).asImage(), isSampled = false, ) class Factory : Decoder.Factory { override fun create( - result: SourceResult, + result: SourceFetchResult, options: Options, imageLoader: ImageLoader, ): Decoder? = diff --git a/app/src/main/java/dev/dimension/flare/data/model/AppearanceSettings.kt b/app/src/main/java/dev/dimension/flare/data/model/AppearanceSettings.kt index 9ff7ec473..0409cbd60 100644 --- a/app/src/main/java/dev/dimension/flare/data/model/AppearanceSettings.kt +++ b/app/src/main/java/dev/dimension/flare/data/model/AppearanceSettings.kt @@ -35,17 +35,20 @@ data class AppearanceSettings( val compatLinkPreview: Boolean = false, ) +@Serializable enum class Theme { LIGHT, DARK, SYSTEM, } +@Serializable enum class AvatarShape { CIRCLE, SQUARE, } +@Serializable enum class VideoAutoplay { ALWAYS, WIFI, diff --git a/app/src/main/java/dev/dimension/flare/molecule/Molecule.kt b/app/src/main/java/dev/dimension/flare/molecule/Molecule.kt deleted file mode 100644 index c0cdf0f86..000000000 --- a/app/src/main/java/dev/dimension/flare/molecule/Molecule.kt +++ /dev/null @@ -1,42 +0,0 @@ -package dev.dimension.flare.molecule - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.currentCompositeKeyHash -import androidx.lifecycle.ViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewModelScope -import androidx.lifecycle.viewmodel.compose.viewModel -import app.cash.molecule.AndroidUiDispatcher -import app.cash.molecule.RecompositionMode -import app.cash.molecule.launchMolecule -import kotlinx.coroutines.CoroutineScope - -private class PresenterHolder( - body: @Composable () -> T, -) : ViewModel() { - private val scope = CoroutineScope(viewModelScope.coroutineContext + AndroidUiDispatcher.Main) - val state = scope.launchMolecule(mode = RecompositionMode.ContextClock, body = body) -} - -/** - * Return State, use it in your Compose UI - * The molecule scope will be managed by the [ViewModel], so it has the same lifecycle as the [ViewModel] - * @param body The body of the molecule presenter - * @return State - */ -@Composable -fun producePresenter( - key: String? = null, - body: @Composable () -> T, -): State = createPresenter(body, key) - -@Composable -private fun createPresenter( - body: @Composable () -> T, - key: String? = null, - holder: PresenterHolder = - viewModel(key = key + currentCompositeKeyHash.toString()) { - PresenterHolder(body) - }, -): State = holder.state.collectAsStateWithLifecycle() diff --git a/app/src/main/java/dev/dimension/flare/ui/component/NetworkImage.kt b/app/src/main/java/dev/dimension/flare/ui/component/NetworkImage.kt index a5111527f..c73f4db1a 100644 --- a/app/src/main/java/dev/dimension/flare/ui/component/NetworkImage.kt +++ b/app/src/main/java/dev/dimension/flare/ui/component/NetworkImage.kt @@ -7,6 +7,8 @@ import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -15,14 +17,14 @@ import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp -import coil.compose.AsyncImagePainter -import coil.compose.SubcomposeAsyncImage -import coil.compose.rememberAsyncImagePainter -import coil.request.ImageRequest -import coil.size.Size -import com.eygraber.compose.placeholder.material3.placeholder +import coil3.compose.AsyncImagePainter +import coil3.compose.LocalPlatformContext +import coil3.compose.SubcomposeAsyncImage +import coil3.compose.rememberAsyncImagePainter +import coil3.request.ImageRequest +import coil3.size.Size +import io.github.fornewid.placeholder.material3.placeholder @Composable fun NetworkImage( @@ -46,7 +48,7 @@ fun NetworkImage( SubcomposeAsyncImage( model = ImageRequest - .Builder(LocalContext.current) + .Builder(LocalPlatformContext.current) .data(model) .let { if (model is String) { @@ -69,11 +71,11 @@ fun NetworkImage( } @Composable -fun EmojiImage( +internal fun EmojiImage( uri: String, modifier: Modifier = Modifier, ) { - val context = LocalContext.current + val context = LocalPlatformContext.current val painter = rememberAsyncImagePainter( model = @@ -85,7 +87,8 @@ fun EmojiImage( .build() }, ) - if (painter.state is AsyncImagePainter.State.Success) { + val state by painter.state.collectAsState(AsyncImagePainter.State.Loading(painter)) + if (state is AsyncImagePainter.State.Success) { val aspectRatio = remember(painter.intrinsicSize) { val size = painter.intrinsicSize diff --git a/app/src/main/java/dev/dimension/flare/ui/component/status/CommonStatusComponent.kt b/app/src/main/java/dev/dimension/flare/ui/component/status/CommonStatusComponent.kt index fcf9f04c8..6c649732c 100644 --- a/app/src/main/java/dev/dimension/flare/ui/component/status/CommonStatusComponent.kt +++ b/app/src/main/java/dev/dimension/flare/ui/component/status/CommonStatusComponent.kt @@ -56,7 +56,6 @@ import androidx.compose.ui.text.intl.Locale import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.fleeksoft.ksoup.nodes.Element import compose.icons.FontAwesomeIcons import compose.icons.fontawesomeicons.Regular @@ -83,7 +82,6 @@ import dev.dimension.flare.data.datasource.microblog.StatusAction import dev.dimension.flare.data.model.AppearanceSettings import dev.dimension.flare.data.model.LocalAppearanceSettings import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AdaptiveGrid import dev.dimension.flare.ui.component.EmojiImage import dev.dimension.flare.ui.component.FAIcon @@ -99,8 +97,10 @@ import dev.dimension.flare.ui.model.onLoading import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.screen.status.statusTranslatePresenter import dev.dimension.flare.ui.theme.MediumAlpha +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import moe.tlaster.precompose.molecule.producePresenter @Composable fun CommonStatusComponent( @@ -112,7 +112,7 @@ fun CommonStatusComponent( val appearanceSettings = LocalAppearanceSettings.current Column( modifier = - modifier + Modifier .let { if (isDetail) { it @@ -127,7 +127,7 @@ fun CommonStatusComponent( ) } } - }, + }.then(modifier), ) { item.user?.let { user -> CommonStatusHeaderComponent( @@ -823,7 +823,7 @@ private fun StatusPollComponent( text = stringResource( id = R.string.poll_expired_at, - poll.expiresAt.localizedFullTime, + poll.expiredAt.value.localizedFullTime, ), modifier = Modifier @@ -964,14 +964,14 @@ private fun ExpandedCard( val appearanceSettings = LocalAppearanceSettings.current Column( modifier = - modifier + Modifier .border( FlareDividerDefaults.thickness, color = FlareDividerDefaults.color, shape = MaterialTheme.shapes.medium, ).clip( shape = MaterialTheme.shapes.medium, - ), + ).then(modifier), ) { card.media?.let { AdaptiveGrid( @@ -1016,14 +1016,14 @@ fun CompatCard( ) { Row( modifier = - modifier + Modifier .border( FlareDividerDefaults.thickness, color = FlareDividerDefaults.color, shape = MaterialTheme.shapes.medium, ).clip( shape = MaterialTheme.shapes.medium, - ), + ).then(modifier), ) { card.media?.let { MediaItem( diff --git a/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusItems.kt b/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusItems.kt index 0f4beae11..d09e25d7a 100644 --- a/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusItems.kt +++ b/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusItems.kt @@ -27,7 +27,6 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.generated.destinations.ServiceSelectRouteDestination import compose.icons.FontAwesomeIcons import compose.icons.fontawesomeicons.Solid @@ -49,6 +48,7 @@ import dev.dimension.flare.ui.model.UiTimeline import dev.dimension.flare.ui.theme.DisabledAlpha import dev.dimension.flare.ui.theme.MediumAlpha import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder internal fun LazyStaggeredGridScope.status( pagingState: PagingState, @@ -254,18 +254,20 @@ internal fun StatusItem( ) { if (item == null) { Column( - modifier = modifier.padding(horizontal = horizontalPadding), + modifier = + modifier.padding( + horizontal = horizontalPadding, + vertical = 8.dp, + ), ) { StatusPlaceholder() - Spacer(modifier = Modifier.height(8.dp)) } } else { UiTimelineComponent( item = item, detailStatusKey = detailStatusKey, - modifier = - modifier - .padding(horizontal = horizontalPadding), + modifier = modifier, + horizontalPadding = screenHorizontalPadding, ) } } diff --git a/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt b/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt index c927f29e9..14f93cb6e 100644 --- a/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt +++ b/app/src/main/java/dev/dimension/flare/ui/component/status/LazyStatusVerticalStaggeredGrid.kt @@ -21,7 +21,7 @@ fun LazyStatusVerticalStaggeredGrid( state: LazyStaggeredGridState = rememberLazyStaggeredGridState(), contentPadding: PaddingValues = PaddingValues(0.dp), reverseLayout: Boolean = false, - verticalItemSpacing: Dp = 8.dp, + verticalItemSpacing: Dp = 0.dp, horizontalArrangement: Arrangement.Horizontal = Arrangement.spacedBy(8.dp), flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), userScrollEnabled: Boolean = true, diff --git a/app/src/main/java/dev/dimension/flare/ui/component/status/UiTimelineComponent.kt b/app/src/main/java/dev/dimension/flare/ui/component/status/UiTimelineComponent.kt index b87233aed..d6ed8c2b6 100644 --- a/app/src/main/java/dev/dimension/flare/ui/component/status/UiTimelineComponent.kt +++ b/app/src/main/java/dev/dimension/flare/ui/component/status/UiTimelineComponent.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import compose.icons.FontAwesomeIcons import compose.icons.fontawesomeicons.Solid @@ -30,22 +31,39 @@ import dev.dimension.flare.model.MicroBlogKey import dev.dimension.flare.ui.model.ClickContext import dev.dimension.flare.ui.model.UiTimeline import dev.dimension.flare.ui.model.mapper.MisskeyAchievement +import dev.dimension.flare.ui.theme.screenHorizontalPadding @Composable internal fun UiTimelineComponent( item: UiTimeline, modifier: Modifier = Modifier, detailStatusKey: MicroBlogKey? = null, + horizontalPadding: Dp = screenHorizontalPadding, ) { Column( modifier = modifier, ) { - item.topMessage?.let { TopMessageComponent(it) } - Spacer(modifier = Modifier.height(4.dp)) + item.topMessage?.let { + Spacer(modifier = Modifier.height(8.dp)) + TopMessageComponent( + data = it, + modifier = Modifier.padding(horizontal = horizontalPadding), + ) + } item.content?.let { ItemContentComponent( item = it, detailStatusKey = detailStatusKey, + modifier = + Modifier + .let { + if (item.topMessage == null) { + it.padding(top = 4.dp) + } else { + it + } + }.padding(top = 4.dp) + .padding(horizontal = horizontalPadding), ) } } diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedScreen.kt index 9a4f065d8..aa7009008 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedScreen.kt @@ -28,7 +28,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator @@ -40,7 +39,6 @@ import compose.icons.fontawesomeicons.solid.Heart import compose.icons.fontawesomeicons.solid.Rss import dev.dimension.flare.R import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon @@ -59,7 +57,9 @@ import dev.dimension.flare.ui.presenter.home.bluesky.BlueskyFeedState import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.theme.MediumAlpha import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedsScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedsScreen.kt index bbb292434..39031c04e 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedsScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/bluesky/BlueskyFeedsScreen.kt @@ -37,7 +37,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator @@ -48,7 +47,6 @@ import compose.icons.fontawesomeicons.solid.Rss import compose.icons.fontawesomeicons.solid.Trash import dev.dimension.flare.R import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.items import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.FAIcon @@ -64,8 +62,10 @@ import dev.dimension.flare.ui.presenter.home.bluesky.BlueskyFeedsState import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.theme.MediumAlpha import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize +import moe.tlaster.precompose.molecule.producePresenter @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/compose/ComposeScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/compose/ComposeScreen.kt index d7b02b16f..c2cca3ba3 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/compose/ComposeScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/compose/ComposeScreen.kt @@ -94,7 +94,6 @@ import dev.dimension.flare.data.datasource.microblog.ComposeConfig import dev.dimension.flare.data.datasource.microblog.ComposeData import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.NetworkImage @@ -120,6 +119,7 @@ import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList +import moe.tlaster.precompose.molecule.producePresenter import kotlin.time.Duration import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.hours diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMConversationScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMConversationScreen.kt index 1587bbbfe..b2186af91 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMConversationScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMConversationScreen.kt @@ -57,7 +57,6 @@ import dev.dimension.flare.R import dev.dimension.flare.common.onSuccess import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.items import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon @@ -75,6 +74,7 @@ import dev.dimension.flare.ui.presenter.dm.DMConversationState import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.screen.home.NavigationState import dev.dimension.flare.ui.theme.screenHorizontalPadding +import moe.tlaster.precompose.molecule.producePresenter @OptIn( ExperimentalMaterial3Api::class, diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMListScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMListScreen.kt index f452e6fcc..d6a46e3b6 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMListScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/dm/DMListScreen.kt @@ -46,7 +46,6 @@ import compose.icons.fontawesomeicons.solid.List import dev.dimension.flare.R import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.items import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.AvatarComponentDefaults @@ -67,6 +66,7 @@ import dev.dimension.flare.ui.theme.MediumAlpha import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize +import moe.tlaster.precompose.molecule.producePresenter @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/dm/UserDMConversationScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/dm/UserDMConversationScreen.kt index 1dfaa0c73..06ef6a14f 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/dm/UserDMConversationScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/dm/UserDMConversationScreen.kt @@ -12,11 +12,9 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import com.eygraber.compose.placeholder.material3.placeholder import dev.dimension.flare.R import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.FlareTopAppBar @@ -26,6 +24,8 @@ import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.dm.UserDMConversationPresenter import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.screen.home.NavigationState +import io.github.fornewid.placeholder.material3.placeholder +import moe.tlaster.precompose.molecule.producePresenter @OptIn(ExperimentalMaterial3Api::class) @Composable diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt index e85bb7b09..e4bc5cb62 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.window.core.layout.WindowWidthSizeClass -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.ProfileRouteDestination @@ -41,7 +40,6 @@ import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.RefreshContainer import dev.dimension.flare.ui.component.SearchBar @@ -58,7 +56,9 @@ import dev.dimension.flare.ui.presenter.home.DiscoverState import dev.dimension.flare.ui.presenter.home.SearchPresenter import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeScreen.kt index 74d48c1ba..aa44dc00f 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeScreen.kt @@ -103,7 +103,6 @@ import dev.dimension.flare.data.model.TimelineTabItem import dev.dimension.flare.data.repository.SettingsRepository import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.HtmlText @@ -135,6 +134,7 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject import soup.compose.material.motion.animation.materialSharedAxisXIn import soup.compose.material.motion.animation.materialSharedAxisXOut diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt index 61c93210c..3dee0c81c 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/HomeTimelineScreen.kt @@ -60,7 +60,6 @@ import dev.dimension.flare.data.model.HomeTimelineTabItem import dev.dimension.flare.data.model.TimelineTabItem import dev.dimension.flare.data.repository.SettingsRepository import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -87,6 +86,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt index cbda218d5..5bb2770a0 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/NotificationScreen.kt @@ -29,7 +29,6 @@ import dev.dimension.flare.R import dev.dimension.flare.common.isRefreshing import dev.dimension.flare.data.datasource.microblog.NotificationFilter import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.LocalBottomBarHeight @@ -46,6 +45,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/SearchScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/SearchScreen.kt index dcd07dfc6..262c0644c 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/SearchScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/SearchScreen.kt @@ -21,7 +21,6 @@ import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.common.isRefreshing import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.RefreshContainer import dev.dimension.flare.ui.component.SearchBar @@ -33,6 +32,7 @@ import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid import dev.dimension.flare.ui.presenter.home.SearchPresenter import dev.dimension.flare.ui.presenter.invoke import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/TabSettingScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/TabSettingScreen.kt index 19276a292..794eee4ec 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/TabSettingScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/TabSettingScreen.kt @@ -55,7 +55,6 @@ import dev.dimension.flare.data.model.HomeTimelineTabItem import dev.dimension.flare.data.model.TimelineTabItem import dev.dimension.flare.data.repository.SettingsRepository import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -72,6 +71,7 @@ import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.rememberReorderableLazyListState diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/home/TimelineScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/home/TimelineScreen.kt index f3a2d194c..e71f4c44a 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/home/TimelineScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/home/TimelineScreen.kt @@ -30,7 +30,6 @@ import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.Pen import dev.dimension.flare.R import dev.dimension.flare.data.model.TimelineTabItem -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -43,6 +42,7 @@ import dev.dimension.flare.ui.presenter.home.UserState import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.screen.settings.TabTitle import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter // @RootNavGraph(start = true) // sets this as the start destination of the default nav graph @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/list/CreateListDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/list/CreateListDialog.kt index 5f98a757e..23b0b84b7 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/list/CreateListDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/list/CreateListDialog.kt @@ -43,7 +43,6 @@ import dev.dimension.flare.common.FileItem import dev.dimension.flare.data.datasource.microblog.ListMetaData import dev.dimension.flare.data.datasource.microblog.ListMetaDataType import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.NetworkImage @@ -54,6 +53,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.list.CreateListPresenter import dev.dimension.flare.ui.presenter.list.CreateListState import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/list/DeleteListDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/list/DeleteListDialog.kt index 7b731d34b..fc3c12acb 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/list/DeleteListDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/list/DeleteListDialog.kt @@ -18,11 +18,11 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.spec.DestinationStyle import dev.dimension.flare.R import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.list.DeleteListPresenter import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/list/EditAccountListScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/list/EditAccountListScreen.kt index 9d6ba0b21..707a5894e 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/list/EditAccountListScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/list/EditAccountListScreen.kt @@ -11,7 +11,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator @@ -22,7 +21,6 @@ import compose.icons.fontawesomeicons.solid.Trash import dev.dimension.flare.R import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -30,6 +28,8 @@ import dev.dimension.flare.ui.model.onLoading import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.list.EditAccountListPresenter +import io.github.fornewid.placeholder.material3.placeholder +import moe.tlaster.precompose.molecule.producePresenter @Destination @Composable diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListMemberScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListMemberScreen.kt index 8a4225d11..d4296094a 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListMemberScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListMemberScreen.kt @@ -33,7 +33,6 @@ import dev.dimension.flare.common.onError import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -45,6 +44,7 @@ import dev.dimension.flare.ui.presenter.list.EditListMemberPresenter import dev.dimension.flare.ui.presenter.list.EditListMemberState import dev.dimension.flare.ui.presenter.list.EmptyQueryException import dev.dimension.flare.ui.screen.settings.AccountItem +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListScreen.kt index 372dd24b8..aa3c9b1bb 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/list/EditListScreen.kt @@ -39,7 +39,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.EditListMemberRouteDestination @@ -60,7 +59,6 @@ import dev.dimension.flare.common.onSuccess import dev.dimension.flare.data.datasource.microblog.ListMetaData import dev.dimension.flare.data.datasource.microblog.ListMetaDataType import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon @@ -76,7 +74,9 @@ import dev.dimension.flare.ui.presenter.list.EditListState import dev.dimension.flare.ui.presenter.list.ListEditPresenter import dev.dimension.flare.ui.screen.settings.AccountItem import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/list/ListScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/list/ListScreen.kt index cf8b7a980..6bb9714e4 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/list/ListScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/list/ListScreen.kt @@ -41,7 +41,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.CreateListRouteDestination @@ -64,7 +63,6 @@ import dev.dimension.flare.data.model.ListTimelineTabItem import dev.dimension.flare.data.model.TabMetaData import dev.dimension.flare.data.model.TitleType import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.items import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.FAIcon @@ -79,7 +77,9 @@ import dev.dimension.flare.ui.presenter.list.AllListPresenter import dev.dimension.flare.ui.screen.home.TimelineRoute import dev.dimension.flare.ui.theme.MediumAlpha import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.parcelize.Parcelize +import moe.tlaster.precompose.molecule.producePresenter @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/login/bluesky/BlueskyLoginScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/login/bluesky/BlueskyLoginScreen.kt index 5b149dbe7..9929eae1c 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/login/bluesky/BlueskyLoginScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/login/bluesky/BlueskyLoginScreen.kt @@ -36,7 +36,6 @@ import compose.icons.FontAwesomeIcons import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.CaretDown import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon @@ -46,6 +45,7 @@ import dev.dimension.flare.ui.component.OutlinedTextField2 import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.login.BlueskyLoginPresenter import dev.dimension.flare.ui.theme.screenHorizontalPadding +import moe.tlaster.precompose.molecule.producePresenter // @Composable // @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonCallbackScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonCallbackScreen.kt index e54c3eb73..db3e605b9 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonCallbackScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonCallbackScreen.kt @@ -18,12 +18,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.model.UiState import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.login.MastodonCallbackPresenter import dev.dimension.flare.ui.theme.screenHorizontalPadding +import moe.tlaster.precompose.molecule.producePresenter // @Destination( // deepLinks = [ diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonLoginScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonLoginScreen.kt index 4ff4924f7..6ffeaf7d2 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonLoginScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/login/mastodon/MastodonLoginScreen.kt @@ -34,7 +34,6 @@ import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator import dev.dimension.flare.R import dev.dimension.flare.data.repository.ApplicationRepository -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold @@ -43,6 +42,7 @@ import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.login.mastodonLoginUseCase import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyCallbackScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyCallbackScreen.kt index 78163bc6c..a59324e8f 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyCallbackScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyCallbackScreen.kt @@ -19,12 +19,12 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.model.UiState import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.login.MisskeyCallbackPresenter import dev.dimension.flare.ui.theme.screenHorizontalPadding +import moe.tlaster.precompose.molecule.producePresenter // @Destination( // deepLinks = [ diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyLoginScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyLoginScreen.kt index d06541a9b..b3751a008 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyLoginScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/login/misskey/MisskeyLoginScreen.kt @@ -34,7 +34,6 @@ import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.navigation.DestinationsNavigator import dev.dimension.flare.R import dev.dimension.flare.data.repository.ApplicationRepository -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold @@ -43,6 +42,7 @@ import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.login.misskeyLoginUseCase import dev.dimension.flare.ui.theme.screenHorizontalPadding import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/media/MediaScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/media/MediaScreen.kt index f5a29283f..adba2a015 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/media/MediaScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/media/MediaScreen.kt @@ -46,10 +46,11 @@ import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogWindowProvider -import coil.annotation.ExperimentalCoilApi -import coil.compose.rememberAsyncImagePainter -import coil.imageLoader -import coil.request.ImageRequest +import coil3.annotation.ExperimentalCoilApi +import coil3.compose.rememberAsyncImagePainter +import coil3.imageLoader +import coil3.request.ImageRequest +import coil3.request.crossfade import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState @@ -64,7 +65,6 @@ import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.FloppyDisk import dev.dimension.flare.R import dev.dimension.flare.common.AppDeepLink -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.theme.FlareTheme import kotlinx.coroutines.CoroutineScope @@ -75,6 +75,7 @@ import me.saket.telephoto.zoomable.ZoomSpec import me.saket.telephoto.zoomable.ZoomableContentLocation import me.saket.telephoto.zoomable.rememberZoomableState import me.saket.telephoto.zoomable.zoomable +import moe.tlaster.precompose.molecule.producePresenter import moe.tlaster.swiper.Swiper import moe.tlaster.swiper.rememberSwiperState import org.koin.compose.koinInject diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/media/StatusMediaScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/media/StatusMediaScreen.kt index 48d90406e..675059d63 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/media/StatusMediaScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/media/StatusMediaScreen.kt @@ -54,11 +54,11 @@ import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.NavBackStackEntry -import coil.annotation.ExperimentalCoilApi -import coil.imageLoader -import coil.request.ImageRequest -import coil.size.Size -import com.eygraber.compose.placeholder.material3.placeholder +import coil3.annotation.ExperimentalCoilApi +import coil3.imageLoader +import coil3.request.ImageRequest +import coil3.request.crossfade +import coil3.size.Size import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberPermissionState @@ -77,7 +77,6 @@ import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.data.model.LocalAppearanceSettings import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.VideoPlayer import dev.dimension.flare.ui.component.VideoPlayerPool @@ -92,14 +91,16 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.StatusPresenter import dev.dimension.flare.ui.screen.home.NavigationState import dev.dimension.flare.ui.theme.FlareTheme +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import me.saket.telephoto.zoomable.ZoomSpec -import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage +import me.saket.telephoto.zoomable.coil3.ZoomableAsyncImage import me.saket.telephoto.zoomable.rememberZoomableImageState import me.saket.telephoto.zoomable.rememberZoomableState +import moe.tlaster.precompose.molecule.producePresenter import okhttp3.internal.toImmutableList import org.koin.compose.koinInject import soup.compose.material.motion.animation.materialFadeThroughIn diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileMediaScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileMediaScreen.kt index 569f7f309..b9ae172e1 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileMediaScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileMediaScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.StatusMediaRouteDestination @@ -30,7 +29,6 @@ import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold @@ -41,6 +39,8 @@ import dev.dimension.flare.ui.model.UiTimeline import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.profile.ProfileMediaPresenter import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileScreen.kt index f09525952..3474ca78d 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/profile/ProfileScreen.kt @@ -68,7 +68,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.toSize import androidx.window.core.layout.WindowWidthSizeClass -import com.eygraber.compose.placeholder.material3.placeholder import com.fleeksoft.ksoup.nodes.Element import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph @@ -107,7 +106,6 @@ import dev.dimension.flare.data.datasource.microblog.ProfileAction import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey import dev.dimension.flare.model.PlatformType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.BackButton @@ -141,12 +139,14 @@ import dev.dimension.flare.ui.presenter.settings.AccountsPresenter import dev.dimension.flare.ui.screen.home.RegisterTabCallback import dev.dimension.flare.ui.theme.MediumAlpha import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentMapOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch import moe.tlaster.nestedscrollview.VerticalNestedScrollView import moe.tlaster.nestedscrollview.rememberNestedScrollViewState +import moe.tlaster.precompose.molecule.producePresenter import kotlin.math.max @Composable diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/profile/UserListScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/profile/UserListScreen.kt index 50f3ef059..196948150 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/profile/UserListScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/profile/UserListScreen.kt @@ -21,7 +21,6 @@ import dev.dimension.flare.common.PagingState import dev.dimension.flare.common.isRefreshing import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.items import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold @@ -36,6 +35,7 @@ import dev.dimension.flare.ui.presenter.profile.FollowingPresenter import dev.dimension.flare.ui.presenter.profile.UserListPresenter import dev.dimension.flare.ui.screen.settings.AccountItem import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/ServiceSelectScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/ServiceSelectScreen.kt index 0a7c0d8cc..10639d13e 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/ServiceSelectScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/ServiceSelectScreen.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.annotation.parameters.DeepLink @@ -58,7 +57,6 @@ import dev.dimension.flare.common.onLoading import dev.dimension.flare.common.onSuccess import dev.dimension.flare.model.PlatformType import dev.dimension.flare.model.logoUrl -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.OnNewIntent import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.BackButton @@ -77,8 +75,10 @@ import dev.dimension.flare.ui.presenter.login.ServiceSelectPresenter import dev.dimension.flare.ui.presenter.login.ServiceSelectState import dev.dimension.flare.ui.theme.FlareTheme import dev.dimension.flare.ui.theme.screenHorizontalPadding +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.distinctUntilChanged +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/VVOLoginScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/VVOLoginScreen.kt index e91e093cd..e8a03973d 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/VVOLoginScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/VVOLoginScreen.kt @@ -14,7 +14,6 @@ import com.kevinnzou.web.rememberWebViewState import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.result.ResultBackNavigator -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.model.UiApplication @@ -22,6 +21,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.login.VVOLoginPresenter import dev.dimension.flare.ui.screen.home.NavigationState import kotlinx.coroutines.delay +import moe.tlaster.precompose.molecule.producePresenter import kotlin.time.Duration.Companion.seconds @Composable diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/XQTLoginScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/XQTLoginScreen.kt index 1fcc8abd7..90bcbde96 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/XQTLoginScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/serviceselect/XQTLoginScreen.kt @@ -15,7 +15,6 @@ import com.kevinnzou.web.rememberWebViewState import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.result.ResultBackNavigator -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.model.UiApplication @@ -23,6 +22,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.login.XQTLoginPresenter import dev.dimension.flare.ui.screen.home.NavigationState import kotlinx.coroutines.delay +import moe.tlaster.precompose.molecule.producePresenter import kotlin.time.Duration.Companion.seconds @Composable diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/AboutScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/AboutScreen.kt index c28333998..c2ce9f53a 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/AboutScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/AboutScreen.kt @@ -1,41 +1,19 @@ package dev.dimension.flare.ui.screen.settings -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ListItem -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph -import compose.icons.FontAwesomeIcons -import compose.icons.fontawesomeicons.Brands -import compose.icons.fontawesomeicons.Solid -import compose.icons.fontawesomeicons.brands.Github -import compose.icons.fontawesomeicons.brands.Telegram -import compose.icons.fontawesomeicons.solid.Language import dev.dimension.flare.BuildConfig import dev.dimension.flare.R import dev.dimension.flare.ui.component.BackButton -import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.ThemeWrapper -import dev.dimension.flare.ui.theme.MediumAlpha @Destination( wrappers = [ThemeWrapper::class], @@ -50,7 +28,6 @@ internal fun AboutRoute(navigator: ProxyDestinationsNavigator) { @OptIn(ExperimentalMaterial3Api::class) @Composable private fun AboutScreen(onBack: () -> Unit) { - val uriHandler = LocalUriHandler.current FlareScaffold( topBar = { TopAppBar( @@ -63,101 +40,11 @@ private fun AboutScreen(onBack: () -> Unit) { ) }, ) { - Column( + AboutScreenContent( + version = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})", modifier = Modifier - .padding(it) - .verticalScroll(rememberScrollState()), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Image( - painter = painterResource(R.drawable.ic_launcher_foreground), - contentDescription = stringResource(id = R.string.app_name), - ) - Text( - text = stringResource(id = R.string.app_name), - style = MaterialTheme.typography.headlineMedium, - ) - Text( - text = stringResource(id = R.string.settings_about_description), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodySmall, - modifier = - Modifier - .alpha(MediumAlpha) - .padding(horizontal = 16.dp), - ) - Text( - text = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})", - style = MaterialTheme.typography.bodySmall, - modifier = Modifier.alpha(MediumAlpha), - ) - ListItem( - headlineContent = { - Text(text = stringResource(id = R.string.settings_about_source_code)) - }, - supportingContent = { - Text( - text = "https://github.com/DimensionDev/Flare", - modifier = Modifier.alpha(MediumAlpha), - ) - }, - modifier = - Modifier.clickable { - uriHandler.openUri("https://github.com/DimensionDev/Flare") - }, - leadingContent = { - FAIcon( - imageVector = FontAwesomeIcons.Brands.Github, - contentDescription = "GitHub", - modifier = Modifier.size(24.dp), - ) - }, - ) - ListItem( - headlineContent = { - Text(text = stringResource(id = R.string.settings_about_telegram)) - }, - supportingContent = { - Text( - text = stringResource(id = R.string.settings_about_telegram_description), - modifier = Modifier.alpha(MediumAlpha), - ) - }, - modifier = - Modifier.clickable { - uriHandler.openUri("https://t.me/+0UtcP6_qcDoyOWE1") - }, - leadingContent = { - FAIcon( - imageVector = FontAwesomeIcons.Brands.Telegram, - contentDescription = stringResource(id = R.string.settings_about_telegram), - modifier = Modifier.size(24.dp), - ) - }, - ) - ListItem( - headlineContent = { - Text(text = stringResource(id = R.string.settings_about_localization)) - }, - supportingContent = { - Text( - text = stringResource(id = R.string.settings_about_localization_description), - modifier = Modifier.alpha(MediumAlpha), - ) - }, - modifier = - Modifier.clickable { - uriHandler.openUri("https://crowdin.com/project/flareapp") - }, - leadingContent = { - FAIcon( - imageVector = FontAwesomeIcons.Solid.Language, - contentDescription = stringResource(id = R.string.settings_about_localization), - modifier = Modifier.size(24.dp), - ) - }, - ) - } + .padding(it), + ) } } diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/AccountsScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/AccountsScreen.kt index e161d8694..a2f77e8f3 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/AccountsScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/AccountsScreen.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.ServiceSelectRouteDestination @@ -40,7 +39,6 @@ import compose.icons.fontawesomeicons.solid.Plus import dev.dimension.flare.R import dev.dimension.flare.data.repository.LoginExpiredException import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.BackButton @@ -57,6 +55,8 @@ import dev.dimension.flare.ui.model.onLoading import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.settings.AccountsPresenter +import io.github.fornewid.placeholder.material3.placeholder +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/AppearanceScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/AppearanceScreen.kt index ac636e06b..19c6d5156 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/AppearanceScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/AppearanceScreen.kt @@ -44,7 +44,6 @@ import dev.dimension.flare.data.model.LocalAppearanceSettings import dev.dimension.flare.data.model.Theme import dev.dimension.flare.data.model.VideoAutoplay import dev.dimension.flare.data.repository.SettingsRepository -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.ThemeWrapper @@ -56,6 +55,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.settings.AppearancePresenter import dev.dimension.flare.ui.presenter.settings.AppearanceState import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/ColorPickerDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/ColorPickerDialog.kt index d63cb512e..58aabba6e 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/ColorPickerDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/ColorPickerDialog.kt @@ -30,10 +30,10 @@ import com.ramcosta.composedestinations.spec.DestinationStyle import dev.dimension.flare.R import dev.dimension.flare.data.model.LocalAppearanceSettings import dev.dimension.flare.data.repository.SettingsRepository -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.ThemeWrapper import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/EditTabDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/EditTabDialog.kt index 1ab1fa342..1bc9fbed6 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/EditTabDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/EditTabDialog.kt @@ -30,11 +30,11 @@ import dev.dimension.flare.data.model.TabItem import dev.dimension.flare.data.model.TitleType import dev.dimension.flare.data.repository.SettingsRepository import dev.dimension.flare.model.AccountType -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.OutlinedTextField2 import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.CoroutineScope +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject @Composable diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterEditDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterEditDialog.kt index 5938409cb..8ac51c265 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterEditDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterEditDialog.kt @@ -29,7 +29,6 @@ import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.Check import compose.icons.fontawesomeicons.solid.Trash import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -41,6 +40,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.settings.LocalFilterPresenter import dev.dimension.flare.ui.screen.media.FullScreenDialogStyle import dev.dimension.flare.ui.screen.media.SetDialogDestinationToEdgeToEdge +import moe.tlaster.precompose.molecule.producePresenter @Destination( style = FullScreenDialogStyle::class, diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterScreen.kt index 27bc0540e..e433a9e5f 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/LocalFilterScreen.kt @@ -18,7 +18,6 @@ import compose.icons.fontawesomeicons.Solid import compose.icons.fontawesomeicons.solid.Pen import compose.icons.fontawesomeicons.solid.Plus import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold @@ -27,6 +26,7 @@ import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.settings.LocalFilterPresenter import dev.dimension.flare.ui.presenter.settings.LocalFilterState +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/SettingsScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/SettingsScreen.kt index ad5975db6..476a40a31 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/SettingsScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/SettingsScreen.kt @@ -44,7 +44,6 @@ import compose.icons.fontawesomeicons.solid.Filter import compose.icons.fontawesomeicons.solid.Palette import compose.icons.fontawesomeicons.solid.Table import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.FAIcon import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.ThemeWrapper @@ -56,6 +55,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.screen.home.NavigationState import dev.dimension.flare.ui.screen.home.Router import kotlinx.parcelize.Parcelize +import moe.tlaster.precompose.molecule.producePresenter @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/StorageScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/StorageScreen.kt index 71a4958d3..de270496b 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/StorageScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/StorageScreen.kt @@ -18,18 +18,17 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import coil.annotation.ExperimentalCoilApi -import coil.imageLoader +import coil3.imageLoader import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import dev.dimension.flare.R -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.settings.StoragePresenter import dev.dimension.flare.ui.presenter.settings.StorageState +import moe.tlaster.precompose.molecule.producePresenter @Destination( wrappers = [ThemeWrapper::class], @@ -107,7 +106,6 @@ private fun StorageScreen(onBack: () -> Unit) { } } -@OptIn(ExperimentalCoilApi::class) @Composable private fun storagePresenter(context: Context) = run { diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/settings/TabCustomizeScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/settings/TabCustomizeScreen.kt index 01abcfc8b..4da6eaaa6 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/settings/TabCustomizeScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/settings/TabCustomizeScreen.kt @@ -48,7 +48,6 @@ import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.eygraber.compose.placeholder.material3.placeholder import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import compose.icons.FontAwesomeIcons @@ -68,7 +67,6 @@ import dev.dimension.flare.data.model.TitleType import dev.dimension.flare.data.repository.SettingsRepository import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.AvatarComponent import dev.dimension.flare.ui.component.AvatarComponentDefaults import dev.dimension.flare.ui.component.BackButton @@ -87,6 +85,7 @@ import dev.dimension.flare.ui.presenter.home.UserPresenter import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.list.PinnableListPresenter import dev.dimension.flare.ui.presenter.settings.AccountsPresenter +import io.github.fornewid.placeholder.material3.placeholder import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -94,6 +93,7 @@ import kotlinx.collections.immutable.toImmutableMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter import org.koin.compose.koinInject import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.ReorderableLazyListState diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt index aacfa5621..1a072904f 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/StatusScreen.kt @@ -24,7 +24,6 @@ import dev.dimension.flare.R import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.RefreshContainer @@ -34,6 +33,7 @@ import dev.dimension.flare.ui.component.status.status import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.StatusContextPresenter import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOCommentScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOCommentScreen.kt index b81b73ce9..f77fff6c0 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOCommentScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOCommentScreen.kt @@ -25,7 +25,6 @@ import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.common.onSuccess import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FlareScaffold import dev.dimension.flare.ui.component.RefreshContainer @@ -38,6 +37,7 @@ import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.VVOCommentPresenter import kotlinx.coroutines.launch +import moe.tlaster.precompose.molecule.producePresenter @Destination( deepLinks = [ diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOStatusScreen.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOStatusScreen.kt index 217375fd9..d947165ff 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOStatusScreen.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/VVOStatusScreen.kt @@ -48,7 +48,6 @@ import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.common.PagingState import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.common.plus import dev.dimension.flare.ui.component.BackButton import dev.dimension.flare.ui.component.FAIcon @@ -66,6 +65,7 @@ import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.VVOStatusDetailPresenter import dev.dimension.flare.ui.presenter.status.VVOStatusDetailState import dev.dimension.flare.ui.theme.screenHorizontalPadding +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/BlueskyReportStatusDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/BlueskyReportStatusDialog.kt index 49c4244e2..045f42ac4 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/BlueskyReportStatusDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/BlueskyReportStatusDialog.kt @@ -23,12 +23,12 @@ import dev.dimension.flare.R import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.action.BlueskyReportStatusPresenter import dev.dimension.flare.ui.presenter.status.action.BlueskyReportStatusState +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/DeleteStatusConfirmDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/DeleteStatusConfirmDialog.kt index 6a468e824..24ed7a428 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/DeleteStatusConfirmDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/DeleteStatusConfirmDialog.kt @@ -17,11 +17,11 @@ import dev.dimension.flare.R import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.action.DeleteStatusPresenter import dev.dimension.flare.ui.presenter.status.action.DeleteStatusState +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MastodonReportDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MastodonReportDialog.kt index 8cfbfab98..7f86adfc3 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MastodonReportDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MastodonReportDialog.kt @@ -17,10 +17,10 @@ import dev.dimension.flare.R import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.action.MastodonReportPresenter +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReactionSheet.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReactionSheet.kt index 16c7a366a..654a6a9c1 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReactionSheet.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReactionSheet.kt @@ -22,12 +22,12 @@ import com.ramcosta.composedestinations.spec.DestinationStyle import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.NetworkImage import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.model.onSuccess import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.action.MisskeyReactionPresenter +import moe.tlaster.precompose.molecule.producePresenter @Destination( style = DestinationStyle.Dialog::class, diff --git a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReportDialog.kt b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReportDialog.kt index acb556ab5..a15831b7c 100644 --- a/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReportDialog.kt +++ b/app/src/main/java/dev/dimension/flare/ui/screen/status/action/MisskeyReportDialog.kt @@ -17,10 +17,10 @@ import dev.dimension.flare.R import dev.dimension.flare.common.AppDeepLink import dev.dimension.flare.model.AccountType import dev.dimension.flare.model.MicroBlogKey -import dev.dimension.flare.molecule.producePresenter import dev.dimension.flare.ui.component.ThemeWrapper import dev.dimension.flare.ui.presenter.invoke import dev.dimension.flare.ui.presenter.status.action.MisskeyReportPresenter +import moe.tlaster.precompose.molecule.producePresenter @Composable @Destination( diff --git a/build.gradle.kts b/build.gradle.kts index 1986b52ea..d42cfd79f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,12 +13,13 @@ plugins { alias(libs.plugins.ben.manes.versions) alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.room) apply false + alias(libs.plugins.composeMultiplatform) apply false } allprojects { tasks.withType { compilerOptions { - jvmTarget.set(JvmTarget.JVM_17) + jvmTarget.set(JvmTarget.JVM_21) allWarningsAsErrors.set(true) freeCompilerArgs.set(listOf( "-Xexpect-actual-classes", diff --git a/gradle.properties b/gradle.properties index ef37f1f59..3b87aed82 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,6 +12,7 @@ kotlin.mpp.stability.nowarn=true kotlin.mpp.enableCInteropCommonization=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.mpp.androidGradlePluginCompatibility.nowarn=true +org.jetbrains.compose.experimental.macos.enabled=true systemProp.javax.xml.parsers.SAXParserFactory=com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl systemProp.javax.xml.transform.TransformerFactory=com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 605143d6e..0c3cc4c56 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,8 @@ [versions] compileSdk = "35" -minSdk = "23" -java = "17" +lifecycleViewmodelCompose = "2.8.4" +minSdk = "24" +java = "21" agp = "8.7.2" kotlin = "2.0.21" core-ktx = "1.15.0" @@ -11,14 +12,14 @@ espresso-core = "3.6.1" lifecycle-runtime-ktx = "2.8.7" activity-compose = "1.9.3" compose-bom = "2024.10.01" -ksp = "2.0.21-1.0.25" +ksp = "2.0.21-1.0.27" paging = "3.3.2" navigation = "2.8.3" kotlinx-datetime = "0.6.1" kotlinx-collections-immutable = "0.3.8" kotlinx-serialization = "1.7.3" -coil = "2.7.0" -ktorfit = "2.1.0" +coil3 = "3.0.2" +ktorfit = "2.2.0" ktor = "3.0.1" reorderable = "2.4.0" stately = "2.1.0" @@ -37,7 +38,7 @@ versionUpdate = "0.51.0" bluesky = "0.1.1-SNAPSHOT" kotlinx-coroutines = "1.9.0" koin = "4.0.0" -composeIcons = "1.2.5" +composeIcons = "1.3.0" media3 = "1.4.1" desugar_jdk_libs = "2.1.3" firebase-bom = "33.5.1" @@ -46,6 +47,7 @@ firebase-crashlytics = "3.0.2" napier = "2.7.1" materialKolor = "2.0.0" room = "2.7.0-alpha11" +compose-multiplatform = "1.7.1" [libraries] bluesky = { module = "moe.tlaster.ozone:bluesky", version.ref = "bluesky" } @@ -58,6 +60,7 @@ lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtim lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle-runtime-ktx" } activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" } compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } +lifecycle-viewmodel-compose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleViewmodelCompose" } reorderable = { module = "sh.calvin.reorderable:reorderable", version.ref = "reorderable" } stately-iso-collections = { module = "co.touchlab:stately-iso-collections", version.ref = "stately" } stately-isolate = { module = "co.touchlab:stately-isolate", version.ref = "stately" } @@ -78,7 +81,7 @@ material3-adaptive-navigation = { group = "androidx.compose.material3.adaptive", paging-common = { group = "androidx.paging", name = "paging-common", version.ref = "paging" } paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "paging" } navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } -composeIcons-fontAwesome = { module = "com.github.Tlaster.compose-icons:font-awesome", version.ref = "composeIcons" } +composeIcons-fontAwesome = { module = "moe.tlaster.compose.icons:font-awesome", version.ref = "composeIcons" } datastore = { group = "androidx.datastore", name = "datastore", version = "1.1.1" } desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" } androidx-window = { group = "androidx.window", name = "window-core", version = "1.3.0" } @@ -107,19 +110,20 @@ koin-android = { group = "io.insert-koin", name = "koin-android" } koin-compose = { group = "io.insert-koin", name = "koin-compose" } koin-androidx-compose = { group = "io.insert-koin", name = "koin-androidx-compose" } -coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } -coil-gif = { group = "io.coil-kt", name = "coil-gif", version.ref = "coil" } -coil-svg = { group = "io.coil-kt", name = "coil-svg", version.ref = "coil" } +coil3-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version.ref = "coil3" } +coil3-gif = { group = "io.coil-kt.coil3", name = "coil-gif", version.ref = "coil3" } +coil3-svg = { group = "io.coil-kt.coil3", name = "coil-svg", version.ref = "coil3" } +coil3-ktor3 = { group = "io.coil-kt.coil3", name = "coil-network-ktor3", version.ref = "coil3" } apng = { group = "com.github.penfeizhou.android.animation", name = "apng", version.ref = "apng-android" } awebp = { group = "com.github.penfeizhou.android.animation", name = "awebp", version.ref = "apng-android" } vectordrawable-animated = { group = "androidx.vectordrawable", name = "vectordrawable-animated", version = "1.2.0" } -zoomable-image = { group = "me.saket.telephoto", name = "zoomable-image-coil", version = "0.13.0" } +zoomable-image = { group = "me.saket.telephoto", name = "zoomable-image-coil3", version = "0.14.0" } -ktorfit-lib = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-lib-ktor-3.0.0", version.ref = "ktorfit" } +ktorfit-lib = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-lib", version.ref = "ktorfit" } ktorfit-ksp = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-ksp", version.ref = "ktorfit" } -ktorfit-converters-response = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-response-ktor-3.0.0", version.ref = "ktorfit" } -ktorfit-converters-call = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-call-ktor-3.0.0", version.ref = "ktorfit" } -ktorfit-converters-flow = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-flow-ktor-3.0.0", version.ref = "ktorfit" } +ktorfit-converters-response = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-response", version.ref = "ktorfit" } +ktorfit-converters-call = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-call", version.ref = "ktorfit" } +ktorfit-converters-flow = { group = "de.jensklingenberg.ktorfit", name = "ktorfit-converters-flow", version.ref = "ktorfit" } ktor-client-content-negotiation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor" } ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor" } @@ -144,7 +148,7 @@ mfm-multiplatform = "moe.tlaster:mfm-multiplatform:0.1.2-SNAPSHOT" compose-webview = { group = "io.github.kevinnzou", name = "compose-webview", version = "0.33.6" } -compose-placeholder-material3 = { group = "com.eygraber", name = "compose-placeholder-material3", version = "1.0.8" } +compose-placeholder-material3 = { group = "io.github.fornewid", name = "placeholder-material3", version = "2.0.0" } okio = { group = "com.squareup.okio", name = "okio", version.ref = "okio" } @@ -163,13 +167,18 @@ materialKolor = { module = "com.materialkolor:material-kolor", version.ref = "ma colorpicker-compose = { module = "com.github.skydoves:colorpicker-compose", version = "1.1.2" } material-motion-compose = { module = "io.github.fornewid:material-motion-compose-core", version = "1.2.1" } +precompose-molecule = { module = "moe.tlaster:precompose-molecule", version = "1.7.0-alpha03" } + +compose-cupertino = { module = "io.github.alexzhirkevich:cupertino-core", version = "0.1.0-alpha04" } + [bundles] compose = ["ui", "ui-util", "ui-graphics", "ui-tooling", "ui-tooling-preview", "material3", "material3WindowSizeClass", "material3-adaptive-navigation-suite", "material3-adaptive", "material3-adaptive-navigation", "material3-adaptive-layout"] navigation = ["navigation-compose"] kotlinx = ["kotlinx-datetime", "kotlinx-immutable", "kotlinx-serialization-json", "kotlinx-coroutines-core"] koin = ["koin-core", "koin-android", "koin-compose", "koin-androidx-compose"] ktor = ["ktor-client-content-negotiation", "ktor-serialization-kotlinx-json", "ktor-client-logging"] -coil = ["coil-compose", "coil-gif", "apng", "coil-svg", "awebp", "vectordrawable-animated", "zoomable-image"] +coil3 = ["coil3-compose", "coil3-svg", "coil3-ktor3"] +coil3-extensions = ["apng", "awebp", "vectordrawable-animated", "zoomable-image", "coil3-gif"] accompanist = ["accompanist-permissions", "accompanist-drawablepainter"] compose-destinations = ["compose-destinations"] media3 = ["media3-exoplayer", "media3-ui", "media3-hls"] @@ -190,4 +199,5 @@ ben-manes-versions = { id = "com.github.ben-manes.versions", version.ref = "vers google-services = { id = "com.google.gms.google-services", version.ref = "google-services" } firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } -room = { id = "androidx.room", version.ref = "room" } \ No newline at end of file +room = { id = "androidx.room", version.ref = "room" } +composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" } \ No newline at end of file diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj index 643f7dda0..b293ea71e 100644 --- a/iosApp/iosApp.xcodeproj/project.pbxproj +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; }; 058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; }; + 06005F5A2CEC976F0060A785 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06005F592CEC97660060A785 /* ComposeView.swift */; }; 060501BC2ACA985B00DBCCEB /* StatusTimelineBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 060501BB2ACA985B00DBCCEB /* StatusTimelineBuilder.swift */; }; 060501BE2ACAC4ED00DBCCEB /* NotificationScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 060501BD2ACAC4ED00DBCCEB /* NotificationScreen.swift */; }; 060501C02ACAC8AF00DBCCEB /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 060501BF2ACAC8AF00DBCCEB /* SplashScreen.swift */; }; @@ -78,6 +79,7 @@ /* Begin PBXFileReference section */ 058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 06005F592CEC97660060A785 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = ""; }; 060501BB2ACA985B00DBCCEB /* StatusTimelineBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTimelineBuilder.swift; sourceTree = ""; }; 060501BD2ACAC4ED00DBCCEB /* NotificationScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationScreen.swift; sourceTree = ""; }; 060501BF2ACAC8AF00DBCCEB /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = ""; }; @@ -239,6 +241,7 @@ 066151222AC54A8200CCB945 /* Component */ = { isa = PBXGroup; children = ( + 06005F592CEC97660060A785 /* ComposeView.swift */, 069050772CAE6100007FC957 /* SwitUIInAppNotification.swift */, 06C862742B4D2A46008C902C /* Compact */, 060501C42ACBF40700DBCCEB /* User */, @@ -577,6 +580,7 @@ 062A3C892C6C9ECD00A45E44 /* VVOLoginScreen.swift in Sources */, 060881C12AE10D35001AAD2F /* ComposeViewModel.swift in Sources */, 0620DD9E2AC44237009BD1BE /* HomeTimelineScreen.swift in Sources */, + 06005F5A2CEC976F0060A785 /* ComposeView.swift in Sources */, 061C2CFC2B4E77D700249514 /* FullScreenImageViewer.swift in Sources */, 061C2CFE2B4E82C900249514 /* ImageViewWindow.swift in Sources */, 06F4B4C92C6369390005317F /* VGrid.swift in Sources */, @@ -779,7 +783,7 @@ PRODUCT_NAME = "${APP_NAME}"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = NO; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_VERSION = 5.0; @@ -826,7 +830,7 @@ PRODUCT_NAME = "${APP_NAME}"; PROVISIONING_PROFILE_SPECIFIER = ""; REGISTER_APP_GROUPS = NO; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_VERSION = 5.0; diff --git a/iosApp/iosApp.xcodeproj/xcuserdata/tlaster.xcuserdatad/xcschemes/xcschememanagement.plist b/iosApp/iosApp.xcodeproj/xcuserdata/tlaster.xcuserdatad/xcschemes/xcschememanagement.plist index 6f810bc26..889d6dd07 100644 --- a/iosApp/iosApp.xcodeproj/xcuserdata/tlaster.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/iosApp/iosApp.xcodeproj/xcuserdata/tlaster.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,32 +9,27 @@ isShown orderHint - 3 + 2 Promises (Playground) 2.xcscheme isShown orderHint - 4 + 3 Promises (Playground).xcscheme isShown orderHint - 2 + 1 iosApp.xcscheme orderHint 0 - iosApp.xcscheme_^#shared#^_ - - orderHint - 1 - diff --git a/iosApp/iosApp/UI/Component/ComposeView.swift b/iosApp/iosApp/UI/Component/ComposeView.swift new file mode 100644 index 000000000..f5f451403 --- /dev/null +++ b/iosApp/iosApp/UI/Component/ComposeView.swift @@ -0,0 +1,12 @@ +import shared +import SwiftUI + +struct ComposeView: UIViewControllerRepresentable { + let controller: UIViewController + func makeUIViewController(context: Context) -> UIViewController { + return controller + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) { + } +} diff --git a/iosApp/iosApp/UI/Screen/Home/StatusMediaScreen.swift b/iosApp/iosApp/UI/Screen/Home/StatusMediaScreen.swift index 676ed6c96..630e9ef27 100644 --- a/iosApp/iosApp/UI/Screen/Home/StatusMediaScreen.swift +++ b/iosApp/iosApp/UI/Screen/Home/StatusMediaScreen.swift @@ -6,14 +6,14 @@ struct StatusMediaScreen: View { @State private var selectedImage: Int private let initialIndex: Int32 private let dismiss: () -> Void - + init(accountType: AccountType, statusKey: MicroBlogKey, index: Int32, dismiss: @escaping () -> Void) { presenter = .init(accountType: accountType, statusKey: statusKey) self.initialIndex = index self.dismiss = dismiss selectedImage = .init(index + 1) } - + var body: some View { ObservePresenter(presenter: presenter) { state in ZStack { diff --git a/iosApp/iosApp/UI/Screen/Settings/AboutScreen.swift b/iosApp/iosApp/UI/Screen/Settings/AboutScreen.swift index 85b1b6bee..6c3dd912f 100644 --- a/iosApp/iosApp/UI/Screen/Settings/AboutScreen.swift +++ b/iosApp/iosApp/UI/Screen/Settings/AboutScreen.swift @@ -1,54 +1,19 @@ import SwiftUI +import shared struct AboutScreen: View { + @Environment(\.colorScheme) var colorScheme + @Environment(\.openURL) var openURL var body: some View { let versionName = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" let versionCode = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "" - ScrollView { - VStack { - Image(.logo) - .resizable() - .frame(width: 96, height: 96) - .clipShape(RoundedRectangle(cornerRadius: 16)) - .clipped() - .padding() - Text("Flare") - .font(.title) - Text("about_description") - .multilineTextAlignment(.center) - HStack { - Text(versionName) - Text("("+versionCode+")") - } - .opacity(0.5) - .font(.caption) - Link( - destination: URL(string: "https://github.com/DimensionDev/Flare")! - ) { - HStack { - AsyncImage( - url: URL(string: "https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png") - ) { image in - image.image?.resizable() - } - .frame(width: 48, height: 48) - VStack(alignment: .leading) { - Text("about_source_code") - Text("https://github.com/DimensionDev/Flare") - } - Spacer() - } - } - .buttonStyle(.plain) - } - .padding() - } + ComposeView( + controller: AboutViewController( + version: "\(versionName) (\(versionCode))", + onOpenLink: { openURL(.init(string: $0)!) }, + darkMode: colorScheme == .dark + ) + ) .navigationTitle("about_title") } } - -#Preview { - NavigationStack { - AboutScreen() - } -} diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 2087c7aa4..2bdcb5674 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -10,6 +10,7 @@ plugins { alias(libs.plugins.ktlint) alias(libs.plugins.compose.compiler) alias(libs.plugins.room) + alias(libs.plugins.composeMultiplatform) } kotlin { @@ -21,8 +22,8 @@ kotlin { iosX64(), iosArm64(), iosSimulatorArm64(), - macosArm64(), - macosX64(), +// macosArm64(), +// macosX64(), ).forEach { appleTarget -> appleTarget.binaries.framework { baseName = "shared" @@ -74,15 +75,35 @@ kotlin { implementation(kotlin("test")) } } + val composeMain by creating { + dependsOn(commonMain) + dependencies { + implementation(compose.ui) + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.components.resources) + implementation(libs.composeIcons.fontAwesome) + implementation(libs.bundles.coil3) + implementation(libs.compose.placeholder.material3) + implementation(libs.precompose.molecule) + } + } val androidMain by getting { + dependsOn(composeMain) dependencies { implementation(project.dependencies.platform(libs.compose.bom)) implementation(libs.compose.foundation) + implementation(libs.bundles.media3) + implementation(libs.core.ktx) } } val appleMain by getting { + dependsOn(composeMain) dependencies { implementation(libs.ktor.client.darwin) + implementation(libs.lifecycle.viewmodel.compose) + implementation(libs.compose.cupertino) } } val nativeMain by getting { @@ -133,6 +154,15 @@ skie { } } +compose.resources { + customDirectory( + sourceSetName = "commonMain", + directoryProvider = provider { layout.projectDirectory.dir("composeMain").dir("composeResources") } + ) + packageOfResClass = "dev.dimension.flare" + generateResClass = always +} + afterEvaluate { // val kspCommonMainKotlinMetadata by tasks val runKtlintFormatOverCommonMainSourceSet by tasks diff --git a/shared/src/androidMain/AndroidManifest.xml b/shared/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..bdb600945 --- /dev/null +++ b/shared/src/androidMain/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/dev/dimension/flare/common/PlayerPoll.kt b/shared/src/androidMain/kotlin/dev/dimension/flare/common/PlayerPoll.kt similarity index 100% rename from app/src/main/java/dev/dimension/flare/common/PlayerPoll.kt rename to shared/src/androidMain/kotlin/dev/dimension/flare/common/PlayerPoll.kt diff --git a/shared/src/commonMain/kotlin/dev/dimension/flare/ui/model/UiPoll.kt b/shared/src/commonMain/kotlin/dev/dimension/flare/ui/model/UiPoll.kt index 9b2114db2..80a756cf7 100644 --- a/shared/src/commonMain/kotlin/dev/dimension/flare/ui/model/UiPoll.kt +++ b/shared/src/commonMain/kotlin/dev/dimension/flare/ui/model/UiPoll.kt @@ -2,6 +2,7 @@ package dev.dimension.flare.ui.model import androidx.compose.runtime.Immutable import dev.dimension.flare.ui.humanizer.humanizePercentage +import dev.dimension.flare.ui.render.toUi import kotlinx.collections.immutable.ImmutableList import kotlinx.datetime.Clock import kotlinx.datetime.Instant @@ -10,14 +11,15 @@ import kotlinx.datetime.Instant data class UiPoll internal constructor( val id: String, val options: ImmutableList