diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index e805548a..8d81632f 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/app/src/main/java/city/zouitel/jetnote/NoteActivity.kt b/app/src/main/java/city/zouitel/jetnote/NoteActivity.kt index a4e07d02..bb77d2c1 100644 --- a/app/src/main/java/city/zouitel/jetnote/NoteActivity.kt +++ b/app/src/main/java/city/zouitel/jetnote/NoteActivity.kt @@ -13,10 +13,10 @@ import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import androidx.core.view.WindowCompat import androidx.navigation.compose.rememberNavController +import city.zouitel.links.ui.LinkVM import city.zouitel.navigation.Graph import city.zouitel.navigation.checkShortcut import city.zouitel.navigation.intentHandler -import city.zouitel.navigation.urlPreview import city.zouitel.systemDesign.Cons.AUDIOS import city.zouitel.systemDesign.Cons.IMAGES import city.zouitel.systemDesign.DataStoreVM @@ -24,10 +24,14 @@ import city.zouitel.widget.WidgetReceiver import com.google.accompanist.systemuicontroller.rememberSystemUiController import kotlinx.coroutines.* import org.koin.androidx.compose.koinViewModel +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject import java.io.File import java.util.* -class NoteActivity : ComponentActivity() { +class NoteActivity : ComponentActivity(), KoinComponent { + + val linkViewModel: LinkVM by inject() @SuppressLint("CoroutineCreationDuringComposition") override fun onCreate(savedInstanceState: Bundle?) { @@ -83,7 +87,7 @@ class NoteActivity : ComponentActivity() { override fun onDestroy() { super.onDestroy() - urlPreview(this, null, null, null, null, null, null)?.cleanUp() + linkViewModel.urlPreview(this, null, null, null, null)?.cleanUp() } override fun onStart() { diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml index fa0f996d..3f094b76 100644 --- a/app/src/main/res/xml/backup_rules.xml +++ b/app/src/main/res/xml/backup_rules.xml @@ -2,7 +2,7 @@ Sample backup rules file; uncomment and customize as necessary. See https://developer.android.com/guide/topics/data/autobackup for details. - Note: This file is ignored for devices older that API 31 + WidgetNote: This file is ignored for devices older that API 31 See https://developer.android.com/about/versions/12/backup-restore --> diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 817c616a..8d26c654 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] agp = "8.2.1" -kotlin = "1.9.20" +kotlin = "1.9.22" compileSdkVersion = "34" minSdkVersion = "26" targetSdkVersion = "34" -codeVersion = "402" -nameVersion = "4.0.2" -composeVersion = "1.5.4" +codeVersion = "403" +nameVersion = "4.0.3" +composeVersion = "1.5.8" #Android. core-ktx = "1.12.0" @@ -22,26 +22,26 @@ startup = "1.1.1" #Compose. activity-compose = "1.8.2" -compose-bom = "2023.10.01" +compose-bom = "2024.01.00" appcompat = "1.6.1" material = "1.11.0" navigation-compose = "2.7.6" compose-constraintlayout = "1.1.0-alpha13" #Plugins. -ksp = "1.9.21-1.0.16" +ksp = "1.9.22-1.0.17" dependencyanalysis = "1.25.0" #KotlinX. -serialization = "1.6.0" +serialization = "1.6.2" coroutines = "1.7.3" #Koin. -koin-core = "3.5.0" -koin-compose = "3.5.0" -koin-android = "3.5.0" +koin-core = "3.5.3" +koin-compose = "3.5.3" +koin-android = "3.5.3" koin-worker = "3.5.0" -koin-test = "3.5.0" +koin-test = "3.5.3" koin-gradle = "3.5.0" #Room. @@ -73,6 +73,8 @@ global-exception = "1.0.1" url-preview = "1.0.1" beetle = "2.0.1" sqlcipher = "4.5.4" +waveslider = "0.0.3" +audiowaveform = "1.1.1" [libraries] # Kotlin. @@ -162,6 +164,8 @@ swipe = { module = "me.saket.swipe:swipe", version.ref = "swipe" } #globalexception = { module = "com.github.emirhankolver:GlobalExceptionHandler", version.ref = "global-exception" } sketchbook = { module = "io.getstream:sketchbook", version.ref = "sketchbook" } sqlcipher = { module = "net.zetetic:android-database-sqlcipher", version.ref = "sqlcipher" } +waveslider = { module = "com.github.galaxygoldfish:waveslider", version.ref = "waveslider" } +audiowaveform = { module = "com.github.lincollincol:compose-audiowaveform", version.ref = "audiowaveform" } [bundles] compose = ["ui", "ui-tooling-preview", "material3"] diff --git a/ui/common/systemDesign/src/main/java/city/zouitel/systemDesign/Cons.kt b/ui/common/systemDesign/src/main/java/city/zouitel/systemDesign/Cons.kt index bc6e5f6b..67807a3f 100644 --- a/ui/common/systemDesign/src/main/java/city/zouitel/systemDesign/Cons.kt +++ b/ui/common/systemDesign/src/main/java/city/zouitel/systemDesign/Cons.kt @@ -5,7 +5,7 @@ object Cons { const val TAG = "This" const val NUL = "null" - const val APP_VERSION = "4.0.2" + const val APP_VERSION = "4.0.3" const val ID = "Id" const val TITLE = "Title" diff --git a/ui/features/audios/build.gradle.kts b/ui/features/audios/build.gradle.kts index db6c5121..fc647845 100644 --- a/ui/features/audios/build.gradle.kts +++ b/ui/features/audios/build.gradle.kts @@ -16,4 +16,11 @@ dependencies { //AndroidX. implementation(libs.constraintlayout) + + //Swipe. + implementation(libs.swipe) + + //Sliders. + implementation(libs.waveslider) + implementation(libs.audiowaveform) } \ No newline at end of file diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/NoteMediaPlayer.kt b/ui/features/audios/src/main/java/city/zouitel/audios/NoteMediaPlayer.kt deleted file mode 100644 index 22e12501..00000000 --- a/ui/features/audios/src/main/java/city/zouitel/audios/NoteMediaPlayer.kt +++ /dev/null @@ -1,131 +0,0 @@ -package city.zouitel.audios - -import android.annotation.SuppressLint -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import city.zouitel.systemDesign.AdaptingRow -import city.zouitel.systemDesign.Cons.AUDIOS -import city.zouitel.systemDesign.Cons.MP3 -import city.zouitel.systemDesign.DataStoreVM -import city.zouitel.systemDesign.Icons.PAUSE_CIRCLE_FILLED_ICON -import city.zouitel.systemDesign.Icons.PLAY_CIRCLE_FILLED_ICON -import city.zouitel.systemDesign.Icons.TRASH_ICON -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import org.koin.androidx.compose.koinViewModel -import java.io.File - -@SuppressLint("CoroutineCreationDuringComposition") -@Composable -fun NoteMediaPlayer( - exoViewModule: MediaPlayerViewModel = koinViewModel(), - datastoreVM: DataStoreVM = koinViewModel(), - localMediaUid: String? -) { - val context = LocalContext.current - - val scope = rememberCoroutineScope() - val mediaFile = context.filesDir.path + "/$AUDIOS/" + localMediaUid + "." + MP3 - var processState by remember { mutableFloatStateOf(0f) } - var isPlaying by remember { mutableStateOf(false) } - - val currentLayout by datastoreVM.getLayout.collectAsState() - -// val exoMedia = exoViewModule.prepareMediaPlayer(mediaFile) - scope.launch { - while(isPlaying && processState <= 1f) { - delay(exoViewModule.getMediaDuration(context,mediaFile) / 100) - processState += .011f - } - when { - processState >= 1f -> { - isPlaying = false - processState = 0f - } - } - } - - if (isPlaying) exoViewModule.playMedia(mediaFile) else exoViewModule.pauseMedia(mediaFile) - - Surface( - modifier = Modifier - .padding(10.dp), - color = MaterialTheme.colorScheme.surfaceVariant, - shape = RoundedCornerShape(20.dp) - ) { - Row { - AdaptingRow(modifier = Modifier - .padding(start = 5.dp, end = 5.dp)) { - // - if (currentLayout == "GRID"){ - Icon( - painter = painterResource( - id = if (isPlaying) PAUSE_CIRCLE_FILLED_ICON else PLAY_CIRCLE_FILLED_ICON - ), - null, - modifier = Modifier.clickable { - isPlaying = !isPlaying - } - ) - - LinearProgressIndicator( - progress = processState, - modifier = Modifier - .weight(1f) - .padding(10.dp), - trackColor = MaterialTheme.colorScheme.inverseOnSurface - ) - } else { - Box( - contentAlignment = Alignment.Center - ) { - Icon( - painter = painterResource( - id = if (isPlaying) PAUSE_CIRCLE_FILLED_ICON else PLAY_CIRCLE_FILLED_ICON - ), - null, - modifier = Modifier - .padding(start = 3.dp) - .clickable { - isPlaying = !isPlaying - } - ) - CircularProgressIndicator(progress = processState, - modifier = Modifier, - ) - } - } - // - Text( - text = - exoViewModule.formatLong( - exoViewModule.getMediaDuration(context,mediaFile) - ) - ) - // - Icon( - painter = painterResource(id = TRASH_ICON), - null, - modifier = Modifier - .padding(5.dp) - .clickable { - File( - context.filesDir.path + "/" + AUDIOS, - "$localMediaUid.$MP3" - ).delete() - } - ) - } - } - } -} \ No newline at end of file diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/di/ExoPlayerMod.kt b/ui/features/audios/src/main/java/city/zouitel/audios/di/ExoPlayerMod.kt deleted file mode 100644 index cd8f3569..00000000 --- a/ui/features/audios/src/main/java/city/zouitel/audios/di/ExoPlayerMod.kt +++ /dev/null @@ -1,19 +0,0 @@ -package city.zouitel.audios.di - -import android.content.Context -import com.google.android.exoplayer2.ExoPlayer - -//@Module -//@InstallIn(SingletonComponent::class) -object ExoPlayerMod { - -// @Singleton -// @Provides - fun buildMediaPlayer( - /*@ApplicationContext*/ context: Context, - ) = ExoPlayer.Builder(context).build().apply { - setHandleAudioBecomingNoisy(true) - } -} - - diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/di/exoPlayerDI.kt b/ui/features/audios/src/main/java/city/zouitel/audios/di/exoPlayerDI.kt index a574de4c..2b1cb04a 100644 --- a/ui/features/audios/src/main/java/city/zouitel/audios/di/exoPlayerDI.kt +++ b/ui/features/audios/src/main/java/city/zouitel/audios/di/exoPlayerDI.kt @@ -2,10 +2,9 @@ package city.zouitel.audios.di import com.google.android.exoplayer2.ExoPlayer import org.koin.android.ext.koin.androidContext -import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.dsl.module -import city.zouitel.audios.MediaPlayerViewModel +import city.zouitel.audios.ui.MediaPlayerViewModel import org.koin.core.module.dsl.singleOf import city.zouitel.domain.exoplayer.* import org.koin.dsl.bind diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/MediaPlayerViewModel.kt b/ui/features/audios/src/main/java/city/zouitel/audios/ui/MediaPlayerViewModel.kt similarity index 91% rename from ui/features/audios/src/main/java/city/zouitel/audios/MediaPlayerViewModel.kt rename to ui/features/audios/src/main/java/city/zouitel/audios/ui/MediaPlayerViewModel.kt index 774afe4c..346f2424 100644 --- a/ui/features/audios/src/main/java/city/zouitel/audios/MediaPlayerViewModel.kt +++ b/ui/features/audios/src/main/java/city/zouitel/audios/ui/MediaPlayerViewModel.kt @@ -1,4 +1,4 @@ -package city.zouitel.audios +package city.zouitel.audios.ui import android.content.Context import androidx.compose.runtime.mutableLongStateOf @@ -11,11 +11,10 @@ import java.text.SimpleDateFormat import java.util.* class MediaPlayerViewModel ( - private val exoBuilder : ExoPlayerImpl, + private val exoBuilder : ExoPlayerImpl ): ViewModel() { - var getMediaDuration = mutableLongStateOf(0L) - private set + private var getMediaDuration = mutableLongStateOf(0L) fun playMedia(mediaUri: String) { viewModelScope.launch { diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/ui/MiniMediaPlayer.kt b/ui/features/audios/src/main/java/city/zouitel/audios/ui/MiniMediaPlayer.kt new file mode 100644 index 00000000..f3db418b --- /dev/null +++ b/ui/features/audios/src/main/java/city/zouitel/audios/ui/MiniMediaPlayer.kt @@ -0,0 +1,97 @@ +package city.zouitel.audios.ui + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import city.zouitel.audios.utils.ControlButton +import city.zouitel.systemDesign.AdaptingRow +import city.zouitel.systemDesign.Cons +import city.zouitel.systemDesign.Cons.LIST +import city.zouitel.systemDesign.DataStoreVM +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.koin.androidx.compose.koinViewModel + +@SuppressLint("CoroutineCreationDuringComposition") +@Composable +fun MiniMediaPlayer( + exoViewModule: MediaPlayerViewModel = koinViewModel(), + datastoreVM: DataStoreVM = koinViewModel(), + localMediaUid: String? +) { + val context = LocalContext.current + val mediaFile = context.filesDir.path + "/${Cons.AUDIOS}/" + localMediaUid + "." + Cons.MP3 + var processState by remember { mutableFloatStateOf(0f) } + val isPlaying = remember { mutableStateOf(false) } + val currentLayout by datastoreVM.getLayout.collectAsState() + val scope = rememberCoroutineScope() + + scope.launch { + while (isPlaying.value && processState <= 1f) { + delay(exoViewModule.getMediaDuration(context, mediaFile) / 100) + processState += .011f + } + when { + processState >= 1f -> { + isPlaying.value = false + processState = 0f + } + } + } + + if (isPlaying.value) exoViewModule.playMedia(mediaFile) else exoViewModule.pauseMedia(mediaFile) + + Card( + modifier = Modifier.padding(10.dp), + shape = RoundedCornerShape(17.dp), + colors = CardDefaults.cardColors( + containerColor = Color(.6f, .6f, .6f, .5f) + ) + ) { + Row { + AdaptingRow( + modifier = Modifier + .padding(start = 5.dp, end = 5.dp) + ) { + if (currentLayout == LIST) { + ControlButton(isPlaying) + + LinearProgressIndicator( + progress = processState, + modifier = Modifier + .weight(1f) + .padding(7.dp), + trackColor = MaterialTheme.colorScheme.inverseOnSurface + ) + } else { + Box( + contentAlignment = Alignment.Center + ) { + ControlButton(isPlaying) + + CircularProgressIndicator( + progress = processState, + color = MaterialTheme.colorScheme.surfaceVariant, + ) + } + } + + Text( + modifier = Modifier.padding(end = 7.dp), + text = exoViewModule.formatLong( + exoViewModule.getMediaDuration(context, mediaFile) + ) + ) + } + } + } +} \ No newline at end of file diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/ui/NormalMediaPlayer.kt b/ui/features/audios/src/main/java/city/zouitel/audios/ui/NormalMediaPlayer.kt new file mode 100644 index 00000000..61451976 --- /dev/null +++ b/ui/features/audios/src/main/java/city/zouitel/audios/ui/NormalMediaPlayer.kt @@ -0,0 +1,130 @@ +package city.zouitel.audios.ui + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.DrawStyle +import androidx.compose.ui.graphics.drawscope.Fill +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import city.zouitel.audios.utils.ControlButton +import city.zouitel.systemDesign.AdaptingRow +import city.zouitel.systemDesign.Cons +import city.zouitel.systemDesign.Icons +import com.galaxygoldfish.waveslider.WaveSlider +import com.linc.audiowaveform.AudioWaveform +import com.linc.audiowaveform.model.AmplitudeType +import com.linc.audiowaveform.model.WaveformAlignment +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import me.saket.swipe.SwipeAction +import me.saket.swipe.SwipeableActionsBox +import me.saket.swipe.rememberSwipeableActionsState +import org.koin.androidx.compose.koinViewModel +import java.io.File + +@SuppressLint("CoroutineCreationDuringComposition") +@Composable +fun NormalMediaPlayer( + exoViewModule: MediaPlayerViewModel = koinViewModel(), + localMediaUid: String? +) { + val context = LocalContext.current + val mediaFile = arrayOf(context.filesDir.path, Cons.AUDIOS, localMediaUid + "." + Cons.MP3).joinToString("/") + var processState by remember { mutableFloatStateOf(0f) } + val isPlaying = remember { mutableStateOf(false) } + val scope = rememberCoroutineScope() + val swipeState = rememberSwipeableActionsState() + + scope.launch { + while(isPlaying.value && processState <= 1f) { + delay(exoViewModule.getMediaDuration(context,mediaFile) / 100) + processState += .011f + } + when { + processState >= 1f -> { + isPlaying.value = false + processState = 0f + } + } + } + + if (isPlaying.value) exoViewModule.playMedia(mediaFile) else exoViewModule.pauseMedia(mediaFile) + + val swipeAction = SwipeAction( + onSwipe = { + File( + context.filesDir.path + "/" + Cons.AUDIOS, + "$localMediaUid.${Cons.MP3}" + ).delete() + }, + icon = { + Icon(painterResource(Icons.DELETE_OUTLINE_ICON), null) + }, + background = Color.Red + ) + + SwipeableActionsBox( + backgroundUntilSwipeThreshold = Color.Transparent, + swipeThreshold = 100.dp, + state = swipeState, + endActions = listOf(swipeAction) + ) { + Card( + modifier = Modifier.padding(10.dp), + shape = RoundedCornerShape(17.dp), + colors = CardDefaults.cardColors( + containerColor = Color(.6f, .6f, .6f, .5f) + ) + ) { + Row { + AdaptingRow( + modifier = Modifier + .padding(start = 5.dp, end = 5.dp) + .height(80.dp) + ) { + ControlButton(isPlaying) + + AudioWaveform( + modifier = Modifier.weight(1f), + amplitudes = listOf(1,2,3,4,5,6), + progress = processState, + onProgressChange = { processState = it }, + waveformAlignment = WaveformAlignment.Center, + style = Fill, + amplitudeType = AmplitudeType.Avg, + spikePadding = 2.dp, + spikeRadius = 2.dp, + spikeWidth = 2.dp + ) + + Text( + modifier = Modifier.padding(end = 10.dp), + text = exoViewModule.formatLong( + exoViewModule.getMediaDuration(context,mediaFile) + ), + color = MaterialTheme.colorScheme.surfaceVariant + ) + } + } + } + } +} \ No newline at end of file diff --git a/ui/features/audios/src/main/java/city/zouitel/audios/utils/ControlButton.kt b/ui/features/audios/src/main/java/city/zouitel/audios/utils/ControlButton.kt new file mode 100644 index 00000000..b2c04164 --- /dev/null +++ b/ui/features/audios/src/main/java/city/zouitel/audios/utils/ControlButton.kt @@ -0,0 +1,27 @@ +package city.zouitel.audios.utils + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import city.zouitel.systemDesign.Icons + +@Composable +internal fun ControlButton(isPlaying: MutableState) { + Icon( + painter = painterResource( + id = if (isPlaying.value) Icons.PAUSE_CIRCLE_FILLED_ICON else Icons.PLAY_CIRCLE_FILLED_ICON + ), + null, + modifier = Modifier + .padding(start = 0.dp) + .clickable { + isPlaying.value = !isPlaying.value + } + ) + +} \ No newline at end of file diff --git a/ui/features/links/src/main/java/city/zouitel/links/ui/CacheLinks.kt b/ui/features/links/src/main/java/city/zouitel/links/ui/CacheLinks.kt index e8217408..1d33695a 100644 --- a/ui/features/links/src/main/java/city/zouitel/links/ui/CacheLinks.kt +++ b/ui/features/links/src/main/java/city/zouitel/links/ui/CacheLinks.kt @@ -12,6 +12,7 @@ import androidx.work.OneTimeWorkRequest import androidx.work.OutOfQuotaPolicy import androidx.work.WorkManager import city.zouitel.links.worker.LinkWorker +import kotlinx.coroutines.job import java.util.* @SuppressLint("CoroutineCreationDuringComposition") @@ -23,8 +24,7 @@ fun CacheLinks( url: String ) { val observeLinks = remember(linkVM, linkVM::getAllLinks).collectAsState() - val observerNoteAndLinks = - remember(noteAndLinkVM, noteAndLinkVM::getAllNotesAndLinks).collectAsState() + val observerNoteAndLinks = remember(noteAndLinkVM, noteAndLinkVM::getAllNotesAndLinks).collectAsState() val ctx = LocalContext.current val linkImgPath = ctx.filesDir.path + "/" + "links_img" @@ -39,7 +39,7 @@ fun CacheLinks( // linkVM.urlPreview( ctx, url, title, host, img - ) + )?.fetchUrlPreview() if ( observeLinks.value.none { it.image == img.value } && @@ -56,37 +56,5 @@ fun CacheLinks( title = title.value, host = host.value ) - -// linkVM.addLink( -// Link( -// id = link_id, -// url = url, -// image = img.value, -// title = title.value, -// host = host.value -// ) -// ) -// noteAndLinkVM.addNoteAndLink( -// NoteAndLink( -// noteUid = noteUid, -// linkId = link_id -// ) -// ) - -// scope.launch(Dispatchers.IO) { -// // save link image in local link images file. -// val ss = ImageLoader(ctx) -// val cc = ImageRequest.Builder(ctx) -// .data(img.value) -// .target { -// linkVM.saveImageLocally( -// img = it.toBitmap(), -// path = linkImgPath, -// name = "$link_id.$JPEG" -// ) -// } -// .build() -// ss.enqueue(cc) -// } } } \ No newline at end of file diff --git a/ui/features/links/src/main/java/city/zouitel/links/ui/LinkVM.kt b/ui/features/links/src/main/java/city/zouitel/links/ui/LinkVM.kt index 21101bf1..db68d5bd 100644 --- a/ui/features/links/src/main/java/city/zouitel/links/ui/LinkVM.kt +++ b/ui/features/links/src/main/java/city/zouitel/links/ui/LinkVM.kt @@ -62,22 +62,22 @@ class LinkVM( title: MutableState?, host: MutableState?, img: MutableState? - ) = viewModelScope.launch(Dispatchers.IO) { - res?.let { - BahaUrlPreview(it, object : IUrlPreviewCallback { - override fun onComplete(urlInfo: UrlInfoItem) { - urlInfo.apply { - title?.value = this.title - host?.value = URL(this.url).host - img?.value = this.image - } + ) = res?.let { + BahaUrlPreview(it, object : IUrlPreviewCallback { + override fun onComplete(urlInfo: UrlInfoItem) { + viewModelScope.launch(Dispatchers.IO) { + urlInfo.apply { + title?.value = this.title + host?.value = URL(this.url).host + img?.value = this.image + } } + } - override fun onFailed(throwable: Throwable) { - Toast.makeText(ctx, "Can't load link", Toast.LENGTH_SHORT).show() - } - }).fetchUrlPreview() - } + override fun onFailed(throwable: Throwable) { + Toast.makeText(ctx, "Can't load link", Toast.LENGTH_SHORT).show() + } + }) } fun imageDecoder(context: Context, id:String): ImageBitmap? { @@ -86,7 +86,6 @@ class LinkVM( return bitImg?.asImageBitmap() } - fun doWork( linkId: String, noteId: String, diff --git a/ui/features/note/src/main/java/city/zouitel/note/ui/add_screen/AddNote.kt b/ui/features/note/src/main/java/city/zouitel/note/ui/add_screen/AddNote.kt index 44208917..2ae401ec 100644 --- a/ui/features/note/src/main/java/city/zouitel/note/ui/add_screen/AddNote.kt +++ b/ui/features/note/src/main/java/city/zouitel/note/ui/add_screen/AddNote.kt @@ -67,7 +67,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.net.toUri import androidx.navigation.NavController -import city.zouitel.audios.MediaPlayerViewModel +import city.zouitel.audios.ui.MediaPlayerViewModel +import city.zouitel.audios.ui.NormalMediaPlayer import city.zouitel.links.model.NoteAndLink import city.zouitel.links.ui.CacheLinks import city.zouitel.links.ui.LinkPart @@ -273,17 +274,6 @@ fun NoteAdd( ImageDisplayed(media = img.value?.asImageBitmap()) } - // display the media player. - item { - Spacer(modifier = Modifier.height(18.dp)) - if ( - File(mediaFile).exists() && !recordDialogState.value - ) { - city.zouitel.audios.NoteMediaPlayer(localMediaUid = uid) - audioDurationState.intValue = exoVM.getMediaDuration(ctx, mediaFile).toInt() - } - } - // The Title. item { OutlinedTextField( @@ -370,6 +360,17 @@ fun NoteAdd( ) } + // display the media player. + item { + Spacer(modifier = Modifier.height(18.dp)) + if ( + File(mediaFile).exists() && !recordDialogState.value + ) { + NormalMediaPlayer(localMediaUid = uid) + audioDurationState.intValue = exoVM.getMediaDuration(ctx, mediaFile).toInt() + } + } + // Link display. item { findUrlLink(descriptionState.value)?.let { url -> diff --git a/ui/features/note/src/main/java/city/zouitel/note/ui/bottom_bar/Plus.kt b/ui/features/note/src/main/java/city/zouitel/note/ui/bottom_bar/Plus.kt index 814781c5..279f18af 100644 --- a/ui/features/note/src/main/java/city/zouitel/note/ui/bottom_bar/Plus.kt +++ b/ui/features/note/src/main/java/city/zouitel/note/ui/bottom_bar/Plus.kt @@ -71,7 +71,11 @@ internal fun Plus( permission.WRITE_EXTERNAL_STORAGE, ) ) { - recordDialogState.value = it.values.all { true } + if (it.values.all { true }) { + recordDialogState.value = true + } else { + Toast.makeText(ctx, "*********************", Toast.LENGTH_LONG).show() + } } val currentColor = remember { mutableStateOf(getColorOfPriority(priorityColorState.value)) } diff --git a/ui/features/note/src/main/java/city/zouitel/note/ui/edit_screen/EditNote.kt b/ui/features/note/src/main/java/city/zouitel/note/ui/edit_screen/EditNote.kt index 16533339..6dbf37d1 100644 --- a/ui/features/note/src/main/java/city/zouitel/note/ui/edit_screen/EditNote.kt +++ b/ui/features/note/src/main/java/city/zouitel/note/ui/edit_screen/EditNote.kt @@ -64,7 +64,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.net.toUri import androidx.navigation.NavController -import city.zouitel.audios.MediaPlayerViewModel +import city.zouitel.audios.ui.MediaPlayerViewModel +import city.zouitel.audios.ui.NormalMediaPlayer import city.zouitel.links.model.NoteAndLink import city.zouitel.links.ui.CacheLinks import city.zouitel.links.ui.LinkPart @@ -268,21 +269,8 @@ fun NoteEdit( ImageDisplayed(media = img.value?.asImageBitmap()) } - // display the media player. - item { - Spacer(modifier = Modifier.height(18.dp)) - if ( - File(mediaFile).exists() && !recordDialogState.value - ) { - city.zouitel.audios.NoteMediaPlayer(localMediaUid = uid) - audioDurationState.intValue = exoViewModule.getMediaDuration(ctx, mediaFile).toInt() - - } - } - // The Title. item { - OutlinedTextField( value = titleState.value ?: "", onValueChange = { titleState.value = it }, @@ -327,7 +315,6 @@ fun NoteEdit( // The Description. item { - OutlinedTextField( value = descriptionState.value ?: "", onValueChange = { @@ -363,6 +350,18 @@ fun NoteEdit( ) } + // display the media player. + item { + Spacer(modifier = Modifier.height(18.dp)) + if ( + File(mediaFile).exists() && !recordDialogState.value + ) { + NormalMediaPlayer(localMediaUid = uid) + audioDurationState.intValue = exoViewModule.getMediaDuration(ctx, mediaFile).toInt() + + } + } + // Link display. item { findUrlLink(descriptionState.value)?.let { url -> diff --git a/ui/features/recorder/src/main/java/city/zouitel/recoder/viewmodel/RecorderVM.kt b/ui/features/recorder/src/main/java/city/zouitel/recoder/viewmodel/RecorderVM.kt index d3e14726..bfc6cbcb 100644 --- a/ui/features/recorder/src/main/java/city/zouitel/recoder/viewmodel/RecorderVM.kt +++ b/ui/features/recorder/src/main/java/city/zouitel/recoder/viewmodel/RecorderVM.kt @@ -17,7 +17,7 @@ class RecorderVM : ViewModel() { var seconds by mutableStateOf("00") var minutes by mutableStateOf("00") var hours by mutableStateOf("00") - var isPlaying by mutableStateOf(false) + private var isPlaying by mutableStateOf(false) fun start() { timer = fixedRateTimer(initialDelay = 1000L, period = 1000L) { diff --git a/ui/features/tasks/src/main/java/city/zouitel/tasks/TaskList.kt b/ui/features/tasks/src/main/java/city/zouitel/tasks/TaskList.kt index 2d1c66b9..84b5a96d 100644 --- a/ui/features/tasks/src/main/java/city/zouitel/tasks/TaskList.kt +++ b/ui/features/tasks/src/main/java/city/zouitel/tasks/TaskList.kt @@ -40,7 +40,6 @@ import org.koin.androidx.compose.koinViewModel import kotlin.random.Random private val getMatColor = MaterialColors().getMaterialColor - @OptIn(ExperimentalMaterial3Api::class) @SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable diff --git a/ui/features/widget/build.gradle.kts b/ui/features/widget/build.gradle.kts index 326f8b79..d6920b61 100644 --- a/ui/features/widget/build.gradle.kts +++ b/ui/features/widget/build.gradle.kts @@ -17,4 +17,7 @@ dependencies { implementation(libs.constraintlayout) implementation(libs.glance) implementation(project(":ui:features:note")) + implementation(project(":ui:features:tags")) + implementation(project(":ui:features:tasks")) + implementation(project(":ui:features:links")) } \ No newline at end of file diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/EntryPoint.kt b/ui/features/widget/src/main/java/city/zouitel/widget/EntryPoint.kt deleted file mode 100644 index 861e37d7..00000000 --- a/ui/features/widget/src/main/java/city/zouitel/widget/EntryPoint.kt +++ /dev/null @@ -1,9 +0,0 @@ -package city.zouitel.widget - -import city.zouitel.widget.ui.WidgetViewModel - -//@EntryPoint -//@InstallIn(SingletonComponent::class) -interface EntryPoint { - fun viewmodel(): WidgetViewModel -} \ No newline at end of file diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/WidgetReceiver.kt b/ui/features/widget/src/main/java/city/zouitel/widget/WidgetReceiver.kt index 2e050c86..17784b59 100644 --- a/ui/features/widget/src/main/java/city/zouitel/widget/WidgetReceiver.kt +++ b/ui/features/widget/src/main/java/city/zouitel/widget/WidgetReceiver.kt @@ -8,7 +8,6 @@ import androidx.glance.appwidget.GlanceAppWidget import androidx.glance.appwidget.GlanceAppWidgetReceiver import city.zouitel.widget.ui.AppWidget -//@AndroidEntryPoint class WidgetReceiver: GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget get() = AppWidget() diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/data/Note.kt b/ui/features/widget/src/main/java/city/zouitel/widget/data/Note.kt deleted file mode 100644 index edf9de63..00000000 --- a/ui/features/widget/src/main/java/city/zouitel/widget/data/Note.kt +++ /dev/null @@ -1,15 +0,0 @@ -package city.zouitel.widget.data - -import androidx.annotation.Keep -import city.zouitel.domain.model.Data -import city.zouitel.domain.model.Link -import city.zouitel.domain.model.Tag -import city.zouitel.domain.model.Task - -@Keep -data class Note( - val dataEntity: Data, - val tagEntities: List, - val taskEntities: List, - val linkEntities: List -) \ No newline at end of file diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/di/widgetKoinModule.kt b/ui/features/widget/src/main/java/city/zouitel/widget/di/widgetKoinModule.kt index ae581855..2a6e6aa6 100644 --- a/ui/features/widget/src/main/java/city/zouitel/widget/di/widgetKoinModule.kt +++ b/ui/features/widget/src/main/java/city/zouitel/widget/di/widgetKoinModule.kt @@ -1,7 +1,6 @@ package city.zouitel.widget.di -import city.zouitel.widget.ui.WidgetViewModel -import org.koin.androidx.viewmodel.dsl.viewModel +import city.zouitel.widget.viewmodel.WidgetViewModel import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.dsl.module diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/mapper/WidgetMapper.kt b/ui/features/widget/src/main/java/city/zouitel/widget/mapper/WidgetMapper.kt new file mode 100644 index 00000000..4a74d3d5 --- /dev/null +++ b/ui/features/widget/src/main/java/city/zouitel/widget/mapper/WidgetMapper.kt @@ -0,0 +1,25 @@ +package city.zouitel.widget.mapper + +import city.zouitel.widget.mapper.base.Mapper +import city.zouitel.links.mapper.LinkMapper +import city.zouitel.note.mapper.DataMapper +import city.zouitel.domain.model.Note as OutNote +import city.zouitel.tags.mapper.TagMapper +import city.zouitel.tasks.mapper.TaskMapper +import city.zouitel.widget.model.WidgetNote as InNote + +class WidgetMapper ( + private val dataMapper: DataMapper, + private val tagMapper: TagMapper, + private val taskMapper: TaskMapper, + private val linkMapper: LinkMapper +): Mapper.ReadOnly { + override fun toView(data: OutNote): InNote = with(data){ + InNote( + dataEntity = dataMapper.toView(dataEntity), + tagEntities = tagEntities.map { tagMapper.toView(it) }, + taskEntities = taskEntities.map { taskMapper.toView(it) }, + linkEntities = linkEntities.map { linkMapper.toView(it) } + ) + } +} \ No newline at end of file diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/mapper/base/Mapper.kt b/ui/features/widget/src/main/java/city/zouitel/widget/mapper/base/Mapper.kt new file mode 100644 index 00000000..371e234e --- /dev/null +++ b/ui/features/widget/src/main/java/city/zouitel/widget/mapper/base/Mapper.kt @@ -0,0 +1,14 @@ +package city.zouitel.widget.mapper.base + +sealed interface Mapper { + interface Base { + + fun toView(data: Out): In + + fun toDomain(data: In): Out + } + interface ReadOnly { + + fun toView(data: Out): In + } +} \ No newline at end of file diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/model/WidgetNote.kt b/ui/features/widget/src/main/java/city/zouitel/widget/model/WidgetNote.kt new file mode 100644 index 00000000..393e6026 --- /dev/null +++ b/ui/features/widget/src/main/java/city/zouitel/widget/model/WidgetNote.kt @@ -0,0 +1,15 @@ +package city.zouitel.widget.model + +import androidx.annotation.Keep +import city.zouitel.links.model.Link +import city.zouitel.note.model.Data +import city.zouitel.tags.model.Tag +import city.zouitel.tasks.model.Task + +@Keep +data class WidgetNote( + val dataEntity: Data, + val tagEntities: List, + val taskEntities: List, + val linkEntities: List +) \ No newline at end of file diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/ui/AppWidget.kt b/ui/features/widget/src/main/java/city/zouitel/widget/ui/AppWidget.kt index 00535a75..dcab2843 100644 --- a/ui/features/widget/src/main/java/city/zouitel/widget/ui/AppWidget.kt +++ b/ui/features/widget/src/main/java/city/zouitel/widget/ui/AppWidget.kt @@ -16,6 +16,7 @@ import androidx.glance.text.Text import androidx.glance.unit.ColorProvider import city.zouitel.domain.model.Note import city.zouitel.domain.usecase.WidgetUseCase +import city.zouitel.widget.viewmodel.WidgetViewModel import org.koin.androidx.compose.koinViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -25,13 +26,6 @@ class AppWidget: GlanceAppWidget(), KoinComponent { private val getAll: WidgetUseCase.GetAllWidgetMainEntityById by inject() override suspend fun provideGlance(context: Context, id: GlanceId) = provideContent { -// val viewModel = koinViewModel() -// val ctx = LocalContext.current.applicationContext - -// val viewModel = EntryPoints.get( -// ctx, -// EntryPoint::class.java -// ).viewmodel() val getAllNotes by getAll().collectAsState(initial = null) diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/utils.kt b/ui/features/widget/src/main/java/city/zouitel/widget/utils.kt deleted file mode 100644 index f77b5d0b..00000000 --- a/ui/features/widget/src/main/java/city/zouitel/widget/utils.kt +++ /dev/null @@ -1,6 +0,0 @@ -package city.zouitel.widget - -import androidx.core.net.toUri - -private val baseUri = "app://city.zouitel.jetnote".toUri() - diff --git a/ui/features/widget/src/main/java/city/zouitel/widget/ui/WidgetViewModel.kt b/ui/features/widget/src/main/java/city/zouitel/widget/viewmodel/WidgetViewModel.kt similarity index 81% rename from ui/features/widget/src/main/java/city/zouitel/widget/ui/WidgetViewModel.kt rename to ui/features/widget/src/main/java/city/zouitel/widget/viewmodel/WidgetViewModel.kt index 6cfd9f0b..453acb97 100644 --- a/ui/features/widget/src/main/java/city/zouitel/widget/ui/WidgetViewModel.kt +++ b/ui/features/widget/src/main/java/city/zouitel/widget/viewmodel/WidgetViewModel.kt @@ -1,4 +1,4 @@ -package city.zouitel.widget.ui +package city.zouitel.widget.viewmodel import android.content.Context import android.graphics.Bitmap @@ -7,9 +7,9 @@ import androidx.annotation.WorkerThread import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import city.zouitel.domain.usecase.WidgetUseCase -import city.zouitel.note.mapper.NoteMapper -import city.zouitel.note.model.Note as InNote import city.zouitel.systemDesign.Cons +import city.zouitel.widget.mapper.WidgetMapper +import city.zouitel.widget.model.WidgetNote as InNote import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -21,11 +21,8 @@ import org.koin.core.component.inject import java.io.File class WidgetViewModel: ViewModel(), KoinComponent { - private val getAll: WidgetUseCase.GetAllWidgetMainEntityById by inject() - private val mapper: NoteMapper by inject() - -// @WorkerThread -// fun getAllEntities() = getAll + private val getAllNotes: WidgetUseCase.GetAllWidgetMainEntityById by inject() + private val mapper: WidgetMapper by inject() // for observing the dataEntity changes. private val _allNotesById = MutableStateFlow>(emptyList()) @@ -34,7 +31,7 @@ class WidgetViewModel: ViewModel(), KoinComponent { init { viewModelScope.launch(context = Dispatchers.IO) { - getAll.invoke().collect { list -> + getAllNotes.invoke().collect { list -> _allNotesById.value = list.map { note -> mapper.toView(note) } } } diff --git a/ui/navigation/src/main/java/city/zouitel/navigation/home_screen/NoteHome.kt b/ui/navigation/src/main/java/city/zouitel/navigation/home_screen/NoteHome.kt index 88b264d6..6c401271 100644 --- a/ui/navigation/src/main/java/city/zouitel/navigation/home_screen/NoteHome.kt +++ b/ui/navigation/src/main/java/city/zouitel/navigation/home_screen/NoteHome.kt @@ -29,6 +29,8 @@ import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -115,6 +117,17 @@ fun NoteHome( else -> remember(entityVM, entityVM::allNotesById).collectAsState() } + val filteredObserverLocalNotes by remember(observerLocalNotes.value) { + derivedStateOf { + observerLocalNotes.value.filter { + it.dataEntity.title?.contains( + searchTitleState.value, + true + ) ?: true || it.tagEntities.contains(searchTagEntityState.value) + } + } + } + val uid by lazy { UUID.randomUUID().toString() } val topAppBarState = rememberTopAppBarState() val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState) @@ -229,16 +242,8 @@ fun NoteHome( .fillMaxSize(), ) { items( - items = observerLocalNotes.value.filter { - it.dataEntity.title?.contains( - searchTitleState.value, - true - ) ?: true || - it.tagEntities.contains(searchTagEntityState.value) - }, - key = { - it.dataEntity.uid - } + items = filteredObserverLocalNotes, + key = { it.dataEntity.uid } ) { entity -> NoteCard( screen = Screens.HOME_SCREEN, @@ -270,14 +275,8 @@ fun NoteHome( state = gridLayoutState ) { items( - key = { it.dataEntity.uid }, - items = observerLocalNotes.value.filter { - it.dataEntity.title?.contains( - searchTitleState.value, - true - ) ?: true || - it.tagEntities.contains(searchTagEntityState.value) - } + items = filteredObserverLocalNotes, + key = { it.dataEntity.uid } ) { entity -> NoteCard( screen = Screens.HOME_SCREEN, diff --git a/ui/navigation/src/main/java/city/zouitel/navigation/note_card/NoteCard.kt b/ui/navigation/src/main/java/city/zouitel/navigation/note_card/NoteCard.kt index 8137a6f0..ec52b2bc 100644 --- a/ui/navigation/src/main/java/city/zouitel/navigation/note_card/NoteCard.kt +++ b/ui/navigation/src/main/java/city/zouitel/navigation/note_card/NoteCard.kt @@ -32,6 +32,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.net.toUri import androidx.navigation.NavController +import city.zouitel.audios.ui.MiniMediaPlayer +import city.zouitel.audios.ui.NormalMediaPlayer import city.zouitel.links.model.NoteAndLink import city.zouitel.links.ui.LinkPart import city.zouitel.links.ui.LinkVM @@ -260,7 +262,7 @@ private fun Card( if ( File(mediaPath).exists() ) { - city.zouitel.audios.NoteMediaPlayer(localMediaUid = note.uid) + MiniMediaPlayer(localMediaUid = note.uid) } // tagEntities. diff --git a/ui/navigation/src/main/java/city/zouitel/navigation/top_action_bar/selection_bars/HomeSelectionTopAppBar.kt b/ui/navigation/src/main/java/city/zouitel/navigation/top_action_bar/selection_bars/HomeSelectionTopAppBar.kt index de9f5967..7066111a 100644 --- a/ui/navigation/src/main/java/city/zouitel/navigation/top_action_bar/selection_bars/HomeSelectionTopAppBar.kt +++ b/ui/navigation/src/main/java/city/zouitel/navigation/top_action_bar/selection_bars/HomeSelectionTopAppBar.kt @@ -102,7 +102,7 @@ fun HomeSelectionTopAppBar( AnimatedVisibility(visible = selectedNotes?.count() == 1) { Row { // share - PopupTip(message = "Share Note") { + PopupTip(message = "Share WidgetNote") { Icon(painter = painterResource(id = SHARE_ICON), contentDescription = null, modifier = Modifier .padding(7.dp) @@ -129,7 +129,7 @@ fun HomeSelectionTopAppBar( } // copy the dataEntity. - PopupTip(message = "Copy Note") { + PopupTip(message = "Copy WidgetNote") { Icon(painter = painterResource(id = COPY_ICON), contentDescription = null, modifier = Modifier .padding(7.dp) diff --git a/ui/navigation/src/main/java/city/zouitel/navigation/urlPreview.kt b/ui/navigation/src/main/java/city/zouitel/navigation/urlPreview.kt index 1de8d1ae..0bd95c40 100644 --- a/ui/navigation/src/main/java/city/zouitel/navigation/urlPreview.kt +++ b/ui/navigation/src/main/java/city/zouitel/navigation/urlPreview.kt @@ -11,30 +11,30 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.net.URL -fun urlPreview( - ctx: Context, - scope: CoroutineScope?, - res: String?, - url: MutableState?, - title: MutableState?, - host: MutableState?, - img: MutableState? -) = res?.let { - BahaUrlPreview(it, object : IUrlPreviewCallback { - override fun onComplete(urlInfo: UrlInfoItem) { - scope?.launch(Dispatchers.IO) { - urlInfo.apply { - title?.value = this.title -// description.value = this.description - host?.value = URL(this.url).host - url?.value = this.url - img?.value = this.image - } - } - } - - override fun onFailed(throwable: Throwable) { - Toast.makeText(ctx, "Can't load link", Toast.LENGTH_SHORT).show() - } - }) -} \ No newline at end of file +//fun urlPreview( +// ctx: Context, +// scope: CoroutineScope?, +// res: String?, +// url: MutableState?, +// title: MutableState?, +// host: MutableState?, +// img: MutableState? +//) = res?.let { +// BahaUrlPreview(it, object : IUrlPreviewCallback { +// override fun onComplete(urlInfo: UrlInfoItem) { +// scope?.launch(Dispatchers.IO) { +// urlInfo.apply { +// title?.value = this.title +//// description.value = this.description +// host?.value = URL(this.url).host +// url?.value = this.url +// img?.value = this.image +// } +// } +// } +// +// override fun onFailed(throwable: Throwable) { +// Toast.makeText(ctx, "Can't load link", Toast.LENGTH_SHORT).show() +// } +// }) +//} \ No newline at end of file