Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resources: smoother html apps (fixes #4896) #4897

Merged
merged 9 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,16 @@ abstract class BaseContainerFragment : BaseResourceFragment() {
AdapterCourses.showRating(`object`, rating, timesRated, ratingBar)
}
}
fun getUrlsAndStartDownload(
lib: List<RealmMyLibrary?>, urls: ArrayList<String>
) {
fun getUrlsAndStartDownload(lib: List<RealmMyLibrary?>, urls: ArrayList<String>) {
for (library in lib) {
val url = Utilities.getUrl(library)
if (!FileUtils.checkFileExist(url) && !TextUtils.isEmpty(url)) urls.add(url)
if (!FileUtils.checkFileExist(url) && !TextUtils.isEmpty(url)) {
urls.add(url)
}
}
if (urls.isNotEmpty()) {
startDownload(urls)
}
if (urls.isNotEmpty()) startDownload(urls)
}
fun initRatingView(type: String?, id: String?, title: String?, listener: OnRatingChangeListener?) {
timesRated = requireView().findViewById(R.id.times_rated)
Expand Down Expand Up @@ -123,23 +125,53 @@ abstract class BaseContainerFragment : BaseResourceFragment() {
}

fun openResource(items: RealmMyLibrary) {
val matchingItems = mRealm.where(RealmMyLibrary::class.java)
.equalTo("resourceLocalAddress", items.resourceLocalAddress)
.findAll()
val anyOffline = matchingItems.any { it.isResourceOffline() }
if (anyOffline) {
val offlineItem = matchingItems.first { it.isResourceOffline()}
openFileType(offlineItem, "offline")
if (items.openWith == "HTML") {
if (items.resourceOffline) {
val intent = Intent(activity, WebViewActivity::class.java)
intent.putExtra("RESOURCE_ID", items.id)
intent.putExtra("LOCAL_ADDRESS", items.resourceLocalAddress)
intent.putExtra("title", items.title)
startActivity(intent)
} else {
val resource = mRealm.where(RealmMyLibrary::class.java).equalTo("_id", items.resourceId).findFirst()
val downloadUrls = ArrayList<String>()
resource?.attachments?.forEach { attachment ->
attachment.name?.let { name ->
val url = Utilities.getUrl("${items.resourceId}", name)
downloadUrls.add(url)

val baseDir = File(context?.getExternalFilesDir(null), "ole/${items.resourceId}")
val lastSlashIndex = name.lastIndexOf('/')
if (lastSlashIndex > 0) {
val dirPath = name.substring(0, lastSlashIndex)
File(baseDir, dirPath).mkdirs()
}
}
}

if (downloadUrls.isNotEmpty()) {
startDownload(downloadUrls)
}
}
} else {
if (items.isResourceOffline()) {
openFileType(items, "offline")
} else if (FileUtils.getFileExtension(items.resourceLocalAddress) == "mp4") {
openFileType(items, "online")
val matchingItems = mRealm.where(RealmMyLibrary::class.java)
.equalTo("resourceLocalAddress", items.resourceLocalAddress)
.findAll()
val anyOffline = matchingItems.any { it.isResourceOffline() }
if (anyOffline) {
val offlineItem = matchingItems.first { it.isResourceOffline() }
openFileType(offlineItem, "offline")
} else {
val arrayList = ArrayList<String>()
arrayList.add(Utilities.getUrl(items))
startDownload(arrayList)
profileDbHandler.setResourceOpenCount(items, KEY_RESOURCE_DOWNLOAD)
if (items.isResourceOffline()) {
openFileType(items, "offline")
} else if (FileUtils.getFileExtension(items.resourceLocalAddress) == "mp4") {
openFileType(items, "online")
} else {
val arrayList = ArrayList<String>()
arrayList.add(Utilities.getUrl(items))
startDownload(arrayList)
profileDbHandler.setResourceOpenCount(items, KEY_RESOURCE_DOWNLOAD)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,16 @@ abstract class BaseContainerFragment : BaseResourceFragment() {
AdapterCourses.showRating(`object`, rating, timesRated, ratingBar)
}
}
fun getUrlsAndStartDownload(
lib: List<RealmMyLibrary?>, urls: ArrayList<String>
) {
fun getUrlsAndStartDownload(lib: List<RealmMyLibrary?>, urls: ArrayList<String>) {
for (library in lib) {
val url = Utilities.getUrl(library)
if (!FileUtils.checkFileExist(url) && !TextUtils.isEmpty(url)) urls.add(url)
if (!FileUtils.checkFileExist(url) && !TextUtils.isEmpty(url)) {
urls.add(url)
}
}
if (urls.isNotEmpty()) {
startDownload(urls)
}
if (urls.isNotEmpty()) startDownload(urls)
}
fun initRatingView(type: String?, id: String?, title: String?, listener: OnRatingChangeListener?) {
timesRated = requireView().findViewById(R.id.times_rated)
Expand Down Expand Up @@ -123,23 +125,53 @@ abstract class BaseContainerFragment : BaseResourceFragment() {
}

fun openResource(items: RealmMyLibrary) {
val matchingItems = mRealm.where(RealmMyLibrary::class.java)
.equalTo("resourceLocalAddress", items.resourceLocalAddress)
.findAll()
val anyOffline = matchingItems.any { it.isResourceOffline() }
if (anyOffline) {
val offlineItem = matchingItems.first { it.isResourceOffline()}
openFileType(offlineItem, "offline")
if (items.openWith == "HTML") {
if (items.resourceOffline) {
val intent = Intent(activity, WebViewActivity::class.java)
intent.putExtra("RESOURCE_ID", items.id)
intent.putExtra("LOCAL_ADDRESS", items.resourceLocalAddress)
intent.putExtra("title", items.title)
startActivity(intent)
} else {
val resource = mRealm.where(RealmMyLibrary::class.java).equalTo("_id", items.resourceId).findFirst()
val downloadUrls = ArrayList<String>()
resource?.attachments?.forEach { attachment ->
attachment.name?.let { name ->
val url = Utilities.getUrl("${items.resourceId}", name)
downloadUrls.add(url)

val baseDir = File(context?.getExternalFilesDir(null), "ole/${items.resourceId}")
val lastSlashIndex = name.lastIndexOf('/')
if (lastSlashIndex > 0) {
val dirPath = name.substring(0, lastSlashIndex)
File(baseDir, dirPath).mkdirs()
}
}
}

if (downloadUrls.isNotEmpty()) {
startDownload(downloadUrls)
}
}
} else {
if (items.isResourceOffline()) {
openFileType(items, "offline")
} else if (FileUtils.getFileExtension(items.resourceLocalAddress) == "mp4") {
openFileType(items, "online")
val matchingItems = mRealm.where(RealmMyLibrary::class.java)
.equalTo("resourceLocalAddress", items.resourceLocalAddress)
.findAll()
val anyOffline = matchingItems.any { it.isResourceOffline() }
if (anyOffline) {
val offlineItem = matchingItems.first { it.isResourceOffline() }
openFileType(offlineItem, "offline")
} else {
val arrayList = ArrayList<String>()
arrayList.add(Utilities.getUrl(items))
startDownload(arrayList)
profileDbHandler.setResourceOpenCount(items, KEY_RESOURCE_DOWNLOAD)
if (items.isResourceOffline()) {
openFileType(items, "offline")
} else if (FileUtils.getFileExtension(items.resourceLocalAddress) == "mp4") {
openFileType(items, "online")
} else {
val arrayList = ArrayList<String>()
arrayList.add(Utilities.getUrl(items))
startDownload(arrayList)
profileDbHandler.setResourceOpenCount(items, KEY_RESOURCE_DOWNLOAD)
}
}
}
}
Expand Down
36 changes: 34 additions & 2 deletions app/src/main/java/org/ole/planet/myplanet/model/RealmMyLibrary.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.io.FileWriter
import java.io.IOException
import java.util.Calendar
import java.util.Date
import java.util.UUID

open class RealmMyLibrary : RealmObject() {
@PrimaryKey
Expand Down Expand Up @@ -63,6 +64,8 @@ open class RealmMyLibrary : RealmObject() {
var courseId: String? = null
var stepId: String? = null
var isPrivate: Boolean = false
var attachments: RealmList<RealmAttachment>? = null

fun serializeResource(): JsonObject {
return JsonObject().apply {
addProperty("_id", _id)
Expand Down Expand Up @@ -279,7 +282,25 @@ open class RealmMyLibrary : RealmObject() {
description = JsonUtils.getString("description", doc)
if (doc.has("_attachments")) {
val attachments = doc["_attachments"].asJsonObject
attachments.entrySet().forEach { (key, _) ->
if (this.attachments == null) {
this.attachments = RealmList()
}

attachments.entrySet().forEach { (key, attachmentValue) ->
val attachmentObj = attachmentValue.asJsonObject

val realmAttachment = mRealm.createObject(RealmAttachment::class.java, UUID.randomUUID().toString())
realmAttachment.apply {
name = key
contentType = attachmentObj.get("content_type")?.asString
length = attachmentObj.get("length")?.asLong ?: 0
digest = attachmentObj.get("digest")?.asString
isStub = attachmentObj.get("stub")?.asBoolean == true
revpos = attachmentObj.get("revpos")?.asInt ?: 0
}

this.attachments?.add(realmAttachment)

if (key.indexOf("/") < 0) {
resourceRemoteAddress = "${settings.getString("couchdbURL", "http://")}/resources/$resourceId/$key"
resourceLocalAddress = key
Expand Down Expand Up @@ -410,4 +431,15 @@ open class RealmMyLibrary : RealmObject() {
return libraries.flatMap { it.subject ?: emptyList() }.toSet()
}
}
}
}

open class RealmAttachment : RealmObject() {
@PrimaryKey
var id: String? = null
var name: String? = null
var contentType: String? = null
var length: Long = 0
var digest: String? = null
var isStub: Boolean = false
var revpos: Int = 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.webkit.CookieManager
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.webkit.WebViewClient
import android.webkit.*
import androidx.appcompat.app.AppCompatActivity
import org.ole.planet.myplanet.R
import org.ole.planet.myplanet.databinding.ActivityWebViewBinding
import java.io.File

class WebViewActivity : AppCompatActivity() {
private lateinit var activityWebViewBinding: ActivityWebViewBinding
Expand All @@ -25,34 +24,73 @@ class WebViewActivity : AppCompatActivity() {
fromDeepLink = !TextUtils.isEmpty(dataFromDeepLink)
val title: String? = intent.getStringExtra("title")
link = intent.getStringExtra("link") ?: ""
val resourceId = intent.getStringExtra("RESOURCE_ID")
val localAddress = intent.getStringExtra("LOCAL_ADDRESS")

clearCookie()
if (!TextUtils.isEmpty(title)) {
activityWebViewBinding.contentWebView.webTitle.text = title
}
activityWebViewBinding.contentWebView.pBar.max = 100
activityWebViewBinding.contentWebView.pBar.progress = 0

setupWebView()
setListeners()
activityWebViewBinding.contentWebView.wv.settings.javaScriptEnabled = true
activityWebViewBinding.contentWebView.wv.settings.javaScriptCanOpenWindowsAutomatically = true
activityWebViewBinding.contentWebView.wv.loadUrl(link)

if (resourceId != null) {
val directory = File(getExternalFilesDir(null), "ole/$resourceId")
val indexFile = File(directory, "index.html")

if (indexFile.exists()) {
activityWebViewBinding.contentWebView.wv.loadUrl("file://${indexFile.absolutePath}")
}
} else {
activityWebViewBinding.contentWebView.wv.loadUrl(link)
}

activityWebViewBinding.contentWebView.finish.setOnClickListener { finish() }
setWebClient()
}

private fun setupWebView() {
activityWebViewBinding.contentWebView.wv.settings.apply {
javaScriptEnabled = true
javaScriptCanOpenWindowsAutomatically = true
allowFileAccess = true
domStorageEnabled = true
allowContentAccess = true
allowFileAccessFromFileURLs = true
allowUniversalAccessFromFileURLs = true
defaultTextEncodingName = "utf-8"
}
}

private fun setWebClient() {
activityWebViewBinding.contentWebView.wv.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
if (url.endsWith("/eng/")) {
if (!url.startsWith("file://") && url.endsWith("/eng/")) {
finish()
}
val i = Uri.parse(url)
activityWebViewBinding.contentWebView.webSource.text = i.host
if (url.startsWith("file://")) {
activityWebViewBinding.contentWebView.webSource.text = getString(R.string.local_resource)
} else {
val i = Uri.parse(url)
activityWebViewBinding.contentWebView.webSource.text = i.host
}
}

override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
}

override fun onReceivedError(view: WebView?, errorCode: Int, description: String?, failingUrl: String?) {
super.onReceivedError(view, errorCode, description, failingUrl)
}

override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
return super.shouldInterceptRequest(view, request)
}
}
}

Expand All @@ -62,12 +100,11 @@ class WebViewActivity : AppCompatActivity() {
cookieManager.flush()
}


private fun setListeners() {
activityWebViewBinding.contentWebView.wv.webChromeClient = object : WebChromeClient() {
override fun onProgressChanged(view: WebView, newProgress: Int) {
activityWebViewBinding.contentWebView.pBar.progress = newProgress
if (view.url?.endsWith("/eng/") == true) {
if (view.url?.startsWith("file://") == false && view.url?.endsWith("/eng/") == true) {
finish()
}
activityWebViewBinding.contentWebView.pBar.incrementProgressBy(newProgress)
Expand All @@ -80,6 +117,10 @@ class WebViewActivity : AppCompatActivity() {
activityWebViewBinding.contentWebView.webTitle.text = title
super.onReceivedTitle(view, title)
}

override fun onConsoleMessage(message: String?, lineNumber: Int, sourceID: String?) {
super.onConsoleMessage(message, lineNumber, sourceID)
}
}
}
}
Loading
Loading