DROID-81 Editor | Enhancement | Share files (#2568)
This commit is contained in:
parent
a64a23e51c
commit
2acfccb6e2
|
@ -95,6 +95,8 @@ import com.anytypeio.anytype.presentation.editor.template.EditorTemplateDelegate
|
|||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import com.anytypeio.anytype.providers.DefaultUriFileProvider
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
|
@ -127,9 +129,12 @@ open class EditorTestSetup {
|
|||
lateinit var updateDetail: UpdateDetail
|
||||
lateinit var getCompatibleObjectTypes: GetCompatibleObjectTypes
|
||||
|
||||
@Mock
|
||||
|
||||
lateinit var copyFileToCacheDirectory: CopyFileToCacheDirectory
|
||||
|
||||
@Mock
|
||||
lateinit var middlewareShareDownloader: MiddlewareShareDownloader
|
||||
|
||||
@Mock
|
||||
lateinit var openPage: OpenPage
|
||||
@Mock
|
||||
|
@ -352,6 +357,7 @@ open class EditorTestSetup {
|
|||
duplicateBlock = duplicateBlock,
|
||||
updateAlignment = updateAlignment,
|
||||
downloadFile = downloadFile,
|
||||
middlewareShareDownloader = middlewareShareDownloader,
|
||||
mergeBlocks = mergeBlocks,
|
||||
updateTextColor = updateTextColor,
|
||||
replaceBlock = replaceBlock,
|
||||
|
|
|
@ -48,6 +48,15 @@
|
|||
android:screenOrientation="fullSensor"
|
||||
android:exported="false"
|
||||
tools:replace="screenOrientation" />
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -20,6 +20,7 @@ import dagger.Subcomponent
|
|||
modules = [
|
||||
ArchiveModule::class,
|
||||
EditorUseCaseModule::class,
|
||||
EditorUseCaseModule.Bindings::class,
|
||||
EditorSessionModule::class
|
||||
]
|
||||
)
|
||||
|
|
|
@ -48,8 +48,6 @@ import com.anytypeio.anytype.domain.clipboard.Paste
|
|||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.cover.SetDocCoverImage
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.GetCompatibleObjectTypes
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.download.DownloadFile
|
||||
import com.anytypeio.anytype.domain.download.Downloader
|
||||
import com.anytypeio.anytype.domain.event.interactor.EventChannel
|
||||
|
@ -72,6 +70,8 @@ import com.anytypeio.anytype.domain.page.UpdateTitle
|
|||
import com.anytypeio.anytype.domain.page.bookmark.CreateBookmarkBlock
|
||||
import com.anytypeio.anytype.domain.page.bookmark.SetupBookmark
|
||||
import com.anytypeio.anytype.domain.relations.AddFileToObject
|
||||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.status.ThreadStatusChannel
|
||||
|
@ -108,14 +108,24 @@ import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvide
|
|||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.providers.DefaultCoverImageHashProvider
|
||||
import com.anytypeio.anytype.providers.DefaultUriFileProvider
|
||||
import com.anytypeio.anytype.ui.editor.EditorFragment
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
@Subcomponent(modules = [EditorSessionModule::class, EditorUseCaseModule::class])
|
||||
@Subcomponent(
|
||||
modules = [
|
||||
EditorSessionModule::class,
|
||||
EditorUseCaseModule::class,
|
||||
EditorUseCaseModule.Bindings::class
|
||||
]
|
||||
)
|
||||
@PerScreen
|
||||
interface EditorSubComponent {
|
||||
|
||||
|
@ -134,23 +144,23 @@ interface EditorSubComponent {
|
|||
// Relations
|
||||
|
||||
fun documentRelationSubComponent(): DocumentRelationSubComponent.Builder
|
||||
fun relationAddToObjectComponent() : RelationAddToObjectSubComponent.Builder
|
||||
fun relationCreateFromScratchForObjectComponent() : RelationCreateFromScratchForObjectSubComponent.Builder
|
||||
fun relationCreateFromScratchForObjectBlockComponent() : RelationCreateFromScratchForObjectBlockSubComponent.Builder
|
||||
fun relationAddToObjectComponent(): RelationAddToObjectSubComponent.Builder
|
||||
fun relationCreateFromScratchForObjectComponent(): RelationCreateFromScratchForObjectSubComponent.Builder
|
||||
fun relationCreateFromScratchForObjectBlockComponent(): RelationCreateFromScratchForObjectBlockSubComponent.Builder
|
||||
fun relationTextValueComponent(): RelationTextValueSubComponent.Builder
|
||||
fun editDocRelationComponent() : ObjectObjectRelationValueSubComponent.Builder
|
||||
fun editDocRelationComponent(): ObjectObjectRelationValueSubComponent.Builder
|
||||
fun editRelationDateComponent(): RelationDataValueSubComponent.Builder
|
||||
|
||||
fun objectCoverComponent() : SelectCoverObjectSubComponent.Builder
|
||||
fun objectUnsplashComponent() : UnsplashSubComponent.Builder
|
||||
fun objectMenuComponent() : ObjectMenuComponent.Builder
|
||||
fun objectCoverComponent(): SelectCoverObjectSubComponent.Builder
|
||||
fun objectUnsplashComponent(): UnsplashSubComponent.Builder
|
||||
fun objectMenuComponent(): ObjectMenuComponent.Builder
|
||||
|
||||
fun objectLayoutComponent() : ObjectLayoutSubComponent.Builder
|
||||
fun objectAppearanceSettingComponent() : ObjectAppearanceSettingSubComponent.Builder
|
||||
fun objectAppearanceIconComponent() : ObjectAppearanceIconSubComponent.Builder
|
||||
fun objectAppearancePreviewLayoutComponent() : ObjectAppearancePreviewLayoutSubComponent.Builder
|
||||
fun objectAppearanceCoverComponent() : ObjectAppearanceCoverSubComponent.Builder
|
||||
fun objectAppearanceChooseDescription() : ObjectAppearanceChooseDescriptionSubComponent.Builder
|
||||
fun objectLayoutComponent(): ObjectLayoutSubComponent.Builder
|
||||
fun objectAppearanceSettingComponent(): ObjectAppearanceSettingSubComponent.Builder
|
||||
fun objectAppearanceIconComponent(): ObjectAppearanceIconSubComponent.Builder
|
||||
fun objectAppearancePreviewLayoutComponent(): ObjectAppearancePreviewLayoutSubComponent.Builder
|
||||
fun objectAppearanceCoverComponent(): ObjectAppearanceCoverSubComponent.Builder
|
||||
fun objectAppearanceChooseDescription(): ObjectAppearanceChooseDescriptionSubComponent.Builder
|
||||
|
||||
fun setBlockTextValueComponent(): SetBlockTextValueSubComponent.Builder
|
||||
}
|
||||
|
@ -253,7 +263,7 @@ object EditorSessionModule {
|
|||
getDefaultEditorType: GetDefaultEditorType,
|
||||
getTemplates: GetTemplates,
|
||||
createPage: CreatePage,
|
||||
) : CreateNewObject = CreateNewObject(
|
||||
): CreateNewObject = CreateNewObject(
|
||||
getDefaultEditorType,
|
||||
getTemplates,
|
||||
createPage
|
||||
|
@ -265,7 +275,7 @@ object EditorSessionModule {
|
|||
fun provideTemplateDelegate(
|
||||
getTemplates: GetTemplates,
|
||||
applyTemplate: ApplyTemplate
|
||||
) : EditorTemplateDelegate = DefaultEditorTemplateDelegate(
|
||||
): EditorTemplateDelegate = DefaultEditorTemplateDelegate(
|
||||
getTemplates = getTemplates,
|
||||
applyTemplate = applyTemplate
|
||||
)
|
||||
|
@ -274,7 +284,7 @@ object EditorSessionModule {
|
|||
@Provides
|
||||
@PerScreen
|
||||
fun provideSimpleTableDelegate(
|
||||
) : SimpleTableDelegate = DefaultSimpleTableDelegate()
|
||||
): SimpleTableDelegate = DefaultSimpleTableDelegate()
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
@ -294,7 +304,8 @@ object EditorSessionModule {
|
|||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
fun provideDocumentExternalEventReducer(): DocumentExternalEventReducer = DocumentExternalEventReducer()
|
||||
fun provideDocumentExternalEventReducer(): DocumentExternalEventReducer =
|
||||
DocumentExternalEventReducer()
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
@ -349,7 +360,8 @@ object EditorSessionModule {
|
|||
redo: Redo,
|
||||
setRelationKey: SetRelationKey,
|
||||
analytics: Analytics,
|
||||
updateBlocksMark: UpdateBlocksMark
|
||||
updateBlocksMark: UpdateBlocksMark,
|
||||
middlewareShareDownloader: MiddlewareShareDownloader
|
||||
): Orchestrator = Orchestrator(
|
||||
stores = storage,
|
||||
createBlock = createBlock,
|
||||
|
@ -369,6 +381,7 @@ object EditorSessionModule {
|
|||
updateDivider = updateDivider,
|
||||
memory = memory,
|
||||
downloadFile = downloadFile,
|
||||
middlewareShareDownloader = middlewareShareDownloader,
|
||||
turnIntoDocument = turnIntoDocument,
|
||||
textInteractor = Interactor.TextInteractor(
|
||||
proxies = proxer,
|
||||
|
@ -389,7 +402,7 @@ object EditorSessionModule {
|
|||
updateBlocksMark = updateBlocksMark,
|
||||
setObjectType = setObjectType,
|
||||
createTable = createTable,
|
||||
fillTableRow = fillTableRow
|
||||
fillTableRow = fillTableRow,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -790,21 +803,21 @@ object EditorUseCaseModule {
|
|||
@PerScreen
|
||||
fun provideDefaultObjectRelationProvider(
|
||||
storage: Editor.Storage
|
||||
) : ObjectRelationProvider = DefaultObjectRelationProvider(storage.relations)
|
||||
): ObjectRelationProvider = DefaultObjectRelationProvider(storage.relations)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideDefaultObjectValueProvider(
|
||||
storage: Editor.Storage
|
||||
) : ObjectValueProvider = DefaultObjectValueProvider(storage.details)
|
||||
): ObjectValueProvider = DefaultObjectValueProvider(storage.details)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideObjectTypeProvider(
|
||||
storage: Editor.Storage
|
||||
) : ObjectTypeProvider = object : ObjectTypeProvider {
|
||||
): ObjectTypeProvider = object : ObjectTypeProvider {
|
||||
override fun provide(): List<ObjectType> = storage.objectTypes.current()
|
||||
}
|
||||
|
||||
|
@ -813,26 +826,26 @@ object EditorUseCaseModule {
|
|||
@PerScreen
|
||||
fun provideObjectDetailProvider(
|
||||
storage: Editor.Storage
|
||||
) : ObjectDetailProvider = object : ObjectDetailProvider {
|
||||
): ObjectDetailProvider = object : ObjectDetailProvider {
|
||||
override fun provide(): Map<Id, Block.Fields> = storage.details.current().details
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun providePayloadDispatcher() : Dispatcher<Payload> = Dispatcher.Default()
|
||||
fun providePayloadDispatcher(): Dispatcher<Payload> = Dispatcher.Default()
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideDelegator() : Delegator<Action> = Delegator.Default()
|
||||
fun provideDelegator(): Delegator<Action> = Delegator.Default()
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideDetailManager(
|
||||
storage: Editor.Storage
|
||||
) : DetailModificationManager = InternalDetailModificationManager(
|
||||
): DetailModificationManager = InternalDetailModificationManager(
|
||||
store = storage.details
|
||||
)
|
||||
|
||||
|
@ -846,14 +859,14 @@ object EditorUseCaseModule {
|
|||
@PerScreen
|
||||
fun provideUpdateDetailUseCase(
|
||||
repository: BlockRepository
|
||||
) : UpdateDetail = UpdateDetail(repository)
|
||||
): UpdateDetail = UpdateDetail(repository)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetObjectTypesUseCase(
|
||||
repository: BlockRepository
|
||||
) : GetObjectTypes = GetObjectTypes(repository)
|
||||
): GetObjectTypes = GetObjectTypes(repository)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
@ -934,7 +947,7 @@ object EditorUseCaseModule {
|
|||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun getTemplates(repo: BlockRepository) : GetTemplates = GetTemplates(
|
||||
fun getTemplates(repo: BlockRepository): GetTemplates = GetTemplates(
|
||||
repo = repo,
|
||||
dispatchers = AppCoroutineDispatchers(
|
||||
io = Dispatchers.IO,
|
||||
|
@ -946,7 +959,7 @@ object EditorUseCaseModule {
|
|||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun applyTemplates(repo: BlockRepository) : ApplyTemplate = ApplyTemplate(
|
||||
fun applyTemplates(repo: BlockRepository): ApplyTemplate = ApplyTemplate(
|
||||
repo = repo,
|
||||
dispatchers = AppCoroutineDispatchers(
|
||||
io = Dispatchers.IO,
|
||||
|
@ -954,4 +967,32 @@ object EditorUseCaseModule {
|
|||
main = Dispatchers.Main
|
||||
)
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun providesMiddlewareShareDownloader(
|
||||
repo: BlockRepository,
|
||||
context: Context,
|
||||
fileProvider: UriFileProvider
|
||||
): MiddlewareShareDownloader = MiddlewareShareDownloader(
|
||||
repo = repo,
|
||||
dispatchers = AppCoroutineDispatchers(
|
||||
io = Dispatchers.IO,
|
||||
computation = Dispatchers.Default,
|
||||
main = Dispatchers.Main
|
||||
),
|
||||
context = context.applicationContext,
|
||||
uriFileProvider = fileProvider
|
||||
)
|
||||
|
||||
@Module
|
||||
interface Bindings {
|
||||
|
||||
@PerScreen
|
||||
@Binds
|
||||
fun bindUriFileProvider(
|
||||
defaultProvider: DefaultUriFileProvider
|
||||
): UriFileProvider
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.anytypeio.anytype.providers
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.core.content.FileProvider
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
|
||||
class DefaultUriFileProvider @Inject constructor(
|
||||
private val context: Context
|
||||
) : UriFileProvider {
|
||||
|
||||
override fun getUriForFile(file: File): Uri = FileProvider.getUriForFile(
|
||||
context,
|
||||
BuildConfig.APPLICATION_ID + PROVIDER,
|
||||
file
|
||||
)
|
||||
}
|
||||
|
||||
private const val PROVIDER = ".provider"
|
|
@ -2,9 +2,13 @@ package com.anytypeio.anytype.ui.editor
|
|||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.app.Activity
|
||||
import android.app.DownloadManager
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ClipData
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Point
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
|
@ -22,6 +26,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
|||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.animation.doOnStart
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP
|
||||
|
@ -1104,7 +1109,11 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
is Command.ShowKeyboard -> {
|
||||
binding.recycler.findFocus()?.focusAndShowKeyboard()
|
||||
}
|
||||
is Command.OpenFileByDefaultApp -> openFileByDefaultApp(command)
|
||||
is Command.OpenFileByDefaultApp -> {
|
||||
vm.startSharingFile(command.id) { uri ->
|
||||
openFileByDefaultApp(uri)
|
||||
}
|
||||
}
|
||||
Command.ShowTextLinkMenu -> {
|
||||
val urlButton = binding.markupToolbar.findViewById<View>(R.id.url)
|
||||
val popup = TextLinkPopupMenu(
|
||||
|
@ -1149,22 +1158,18 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
}
|
||||
}
|
||||
|
||||
private fun openFileByDefaultApp(command: Command.OpenFileByDefaultApp) {
|
||||
private fun openFileByDefaultApp(uri: Uri) {
|
||||
try {
|
||||
val uri = Uri.parse(command.uri)
|
||||
val intent = Intent().apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
if (command.mime.isNotEmpty()) {
|
||||
setDataAndTypeAndNormalize(uri, command.mime)
|
||||
} else {
|
||||
data = uri
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
.apply {
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
startActivity(intent)
|
||||
startActivity(
|
||||
intent
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
if (e is ActivityNotFoundException) {
|
||||
toast("No Application found to open the selected file")
|
||||
toast("No application found to open the selected file")
|
||||
} else {
|
||||
toast("Could not open file: ${e.message}")
|
||||
}
|
||||
|
|
4
app/src/main/res/xml/provider_paths.xml
Normal file
4
app/src/main/res/xml/provider_paths.xml
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<cache-path name="." path="/" />
|
||||
</paths>
|
|
@ -7,6 +7,11 @@ sealed class Command {
|
|||
val type: Block.Content.File.Type?
|
||||
)
|
||||
|
||||
class DownloadFile(
|
||||
val path: String,
|
||||
val hash: Hash
|
||||
)
|
||||
|
||||
/**
|
||||
* Command for turning simple blocks into documents
|
||||
* @property context id of the context
|
||||
|
|
|
@ -5,7 +5,5 @@ import com.anytypeio.anytype.domain.download.Downloader
|
|||
|
||||
class DataDownloader(private val device: Device) : Downloader {
|
||||
|
||||
override fun download(url: Url, name: String) {
|
||||
device.download(url, name)
|
||||
}
|
||||
override fun download(url: Url, name: String) = device.download(url, name)
|
||||
}
|
|
@ -256,6 +256,10 @@ class BlockDataRepository(
|
|||
command: Command.UploadFile
|
||||
): Hash = remote.uploadFile(command)
|
||||
|
||||
override suspend fun downloadFile(
|
||||
command: Command.DownloadFile
|
||||
): String = remote.downloadFile(command)
|
||||
|
||||
override suspend fun getObjectInfoWithLinks(
|
||||
pageId: String
|
||||
): ObjectInfoWithLinks = remote.getObjectInfoWithLinks(pageId)
|
||||
|
|
|
@ -77,6 +77,7 @@ interface BlockDataStore {
|
|||
suspend fun setRelationKey(command: Command.SetRelationKey): Payload
|
||||
|
||||
suspend fun uploadFile(command: Command.UploadFile): String
|
||||
suspend fun downloadFile(command: Command.DownloadFile): String
|
||||
|
||||
suspend fun getObjectInfoWithLinks(pageId: String): ObjectInfoWithLinks
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ interface BlockRemote {
|
|||
suspend fun copy(command: Command.Copy) : Response.Clipboard.Copy
|
||||
|
||||
suspend fun uploadFile(command: Command.UploadFile): String
|
||||
suspend fun downloadFile(command: Command.DownloadFile): String
|
||||
|
||||
suspend fun getObjectInfoWithLinks(pageId: String): ObjectInfoWithLinks
|
||||
|
||||
|
|
|
@ -198,6 +198,10 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
command: Command.UploadFile
|
||||
): String = remote.uploadFile(command)
|
||||
|
||||
override suspend fun downloadFile(
|
||||
command: Command.DownloadFile
|
||||
): String = remote.downloadFile(command)
|
||||
|
||||
override suspend fun getObjectInfoWithLinks(pageId: String): ObjectInfoWithLinks =
|
||||
remote.getObjectInfoWithLinks(pageId)
|
||||
|
||||
|
|
|
@ -6,7 +6,5 @@ import com.anytypeio.anytype.device.download.AndroidDeviceDownloader
|
|||
class AndroidDevice(
|
||||
private val downloader: AndroidDeviceDownloader
|
||||
) : Device {
|
||||
override fun download(url: String, name: String) {
|
||||
downloader.download(url = url, name = name)
|
||||
}
|
||||
override fun download(url: String, name: String) = downloader.download(url = url, name = name)
|
||||
}
|
|
@ -28,6 +28,7 @@ import com.anytypeio.anytype.domain.page.Undo
|
|||
interface BlockRepository {
|
||||
|
||||
suspend fun uploadFile(command: Command.UploadFile): Hash
|
||||
suspend fun downloadFile(command: Command.DownloadFile): String
|
||||
|
||||
suspend fun move(command: Command.Move): Payload
|
||||
suspend fun unlink(command: Command.Unlink): Payload
|
||||
|
|
|
@ -225,6 +225,10 @@ class BlockMiddleware(
|
|||
command: Command.UploadFile
|
||||
): String = middleware.fileUpload(command).hash
|
||||
|
||||
override suspend fun downloadFile(
|
||||
command: Command.DownloadFile
|
||||
): String = middleware.fileDownload(command).localPath
|
||||
|
||||
override suspend fun getObjectInfoWithLinks(pageId: String): ObjectInfoWithLinks {
|
||||
return middleware.navigationGetObjectInfoWithLinks(pageId).toCoreModel()
|
||||
}
|
||||
|
|
|
@ -911,6 +911,18 @@ class Middleware(
|
|||
return Response.Media.Upload(response.hash)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun fileDownload(command: Command.DownloadFile): Rpc.File.Download.Response {
|
||||
val request = Rpc.File.Download.Request(
|
||||
hash = command.hash,
|
||||
path = command.path
|
||||
)
|
||||
if (BuildConfig.DEBUG) logRequest(request)
|
||||
val response = service.fileDownload(request)
|
||||
if (BuildConfig.DEBUG) logResponse(response)
|
||||
return response
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun getConfig(): Config {
|
||||
TODO()
|
||||
|
|
|
@ -156,6 +156,9 @@ interface MiddlewareService {
|
|||
@Throws(Exception::class)
|
||||
fun fileUpload(request: Rpc.File.Upload.Request): Rpc.File.Upload.Response
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun fileDownload(request: Rpc.File.Download.Request): Rpc.File.Download.Response
|
||||
|
||||
//endregion
|
||||
|
||||
//region UNSPLASH commands
|
||||
|
|
|
@ -583,6 +583,17 @@ class MiddlewareServiceImplementation : MiddlewareService {
|
|||
}
|
||||
}
|
||||
|
||||
override fun fileDownload(request: Rpc.File.Download.Request): Rpc.File.Download.Response {
|
||||
val encoded = Service.fileDownload(Rpc.File.Download.Request.ADAPTER.encode(request))
|
||||
val response = Rpc.File.Download.Response.ADAPTER.decode(encoded)
|
||||
val error = response.error
|
||||
if (error != null && error.code != Rpc.File.Download.Response.Error.Code.NULL) {
|
||||
throw Exception(error.description)
|
||||
} else {
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
||||
override fun navigationListObjects(request: Rpc.Navigation.ListObjects.Request): Rpc.Navigation.ListObjects.Response {
|
||||
val encoded =
|
||||
Service.navigationListObjects(Rpc.Navigation.ListObjects.Request.ADAPTER.encode(request))
|
||||
|
|
|
@ -194,6 +194,7 @@ import com.anytypeio.anytype.presentation.util.CopyFileStatus
|
|||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.OnCopyFileToCacheAction
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
@ -3882,6 +3883,31 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun startSharingFile(id: String, onDownloaded: (Uri) -> Unit = {}) {
|
||||
|
||||
Timber.d("startDownloadingFile, id:[$id]")
|
||||
|
||||
sendToast("Preparing file to share...")
|
||||
|
||||
val block = blocks.firstOrNull { it.id == id }
|
||||
val content = block?.content
|
||||
|
||||
if (content is Content.File && content.state == Content.File.State.DONE) {
|
||||
viewModelScope.launch {
|
||||
orchestrator.proxies.intents.send(
|
||||
Media.ShareFile(
|
||||
hash = content.hash.orEmpty(),
|
||||
name = content.name.orEmpty(),
|
||||
type = content.type,
|
||||
onDownloaded = onDownloaded
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Timber.e("Block is not File or with wrong state, can't proceed with share!")
|
||||
}
|
||||
}
|
||||
|
||||
fun startDownloadingFile(id: String) {
|
||||
|
||||
Timber.d("startDownloadingFile, id:[$id]")
|
||||
|
@ -4524,11 +4550,15 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getObjectTypes(excluded: List<Id> = emptyList(), action: (List<ObjectType>) -> Unit) {
|
||||
private fun getObjectTypes(
|
||||
excluded: List<Id> = emptyList(),
|
||||
action: (List<ObjectType>) -> Unit
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
getCompatibleObjectTypes.invoke(
|
||||
GetCompatibleObjectTypes.Params(
|
||||
smartBlockType = blocks.first { it.id == context }.content<Content.Smart>().type,
|
||||
smartBlockType = blocks.first { it.id == context }
|
||||
.content<Content.Smart>().type,
|
||||
excludedTypes = excluded
|
||||
)
|
||||
).proceed(
|
||||
|
@ -5115,7 +5145,9 @@ class EditorViewModel(
|
|||
when (val content = selected.content) {
|
||||
is Content.Bookmark -> {
|
||||
val target = content.targetObjectId
|
||||
if (target != null) { proceedWithOpeningPage(target) }
|
||||
if (target != null) {
|
||||
proceedWithOpeningPage(target)
|
||||
}
|
||||
}
|
||||
else -> sendToast("Unexpected object")
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import com.anytypeio.anytype.domain.block.interactor.UpdateLinkMarks
|
|||
import com.anytypeio.anytype.domain.block.interactor.sets.CreateObjectSet
|
||||
import com.anytypeio.anytype.domain.cover.SetDocCoverImage
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.GetCompatibleObjectTypes
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
|
@ -21,15 +20,16 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
|
|||
import com.anytypeio.anytype.domain.page.CloseBlock
|
||||
import com.anytypeio.anytype.domain.page.CreateDocument
|
||||
import com.anytypeio.anytype.domain.page.CreateNewDocument
|
||||
import com.anytypeio.anytype.domain.page.CreateNewObject
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
import com.anytypeio.anytype.domain.page.OpenPage
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.presentation.common.Action
|
||||
import com.anytypeio.anytype.presentation.common.Delegator
|
||||
import com.anytypeio.anytype.presentation.common.StateReducer
|
||||
import com.anytypeio.anytype.domain.page.CreateNewObject
|
||||
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
|
||||
import com.anytypeio.anytype.presentation.editor.editor.table.SimpleTableDelegate
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.anytypeio.anytype.presentation.editor.editor
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Parcelable
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Position
|
||||
import com.anytypeio.anytype.core_utils.ext.Mimetype
|
||||
|
@ -174,6 +176,13 @@ sealed class Intent {
|
|||
val type: Block.Content.File.Type?
|
||||
) : Media()
|
||||
|
||||
class ShareFile(
|
||||
val hash: Hash,
|
||||
val name: String,
|
||||
val type: Block.Content.File.Type?,
|
||||
val onDownloaded: (Uri) -> Unit
|
||||
) : Media()
|
||||
|
||||
class Upload(
|
||||
val context: Id,
|
||||
val description: Description,
|
||||
|
|
|
@ -35,6 +35,7 @@ import com.anytypeio.anytype.domain.page.bookmark.CreateBookmarkBlock
|
|||
import com.anytypeio.anytype.domain.page.bookmark.SetupBookmark
|
||||
import com.anytypeio.anytype.domain.table.CreateTable
|
||||
import com.anytypeio.anytype.domain.table.FillTableRow
|
||||
import com.anytypeio.anytype.presentation.dashboard.HomeDashboardStateMachine
|
||||
import com.anytypeio.anytype.presentation.editor.Editor
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsChangeTextBlockStyleEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsCopyBlockEvent
|
||||
|
@ -48,6 +49,7 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsReorderBlockEve
|
|||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSplitBlockEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsUndoEvent
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsUploadMediaEvent
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import timber.log.Timber
|
||||
|
||||
class Orchestrator(
|
||||
|
@ -64,6 +66,7 @@ class Orchestrator(
|
|||
private val turnIntoStyle: TurnIntoStyle,
|
||||
private val updateCheckbox: UpdateCheckbox,
|
||||
private val downloadFile: DownloadFile,
|
||||
private val middlewareShareDownloader: MiddlewareShareDownloader,
|
||||
val updateText: UpdateText,
|
||||
private val updateAlignment: UpdateAlignment,
|
||||
private val uploadBlock: UploadBlock,
|
||||
|
@ -432,6 +435,20 @@ class Orchestrator(
|
|||
success = { analytics.sendAnalyticsDownloadMediaEvent(intent.type) }
|
||||
)
|
||||
}
|
||||
is Intent.Media.ShareFile -> {
|
||||
middlewareShareDownloader.execute(
|
||||
params = MiddlewareShareDownloader.Params(
|
||||
hash = intent.hash,
|
||||
name = intent.name
|
||||
)
|
||||
).fold(
|
||||
onSuccess = { uri ->
|
||||
intent.onDownloaded(uri)
|
||||
analytics.sendAnalyticsDownloadMediaEvent(intent.type)
|
||||
},
|
||||
onFailure = { e -> Timber.e(e, "Error while sharing a file") }
|
||||
)
|
||||
}
|
||||
is Intent.Media.Upload -> {
|
||||
uploadBlock(
|
||||
params = UploadBlock.Params(
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package com.anytypeio.anytype.presentation.util.downloader
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.presentation.util.TEMPORARY_DIRECTORY_NAME
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
||||
class MiddlewareShareDownloader(
|
||||
private val repo: BlockRepository,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val context: Context,
|
||||
private val uriFileProvider: UriFileProvider
|
||||
) : ResultInteractor<MiddlewareShareDownloader.Params, Uri>() {
|
||||
|
||||
data class Params(
|
||||
val hash: Hash,
|
||||
val name: String
|
||||
)
|
||||
|
||||
override suspend fun doWork(params: Params) = withContext(dispatchers.io) {
|
||||
val cacheDir = context.cacheDir
|
||||
|
||||
require(cacheDir != null) { "Impossible to cache files!" }
|
||||
|
||||
val downloadFolder = File("${cacheDir.path}/${params.hash}").apply { mkdirs() }
|
||||
|
||||
val resultFilePath = "${cacheDir.path}/${params.hash}/${params.name}"
|
||||
val resultFile = File(resultFilePath)
|
||||
|
||||
if (!resultFile.exists()) {
|
||||
val tempFileFolderPath = "${downloadFolder.absolutePath}/tmp"
|
||||
val tempDir = File(tempFileFolderPath)
|
||||
if (tempDir.exists()) tempDir.deleteRecursively()
|
||||
tempDir.mkdirs()
|
||||
|
||||
val tempResult = File(
|
||||
repo.downloadFile(
|
||||
Command.DownloadFile(
|
||||
hash = params.hash,
|
||||
path = tempFileFolderPath
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
tempResult.renameTo(resultFile)
|
||||
}
|
||||
uriFileProvider.getUriForFile(resultFile)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.anytypeio.anytype.presentation.util.downloader
|
||||
|
||||
import android.net.Uri
|
||||
import java.io.File
|
||||
|
||||
interface UriFileProvider {
|
||||
|
||||
fun getUriForFile(file: File): Uri
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.presentation.editor
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
|
@ -13,7 +14,9 @@ import com.anytypeio.anytype.core_models.SmartBlockType
|
|||
import com.anytypeio.anytype.core_models.StubFile
|
||||
import com.anytypeio.anytype.core_models.StubNumbered
|
||||
import com.anytypeio.anytype.core_models.StubParagraph
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.content
|
||||
import com.anytypeio.anytype.core_models.ext.parseThemeTextColor
|
||||
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
|
||||
import com.anytypeio.anytype.core_utils.common.EventWrapper
|
||||
import com.anytypeio.anytype.core_utils.ext.Mimetype
|
||||
|
@ -50,8 +53,6 @@ import com.anytypeio.anytype.domain.clipboard.Paste
|
|||
import com.anytypeio.anytype.domain.config.Gateway
|
||||
import com.anytypeio.anytype.domain.cover.SetDocCoverImage
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.GetCompatibleObjectTypes
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.download.DownloadFile
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
|
@ -68,12 +69,14 @@ import com.anytypeio.anytype.domain.page.Undo
|
|||
import com.anytypeio.anytype.domain.page.UpdateTitle
|
||||
import com.anytypeio.anytype.domain.page.bookmark.CreateBookmarkBlock
|
||||
import com.anytypeio.anytype.domain.page.bookmark.SetupBookmark
|
||||
import com.anytypeio.anytype.domain.relations.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.sets.FindObjectSetForType
|
||||
import com.anytypeio.anytype.domain.status.InterceptThreadStatus
|
||||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
import com.anytypeio.anytype.domain.templates.GetTemplates
|
||||
import com.anytypeio.anytype.domain.table.CreateTable
|
||||
import com.anytypeio.anytype.domain.table.FillTableRow
|
||||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
import com.anytypeio.anytype.domain.templates.GetTemplates
|
||||
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
|
||||
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
|
||||
import com.anytypeio.anytype.presentation.BuildConfig
|
||||
|
@ -87,8 +90,6 @@ import com.anytypeio.anytype.presentation.editor.editor.Interactor
|
|||
import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Orchestrator
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
import com.anytypeio.anytype.core_models.ext.parseThemeTextColor
|
||||
import com.anytypeio.anytype.presentation.editor.editor.ViewState
|
||||
import com.anytypeio.anytype.presentation.editor.editor.actions.ActionItemType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState
|
||||
|
@ -111,6 +112,7 @@ import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
|||
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.TXT
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import com.anytypeio.anytype.test_utils.ValueClassAnswer
|
||||
import com.jraska.livedata.test
|
||||
|
@ -121,6 +123,7 @@ import kotlinx.coroutines.flow.emptyFlow
|
|||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
@ -132,6 +135,7 @@ import org.mockito.kotlin.argThat
|
|||
import org.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.eq
|
||||
import org.mockito.kotlin.given
|
||||
import org.mockito.kotlin.never
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.times
|
||||
|
@ -223,6 +227,9 @@ open class EditorViewModelTest {
|
|||
@Mock
|
||||
lateinit var downloadFile: DownloadFile
|
||||
|
||||
@Mock
|
||||
lateinit var middlewareShareDownloader: MiddlewareShareDownloader
|
||||
|
||||
@Mock
|
||||
lateinit var uploadBlock: UploadBlock
|
||||
|
||||
|
@ -2616,6 +2623,63 @@ open class EditorViewModelTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start sharing a file`() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
val file = MockBlockFactory.makeFileBlock()
|
||||
val title = MockBlockFactory.makeTitleBlock()
|
||||
|
||||
val page = listOf(
|
||||
Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart(),
|
||||
children = listOf(title.id, file.id)
|
||||
),
|
||||
title,
|
||||
file
|
||||
)
|
||||
|
||||
val flow: Flow<List<Event.Command>> = flow {
|
||||
delay(100)
|
||||
emit(
|
||||
listOf(
|
||||
Event.Command.ShowObject(
|
||||
root = root,
|
||||
blocks = page,
|
||||
context = root
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
stubObserveEvents(flow)
|
||||
stubOpenPage()
|
||||
givenViewModel(builder)
|
||||
|
||||
givenSharedFile()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
|
||||
// TESTING
|
||||
|
||||
vm.startSharingFile(id = file.id)
|
||||
|
||||
runTest {
|
||||
verify(middlewareShareDownloader, times(1)).execute(
|
||||
params = eq(
|
||||
MiddlewareShareDownloader.Params(
|
||||
name = file.content<Block.Content.File>().name.orEmpty(),
|
||||
hash = file.content<Block.Content.File>().hash.orEmpty(),
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start downloading file`() {
|
||||
|
||||
|
@ -3817,6 +3881,12 @@ open class EditorViewModelTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun givenSharedFile() {
|
||||
middlewareShareDownloader.stub {
|
||||
onBlocking { execute(any()) } doAnswer ValueClassAnswer(Uri.EMPTY)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stubUpdateTextColor(root: String) {
|
||||
updateTextColor.stub {
|
||||
onBlocking { invoke(any()) } doReturn Either.Right(
|
||||
|
@ -3878,7 +3948,9 @@ open class EditorViewModelTest {
|
|||
vm = EditorViewModel(
|
||||
openPage = openPage,
|
||||
closePage = closePage,
|
||||
createDocument = createDocument,
|
||||
createObject = createObject,
|
||||
createNewDocument = createNewDocument,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
updateLinkMarks = updateLinkMark,
|
||||
|
@ -3890,16 +3962,13 @@ open class EditorViewModelTest {
|
|||
toggleStateHolder = ToggleStateHolder.Default(),
|
||||
coverImageHashProvider = coverImageHashProvider
|
||||
),
|
||||
createDocument = createDocument,
|
||||
createNewDocument = createNewDocument,
|
||||
analytics = analytics,
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
orchestrator = Orchestrator(
|
||||
createBlock = createBlock,
|
||||
replaceBlock = replaceBlock,
|
||||
updateTextColor = updateTextColor,
|
||||
duplicateBlock = duplicateBlock,
|
||||
downloadFile = downloadFile,
|
||||
middlewareShareDownloader = middlewareShareDownloader,
|
||||
undo = undo,
|
||||
redo = redo,
|
||||
updateText = updateText,
|
||||
|
@ -3935,22 +4004,24 @@ open class EditorViewModelTest {
|
|||
createTable = createTable,
|
||||
fillTableRow = fillTableRow
|
||||
),
|
||||
analytics = analytics,
|
||||
dispatcher = Dispatcher.Default(),
|
||||
delegator = delegator,
|
||||
detailModificationManager = InternalDetailModificationManager(storage.details),
|
||||
updateDetail = updateDetail,
|
||||
getCompatibleObjectTypes = getCompatibleObjectTypes,
|
||||
objectTypesProvider = objectTypesProvider,
|
||||
searchObjects = searchObjects,
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
findObjectSetForType = findObjectSetForType,
|
||||
createObjectSet = createObjectSet,
|
||||
copyFileToCache = copyFileToCacheDirectory,
|
||||
downloadUnsplashImage = downloadUnsplashImage,
|
||||
setDocCoverImage = setDocCoverImage,
|
||||
setDocImageIcon = setDocImageIcon,
|
||||
delegator = delegator,
|
||||
templateDelegate = editorTemplateDelegate,
|
||||
createNewObject = createNewObject,
|
||||
simpleTableDelegate = simpleTableDelegate
|
||||
simpleTableDelegate = simpleTableDelegate,
|
||||
createNewObject = createNewObject
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ import com.anytypeio.anytype.presentation.editor.template.EditorTemplateDelegate
|
|||
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
|
||||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.downloader.MiddlewareShareDownloader
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import com.anytypeio.anytype.test_utils.ValueClassAnswer
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -164,6 +165,9 @@ open class EditorPresentationTestSetup {
|
|||
@Mock
|
||||
lateinit var downloadFile: DownloadFile
|
||||
|
||||
@Mock
|
||||
lateinit var middlewareShareDownloader: MiddlewareShareDownloader
|
||||
|
||||
@Mock
|
||||
lateinit var uploadBlock: UploadBlock
|
||||
|
||||
|
@ -298,6 +302,7 @@ open class EditorPresentationTestSetup {
|
|||
updateTextColor = updateTextColor,
|
||||
duplicateBlock = duplicateBlock,
|
||||
downloadFile = downloadFile,
|
||||
middlewareShareDownloader = middlewareShareDownloader,
|
||||
undo = undo,
|
||||
redo = redo,
|
||||
updateText = updateText,
|
||||
|
@ -337,11 +342,13 @@ open class EditorPresentationTestSetup {
|
|||
return EditorViewModel(
|
||||
openPage = openPage,
|
||||
closePage = closePage,
|
||||
createDocument = createDocument,
|
||||
createObject = createObject,
|
||||
createNewDocument = createNewDocument,
|
||||
interceptEvents = interceptEvents,
|
||||
interceptThreadStatus = interceptThreadStatus,
|
||||
updateLinkMarks = updateLinkMark,
|
||||
removeLinkMark = removeLinkMark,
|
||||
createObject = createObject,
|
||||
reducer = DocumentExternalEventReducer(),
|
||||
urlBuilder = urlBuilder,
|
||||
renderer = DefaultBlockViewRenderer(
|
||||
|
@ -349,11 +356,10 @@ open class EditorPresentationTestSetup {
|
|||
toggleStateHolder = ToggleStateHolder.Default(),
|
||||
coverImageHashProvider = coverImageHashProvider
|
||||
),
|
||||
createDocument = createDocument,
|
||||
createNewDocument = createNewDocument,
|
||||
analytics = analytics,
|
||||
orchestrator = orchestrator,
|
||||
analytics = analytics,
|
||||
dispatcher = Dispatcher.Default(),
|
||||
delegator = delegator,
|
||||
detailModificationManager = InternalDetailModificationManager(storage.details),
|
||||
updateDetail = updateDetail,
|
||||
getCompatibleObjectTypes = getCompatibleObjectTypes,
|
||||
|
@ -363,13 +369,12 @@ open class EditorPresentationTestSetup {
|
|||
findObjectSetForType = findObjectSetForType,
|
||||
createObjectSet = createObjectSet,
|
||||
copyFileToCache = copyFileToCacheDirectory,
|
||||
delegator = delegator,
|
||||
downloadUnsplashImage = downloadUnsplashImage,
|
||||
setDocCoverImage = setDocCoverImage,
|
||||
setDocImageIcon = setDocImageIcon,
|
||||
downloadUnsplashImage = downloadUnsplashImage,
|
||||
templateDelegate = editorTemplateDelegate,
|
||||
createNewObject = createNewObject,
|
||||
simpleTableDelegate = simpleTableDelegate
|
||||
simpleTableDelegate = simpleTableDelegate,
|
||||
createNewObject = createNewObject
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user