feat(common-ui): image share (#22)

This commit is contained in:
Diego Beraldin 2023-09-17 13:13:25 +02:00 committed by GitHub
parent 0f36883dc7
commit 63d492c388
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 141 additions and 5 deletions

View File

@ -4,6 +4,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo.Comm
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.image.ZoomableImageViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.instanceinfo.InstanceInfoViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation.NavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel
@ -97,4 +98,9 @@ actual fun getCreatePostViewModel(communityId: Int): CreatePostViewModel {
parameters = { parametersOf(communityId) }
)
return res
}
actual fun getZoomableImageViewModel(): ZoomableImageViewModel {
val res: ZoomableImageViewModel by inject(ZoomableImageViewModel::class.java)
return res
}

View File

@ -9,6 +9,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.Crea
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.image.ZoomableImageMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.image.ZoomableImageViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.instanceinfo.InstanceInfoMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.instanceinfo.InstanceInfoViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation.DefaultNavigationCoordinator
@ -114,4 +116,10 @@ val commonUiModule = module {
postsRepository = get(),
)
}
factory {
ZoomableImageViewModel(
mvi = DefaultMviModel(ZoomableImageMviModel.UiState()),
shareHelper = get(),
)
}
}

View File

@ -4,6 +4,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo.Comm
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.image.ZoomableImageViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.instanceinfo.InstanceInfoViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation.NavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel
@ -52,4 +53,6 @@ expect fun getCreateCommentViewModel(
expect fun getCreatePostViewModel(
communityId: Int,
): CreatePostViewModel
): CreatePostViewModel
expect fun getZoomableImageViewModel(): ZoomableImageViewModel

View File

@ -0,0 +1,14 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.image
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
interface ZoomableImageMviModel :
MviModel<ZoomableImageMviModel.Intent, ZoomableImageMviModel.UiState, ZoomableImageMviModel.Effect> {
sealed interface Intent {
data class Share(val url: String) : Intent
}
data class UiState(val loading: Boolean = false)
sealed interface Effect
}

View File

@ -1,13 +1,14 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.image
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBar
@ -16,11 +17,13 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
import com.github.diegoberaldin.racconforlemmy.core.utils.onClick
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.ZoomableImage
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getZoomableImageViewModel
class ZoomableImageScreen(
private val url: String,
@ -29,19 +32,33 @@ class ZoomableImageScreen(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
override fun Content() {
val model = rememberScreenModel { getZoomableImageViewModel() }
model.bindToLifecycle(key)
val navigator = remember { getNavigationCoordinator().getRootNavigator() }
Scaffold(
topBar = {
TopAppBar(
title = {},
navigationIcon = {
Image(
Icon(
modifier = Modifier.onClick {
navigator?.pop()
},
imageVector = Icons.Default.ArrowBack,
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onSurface),
tint = MaterialTheme.colorScheme.onSurface,
)
},
actions = {
Icon(
modifier = Modifier.onClick {
model.reduce(ZoomableImageMviModel.Intent.Share(url))
},
imageVector = Icons.Default.Share,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurface,
)
}
)

View File

@ -0,0 +1,21 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.image
import cafe.adriel.voyager.core.model.ScreenModel
import com.github.diegoberaldin.racconforlemmy.core.utils.ShareHelper
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
class ZoomableImageViewModel(
private val mvi: DefaultMviModel<ZoomableImageMviModel.Intent, ZoomableImageMviModel.UiState, ZoomableImageMviModel.Effect>,
private val shareHelper: ShareHelper,
) : ScreenModel,
MviModel<ZoomableImageMviModel.Intent, ZoomableImageMviModel.UiState, ZoomableImageMviModel.Effect> by mvi {
override fun reduce(intent: ZoomableImageMviModel.Intent) {
when (intent) {
is ZoomableImageMviModel.Intent.Share -> {
shareHelper.shareImage(intent.url, "image/*")
}
}
}
}

View File

@ -4,6 +4,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo.Comm
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createpost.CreatePostViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.image.ZoomableImageViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.instanceinfo.InstanceInfoViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation.NavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel
@ -49,9 +50,13 @@ actual fun getCreateCommentViewModel(postId: Int, parentId: Int?): CreateComment
actual fun getCreatePostViewModel(communityId: Int): CreatePostViewModel =
CommonUiViewModelHelper.getCreatePostModel(communityId)
actual fun getZoomableImageViewModel(): ZoomableImageViewModel =
CommonUiViewModelHelper.zoomableImageModel
object CommonUiViewModelHelper : KoinComponent {
val navigationCoordinator: NavigationCoordinator by inject()
val zoomableImageModel: ZoomableImageViewModel by inject()
fun getPostDetailModel(post: PostModel): PostDetailViewModel {
val model: PostDetailViewModel by inject(

View File

@ -0,0 +1,30 @@
package com.github.diegoberaldin.racconforlemmy.core.utils
import android.content.Context
import android.content.Intent
import org.koin.dsl.module
class DefaultShareHelper(
private val context: Context,
) : ShareHelper {
override fun shareImage(url: String, mimeType: String) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, url)
type = mimeType
}
val shareIntent = Intent.createChooser(sendIntent, null).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
}
context.startActivity(shareIntent)
}
}
actual val shareHelperModule = module {
single<ShareHelper> {
DefaultShareHelper(
context = get(),
)
}
}

View File

@ -0,0 +1,9 @@
package com.github.diegoberaldin.racconforlemmy.core.utils
import org.koin.core.module.Module
interface ShareHelper {
fun shareImage(url: String, mimeType: String)
}
expect val shareHelperModule: Module

View File

@ -0,0 +1,19 @@
package com.github.diegoberaldin.racconforlemmy.core.utils
import org.koin.dsl.module
import platform.UIKit.UIActivityViewController
import platform.UIKit.UIApplication
class DefaultShareHelper() : ShareHelper {
override fun shareImage(url: String, mimeType: String) {
val shareActivity = UIActivityViewController(listOf(url), null)
val rvc = UIApplication.sharedApplication().keyWindow?.rootViewController
rvc?.presentViewController(shareActivity, true, null)
}
}
actual val shareHelperModule = module {
single<ShareHelper> {
DefaultShareHelper()
}
}

View File

@ -1,6 +1,7 @@
package com.github.diegoberaldin.raccoonforlemmy.di
import com.github.diegoberaldin.racconforlemmy.core.utils.hapticFeedbackModule
import com.github.diegoberaldin.racconforlemmy.core.utils.shareHelperModule
import com.github.diegoberaldin.raccoonforlemmy.core.api.di.coreApiModule
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.coreAppearanceModule
import com.github.diegoberaldin.raccoonforlemmy.core.crashreport.di.crashReportModule
@ -26,6 +27,7 @@ val sharedHelperModule = module {
crashReportModule,
hapticFeedbackModule,
localizationModule,
shareHelperModule,
homeTabModule,
inboxTabModule,
profileTabModule,

View File

@ -2,6 +2,7 @@ package com.github.diegoberaldin.raccoonforlemmy.di
import com.github.diegoberaldin.racconforlemmy.core.utils.AppInfo
import com.github.diegoberaldin.racconforlemmy.core.utils.hapticFeedbackModule
import com.github.diegoberaldin.racconforlemmy.core.utils.shareHelperModule
import com.github.diegoberaldin.raccoonforlemmy.core.api.di.coreApiModule
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.coreAppearanceModule
import com.github.diegoberaldin.raccoonforlemmy.core.crashreport.di.crashReportModule
@ -29,6 +30,7 @@ fun initKoin() {
crashReportModule,
hapticFeedbackModule,
localizationModule,
shareHelperModule,
homeTabModule,
inboxTabModule,
profileTabModule,