diff --git a/.gitmodules b/.gitmodules index fc49028..0e2fb5e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "app/libgocryptfs"] path = app/libgocryptfs url = https://forge.chapril.org/hardcoresushi/libgocryptfs.git +[submodule "libpdfviewer"] + path = libpdfviewer + url = https://forge.chapril.org/hardcoresushi/libpdfviewer.git diff --git a/README.md b/README.md index 9d309d1..18eb756 100644 --- a/README.md +++ b/README.md @@ -101,14 +101,10 @@ You also need to install the Android SDK build tools and the [Android NDK](https #### Download Sources ``` -$ git clone https://github.com/hardcore-sushi/DroidFS.git -``` -Download [libgocryptfs](https://forge.chapril.org/hardcoresushi/libgocryptfs): -``` +$ git clone --recurse-submodules https://github.com/hardcore-sushi/DroidFS.git $ cd DroidFS -$ git submodule update --init ``` -libgocryptfs needs OpenSSL: +[libgocryptfs](https://forge.chapril.org/hardcoresushi/libgocryptfs) needs OpenSSL: ``` $ cd app/libgocryptfs $ wget https://www.openssl.org/source/openssl-1.1.1m.tar.gz diff --git a/app/build.gradle b/app/build.gradle index 5dd9600..96e74bf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,6 +55,7 @@ android { } dependencies { + implementation project(":libpdfviewer:app") implementation fileTree(dir: "libs", include: ["*.jar"]) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'androidx.core:core-ktx:1.7.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 775016d..f820d2c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -77,6 +77,9 @@ + diff --git a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt index 31c19d8..a1d2291 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt @@ -19,6 +19,7 @@ class ConstValues { Pair("image", listOf("png", "jpg", "jpeg", "gif", "webp", "bmp")), Pair("video", listOf("mp4", "webm", "mkv", "mov")), Pair("audio", listOf("mp3", "ogg", "m4a", "wav", "flac")), + Pair("pdf", listOf("pdf")), Pair("text", listOf("txt", "json", "conf", "log", "xml", "java", "kt", "py", "pl", "rb", "go", "c", "h", "cpp", "hpp", "rs", "sh", "bat", "js", "html", "css", "php", "yml", "yaml", "toml", "ini", "md", "properties")) ) @@ -35,6 +36,9 @@ class ConstValues { fun isAudio(path: String): Boolean { return isExtensionType("audio", path) } + fun isPDF(path: String): Boolean { + return isExtensionType("pdf", path) + } fun isText(path: String): Boolean { return isExtensionType("text", path) } diff --git a/app/src/main/java/sushi/hardcore/droidfs/GocryptfsVolume.kt b/app/src/main/java/sushi/hardcore/droidfs/GocryptfsVolume.kt index 4a1f0eb..2f310ad 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/GocryptfsVolume.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/GocryptfsVolume.kt @@ -238,8 +238,8 @@ class GocryptfsVolume(val applicationContext: Context, var sessionID: Int) { } } - fun loadWholeFile(fullPath: String, maxSize: Long? = null): Pair { - val fileSize = getSize(fullPath) + fun loadWholeFile(fullPath: String, size: Long? = null, maxSize: Long? = null): Pair { + val fileSize = size ?: getSize(fullPath) return if (fileSize >= 0) { maxSize?.let { if (fileSize > it) { diff --git a/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt b/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt index ff2b15f..146668e 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/adapters/ExplorerElementAdapter.kt @@ -127,7 +127,7 @@ class ExplorerElementAdapter( adapter.gocryptfsVolume?.let { volume -> displayThumbnail = true Thread { - volume.loadWholeFile(fullPath, 50_000_000).first?.let { + volume.loadWholeFile(fullPath, maxSize = 50_000_000).first?.let { if (displayThumbnail) { adapter.activity.runOnUiThread { if (displayThumbnail) { diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt index a2fd394..66cd168 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt @@ -25,6 +25,7 @@ import sushi.hardcore.droidfs.BaseActivity import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.ConstValues.Companion.isAudio import sushi.hardcore.droidfs.ConstValues.Companion.isImage +import sushi.hardcore.droidfs.ConstValues.Companion.isPDF import sushi.hardcore.droidfs.ConstValues.Companion.isText import sushi.hardcore.droidfs.ConstValues.Companion.isVideo import sushi.hardcore.droidfs.GocryptfsVolume @@ -35,10 +36,7 @@ import sushi.hardcore.droidfs.content_providers.ExternalProvider import sushi.hardcore.droidfs.content_providers.RestrictedFileProvider import sushi.hardcore.droidfs.file_operations.FileOperationService import sushi.hardcore.droidfs.file_operations.OperationFile -import sushi.hardcore.droidfs.file_viewers.AudioPlayer -import sushi.hardcore.droidfs.file_viewers.ImageViewer -import sushi.hardcore.droidfs.file_viewers.TextEditor -import sushi.hardcore.droidfs.file_viewers.VideoPlayer +import sushi.hardcore.droidfs.file_viewers.* import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder @@ -164,6 +162,7 @@ open class BaseExplorerActivity : BaseActivity() { "image" -> startFileViewer(ImageViewer::class.java, path) "video" -> startFileViewer(VideoPlayer::class.java, path) "audio" -> startFileViewer(AudioPlayer::class.java, path) + "pdf" -> startFileViewer(PdfViewer::class.java, path) "text" -> startFileViewer(TextEditor::class.java, path) "external" -> if (usf_open) { openWithExternalApp(path) @@ -197,6 +196,9 @@ open class BaseExplorerActivity : BaseActivity() { isText(fullPath) -> { startFileViewer(TextEditor::class.java, fullPath) } + isPDF(fullPath) -> { + startFileViewer(PdfViewer::class.java, fullPath) + } isAudio(fullPath) -> { startFileViewer(AudioPlayer::class.java, fullPath) } diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt index 58ba635..e5dedda 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt @@ -66,8 +66,8 @@ abstract class FileViewerActivity: BaseActivity() { } } - protected fun loadWholeFile(path: String): ByteArray? { - val result = gocryptfsVolume.loadWholeFile(path) + protected fun loadWholeFile(path: String, fileSize: Long? = null): ByteArray? { + val result = gocryptfsVolume.loadWholeFile(path, size = fileSize) if (result.second != 0) { val dialog = CustomAlertDialogBuilder(this, themeValue) .setTitle(R.string.error) diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/PdfViewer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/PdfViewer.kt new file mode 100644 index 0000000..02ba9d8 --- /dev/null +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/PdfViewer.kt @@ -0,0 +1,51 @@ +package sushi.hardcore.droidfs.file_viewers + +import android.view.Menu +import android.view.MenuItem +import android.widget.TextView +import androidx.appcompat.widget.Toolbar +import sushi.hardcore.droidfs.R +import sushi.hardcore.droidfs.databinding.ActivityPdfViewerBinding +import java.io.ByteArrayInputStream +import java.io.File + +class PdfViewer: FileViewerActivity() { + private lateinit var binding: ActivityPdfViewerBinding + + override fun hideSystemUi() { + //don't hide system ui + } + + override fun getFileType(): String { + return "pdf" + } + + override fun viewFile() { + binding = ActivityPdfViewerBinding.inflate(layoutInflater) + val toolbar = binding.root.findViewById(R.id.toolbar) + setSupportActionBar(toolbar) + title = "" + val titleText = toolbar.findViewById(R.id.title_text) + val fileName = File(filePath).name + titleText.text = fileName + binding.pdfViewer.activity = this + setContentView(binding.root) + val fileSize = gocryptfsVolume.getSize(filePath) + loadWholeFile(filePath, fileSize)?.let { + binding.pdfViewer.loadPdf(ByteArrayInputStream(it), fileName, fileSize) + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + binding.pdfViewer.onCreateOptionMenu(menu) + return super.onCreateOptionsMenu(menu) + } + + override fun onPrepareOptionsMenu(menu: Menu?): Boolean { + return binding.pdfViewer.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return binding.pdfViewer.onOptionsItemSelected(item) || super.onOptionsItemSelected(item) + } +} diff --git a/app/src/main/res/layout/activity_pdf_viewer.xml b/app/src/main/res/layout/activity_pdf_viewer.xml new file mode 100644 index 0000000..221bbda --- /dev/null +++ b/app/src/main/res/layout/activity_pdf_viewer.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 9a41126..c56ef3c 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.4' + classpath 'com.android.tools.build:gradle:7.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/libpdfviewer b/libpdfviewer new file mode 160000 index 0000000..4e4b7c5 --- /dev/null +++ b/libpdfviewer @@ -0,0 +1 @@ +Subproject commit 4e4b7c5da4dddbc3841abd450fa250936be70f4e diff --git a/settings.gradle b/settings.gradle index 78d2b97..ee71f79 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ -include ':app' +include ':app', ':libpdfviewer:app' rootProject.name = "DroidFS" \ No newline at end of file