mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-08 19:38:39 +01:00
refactor: migrate image loading to Coil3 (#82)
* update dependency declarations * update build scripts * add getTempDir to FileSystemManager * define ImageLoaderProvider * refactor ImagePreloadManager * refactor CustomImage * update DI and utilities * update usages in UI components * update imports for ImagePreloadManager * cleanup main application class * add new image transformer for markdown rendering
This commit is contained in:
parent
2996c3ea96
commit
325a0dbd03
@ -1,20 +1,16 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.android
|
package com.livefast.eattrash.raccoonforlemmy.android
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import coil.ImageLoader
|
|
||||||
import coil.ImageLoaderFactory
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.debug.CrashReportConfiguration
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.debug.CrashReportConfiguration
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.debug.CrashReportWriter
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.debug.CrashReportWriter
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.getCoilImageLoader
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.di.sharedHelperModule
|
import com.livefast.eattrash.raccoonforlemmy.di.sharedHelperModule
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
import org.koin.android.ext.koin.androidLogger
|
import org.koin.android.ext.koin.androidLogger
|
||||||
import org.koin.core.context.startKoin
|
import org.koin.core.context.startKoin
|
||||||
|
|
||||||
class MainApplication :
|
class MainApplication : Application() {
|
||||||
Application(),
|
|
||||||
ImageLoaderFactory {
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
@ -40,6 +36,4 @@ class MainApplication :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun newImageLoader(): ImageLoader = getCoilImageLoader(this)
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ kotlin {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.coil.compose)
|
|
||||||
implementation(libs.exoplayer)
|
implementation(libs.exoplayer)
|
||||||
implementation(libs.exoplayer.dash)
|
implementation(libs.exoplayer.dash)
|
||||||
implementation(libs.exoplayer.ui)
|
implementation(libs.exoplayer.ui)
|
||||||
@ -44,9 +43,11 @@ kotlin {
|
|||||||
implementation(compose.material3)
|
implementation(compose.material3)
|
||||||
implementation(compose.materialIconsExtended)
|
implementation(compose.materialIconsExtended)
|
||||||
|
|
||||||
implementation(projects.core.utils)
|
implementation(libs.coil.compose)
|
||||||
|
|
||||||
implementation(projects.core.appearance)
|
implementation(projects.core.appearance)
|
||||||
implementation(projects.core.l10n)
|
implementation(projects.core.l10n)
|
||||||
|
implementation(projects.core.utils)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val commonTest by getting {
|
val commonTest by getting {
|
||||||
@ -54,18 +55,19 @@ kotlin {
|
|||||||
implementation(kotlin("test"))
|
implementation(kotlin("test"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val iosMain by getting {
|
|
||||||
dependencies {
|
|
||||||
implementation(libs.kamel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.livefast.eattrash.raccoonforlemmy.core.commonui.components"
|
namespace = "com.livefast.eattrash.raccoonforlemmy.core.commonui.components"
|
||||||
compileSdk = libs.versions.android.targetSdk.get().toInt()
|
compileSdk =
|
||||||
|
libs.versions.android.targetSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = libs.versions.android.minSdk.get().toInt()
|
minSdk =
|
||||||
|
libs.versions.android.minSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.commonui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.blur
|
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.graphics.FilterQuality
|
|
||||||
import androidx.compose.ui.layout.ContentScale
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import coil.compose.AsyncImage
|
|
||||||
import coil.compose.AsyncImagePainter
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.l10n.messages.LocalStrings
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
actual fun CustomImage(
|
|
||||||
modifier: Modifier,
|
|
||||||
url: String,
|
|
||||||
autoload: Boolean,
|
|
||||||
blurred: Boolean,
|
|
||||||
loadButtonContent: @Composable (() -> Unit)?,
|
|
||||||
contentDescription: String?,
|
|
||||||
quality: FilterQuality,
|
|
||||||
contentScale: ContentScale,
|
|
||||||
alignment: Alignment,
|
|
||||||
contentAlignment: Alignment,
|
|
||||||
alpha: Float,
|
|
||||||
colorFilter: ColorFilter?,
|
|
||||||
onLoading: @Composable (BoxScope.(Float?) -> Unit)?,
|
|
||||||
onFailure: @Composable (BoxScope.(Throwable) -> Unit)?,
|
|
||||||
) {
|
|
||||||
var shouldBeRendered by remember(autoload) { mutableStateOf(autoload) }
|
|
||||||
var painterState: AsyncImagePainter.State by remember {
|
|
||||||
mutableStateOf(AsyncImagePainter.State.Empty)
|
|
||||||
}
|
|
||||||
Box(
|
|
||||||
modifier = modifier,
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
) {
|
|
||||||
if (shouldBeRendered) {
|
|
||||||
AsyncImage(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.blur(radius = if (blurred) 60.dp else 0.dp),
|
|
||||||
model = url,
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
filterQuality = quality,
|
|
||||||
contentScale = contentScale,
|
|
||||||
alignment = alignment,
|
|
||||||
alpha = alpha,
|
|
||||||
colorFilter = colorFilter,
|
|
||||||
onLoading = {
|
|
||||||
painterState = it
|
|
||||||
},
|
|
||||||
onError = {
|
|
||||||
painterState = it
|
|
||||||
},
|
|
||||||
onSuccess = {
|
|
||||||
painterState = it
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
when (val state = painterState) {
|
|
||||||
AsyncImagePainter.State.Empty -> Unit
|
|
||||||
is AsyncImagePainter.State.Error -> {
|
|
||||||
onFailure?.invoke(this, state.result.throwable)
|
|
||||||
}
|
|
||||||
|
|
||||||
is AsyncImagePainter.State.Loading -> {
|
|
||||||
onLoading?.invoke(this, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> Unit
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
shouldBeRendered = true
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
if (loadButtonContent != null) {
|
|
||||||
loadButtonContent.invoke()
|
|
||||||
} else {
|
|
||||||
Text(
|
|
||||||
text = LocalStrings.current.buttonLoad,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,35 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.commonui.components
|
package com.livefast.eattrash.raccoonforlemmy.core.commonui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
import androidx.compose.foundation.layout.BoxScope
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.blur
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.graphics.DefaultAlpha
|
import androidx.compose.ui.graphics.DefaultAlpha
|
||||||
import androidx.compose.ui.graphics.FilterQuality
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import coil3.compose.AsyncImage
|
||||||
|
import coil3.compose.AsyncImagePainter
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.l10n.messages.LocalStrings
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.getImageLoaderProvider
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
expect fun CustomImage(
|
fun CustomImage(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
url: String,
|
url: String,
|
||||||
autoload: Boolean = true,
|
|
||||||
blurred: Boolean = false,
|
blurred: Boolean = false,
|
||||||
|
autoload: Boolean,
|
||||||
loadButtonContent: @Composable (() -> Unit)? = null,
|
loadButtonContent: @Composable (() -> Unit)? = null,
|
||||||
contentDescription: String? = null,
|
contentDescription: String? = null,
|
||||||
quality: FilterQuality = FilterQuality.Medium,
|
quality: FilterQuality = FilterQuality.Medium,
|
||||||
@ -25,4 +40,74 @@ expect fun CustomImage(
|
|||||||
colorFilter: ColorFilter? = null,
|
colorFilter: ColorFilter? = null,
|
||||||
onLoading: @Composable (BoxScope.(Float?) -> Unit)? = null,
|
onLoading: @Composable (BoxScope.(Float?) -> Unit)? = null,
|
||||||
onFailure: @Composable (BoxScope.(Throwable) -> Unit)? = null,
|
onFailure: @Composable (BoxScope.(Throwable) -> Unit)? = null,
|
||||||
)
|
onSuccess: @Composable (BoxScope.() -> Unit)? = null,
|
||||||
|
) {
|
||||||
|
val imageLoaderProvider = remember { getImageLoaderProvider() }
|
||||||
|
var painterState: AsyncImagePainter.State by remember {
|
||||||
|
mutableStateOf(AsyncImagePainter.State.Empty)
|
||||||
|
}
|
||||||
|
var shouldBeRendered by remember(autoload) { mutableStateOf(autoload) }
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = modifier,
|
||||||
|
contentAlignment = contentAlignment,
|
||||||
|
) {
|
||||||
|
if (shouldBeRendered) {
|
||||||
|
AsyncImage(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.blur(radius = if (blurred) 60.dp else 0.dp),
|
||||||
|
model = url,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
filterQuality = quality,
|
||||||
|
contentScale = contentScale,
|
||||||
|
alignment = alignment,
|
||||||
|
alpha = alpha,
|
||||||
|
colorFilter = colorFilter,
|
||||||
|
onState = {
|
||||||
|
painterState = it
|
||||||
|
},
|
||||||
|
imageLoader = imageLoaderProvider.provideImageLoader(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
shouldBeRendered = true
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
if (loadButtonContent != null) {
|
||||||
|
loadButtonContent.invoke()
|
||||||
|
} else {
|
||||||
|
Text(
|
||||||
|
text = LocalStrings.current.buttonLoad,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (val state = painterState) {
|
||||||
|
AsyncImagePainter.State.Empty -> Unit
|
||||||
|
is AsyncImagePainter.State.Error -> {
|
||||||
|
onFailure?.invoke(this, state.result.throwable)
|
||||||
|
}
|
||||||
|
|
||||||
|
is AsyncImagePainter.State.Loading -> {
|
||||||
|
onLoading?.invoke(this, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
is AsyncImagePainter.State.Success -> {
|
||||||
|
onSuccess?.invoke(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,86 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.commonui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.blur
|
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
|
||||||
import androidx.compose.ui.graphics.FilterQuality
|
|
||||||
import androidx.compose.ui.layout.ContentScale
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.l10n.messages.LocalStrings
|
|
||||||
import io.kamel.image.KamelImage
|
|
||||||
import io.kamel.image.asyncPainterResource
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
actual fun CustomImage(
|
|
||||||
modifier: Modifier,
|
|
||||||
url: String,
|
|
||||||
autoload: Boolean,
|
|
||||||
blurred: Boolean,
|
|
||||||
loadButtonContent: @Composable (() -> Unit)?,
|
|
||||||
contentDescription: String?,
|
|
||||||
quality: FilterQuality,
|
|
||||||
contentScale: ContentScale,
|
|
||||||
alignment: Alignment,
|
|
||||||
contentAlignment: Alignment,
|
|
||||||
alpha: Float,
|
|
||||||
colorFilter: ColorFilter?,
|
|
||||||
onLoading: @Composable (BoxScope.(Float?) -> Unit)?,
|
|
||||||
onFailure: @Composable (BoxScope.(Throwable) -> Unit)?,
|
|
||||||
) {
|
|
||||||
var shouldBeRendered by remember(autoload) { mutableStateOf(autoload) }
|
|
||||||
Box(
|
|
||||||
modifier = modifier,
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
) {
|
|
||||||
if (shouldBeRendered) {
|
|
||||||
val painterResource =
|
|
||||||
asyncPainterResource(
|
|
||||||
data = url,
|
|
||||||
filterQuality = quality,
|
|
||||||
)
|
|
||||||
KamelImage(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.blur(radius = if (blurred) 60.dp else 0.dp),
|
|
||||||
resource = painterResource,
|
|
||||||
contentDescription = contentDescription,
|
|
||||||
contentScale = contentScale,
|
|
||||||
alignment = alignment,
|
|
||||||
contentAlignment = contentAlignment,
|
|
||||||
alpha = alpha,
|
|
||||||
colorFilter = colorFilter,
|
|
||||||
onLoading = onLoading,
|
|
||||||
onFailure = onFailure,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Button(
|
|
||||||
onClick = {
|
|
||||||
shouldBeRendered = true
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
if (loadButtonContent != null) {
|
|
||||||
loadButtonContent()
|
|
||||||
} else {
|
|
||||||
Text(
|
|
||||||
text = LocalStrings.current.buttonLoad,
|
|
||||||
maxLines = 1,
|
|
||||||
overflow = TextOverflow.Ellipsis,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -101,6 +101,7 @@ fun CommunityAndCreatorInfo(
|
|||||||
onDoubleClick = onDoubleClick ?: {},
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
),
|
),
|
||||||
url = communityIcon,
|
url = communityIcon,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
@ -133,6 +134,7 @@ fun CommunityAndCreatorInfo(
|
|||||||
),
|
),
|
||||||
url = creatorAvatar,
|
url = creatorAvatar,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
|
autoload = autoLoadImages,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,6 +64,7 @@ fun CommunityHeader(
|
|||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
url = banner,
|
url = banner,
|
||||||
|
autoload = autoLoadImages,
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
)
|
)
|
||||||
@ -107,6 +108,7 @@ fun CommunityHeader(
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
url = communityIcon,
|
url = communityIcon,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
@ -181,7 +183,7 @@ fun CommunityHeader(
|
|||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.padding(end = Spacing.s).size(iconSize),
|
modifier = Modifier.padding(end = Spacing.s).size(iconSize),
|
||||||
onClick = {
|
onClick = {
|
||||||
onInfo?.invoke()
|
onInfo.invoke()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
|
@ -41,7 +41,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomDrop
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomImage
|
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomImage
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.buildAnnotatedStringWithHighlights
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.buildAnnotatedStringWithHighlights
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.onClick
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.toLocalDp
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.readableHandle
|
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||||
@ -93,6 +92,7 @@ fun CommunityItem(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = communityIcon,
|
url = communityIcon,
|
||||||
|
autoload = autoLoadImages,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,6 +128,7 @@ fun InboxReplySubtitle(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = creatorAvatar,
|
url = creatorAvatar,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
@ -166,6 +167,7 @@ fun InboxReplySubtitle(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = communityIcon,
|
url = communityIcon,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
|
@ -34,7 +34,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomDrop
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomImage
|
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomImage
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.onClick
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.toLocalDp
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.toLocalDp
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -67,6 +66,7 @@ fun MultiCommunityItem(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = communityIcon,
|
url = communityIcon,
|
||||||
|
autoload = autoLoadImages,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -60,6 +60,7 @@ fun SettingsImageInfo(
|
|||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = imageModifier,
|
modifier = imageModifier,
|
||||||
url = url,
|
url = url,
|
||||||
|
autoload = true,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = contentScale,
|
contentScale = contentScale,
|
||||||
)
|
)
|
||||||
|
@ -67,6 +67,7 @@ fun UserHeader(
|
|||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
url = banner,
|
url = banner,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
)
|
)
|
||||||
@ -107,6 +108,7 @@ fun UserHeader(
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
url = userAvatar,
|
url = userAvatar,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
@ -209,7 +211,7 @@ fun UserHeader(
|
|||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.padding(end = Spacing.s).size(iconSize),
|
modifier = Modifier.padding(end = Spacing.s).size(iconSize),
|
||||||
onClick = {
|
onClick = {
|
||||||
onInfo?.invoke()
|
onInfo.invoke()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
|
@ -38,7 +38,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomDrop
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomImage
|
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.CustomImage
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
import com.livefast.eattrash.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.buildAnnotatedStringWithHighlights
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.buildAnnotatedStringWithHighlights
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.compose.onClick
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.toLocalDp
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.readableHandle
|
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.readableHandle
|
||||||
@ -81,6 +80,7 @@ fun UserItem(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = avatar,
|
url = avatar,
|
||||||
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
|
@ -30,7 +30,7 @@ kotlin {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.multiplatform.markdown.renderer.coil2)
|
implementation(libs.multiplatform.markdown.renderer.coil3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
@ -41,6 +41,7 @@ kotlin {
|
|||||||
|
|
||||||
api(libs.multiplatform.markdown.renderer)
|
api(libs.multiplatform.markdown.renderer)
|
||||||
api(libs.multiplatform.markdown.renderer.m3)
|
api(libs.multiplatform.markdown.renderer.m3)
|
||||||
|
api(libs.multiplatform.markdown.renderer.coil3)
|
||||||
|
|
||||||
implementation(projects.core.l10n)
|
implementation(projects.core.l10n)
|
||||||
implementation(projects.core.commonui.components)
|
implementation(projects.core.commonui.components)
|
||||||
@ -57,8 +58,14 @@ kotlin {
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.livefast.eattrash.raccoonforlemmy.core.markdown"
|
namespace = "com.livefast.eattrash.raccoonforlemmy.core.markdown"
|
||||||
compileSdk = libs.versions.android.targetSdk.get().toInt()
|
compileSdk =
|
||||||
|
libs.versions.android.targetSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = libs.versions.android.minSdk.get().toInt()
|
minSdk =
|
||||||
|
libs.versions.android.minSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.markdown
|
|
||||||
|
|
||||||
import com.mikepenz.markdown.coil2.Coil2ImageTransformerImpl
|
|
||||||
import com.mikepenz.markdown.model.ImageTransformer
|
|
||||||
|
|
||||||
actual fun provideImageTransformer(): ImageTransformer = Coil2ImageTransformerImpl
|
|
@ -1,5 +1,6 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.markdown
|
package com.livefast.eattrash.raccoonforlemmy.core.markdown
|
||||||
|
|
||||||
|
import com.mikepenz.markdown.coil3.Coil3ImageTransformerImpl
|
||||||
import com.mikepenz.markdown.model.ImageTransformer
|
import com.mikepenz.markdown.model.ImageTransformer
|
||||||
|
|
||||||
expect fun provideImageTransformer(): ImageTransformer
|
internal fun provideImageTransformer(): ImageTransformer = Coil3ImageTransformerImpl
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.markdown
|
|
||||||
|
|
||||||
import com.mikepenz.markdown.model.ImageTransformer
|
|
||||||
import com.mikepenz.markdown.model.NoOpImageTransformerImpl
|
|
||||||
|
|
||||||
actual fun provideImageTransformer(): ImageTransformer = NoOpImageTransformerImpl()
|
|
@ -36,6 +36,8 @@ kotlin {
|
|||||||
|
|
||||||
implementation(libs.koin.core)
|
implementation(libs.koin.core)
|
||||||
implementation(libs.ktor.cio)
|
implementation(libs.ktor.cio)
|
||||||
|
implementation(libs.coil)
|
||||||
|
implementation(libs.coil.network.ktor)
|
||||||
implementation(project.dependencies.platform(libs.kotlincrypto.bom))
|
implementation(project.dependencies.platform(libs.kotlincrypto.bom))
|
||||||
implementation(libs.kotlincrypto.md5)
|
implementation(libs.kotlincrypto.md5)
|
||||||
|
|
||||||
@ -48,7 +50,6 @@ kotlin {
|
|||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.browser)
|
implementation(libs.androidx.browser)
|
||||||
implementation(libs.ktor.android)
|
implementation(libs.ktor.android)
|
||||||
implementation(libs.coil)
|
|
||||||
implementation(libs.coil.gif)
|
implementation(libs.coil.gif)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,8 +72,14 @@ kotlin {
|
|||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.livefast.eattrash.raccoonforlemmy.core.utils"
|
namespace = "com.livefast.eattrash.raccoonforlemmy.core.utils"
|
||||||
compileSdk = libs.versions.android.targetSdk.get().toInt()
|
compileSdk =
|
||||||
|
libs.versions.android.targetSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = libs.versions.android.minSdk.get().toInt()
|
minSdk =
|
||||||
|
libs.versions.android.minSdk
|
||||||
|
.get()
|
||||||
|
.toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.DefaultFileSystemMana
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.FileSystemManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.FileSystemManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.DefaultGalleryHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.DefaultGalleryHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.GalleryHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.GalleryHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.DefaultImagePreloadManager
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.DefaultNetworkManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.DefaultNetworkManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.NetworkManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.NetworkManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.DefaultShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.DefaultShareHelper
|
||||||
@ -24,15 +22,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.DefaultHapticFee
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
actual val imagePreloadModule =
|
|
||||||
module {
|
|
||||||
single<ImagePreloadManager> {
|
|
||||||
DefaultImagePreloadManager(
|
|
||||||
context = get(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actual val networkModule =
|
actual val networkModule =
|
||||||
module {
|
module {
|
||||||
single<NetworkManager> {
|
single<NetworkManager> {
|
||||||
|
@ -5,6 +5,8 @@ import androidx.activity.compose.rememberLauncherForActivityResult
|
|||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import okio.FileSystem
|
||||||
|
import okio.Path
|
||||||
import org.koin.java.KoinJavaComponent
|
import org.koin.java.KoinJavaComponent
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import java.io.OutputStreamWriter
|
import java.io.OutputStreamWriter
|
||||||
@ -55,6 +57,8 @@ class DefaultFileSystemManager(
|
|||||||
launcher.launch(name)
|
launcher.launch(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getTempDir(): Path = FileSystem.SYSTEM_TEMPORARY_DIRECTORY
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun getFileSystemManager(): FileSystemManager {
|
actual fun getFileSystemManager(): FileSystemManager {
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
|
import coil3.decode.Decoder
|
||||||
|
import coil3.gif.AnimatedImageDecoder
|
||||||
|
import coil3.gif.GifDecoder
|
||||||
|
import org.koin.java.KoinJavaComponent
|
||||||
|
|
||||||
|
actual fun ByteArray.toComposeImageBitmap(): ImageBitmap = BitmapFactory.decodeByteArray(this, 0, size).asImageBitmap()
|
||||||
|
|
||||||
|
actual fun IntArray.toComposeImageBitmap(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
): ImageBitmap = Bitmap.createBitmap(this, width, height, Bitmap.Config.ARGB_8888).asImageBitmap()
|
||||||
|
|
||||||
|
actual fun getNativeDecoders(): List<Decoder.Factory> =
|
||||||
|
buildList {
|
||||||
|
if (Build.VERSION.SDK_INT >= 28) {
|
||||||
|
AnimatedImageDecoder.Factory()
|
||||||
|
} else {
|
||||||
|
GifDecoder.Factory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun getImageLoaderProvider(): ImageLoaderProvider {
|
||||||
|
val inject = KoinJavaComponent.inject<ImageLoaderProvider>(ImageLoaderProvider::class.java)
|
||||||
|
val res by inject
|
||||||
|
return res
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import coil.annotation.ExperimentalCoilApi
|
|
||||||
import coil.imageLoader
|
|
||||||
import coil.memory.MemoryCache
|
|
||||||
import coil.request.ImageRequest
|
|
||||||
|
|
||||||
class DefaultImagePreloadManager(
|
|
||||||
private val context: Context,
|
|
||||||
) : ImagePreloadManager {
|
|
||||||
override fun preload(url: String) {
|
|
||||||
val request =
|
|
||||||
ImageRequest.Builder(context)
|
|
||||||
.data(url)
|
|
||||||
.build()
|
|
||||||
context.imageLoader.enqueue(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoilApi::class)
|
|
||||||
override fun remove(url: String) {
|
|
||||||
context.imageLoader.memoryCache?.remove(MemoryCache.Key(url))
|
|
||||||
context.imageLoader.diskCache?.remove(url)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Build
|
|
||||||
import coil.ImageLoader
|
|
||||||
import coil.decode.GifDecoder
|
|
||||||
import coil.decode.ImageDecoderDecoder
|
|
||||||
import coil.disk.DiskCache
|
|
||||||
import coil.memory.MemoryCache
|
|
||||||
|
|
||||||
fun getCoilImageLoader(context: Context): ImageLoader =
|
|
||||||
ImageLoader.Builder(context)
|
|
||||||
.components {
|
|
||||||
if (Build.VERSION.SDK_INT >= 28) {
|
|
||||||
add(ImageDecoderDecoder.Factory())
|
|
||||||
} else {
|
|
||||||
add(GifDecoder.Factory())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.memoryCache {
|
|
||||||
MemoryCache.Builder(context)
|
|
||||||
.maxSizePercent(0.25)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
.diskCache {
|
|
||||||
DiskCache.Builder()
|
|
||||||
.directory(context.cacheDir.resolve("image_cache"))
|
|
||||||
.maxSizePercent(0.02)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
.crossfade(true)
|
|
||||||
.build()
|
|
@ -2,8 +2,6 @@ package com.livefast.eattrash.raccoonforlemmy.core.utils.di
|
|||||||
|
|
||||||
import org.koin.core.module.Module
|
import org.koin.core.module.Module
|
||||||
|
|
||||||
expect val imagePreloadModule: Module
|
|
||||||
|
|
||||||
expect val networkModule: Module
|
expect val networkModule: Module
|
||||||
|
|
||||||
expect val appIconModule: Module
|
expect val appIconModule: Module
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.di
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.di
|
||||||
|
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.DefaultImageLoaderProvider
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.DefaultImagePreloadManager
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImageLoaderProvider
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.DefaultZombieModeHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.DefaultZombieModeHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.ZombieModeHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.ZombieModeHelper
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
@ -9,4 +13,17 @@ val utilsModule =
|
|||||||
factory<ZombieModeHelper> {
|
factory<ZombieModeHelper> {
|
||||||
DefaultZombieModeHelper()
|
DefaultZombieModeHelper()
|
||||||
}
|
}
|
||||||
|
single<ImageLoaderProvider> {
|
||||||
|
DefaultImageLoaderProvider(
|
||||||
|
context = get(),
|
||||||
|
fileSystemManager = get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
single<ImagePreloadManager> {
|
||||||
|
DefaultImagePreloadManager(
|
||||||
|
context = get(),
|
||||||
|
imageLoaderProvider = get(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.fs
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.fs
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import okio.Path
|
||||||
|
|
||||||
interface FileSystemManager {
|
interface FileSystemManager {
|
||||||
val isSupported: Boolean
|
val isSupported: Boolean
|
||||||
@ -18,6 +19,8 @@ interface FileSystemManager {
|
|||||||
data: String,
|
data: String,
|
||||||
callback: (Boolean) -> Unit,
|
callback: (Boolean) -> Unit,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun getTempDir(): Path
|
||||||
}
|
}
|
||||||
|
|
||||||
expect fun getFileSystemManager(): FileSystemManager
|
expect fun getFileSystemManager(): FileSystemManager
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
|
import coil3.ImageLoader
|
||||||
|
import coil3.PlatformContext
|
||||||
|
import coil3.disk.DiskCache
|
||||||
|
import coil3.memory.MemoryCache
|
||||||
|
import coil3.request.crossfade
|
||||||
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.FileSystemManager
|
||||||
|
|
||||||
|
internal class DefaultImageLoaderProvider(
|
||||||
|
private val context: PlatformContext,
|
||||||
|
private val fileSystemManager: FileSystemManager,
|
||||||
|
) : ImageLoaderProvider {
|
||||||
|
private val imageLoader by lazy {
|
||||||
|
ImageLoader
|
||||||
|
.Builder(context)
|
||||||
|
.components {
|
||||||
|
val decoders = getNativeDecoders()
|
||||||
|
for (decoder in decoders) {
|
||||||
|
add(decoder)
|
||||||
|
}
|
||||||
|
}.memoryCache {
|
||||||
|
MemoryCache
|
||||||
|
.Builder()
|
||||||
|
.maxSizePercent(context, 0.25)
|
||||||
|
.build()
|
||||||
|
}.diskCache {
|
||||||
|
val path = fileSystemManager.getTempDir()
|
||||||
|
DiskCache
|
||||||
|
.Builder()
|
||||||
|
.directory(path)
|
||||||
|
.maxSizePercent(0.02)
|
||||||
|
.build()
|
||||||
|
}.crossfade(true)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun provideImageLoader(): ImageLoader = imageLoader
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
|
import coil3.PlatformContext
|
||||||
|
import coil3.memory.MemoryCache
|
||||||
|
import coil3.request.ImageRequest
|
||||||
|
|
||||||
|
internal class DefaultImagePreloadManager(
|
||||||
|
private val context: PlatformContext,
|
||||||
|
private val imageLoaderProvider: ImageLoaderProvider,
|
||||||
|
) : ImagePreloadManager {
|
||||||
|
override fun preload(url: String) {
|
||||||
|
val imageLoader = imageLoaderProvider.provideImageLoader()
|
||||||
|
val request =
|
||||||
|
ImageRequest
|
||||||
|
.Builder(context)
|
||||||
|
.data(url)
|
||||||
|
.build()
|
||||||
|
imageLoader.enqueue(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(url: String) {
|
||||||
|
val imageLoader = imageLoaderProvider.provideImageLoader()
|
||||||
|
imageLoader.memoryCache?.remove(MemoryCache.Key(url))
|
||||||
|
imageLoader.diskCache?.remove(url)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
|
import coil3.ImageLoader
|
||||||
|
|
||||||
|
interface ImageLoaderProvider {
|
||||||
|
fun provideImageLoader(): ImageLoader
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
interface ImagePreloadManager {
|
interface ImagePreloadManager {
|
||||||
fun preload(url: String)
|
fun preload(url: String)
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import coil3.decode.Decoder
|
||||||
|
|
||||||
|
expect fun ByteArray.toComposeImageBitmap(): ImageBitmap
|
||||||
|
|
||||||
|
expect fun IntArray.toComposeImageBitmap(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
): ImageBitmap
|
||||||
|
|
||||||
|
expect fun getNativeDecoders(): List<Decoder.Factory>
|
||||||
|
|
||||||
|
expect fun getImageLoaderProvider(): ImageLoaderProvider
|
@ -12,8 +12,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.DefaultFileSystemMana
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.FileSystemManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.fs.FileSystemManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.DefaultGalleryHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.DefaultGalleryHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.GalleryHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.GalleryHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.DefaultImagePreloadManager
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.DefaultNetworkManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.DefaultNetworkManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.NetworkManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.network.NetworkManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.DefaultShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.DefaultShareHelper
|
||||||
@ -24,13 +22,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.DefaultHapticFee
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
actual val imagePreloadModule =
|
|
||||||
module {
|
|
||||||
single<ImagePreloadManager> {
|
|
||||||
DefaultImagePreloadManager()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actual val networkModule =
|
actual val networkModule =
|
||||||
module {
|
module {
|
||||||
single<NetworkManager> { DefaultNetworkManager() }
|
single<NetworkManager> { DefaultNetworkManager() }
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.fs
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.fs
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import okio.FileSystem
|
||||||
|
import okio.Path
|
||||||
import org.koin.core.component.KoinComponent
|
import org.koin.core.component.KoinComponent
|
||||||
import org.koin.core.component.inject
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
@ -24,6 +26,8 @@ class DefaultFileSystemManager : FileSystemManager {
|
|||||||
) {
|
) {
|
||||||
callback(false)
|
callback(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getTempDir(): Path = FileSystem.SYSTEM_TEMPORARY_DIRECTORY
|
||||||
}
|
}
|
||||||
|
|
||||||
object FileSystemManagerDiHelper : KoinComponent {
|
object FileSystemManagerDiHelper : KoinComponent {
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.livefast.eattrash.raccoonforlemmy.core.utils.imageload
|
||||||
|
|
||||||
|
import androidx.compose.ui.graphics.ImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.asComposeImageBitmap
|
||||||
|
import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||||
|
import coil3.decode.Decoder
|
||||||
|
import org.jetbrains.skia.Bitmap
|
||||||
|
import org.jetbrains.skia.ColorAlphaType
|
||||||
|
import org.jetbrains.skia.ColorType
|
||||||
|
import org.jetbrains.skia.Image
|
||||||
|
import org.jetbrains.skia.ImageInfo
|
||||||
|
import org.koin.core.component.KoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
|
actual fun ByteArray.toComposeImageBitmap(): ImageBitmap = Image.makeFromEncoded(this).toComposeImageBitmap()
|
||||||
|
|
||||||
|
actual fun IntArray.toComposeImageBitmap(
|
||||||
|
width: Int,
|
||||||
|
height: Int,
|
||||||
|
): ImageBitmap {
|
||||||
|
val bmp = Bitmap()
|
||||||
|
val info = ImageInfo(width, height, ColorType.RGBA_8888, ColorAlphaType.PREMUL)
|
||||||
|
bmp.installPixels(info, map { it.toByte() }.toByteArray(), info.minRowBytes)
|
||||||
|
return bmp.asComposeImageBitmap()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun getNativeDecoders(): List<Decoder.Factory> = emptyList()
|
||||||
|
|
||||||
|
actual fun getImageLoaderProvider(): ImageLoaderProvider = ImageUtilsDiHelper.imageLoaderProvider
|
||||||
|
|
||||||
|
internal object ImageUtilsDiHelper : KoinComponent {
|
||||||
|
val imageLoaderProvider: ImageLoaderProvider by inject()
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
package com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload
|
|
||||||
|
|
||||||
class DefaultImagePreloadManager() : ImagePreloadManager {
|
|
||||||
override fun preload(url: String) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun remove(url: String) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ androidx-media3 = "1.4.1"
|
|||||||
androidx-splashscreen = "1.0.1"
|
androidx-splashscreen = "1.0.1"
|
||||||
androidx-work = "2.9.1"
|
androidx-work = "2.9.1"
|
||||||
android-gradle = "8.5.2"
|
android-gradle = "8.5.2"
|
||||||
coil = "2.7.0"
|
coil = "3.0.0"
|
||||||
colorpicker = "1.1.2"
|
colorpicker = "1.1.2"
|
||||||
compose = "1.7.0"
|
compose = "1.7.0"
|
||||||
detekt = "1.23.7"
|
detekt = "1.23.7"
|
||||||
@ -47,16 +47,16 @@ androidx-security-crypto = { module = "androidx.security:security-crypto", versi
|
|||||||
androidx-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidx-splashscreen" }
|
androidx-splashscreen = { module = "androidx.core:core-splashscreen", version.ref = "androidx-splashscreen" }
|
||||||
androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "androidx-work" }
|
androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "androidx-work" }
|
||||||
|
|
||||||
kamel = { module = "media.kamel:kamel-image", version.ref = "kamel" }
|
coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" }
|
||||||
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
|
coil-network-ktor = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref = "coil" }
|
||||||
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
|
coil-compose = { module = "io.coil-kt.coil3:coil-compose-core", version.ref = "coil" }
|
||||||
coil-gif = { module = "io.coil-kt:coil-gif", version.ref = "coil" }
|
coil-gif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" }
|
||||||
|
|
||||||
compose-colorpicker = { module = "com.github.skydoves:colorpicker-compose", version.ref = "colorpicker" }
|
compose-colorpicker = { module = "com.github.skydoves:colorpicker-compose", version.ref = "colorpicker" }
|
||||||
|
|
||||||
multiplatform-markdown-renderer = { module = "com.mikepenz:multiplatform-markdown-renderer", version.ref = "multiplatform-markdown-renderer" }
|
multiplatform-markdown-renderer = { module = "com.mikepenz:multiplatform-markdown-renderer", version.ref = "multiplatform-markdown-renderer" }
|
||||||
multiplatform-markdown-renderer-m3 = { module = "com.mikepenz:multiplatform-markdown-renderer-m3", version.ref = "multiplatform-markdown-renderer" }
|
multiplatform-markdown-renderer-m3 = { module = "com.mikepenz:multiplatform-markdown-renderer-m3", version.ref = "multiplatform-markdown-renderer" }
|
||||||
multiplatform-markdown-renderer-coil2 = { module = "com.mikepenz:multiplatform-markdown-renderer-coil2", version.ref = "multiplatform-markdown-renderer" }
|
multiplatform-markdown-renderer-coil3= { module = "com.mikepenz:multiplatform-markdown-renderer-coil3", version.ref = "multiplatform-markdown-renderer" }
|
||||||
|
|
||||||
multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" }
|
multiplatform-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "multiplatform-settings" }
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.utils.di.customTabsModule
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.fileSystemModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.fileSystemModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.galleryHelperModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.galleryHelperModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.hapticFeedbackModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.hapticFeedbackModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.imagePreloadModule
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.networkModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.networkModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.shareHelperModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.shareHelperModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.utilsModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.utilsModule
|
||||||
@ -79,7 +78,6 @@ val sharedHelperModule =
|
|||||||
repositoryModule,
|
repositoryModule,
|
||||||
utilsModule,
|
utilsModule,
|
||||||
domainInboxModule,
|
domainInboxModule,
|
||||||
imagePreloadModule,
|
|
||||||
networkModule,
|
networkModule,
|
||||||
coreNavigationModule,
|
coreNavigationModule,
|
||||||
lemmyUiModule,
|
lemmyUiModule,
|
||||||
|
@ -81,12 +81,13 @@ internal fun RowScope.TabNavigationItem(
|
|||||||
val iconSize = IconSize.m
|
val iconSize = IconSize.m
|
||||||
|
|
||||||
CustomImage(
|
CustomImage(
|
||||||
url = customIconUrl,
|
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2))
|
.clip(RoundedCornerShape(iconSize / 2))
|
||||||
.then(pointerInputModifier),
|
.then(pointerInputModifier),
|
||||||
|
url = customIconUrl,
|
||||||
|
autoload = true,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Icon(
|
Icon(
|
||||||
|
@ -17,7 +17,6 @@ import com.livefast.eattrash.raccoonforlemmy.core.utils.di.customTabsModule
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.fileSystemModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.fileSystemModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.galleryHelperModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.galleryHelperModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.hapticFeedbackModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.hapticFeedbackModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.imagePreloadModule
|
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.networkModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.networkModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.shareHelperModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.shareHelperModule
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.utilsModule
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.di.utilsModule
|
||||||
@ -79,7 +78,6 @@ fun initKoin() {
|
|||||||
repositoryModule,
|
repositoryModule,
|
||||||
domainInboxModule,
|
domainInboxModule,
|
||||||
utilsModule,
|
utilsModule,
|
||||||
imagePreloadModule,
|
|
||||||
networkModule,
|
networkModule,
|
||||||
coreNavigationModule,
|
coreNavigationModule,
|
||||||
lemmyUiModule,
|
lemmyUiModule,
|
||||||
|
@ -47,6 +47,7 @@ fun AcknoledgementItem(
|
|||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
url = url,
|
url = url,
|
||||||
|
autoload = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,7 +14,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.Communi
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.CommunitySortRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.CommunitySortRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.FavoriteCommunityRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.FavoriteCommunityRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.ZombieModeHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.ZombieModeHelper
|
||||||
|
@ -45,6 +45,7 @@ internal fun DrawerCommunityItem(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2)),
|
.clip(RoundedCornerShape(iconSize / 2)),
|
||||||
url = url,
|
url = url,
|
||||||
|
autoload = autoLoadImages,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,7 +8,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.architecture.DefaultMviModel
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository
|
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
||||||
@ -390,7 +390,10 @@ class ExploreViewModel(
|
|||||||
val results = paginationManager.loadNextPage()
|
val results = paginationManager.loadNextPage()
|
||||||
if (uiState.value.autoLoadImages) {
|
if (uiState.value.autoLoadImages) {
|
||||||
results.forEach { res ->
|
results.forEach { res ->
|
||||||
(res as? SearchResult.Post)?.model?.imageUrl?.takeIf { it.isNotEmpty() }
|
(res as? SearchResult.Post)
|
||||||
|
?.model
|
||||||
|
?.imageUrl
|
||||||
|
?.takeIf { it.isNotEmpty() }
|
||||||
?.also { url ->
|
?.also { url ->
|
||||||
imagePreloadManager.preload(url)
|
imagePreloadManager.preload(url)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.architecture.DefaultMviModel
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.CommentModel
|
import com.livefast.eattrash.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
|
@ -175,6 +175,7 @@ private fun ModlogHeader(
|
|||||||
url = creatorAvatar,
|
url = creatorAvatar,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
|
autoload = autoLoadImages,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
@ -197,7 +198,6 @@ private fun ModlogFooter(
|
|||||||
onOpen: (() -> Unit)? = null,
|
onOpen: (() -> Unit)? = null,
|
||||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val buttonModifier = Modifier.size(IconSize.l).padding(3.dp)
|
|
||||||
var optionsExpanded by remember { mutableStateOf(false) }
|
var optionsExpanded by remember { mutableStateOf(false) }
|
||||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
|
@ -11,7 +11,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCent
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.MultiCommunityRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.MultiCommunityRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
||||||
|
@ -160,8 +160,8 @@ class MultiCommunityEditorScreen(
|
|||||||
value = uiState.name,
|
value = uiState.name,
|
||||||
keyboardOptions =
|
keyboardOptions =
|
||||||
KeyboardOptions(
|
KeyboardOptions(
|
||||||
|
autoCorrectEnabled = false,
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Text,
|
||||||
autoCorrect = false,
|
|
||||||
imeAction = ImeAction.Next,
|
imeAction = ImeAction.Next,
|
||||||
),
|
),
|
||||||
onValueChange = { value ->
|
onValueChange = { value ->
|
||||||
@ -227,6 +227,7 @@ class MultiCommunityEditorScreen(
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
url = url,
|
url = url,
|
||||||
|
autoload = uiState.autoLoadImages,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.architecture.DefaultMviModel
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.ZombieModeHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.zombiemode.ZombieModeHelper
|
||||||
|
@ -171,6 +171,7 @@ private fun ReportHeader(
|
|||||||
url = creatorAvatar,
|
url = creatorAvatar,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
contentScale = ContentScale.FillBounds,
|
contentScale = ContentScale.FillBounds,
|
||||||
|
autoload = autoLoadImages,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
@ -193,7 +194,6 @@ private fun ReportFooter(
|
|||||||
onOpenResolve: (() -> Unit)? = null,
|
onOpenResolve: (() -> Unit)? = null,
|
||||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val buttonModifier = Modifier.size(IconSize.l).padding(3.dp)
|
|
||||||
var optionsExpanded by remember { mutableStateOf(false) }
|
var optionsExpanded by remember { mutableStateOf(false) }
|
||||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||||
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ancillaryTextAlpha)
|
||||||
|
@ -12,7 +12,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.commonui.lemmyui.UserDetailSec
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenter
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
import com.livefast.eattrash.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository
|
import com.livefast.eattrash.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository
|
||||||
|
@ -9,7 +9,7 @@ import com.livefast.eattrash.raccoonforlemmy.core.persistence.repository.Setting
|
|||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.datetime.epochMillis
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.datetime.epochMillis
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.GalleryHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.GalleryHelper
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.download
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.gallery.download
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.imageload.ImagePreloadManager
|
||||||
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
import com.livefast.eattrash.raccoonforlemmy.core.utils.share.ShareHelper
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user