Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -21,8 +21,11 @@ import android.webkit.WebView
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.os.bundleOf
Expand All @@ -47,6 +50,13 @@ fun ComposeCanvasWebViewWrapper(
embeddedWebViewCallbacks: ComposeEmbeddedWebViewCallbacks? = null,
) {
val webViewState = rememberSaveable(content) { bundleOf() }
val savedHtml = rememberSaveable(content, stateSaver = Saver(
save = { it },
restore = { it }
)) { mutableStateOf(content) }
val savedThemeSwitched = rememberSaveable { bundleOf("themeSwitched" to false) }
val configuration = LocalConfiguration.current
val configKey = "${configuration.orientation}-${configuration.uiMode}"

if (LocalInspectionMode.current) {
Text(text = content)
Expand Down Expand Up @@ -84,27 +94,34 @@ fun ComposeCanvasWebViewWrapper(
applyOnWebView?.let { applyOnWebView -> webView.applyOnWebView() }
}
},
update = {
update = { view ->
configKey // Read configuration to trigger update on change
savedHtml.value = content // Update saved HTML on each update
if (webViewState.isEmpty) {
if (useInAppFormatting) {
it.loadHtml(content, title)
view.loadHtml(savedHtml.value, title)
} else {
it.loadDataWithBaseUrl(CanvasWebView.getReferrer(true), content, contentType, "UTF-8", null)
view.loadDataWithBaseUrl(CanvasWebView.getReferrer(true), savedHtml.value, contentType, "UTF-8", null)
}

if (onLtiButtonPressed != null) {
it.webView.addJavascriptInterface(JsExternalToolInterface(onLtiButtonPressed), Const.LTI_TOOL)
view.webView.addJavascriptInterface(JsExternalToolInterface(onLtiButtonPressed), Const.LTI_TOOL)
}

if (HtmlContentFormatter.hasGoogleDocsUrl(content)) {
it.webView.addJavascriptInterface(JsGoogleDocsInterface(it.context), Const.GOOGLE_DOCS)
if (HtmlContentFormatter.hasGoogleDocsUrl(savedHtml.value)) {
view.webView.addJavascriptInterface(JsGoogleDocsInterface(view.context), Const.GOOGLE_DOCS)
}
view.handleConfigurationChange()
} else {
it.webView.restoreState(webViewState)
view.webView.restoreState(webViewState)
view.setHtmlContent(savedHtml.value)
view.setThemeSwitched(savedThemeSwitched.getBoolean("themeSwitched", false))
view.handleConfigurationChange(reloadContent = false)
}
applyOnUpdate?.let { applyOnUpdate -> it.applyOnUpdate() }
applyOnUpdate?.let { applyOnUpdate -> view.applyOnUpdate() }
},
onRelease = {
savedThemeSwitched.putBoolean("themeSwitched", it.themeSwitched)
it.webView.saveState(webViewState)
},
modifier = modifier.fillMaxSize()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ package com.instructure.pandautils.views

import android.content.Context
import android.content.res.Configuration
import android.os.Parcel
import android.os.Parcelable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import androidx.annotation.ColorRes
import androidx.core.view.isVisible
import com.instructure.canvasapi2.utils.ApiPrefs
import com.instructure.pandautils.R
import com.instructure.pandautils.databinding.ViewCanvasWebViewWrapperBinding
Expand Down Expand Up @@ -137,6 +140,13 @@ open class CanvasWebViewWrapper @JvmOverloads constructor(
}

private fun initVisibility(html: String) {
updateButtonVisibility(html)
if (binding.themeSwitchButton.visibility == android.view.View.VISIBLE) {
changeButtonTheme()
}
}

private fun updateButtonVisibility(html: String) {
val nightModeFlags: Int = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (nightModeFlags == Configuration.UI_MODE_NIGHT_YES && html.isNotEmpty()) {
binding.themeSwitchButton.setVisible()
Expand All @@ -145,6 +155,76 @@ open class CanvasWebViewWrapper @JvmOverloads constructor(
}
}

override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
handleConfigurationChange()
}

fun setHtmlContent(content: String?) {
this.html = content
}

fun setThemeSwitched(switched: Boolean) {
this.themeSwitched = switched
}

fun handleConfigurationChange(reloadContent: Boolean = true) {
html?.let { htmlContent ->
updateButtonVisibility(htmlContent)
if (binding.themeSwitchButton.isVisible) {
changeButtonTheme()
if (reloadContent) {
changeContentTheme(htmlContent)
}
}
}
}

override fun onSaveInstanceState(): Parcelable {
val superState = super.onSaveInstanceState()
return SavedState(superState).apply {
this.themeSwitched = [email protected]
this.html = [email protected]
}
}

override fun onRestoreInstanceState(state: Parcelable?) {
when (state) {
is SavedState -> {
super.onRestoreInstanceState(state.superState)
themeSwitched = state.themeSwitched
html = state.html
}
else -> super.onRestoreInstanceState(state)
}
}

private class SavedState : BaseSavedState {
var themeSwitched: Boolean = false
var html: String? = null

constructor(superState: Parcelable?) : super(superState)

private constructor(parcel: Parcel) : super(parcel) {
themeSwitched = parcel.readInt() == 1
html = parcel.readString()
}

override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeInt(if (themeSwitched) 1 else 0)
out.writeString(html)
}

companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<SavedState> {
override fun createFromParcel(parcel: Parcel) = SavedState(parcel)
override fun newArray(size: Int): Array<SavedState?> = arrayOfNulls(size)
}
}
}

private fun formatHtml(data: String): String {
val textDarkest = colorResToHexString(if (themeSwitched) R.color.licorice else R.color.textDarkest)
val textDark = colorResToHexString(if (themeSwitched) R.color.ash else R.color.textDark)
Expand Down
Loading