diff --git a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt index 4be5336..3c5a6ab 100644 --- a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt +++ b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesScreen.kt @@ -113,6 +113,7 @@ fun FilesScreen( LaunchedEffect(session.serverUrl, session.username, session.davUserId) { OfficeWarmup.warm(session) + OfficeWarmup.warmWebViewEngine(context) // прогрев WebView-движка для быстрого docx/xlsx vm.load(session) vm.loadSidebarData(session) } @@ -241,7 +242,11 @@ fun FilesScreen( ) { val openItem: (FileItem) -> Unit = { item -> val openable = !item.isDirectory && - (OfficeFiles.isOfficeFile(item.name) || OpenableFiles.isOpenable(item.name)) + ( + OfficeFiles.isOfficeFile(item.name) || + WebOpenableFiles.isWebOpenable(item.name) || + OpenableFiles.isOpenable(item.name) + ) when { item.isDirectory -> vm.openFolder(session, item) openable -> vm.openItem(session, item) diff --git a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesViewModel.kt b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesViewModel.kt index de29458..514434f 100644 --- a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesViewModel.kt +++ b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/FilesViewModel.kt @@ -487,6 +487,7 @@ class FilesViewModel( if (item.isDirectory) return when { OfficeFiles.isOfficeFile(item.name) -> openOfficeFile(session, item) + WebOpenableFiles.isWebOpenable(item.name) -> openWebFile(session, item) ArchiveFiles.isArchive(item.name) -> openArchiveFile(session, item) OpenableFiles.isImage(item.name) -> openImageFile(session, item) else -> _state.value = _state.value.copy( @@ -495,6 +496,26 @@ class FilesViewModel( } } + /** Markdown/текст/доска — открываем каноническую ссылку /f/ в авторизованном WebView. */ + private fun openWebFile(session: AuthSession, item: FileItem) { + val fileId = item.fileId ?: run { + _state.value = _state.value.copy(error = "Не удалось определить ID файла") + return + } + val base = session.serverUrl.trimEnd('/') + _state.value = _state.value.copy( + editorLaunch = OfficeEditorLaunch( + url = "$base/index.php/f/$fileId", + title = item.name, + username = session.username, + password = session.appPassword, + trustAllCerts = session.trustAllCerts, + serverUrl = session.serverUrl, + collaboraBaseUrl = "", + ), + ) + } + private fun openOfficeFile(session: AuthSession, item: FileItem) { val fileId = item.fileId ?: run { _state.value = _state.value.copy(error = "Не удалось определить ID файла") diff --git a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/OfficeWarmup.kt b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/OfficeWarmup.kt index b6ff9e0..e70f96a 100644 --- a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/OfficeWarmup.kt +++ b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/OfficeWarmup.kt @@ -63,6 +63,23 @@ object OfficeWarmup { } } + @Volatile + private var engineWarmed = false + + /** + * Прогрев WebView-движка: ПЕРВОЕ создание WebView в процессе тянет провайдер Chromium + * (сотни мс), из-за чего первый docx/xlsx открывается медленно. Создаём и сразу уничтожаем + * пустой WebView заранее (при входе в Файлы) — движок загружается в фоне. Только UI-поток. + */ + fun warmWebViewEngine(context: android.content.Context) { + if (engineWarmed) return + engineWarmed = true + runCatching { + val wv = android.webkit.WebView(context.applicationContext) + wv.destroy() + } + } + fun clear() { cachedServerUrl = null cachedCollaboraUrl = null diff --git a/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/WebOpenableFiles.kt b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/WebOpenableFiles.kt new file mode 100644 index 0000000..776be13 --- /dev/null +++ b/feature/files/src/main/java/ru/forbion/f7cloud/feature/files/WebOpenableFiles.kt @@ -0,0 +1,16 @@ +package ru.forbion.f7cloud.feature.files + +/** + * Файлы, которые открываются во ВЕБ-вьюере Nextcloud по канонической ссылке + * `/index.php/f/` (сервер сам направляет в нужное приложение): + * markdown/текст → Text, доска → Whiteboard. В отличие от office (Collabora direct-edit). + */ +object WebOpenableFiles { + private val EXTENSIONS = setOf( + "md", "markdown", "txt", "text", "org", + "whiteboard", + ) + + fun isWebOpenable(name: String): Boolean = + name.substringAfterLast('.', "").lowercase() in EXTENSIONS +}