From 366d994fa507a4ece3d68eb10076b292f9c40f7a Mon Sep 17 00:00:00 2001 From: Konstantin Ivanov <54908981+konstantiniiv@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:57:28 +0200 Subject: [PATCH] DROID-2642 Sharing extension | Support Videos and Files (#1367) --- app/src/main/AndroidManifest.xml | 15 ++++ .../anytypeio/anytype/ui/main/MainActivity.kt | 23 +++++++ .../anytypeio/anytype/ui/sharing/Sharing.kt | 22 +++--- .../anytype/ui/sharing/SharingFragment.kt | 69 +++++++++++++++---- .../anytypeio/anytype/core_models/Command.kt | 4 ++ .../auth/repo/block/BlockDataRepository.kt | 4 ++ .../data/auth/repo/block/BlockRemote.kt | 2 + .../domain/block/repo/BlockRepository.kt | 2 + .../anytype/domain/download/ProcessCancel.kt | 24 +++++++ localization/src/main/res/values/strings.xml | 1 + .../middleware/block/BlockMiddleware.kt | 4 ++ .../middleware/interactor/Middleware.kt | 10 +++ .../middleware/service/MiddlewareService.kt | 3 + .../MiddlewareServiceImplementation.kt | 13 ++++ .../presentation/main/MainViewModel.kt | 15 ++++ .../sharing/AddToAnytypeViewModel.kt | 36 +++++++--- 16 files changed, 217 insertions(+), 30 deletions(-) create mode 100644 domain/src/main/java/com/anytypeio/anytype/domain/download/ProcessCancel.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index feac624f1c..211e98dc13 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -84,6 +84,21 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/anytypeio/anytype/ui/main/MainActivity.kt b/app/src/main/java/com/anytypeio/anytype/ui/main/MainActivity.kt index 884e32367e..e43f88b833 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/main/MainActivity.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/main/MainActivity.kt @@ -153,6 +153,12 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr SHARE_DIALOG_LABEL ) } + is Command.Sharing.Videos -> { + SharingFragment.videos(command.uris).show( + supportFragmentManager, + SHARE_DIALOG_LABEL + ) + } is Command.Sharing.Files -> { SharingFragment.files(command.uris).show( supportFragmentManager, @@ -342,6 +348,9 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr intent.type?.startsWith(SHARE_IMAGE_INTENT_PATTERN) == true -> { proceedWithImageShareIntent(intent) } + intent.type?.startsWith(SHARE_VIDEO_INTENT_PATTERN) == true -> { + proceedWithVideoShareIntent(intent) + } intent.type?.startsWith(SHARE_FILE_INTENT_PATTERN) == true -> { proceedWithFileShareIntent(intent) } @@ -378,6 +387,19 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr } } + private fun proceedWithVideoShareIntent(intent: Intent) { + if (intent.action == Intent.ACTION_SEND_MULTIPLE) { + vm.onIntentMultipleVideoShare(uris = intent.parseActionSendMultipleUris()) + } else { + val uri = intent.parseActionSendUri() + if (uri != null) { + vm.onIntentMultipleVideoShare(listOf(uri)) + } else { + toast("Could not parse URI") + } + } + } + private fun proceedWithNotificationIntent(intent: Intent) { when(val type = intent.getIntExtra(NOTIFICATION_TYPE, -1)) { AnytypeNotificationService.REQUEST_TO_JOIN_TYPE -> { @@ -560,6 +582,7 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr const val AUTO_UPDATE_URL = "https://fra1.digitaloceanspaces.com/anytype-release/latest-android.json" const val SHARE_DIALOG_LABEL = "anytype.dialog.share.label" const val SHARE_IMAGE_INTENT_PATTERN = "image/" + const val SHARE_VIDEO_INTENT_PATTERN = "video/" const val SHARE_FILE_INTENT_PATTERN = "application/" } } diff --git a/app/src/main/java/com/anytypeio/anytype/ui/sharing/Sharing.kt b/app/src/main/java/com/anytypeio/anytype/ui/sharing/Sharing.kt index 7025ce82d4..b66abec5e1 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/sharing/Sharing.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/sharing/Sharing.kt @@ -85,7 +85,6 @@ fun AddToAnytypeScreenUrlPreview() { onOpenClicked = {}, content = "https://en.wikipedia.org/wiki/Walter_Benjamin", progressState = AddToAnytypeViewModel.ProgressState.Done(""), - onCancelProcessClicked = {} //progressState = AddToAnytypeViewModel.ProgressState.Error(" I understand that contributing to this repository will require me to agree with the CLA I understand that contributing to this repository will require me to agree with the CLA\n") //progressState = AddToAnytypeViewModel.ProgressState.Progress(processId = "dasda", progress = 0.8f) ) @@ -113,7 +112,6 @@ fun AddToAnytypeScreenNotePreview() { wrapperObjId = "" ), onOpenClicked = {}, - onCancelProcessClicked = {} ) } @@ -124,7 +122,6 @@ fun AddToAnytypeScreen( data: SharingData, progressState: AddToAnytypeViewModel.ProgressState, onCancelClicked: () -> Unit, - onCancelProcessClicked: (Id) -> Unit, onAddClicked: (SaveAsOption) -> Unit, onSelectSpaceClicked: (SpaceView) -> Unit, onOpenClicked: (Id) -> Unit @@ -137,6 +134,7 @@ fun AddToAnytypeScreen( is SharingData.Images -> listOf(SAVE_AS_IMAGES) is SharingData.Files -> listOf(SAVE_AS_FILES) is SharingData.Text -> listOf(SAVE_AS_NOTE) + is SharingData.Videos -> listOf(SAVE_AS_VIDEOS) } var selectedIndex by remember { mutableStateOf( @@ -147,6 +145,7 @@ fun AddToAnytypeScreen( is SharingData.Images -> SAVE_AS_IMAGES is SharingData.Files -> SAVE_AS_FILES is SharingData.Text -> SAVE_AS_NOTE + is SharingData.Videos -> SAVE_AS_VIDEOS } ) } @@ -181,6 +180,7 @@ fun AddToAnytypeScreen( SAVE_AS_FILE -> stringResource(id = R.string.sharing_menu_save_as_file_option) SAVE_AS_IMAGES -> stringResource(id = R.string.sharing_menu_save_as_images_option) SAVE_AS_FILES -> stringResource(id = R.string.sharing_menu_save_as_files_option) + SAVE_AS_VIDEOS -> stringResource(id = R.string.sharing_menu_save_as_videos_option) else -> stringResource(id = R.string.sharing_menu_save_as_note_option) }, modifier = Modifier @@ -281,10 +281,7 @@ fun AddToAnytypeScreen( ) } is AddToAnytypeViewModel.ProgressState.Progress -> { - ButtonsProgress( - onCancelProcessClicked = onCancelProcessClicked, - progressState = progressState, - ) + ButtonsProgress(onCancelClicked = onCancelClicked) } } } @@ -438,8 +435,7 @@ private fun ButtonsDone( @Composable private fun ButtonsProgress( - onCancelProcessClicked: (Id) -> Unit, - progressState: AddToAnytypeViewModel.ProgressState.Progress + onCancelClicked: () -> Unit, ) { Row( modifier = Modifier @@ -449,7 +445,7 @@ private fun ButtonsProgress( verticalAlignment = Alignment.CenterVertically ) { ButtonSecondary( - onClick = { onCancelProcessClicked(progressState.processId) }, + onClick = onCancelClicked, size = ButtonSize.Large, text = stringResource(id = R.string.cancel), modifier = Modifier.weight(1.0f) @@ -646,6 +642,7 @@ const val SAVE_AS_IMAGE = 2 const val SAVE_AS_FILE = 3 const val SAVE_AS_IMAGES = 4 const val SAVE_AS_FILES = 5 +const val SAVE_AS_VIDEOS = 6 typealias SaveAsOption = Int sealed class SharingData { @@ -680,6 +677,11 @@ sealed class SharingData { override val data: String get() = uri } + + data class Videos(val uris: List) : SharingData() { + override val data: String + get() = uris.toString() + } } const val DROPDOWN_MENU_VISIBILITY_WINDOW_INTERVAL = 150L \ No newline at end of file diff --git a/app/src/main/java/com/anytypeio/anytype/ui/sharing/SharingFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/sharing/SharingFragment.kt index f5cfedb022..b957cf6594 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/sharing/SharingFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/sharing/SharingFragment.kt @@ -53,7 +53,11 @@ class SharingFragment : BaseBottomSheetComposeFragment() { } else if (args.containsKey(SHARING_MULTIPLE_FILES_KEY)) { val result = argStringList(SHARING_MULTIPLE_FILES_KEY) SharingData.Files(uris = result) - } else { + } else if (args.containsKey(SHARING_MULTIPLE_VIDEOS_KEY)) { + val result = argStringList(SHARING_MULTIPLE_VIDEOS_KEY) + SharingData.Videos(uris = result) + } + else { throw IllegalStateException("Unexpcted shared data") } } @@ -85,17 +89,17 @@ class SharingFragment : BaseBottomSheetComposeFragment() { when(option) { SAVE_AS_BOOKMARK -> vm.onCreateBookmark(url = sharedData.data) SAVE_AS_NOTE -> vm.onCreateNote(sharedData.data) - SAVE_AS_FILE -> vm.onShareMedia(listOf(sharedData.data)) - SAVE_AS_IMAGES, SAVE_AS_IMAGE -> { + SAVE_AS_FILE -> { val formattedDateTime = getFormattedDateTime(Locale.getDefault()) val objTitle = - getString(R.string.sharing_media_wrapper_object_title, formattedDateTime) - val data = sharedData - if (data is SharingData.Images) { - vm.onShareMedia(uris = data.uris, wrapperObjTitle = objTitle) - } else { - toast("Unexpected data format") - } + getString( + R.string.sharing_files_wrapper_object_title, + formattedDateTime + ) + vm.onShareFiles( + uris = listOf(sharedData.data), + wrapperObjTitle = objTitle + ) } SAVE_AS_FILES -> { val formattedDateTime = getFormattedDateTime(Locale.getDefault()) @@ -103,11 +107,45 @@ class SharingFragment : BaseBottomSheetComposeFragment() { getString(R.string.sharing_files_wrapper_object_title, formattedDateTime) val data = sharedData if (data is SharingData.Files) { - vm.onShareMedia(uris = data.uris, wrapperObjTitle = objTitle) + vm.onShareFiles(uris = data.uris, wrapperObjTitle = objTitle) } else { toast("Unexpected data format") } } + SAVE_AS_IMAGES, SAVE_AS_IMAGE, SAVE_AS_VIDEOS -> { + val formattedDateTime = getFormattedDateTime(Locale.getDefault()) + val objTitle = + getString( + R.string.sharing_media_wrapper_object_title, + formattedDateTime + ) + when (val data = sharedData) { + is SharingData.Image -> { + vm.onShareFiles( + uris = listOf(data.uri), + wrapperObjTitle = objTitle + ) + } + + is SharingData.Images -> { + vm.onShareFiles( + uris = data.uris, + wrapperObjTitle = objTitle + ) + } + + is SharingData.Videos -> { + vm.onShareFiles( + uris = data.uris, + wrapperObjTitle = objTitle + ) + } + + else -> { + toast("Unexpected data format") + } + } + } } }, onCancelClicked = { @@ -119,7 +157,6 @@ class SharingFragment : BaseBottomSheetComposeFragment() { onSelectSpaceClicked = { vm.onSelectSpaceClicked(it) }, progressState = vm.progressState.collectAsStateWithLifecycle().value, onOpenClicked = vm::proceedWithNavigation, - onCancelProcessClicked = { processId -> } ) LaunchedEffect(Unit) { vm.navigation.collect { nav -> @@ -175,6 +212,9 @@ class SharingFragment : BaseBottomSheetComposeFragment() { is SharingData.Url -> { vm.onSharedTextData(data.url) } + is SharingData.Videos -> { + vm.onSharedMediaData(data.uris) + } } } @@ -204,6 +244,7 @@ class SharingFragment : BaseBottomSheetComposeFragment() { private const val SHARING_IMAGE_KEY = "arg.sharing.image-key" private const val SHARING_FILE_KEY = "arg.sharing.file-key" private const val SHARING_MULTIPLE_IMAGES_KEY = "arg.sharing.multiple-images-key" + private const val SHARING_MULTIPLE_VIDEOS_KEY = "arg.sharing.multiple-videos-key" private const val SHARING_MULTIPLE_FILES_KEY = "arg.sharing.multiple-files-key" fun text(data: String) : SharingFragment = SharingFragment().apply { @@ -218,6 +259,10 @@ class SharingFragment : BaseBottomSheetComposeFragment() { arguments = bundleOf(SHARING_MULTIPLE_IMAGES_KEY to ArrayList(uris)) } + fun videos(uris: List) : SharingFragment = SharingFragment().apply { + arguments = bundleOf(SHARING_MULTIPLE_VIDEOS_KEY to ArrayList(uris)) + } + fun files(uris: List) : SharingFragment = SharingFragment().apply { arguments = bundleOf(SHARING_MULTIPLE_FILES_KEY to ArrayList(uris)) } diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt index a0817c8649..e8067535af 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/Command.kt @@ -541,4 +541,8 @@ sealed class Command { } } } + + data class ProcessCancel( + val processId: Id + ) : Command() } \ No newline at end of file diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt index 24bbfd30b5..a30d8e7b36 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockDataRepository.kt @@ -1027,4 +1027,8 @@ class BlockDataRepository( override suspend fun membershipGetTiers(command: Command.Membership.GetTiers): List { return remote.membershipGetTiers(command) } + + override suspend fun processCancel(command: Command.ProcessCancel) { + remote.processCancel(command) + } } \ No newline at end of file diff --git a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt index 83069ea7bc..c90dc9560a 100644 --- a/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt +++ b/data/src/main/java/com/anytypeio/anytype/data/auth/repo/block/BlockRemote.kt @@ -434,4 +434,6 @@ interface BlockRemote { suspend fun membershipGetVerificationEmail(command: Command.Membership.GetVerificationEmail) suspend fun membershipVerifyEmailCode(command: Command.Membership.VerifyEmailCode) suspend fun membershipGetTiers(command: Command.Membership.GetTiers): List + + suspend fun processCancel(command: Command.ProcessCancel) } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt index 4f7d624f8e..c7512dc872 100644 --- a/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt +++ b/domain/src/main/java/com/anytypeio/anytype/domain/block/repo/BlockRepository.kt @@ -475,4 +475,6 @@ interface BlockRepository { suspend fun membershipGetVerificationEmail(command: Command.Membership.GetVerificationEmail) suspend fun membershipVerifyEmailCode(command: Command.Membership.VerifyEmailCode) suspend fun membershipGetTiers(command: Command.Membership.GetTiers): List + + suspend fun processCancel(command: Command.ProcessCancel) } \ No newline at end of file diff --git a/domain/src/main/java/com/anytypeio/anytype/domain/download/ProcessCancel.kt b/domain/src/main/java/com/anytypeio/anytype/domain/download/ProcessCancel.kt new file mode 100644 index 0000000000..b23ed4513f --- /dev/null +++ b/domain/src/main/java/com/anytypeio/anytype/domain/download/ProcessCancel.kt @@ -0,0 +1,24 @@ +package com.anytypeio.anytype.domain.download + +import com.anytypeio.anytype.core_models.Command +import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers +import com.anytypeio.anytype.domain.base.ResultInteractor +import com.anytypeio.anytype.domain.block.repo.BlockRepository +import javax.inject.Inject + +class ProcessCancel @Inject constructor( + private val repository: BlockRepository, + dispatchers: AppCoroutineDispatchers +) : ResultInteractor(dispatchers.io) { + + override suspend fun doWork(params: Params) { + val command = Command.ProcessCancel( + processId = params.processId + ) + return repository.processCancel(command) + } + + data class Params( + val processId: String + ) +} \ No newline at end of file diff --git a/localization/src/main/res/values/strings.xml b/localization/src/main/res/values/strings.xml index 5a849bed07..6aedc5a81d 100644 --- a/localization/src/main/res/values/strings.xml +++ b/localization/src/main/res/values/strings.xml @@ -1210,6 +1210,7 @@ File Images Files + Videos Data Add to Anytype Anytype file upload error: %1$s diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt index 0b29820b82..5bc2ac902d 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/block/BlockMiddleware.kt @@ -990,4 +990,8 @@ class BlockMiddleware( override suspend fun membershipGetTiers(command: Command.Membership.GetTiers): List { return middleware.membershipGetTiers(command) } + + override suspend fun processCancel(command: Command.ProcessCancel) { + middleware.processCancel(command) + } } \ No newline at end of file diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt index 213a34d492..1e6d2d0fa1 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/interactor/Middleware.kt @@ -2691,6 +2691,16 @@ class Middleware @Inject constructor( return response.tiers.map { it.toCoreModel() } } + @Throws + fun processCancel(command: Command.ProcessCancel) { + val request = Rpc.Process.Cancel.Request( + id = command.processId + ) + if (BuildConfig.DEBUG) logRequest(request) + val response = service.processCancel(request) + if (BuildConfig.DEBUG) logResponse(response) + } + private fun logRequest(any: Any) { logger.logRequest(any).also { if (BuildConfig.DEBUG && threadInfo.isOnMainThread()) { diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt index ddab08b9fa..ab752900b6 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareService.kt @@ -203,6 +203,9 @@ interface MiddlewareService { @Throws(Exception::class) fun fileDrop(request: Rpc.File.Drop.Request): Rpc.File.Drop.Response + @Throws(Exception::class) + fun processCancel(request: Rpc.Process.Cancel.Request): Rpc.Process.Cancel.Response + //endregion //region UNSPLASH commands diff --git a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt index 80bee7ec0c..12fdea1a59 100644 --- a/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt +++ b/middleware/src/main/java/com/anytypeio/anytype/middleware/service/MiddlewareServiceImplementation.kt @@ -1706,6 +1706,19 @@ class MiddlewareServiceImplementation @Inject constructor( } } + override fun processCancel(request: Rpc.Process.Cancel.Request): Rpc.Process.Cancel.Response { + val encoded = Service.processCancel( + Rpc.Process.Cancel.Request.ADAPTER.encode(request) + ) + val response = Rpc.Process.Cancel.Response.ADAPTER.decode(encoded) + val error = response.error + if (error != null && error.code != Rpc.Process.Cancel.Response.Error.Code.NULL) { + throw Exception(error.description) + } else { + return response + } + } + override fun setInternalFlags(request: Rpc.Object.SetInternalFlags.Request): Rpc.Object.SetInternalFlags.Response { val encoded = Service.objectSetInternalFlags( Rpc.Object.SetInternalFlags.Request.ADAPTER.encode(request) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt index 833f01fbdb..4dab472880 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/main/MainViewModel.kt @@ -292,6 +292,20 @@ class MainViewModel( } } + fun onIntentMultipleVideoShare(uris: List) { + Timber.d("onIntentVideoShare: $uris") + viewModelScope.launch { + checkAuthorizationStatus(Unit).process( + failure = { e -> Timber.e(e, "Error while checking auth status") }, + success = { status -> + if (status == AuthStatus.AUTHORIZED) { + commands.emit(Command.Sharing.Videos(uris)) + } + } + ) + } + } + fun onInterceptNotificationAction(action: NotificationAction) { viewModelScope.launch { proceedWithNotificationAction(action) @@ -362,6 +376,7 @@ class MainViewModel( data class Text(val data: String) : Sharing() data class Image(val uri: String): Sharing() data class Images(val uris: List): Sharing() + data class Videos(val uris: List): Sharing() data class File(val uri: String): Sharing() data class Files(val uris: List): Sharing() } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/sharing/AddToAnytypeViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/sharing/AddToAnytypeViewModel.kt index cf6b1a4ad8..82711f249b 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/sharing/AddToAnytypeViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/sharing/AddToAnytypeViewModel.kt @@ -16,17 +16,17 @@ import com.anytypeio.anytype.core_models.MarketplaceObjectTypeIds import com.anytypeio.anytype.core_models.NO_VALUE import com.anytypeio.anytype.core_models.ObjectOrigin import com.anytypeio.anytype.core_models.ObjectWrapper +import com.anytypeio.anytype.core_models.Process.Event +import com.anytypeio.anytype.core_models.Process.State import com.anytypeio.anytype.core_models.Relations import com.anytypeio.anytype.core_models.ext.EMPTY_STRING_VALUE import com.anytypeio.anytype.core_models.primitives.SpaceId -import com.anytypeio.anytype.core_models.Process.Event -import com.anytypeio.anytype.core_models.Process.State import com.anytypeio.anytype.core_utils.ext.msg import com.anytypeio.anytype.domain.account.AwaitAccountStartManager import com.anytypeio.anytype.domain.base.fold import com.anytypeio.anytype.domain.device.FileSharer +import com.anytypeio.anytype.domain.download.ProcessCancel import com.anytypeio.anytype.domain.media.FileDrop -import com.anytypeio.anytype.domain.media.UploadFile import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.domain.multiplayer.Permissions import com.anytypeio.anytype.domain.objects.CreateBookmarkObject @@ -48,10 +48,13 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.onSubscription +import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.launch import timber.log.Timber @@ -145,12 +148,29 @@ class AddToAnytypeViewModel( } } - private fun subscribeToEventProcessChannel(wrapperObjId: Id) { + private fun subscribeToEventProcessChannel( + wrapperObjId: Id, + filePaths: List, + targetSpaceId: String + ) { if (progressJob?.isActive == true) { + Timber.d("Progress job is already active") progressJob?.cancel() } progressJob = viewModelScope.launch { eventProcessChannel.observe() + .shareIn( + viewModelScope, + replay = 0, + started = SharingStarted.WhileSubscribed() + ) + .onSubscription { + proceedWithFilesDrop( + wrapperObjId = wrapperObjId, + filePaths = filePaths, + targetSpaceId = targetSpaceId + ) + } .collect { events -> events.forEach { event -> when (event) { @@ -208,7 +228,7 @@ class AddToAnytypeViewModel( } } - fun onShareMedia(uris: List, wrapperObjTitle: String? = null) { + fun onShareFiles(uris: List, wrapperObjTitle: String? = null) { viewModelScope.launch(Dispatchers.IO) { val targetSpaceView = spaceViews.value.firstOrNull { view -> view.isSelected @@ -255,7 +275,7 @@ class AddToAnytypeViewModel( startTime = startTime, spaceParams = provideParams(spaceManager.get()) ) - proceedWithFilesDrop( + subscribeToEventProcessChannel( wrapperObjId = wrapperObjId, filePaths = filePaths, targetSpaceId = targetSpaceId @@ -273,7 +293,6 @@ class AddToAnytypeViewModel( filePaths: List, targetSpaceId: String, ) { - subscribeToEventProcessChannel(wrapperObjId = wrapperObjId) val params = FileDrop.Params( ctx = wrapperObjId, space = SpaceId(targetSpaceId), @@ -466,7 +485,8 @@ class AddToAnytypeViewModel( private val permissions: Permissions, private val analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate, private val fileDrop: FileDrop, - private val eventProcessChannel: EventProcessDropFilesChannel + private val eventProcessChannel: EventProcessDropFilesChannel, + private val processCancel: ProcessCancel ) : ViewModelProvider.Factory { @Suppress("UNCHECKED_CAST") override fun create(modelClass: Class): T {