mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Download files on phone (#277)
This commit is contained in:
parent
96d72520a7
commit
cb734d5b86
30 changed files with 422 additions and 32 deletions
|
@ -75,6 +75,7 @@ dependencies {
|
|||
|
||||
implementation project(':domain')
|
||||
implementation project(':data')
|
||||
implementation project(':device')
|
||||
implementation project(':persistence')
|
||||
implementation project(':middleware')
|
||||
implementation project(':presentation')
|
||||
|
|
|
@ -1,35 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.agileburo.anytype">
|
||||
package="com.agileburo.anytype">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application
|
||||
android:name=".app.AndroidApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:fullBackupContent="@xml/my_backup_rules"
|
||||
android:theme="@style/AppTheme">
|
||||
android:allowBackup="true"
|
||||
android:fullBackupContent="@xml/my_backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize">
|
||||
android:windowSoftInputMode="stateHidden|adjustResize">
|
||||
<intent-filter android:label="filter">
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="http"
|
||||
android:host="www.anytype.io"
|
||||
android:pathPrefix="/todo"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="www.anytype.io"
|
||||
android:pathPrefix="/todo"
|
||||
android:scheme="http" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
|
|
@ -17,6 +17,7 @@ class AndroidApplication : Application() {
|
|||
.dataModule(DataModule())
|
||||
.configModule(ConfigModule())
|
||||
.utilModule(UtilModule())
|
||||
.deviceModule(DeviceModule())
|
||||
.build()
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.agileburo.anytype.di.feature
|
|||
import com.agileburo.anytype.core_utils.di.scope.PerScreen
|
||||
import com.agileburo.anytype.domain.block.interactor.*
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.download.Downloader
|
||||
import com.agileburo.anytype.domain.event.interactor.EventChannel
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.misc.UrlBuilder
|
||||
|
@ -53,7 +55,8 @@ class PageModule {
|
|||
splitBlock: SplitBlock,
|
||||
createPage: CreatePage,
|
||||
documentExternalEventReducer: DocumentExternalEventReducer,
|
||||
urlBuilder: UrlBuilder
|
||||
urlBuilder: UrlBuilder,
|
||||
downloadFile: DownloadFile
|
||||
): PageViewModelFactory = PageViewModelFactory(
|
||||
openPage = openPage,
|
||||
closePage = closePage,
|
||||
|
@ -72,7 +75,8 @@ class PageModule {
|
|||
mergeBlocks = mergeBlocks,
|
||||
splitBlock = splitBlock,
|
||||
documentEventReducer = documentExternalEventReducer,
|
||||
urlBuilder = urlBuilder
|
||||
urlBuilder = urlBuilder,
|
||||
downloadFile = downloadFile
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
@ -196,6 +200,15 @@ class PageModule {
|
|||
repo = repo
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideDownloadFileUseCase(
|
||||
downloader: Downloader
|
||||
): DownloadFile = DownloadFile(
|
||||
downloader = downloader,
|
||||
context = Dispatchers.Main
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideDocumentExternalEventReducer(): DocumentExternalEventReducer =
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.agileburo.anytype.di.main
|
||||
|
||||
import android.content.Context
|
||||
import com.agileburo.anytype.data.auth.other.DataDownloader
|
||||
import com.agileburo.anytype.data.auth.other.Device
|
||||
import com.agileburo.anytype.device.base.AndroidDevice
|
||||
import com.agileburo.anytype.device.download.DeviceDownloader
|
||||
import com.agileburo.anytype.domain.download.Downloader
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
class DeviceModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDownloader(
|
||||
device: Device
|
||||
): Downloader = DataDownloader(device = device)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDevice(
|
||||
downloader: DeviceDownloader
|
||||
): Device = AndroidDevice(downloader = downloader)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideDeviceDownloader(
|
||||
context: Context
|
||||
): DeviceDownloader = DeviceDownloader(context = context)
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ import javax.inject.Singleton
|
|||
EventModule::class,
|
||||
ImageModule::class,
|
||||
ConfigModule::class,
|
||||
DeviceModule::class,
|
||||
UtilModule::class
|
||||
]
|
||||
)
|
||||
|
|
|
@ -89,7 +89,8 @@ open class PageFragment : NavigationFragment(R.layout.fragment_page),
|
|||
onNonEmptyBlockBackspaceClicked = vm::onNonEmptyBlockBackspaceClicked,
|
||||
onFooterClicked = vm::onOutsideClicked,
|
||||
onPageClicked = vm::onPageClicked,
|
||||
onTextInputClicked = vm::onTextInputClicked
|
||||
onTextInputClicked = vm::onTextInputClicked,
|
||||
onDownloadFileClicked = vm::onDownloadFileClicked
|
||||
)
|
||||
}
|
||||
|
||||
|
|
6
app/src/main/res/xml/network_security_config.xml
Normal file
6
app/src/main/res/xml/network_security_config.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">127.0.0.1</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
|
@ -47,7 +47,8 @@ class BlockAdapter(
|
|||
private val onEndLineEnterClicked: (String, Editable) -> Unit,
|
||||
private val onFooterClicked: () -> Unit,
|
||||
private val onPageClicked: (String) -> Unit,
|
||||
private val onTextInputClicked: () -> Unit
|
||||
private val onTextInputClicked: () -> Unit,
|
||||
private val onDownloadFileClicked: (String) -> Unit
|
||||
) : RecyclerView.Adapter<BlockViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlockViewHolder {
|
||||
|
@ -380,7 +381,8 @@ class BlockAdapter(
|
|||
}
|
||||
is BlockViewHolder.File -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.File
|
||||
item = blocks[position] as BlockView.File,
|
||||
onDownloadFileClicked = onDownloadFileClicked
|
||||
)
|
||||
}
|
||||
is BlockViewHolder.Page -> {
|
||||
|
|
|
@ -271,12 +271,14 @@ sealed class BlockView : ViewType {
|
|||
* @property size a file's size
|
||||
* @property name a name
|
||||
* @property size file size (in bytes)
|
||||
* @property url file url
|
||||
*/
|
||||
data class File(
|
||||
override val id: String,
|
||||
val size: Long,
|
||||
val name: String,
|
||||
val mime: String
|
||||
val mime: String,
|
||||
val url: String
|
||||
) : BlockView() {
|
||||
override fun getViewType() = HOLDER_FILE
|
||||
}
|
||||
|
|
|
@ -603,7 +603,10 @@ sealed class BlockViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
|||
private val size = itemView.fileSize
|
||||
private val name = itemView.filename
|
||||
|
||||
fun bind(item: BlockView.File) {
|
||||
fun bind(
|
||||
item: BlockView.File,
|
||||
onDownloadFileClicked: (String) -> Unit
|
||||
) {
|
||||
name.text = item.name
|
||||
size.text = FileSizeFormatter.formatFileSize(itemView.context, item.size)
|
||||
when (MimeTypes.category(item.mime)) {
|
||||
|
@ -612,6 +615,7 @@ sealed class BlockViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
|||
// TODO add images when they are ready.
|
||||
}
|
||||
}
|
||||
itemView.setOnClickListener { onDownloadFileClicked(item.id) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -846,7 +846,8 @@ class BlockAdapterTest {
|
|||
onSelectionChanged = { _, _ -> },
|
||||
onFooterClicked = {},
|
||||
onPageClicked = {},
|
||||
onTextInputClicked = {}
|
||||
onTextInputClicked = {},
|
||||
onDownloadFileClicked = {}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.agileburo.anytype.data.auth.other
|
||||
|
||||
import com.agileburo.anytype.domain.common.Url
|
||||
import com.agileburo.anytype.domain.download.Downloader
|
||||
|
||||
class DataDownloader(private val device: Device) : Downloader {
|
||||
|
||||
override fun download(url: Url, name: String) {
|
||||
device.download(url, name)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.agileburo.anytype.data.auth.other
|
||||
|
||||
interface Device {
|
||||
fun download(url: String, name: String)
|
||||
}
|
1
device/.gitignore
vendored
Normal file
1
device/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
56
device/build.gradle
Normal file
56
device/build.gradle
Normal file
|
@ -0,0 +1,56 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
def config = rootProject.extensions.getByName("ext")
|
||||
|
||||
compileSdkVersion config["compile_sdk"]
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion config["min_sdk"]
|
||||
targetSdkVersion config["target_sdk"]
|
||||
versionCode config["version_code"]
|
||||
versionName config["version_name"]
|
||||
|
||||
testInstrumentationRunner config["test_runner"]
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
testOptions {
|
||||
unitTests {
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
def applicationDependencies = rootProject.ext.mainApplication
|
||||
def unitTestDependencies = rootProject.ext.unitTesting
|
||||
|
||||
implementation project(':data')
|
||||
|
||||
implementation applicationDependencies.kotlin
|
||||
implementation applicationDependencies.coroutines
|
||||
implementation applicationDependencies.androidxCore
|
||||
|
||||
implementation applicationDependencies.timber
|
||||
|
||||
testImplementation unitTestDependencies.junit
|
||||
testImplementation unitTestDependencies.kotlinTest
|
||||
}
|
0
device/consumer-rules.pro
Normal file
0
device/consumer-rules.pro
Normal file
21
device/proguard-rules.pro
vendored
Normal file
21
device/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
1
device/src/main/AndroidManifest.xml
Normal file
1
device/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1 @@
|
|||
<manifest package="com.agileburo.anytype.device" />
|
|
@ -0,0 +1,11 @@
|
|||
package com.agileburo.anytype.device.base
|
||||
|
||||
import com.agileburo.anytype.data.auth.other.Device
|
||||
import com.agileburo.anytype.device.download.DeviceDownloader
|
||||
|
||||
class AndroidDevice(private val downloader: DeviceDownloader) : Device {
|
||||
|
||||
override fun download(url: String, name: String) {
|
||||
downloader.download(url = url, name = name)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.agileburo.anytype.device.download
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED
|
||||
import android.content.Context
|
||||
import android.content.Context.DOWNLOAD_SERVICE
|
||||
import android.net.Uri
|
||||
import android.os.Environment.DIRECTORY_DOWNLOADS
|
||||
import timber.log.Timber
|
||||
|
||||
class DeviceDownloader(private val context: Context) {
|
||||
|
||||
private val manager by lazy {
|
||||
context.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
|
||||
}
|
||||
|
||||
fun download(url: String, name: String) {
|
||||
|
||||
Timber.d("Downloading file: $name from url: $url")
|
||||
|
||||
val uri = Uri.parse(url)
|
||||
|
||||
context.getExternalFilesDir(DIRECTORY_DOWNLOADS)?.mkdirs()
|
||||
|
||||
val request = DownloadManager.Request(uri)
|
||||
.setTitle(name)
|
||||
.setDescription(DESCRIPTION_TEXT)
|
||||
.setAllowedOverMetered(true)
|
||||
.setAllowedOverRoaming(true)
|
||||
.setNotificationVisibility(VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||
.setDestinationInExternalPublicDir(DIRECTORY_DOWNLOADS, name)
|
||||
|
||||
manager.enqueue(request)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DESCRIPTION_TEXT = "Downloading..."
|
||||
}
|
||||
}
|
3
device/src/main/res/values/strings.xml
Normal file
3
device/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">Device</string>
|
||||
</resources>
|
|
@ -0,0 +1,36 @@
|
|||
package com.agileburo.anytype.domain.download
|
||||
|
||||
import com.agileburo.anytype.domain.base.BaseUseCase
|
||||
import com.agileburo.anytype.domain.base.Either
|
||||
import com.agileburo.anytype.domain.common.Url
|
||||
import com.agileburo.anytype.domain.download.DownloadFile.Params
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* Use-case for starting downloading files.
|
||||
* @see Params
|
||||
*/
|
||||
class DownloadFile(
|
||||
private val downloader: Downloader,
|
||||
context: CoroutineContext
|
||||
) : BaseUseCase<Unit, Params>(context) {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
downloader.download(
|
||||
url = params.url,
|
||||
name = params.name
|
||||
).let { Either.Right(it) }
|
||||
} catch (t: Throwable) {
|
||||
Either.Left(t)
|
||||
}
|
||||
|
||||
/**
|
||||
* Params for downloading file.
|
||||
* @property name file name
|
||||
* @property url url of the file to download
|
||||
*/
|
||||
data class Params(
|
||||
val name: String,
|
||||
val url: Url
|
||||
)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.agileburo.anytype.domain.download
|
||||
|
||||
import com.agileburo.anytype.domain.common.Url
|
||||
|
||||
/**
|
||||
* Base interface for downloaders.
|
||||
*/
|
||||
interface Downloader {
|
||||
/**
|
||||
* Starts downloading file from url.
|
||||
* @param name file name
|
||||
* @param url url of the file to download
|
||||
*/
|
||||
fun download(url: Url, name: String)
|
||||
}
|
|
@ -98,7 +98,8 @@ fun Block.toView(
|
|||
id = id,
|
||||
size = content.size,
|
||||
name = content.name,
|
||||
mime = content.mime
|
||||
mime = content.mime,
|
||||
url = urlBuilder.file(content.hash)
|
||||
)
|
||||
else -> TODO()
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.agileburo.anytype.domain.block.model.Block.Content
|
|||
import com.agileburo.anytype.domain.block.model.Block.Prototype
|
||||
import com.agileburo.anytype.domain.block.model.Position
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.ext.*
|
||||
|
@ -51,6 +52,7 @@ class PageViewModel(
|
|||
private val removeLinkMark: RemoveLinkMark,
|
||||
private val mergeBlocks: MergeBlocks,
|
||||
private val splitBlock: SplitBlock,
|
||||
private val downloadFile: DownloadFile,
|
||||
private val documentExternalEventReducer: StateReducer<List<Block>, Event>,
|
||||
private val urlBuilder: UrlBuilder
|
||||
) : ViewStateViewModel<PageViewModel.ViewState>(),
|
||||
|
@ -839,6 +841,23 @@ class PageViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onDownloadFileClicked(id: String) {
|
||||
val block = blocks.first { it.id == id }
|
||||
val file = block.content<Content.File>()
|
||||
downloadFile.invoke(
|
||||
scope = viewModelScope,
|
||||
params = DownloadFile.Params(
|
||||
url = urlBuilder.file(file.hash),
|
||||
name = file.name
|
||||
)
|
||||
) { result ->
|
||||
result.either(
|
||||
fnL = { Timber.e(it, "Error while trying to download file: $file") },
|
||||
fnR = { Timber.d("Started download file: $file") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addNewBlockAtTheEnd() {
|
||||
proceedWithCreatingNewTextBlock(
|
||||
id = "",
|
||||
|
|
|
@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.agileburo.anytype.domain.block.interactor.*
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.misc.UrlBuilder
|
||||
|
@ -30,7 +31,8 @@ open class PageViewModelFactory(
|
|||
private val mergeBlocks: MergeBlocks,
|
||||
private val splitBlock: SplitBlock,
|
||||
private val documentEventReducer: StateReducer<List<Block>, Event>,
|
||||
private val urlBuilder: UrlBuilder
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val downloadFile: DownloadFile
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -53,7 +55,8 @@ open class PageViewModelFactory(
|
|||
splitBlock = splitBlock,
|
||||
createPage = createPage,
|
||||
documentExternalEventReducer = documentEventReducer,
|
||||
urlBuilder = urlBuilder
|
||||
urlBuilder = urlBuilder,
|
||||
downloadFile = downloadFile
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -30,6 +30,32 @@ object MockBlockFactory {
|
|||
)
|
||||
)
|
||||
|
||||
fun makeFileBlock(): Block = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.File(
|
||||
hash = MockDataFactory.randomUuid(),
|
||||
name = MockDataFactory.randomString(),
|
||||
state = Block.Content.File.State.DONE,
|
||||
added = MockDataFactory.randomLong(),
|
||||
mime = MockDataFactory.randomString(),
|
||||
size = MockDataFactory.randomLong(),
|
||||
type = Block.Content.File.Type.FILE
|
||||
),
|
||||
children = emptyList()
|
||||
)
|
||||
|
||||
fun makeTitleBlock(): Block = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Text(
|
||||
text = MockDataFactory.randomString(),
|
||||
marks = emptyList(),
|
||||
style = Block.Content.Text.Style.TITLE
|
||||
),
|
||||
children = emptyList()
|
||||
)
|
||||
|
||||
fun makeOnePageWithTwoTextBlocks(
|
||||
root: String,
|
||||
firstChild: String,
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.agileburo.anytype.domain.block.interactor.*
|
|||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.block.model.Position
|
||||
import com.agileburo.anytype.domain.config.Config
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.ext.content
|
||||
|
@ -92,6 +93,9 @@ class PageViewModelTest {
|
|||
@Mock
|
||||
lateinit var updateBackgroundColor: UpdateBackgroundColor
|
||||
|
||||
@Mock
|
||||
lateinit var downloadFile: DownloadFile
|
||||
|
||||
private lateinit var vm: PageViewModel
|
||||
|
||||
@Before
|
||||
|
@ -2693,6 +2697,72 @@ class PageViewModelTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start downloading 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.Page(
|
||||
style = Block.Content.Page.Style.SET
|
||||
),
|
||||
children = listOf(title.id, file.id)
|
||||
),
|
||||
title,
|
||||
file
|
||||
)
|
||||
|
||||
val flow: Flow<List<Event.Command>> = flow {
|
||||
delay(100)
|
||||
emit(
|
||||
listOf(
|
||||
Event.Command.ShowBlock(
|
||||
rootId = root,
|
||||
blocks = page,
|
||||
context = root
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val builder = UrlBuilder(
|
||||
config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomString()
|
||||
)
|
||||
)
|
||||
|
||||
stubObserveEvents(flow)
|
||||
stubOpenPage()
|
||||
buildViewModel(builder)
|
||||
|
||||
vm.open(root)
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
|
||||
// TESTING
|
||||
|
||||
vm.onDownloadFileClicked(id = file.id)
|
||||
|
||||
verify(downloadFile, times(1)).invoke(
|
||||
scope = any(),
|
||||
params = eq(
|
||||
DownloadFile.Params(
|
||||
name = file.content<Block.Content.File>().name,
|
||||
url = builder.file(
|
||||
hash = file.content<Block.Content.File>().hash
|
||||
)
|
||||
)
|
||||
),
|
||||
onResult = any()
|
||||
)
|
||||
}
|
||||
|
||||
private fun simulateNormalPageOpeningFlow() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
|
@ -2769,7 +2839,8 @@ class PageViewModelTest {
|
|||
mergeBlocks = mergeBlocks,
|
||||
splitBlock = splitBlock,
|
||||
documentExternalEventReducer = DocumentExternalEventReducer(),
|
||||
urlBuilder = urlBuilder
|
||||
urlBuilder = urlBuilder,
|
||||
downloadFile = downloadFile
|
||||
)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,8 @@ include ':app',
|
|||
':persistence',
|
||||
':domain',
|
||||
':data',
|
||||
':device',
|
||||
':presentation',
|
||||
':core-ui',
|
||||
':library-kanban-widget',
|
||||
':library-page-icon-picker-widget'
|
||||
':library-page-icon-picker-widget'
|
Loading…
Add table
Add a link
Reference in a new issue