@@ -22,6 +22,9 @@ import android.webkit.WebResourceResponse
2222import android.webkit.WebStorage
2323import android.webkit.WebView
2424import android.webkit.WebViewClient
25+ import androidx.lifecycle.coroutineScope
26+ import androidx.lifecycle.findViewTreeLifecycleOwner
27+ import androidx.lifecycle.lifecycleScope
2528import androidx.webkit.WebViewAssetLoader
2629import androidx.webkit.WebViewAssetLoader.AssetsPathHandler
2730import kotlinx.coroutines.CoroutineScope
@@ -47,8 +50,8 @@ class GutenbergView : WebView {
4750 private var assetLoader = WebViewAssetLoader .Builder ()
4851 .addPathHandler(" /assets/" , AssetsPathHandler (this .context))
4952 .build()
50- private var configuration: EditorConfiguration = EditorConfiguration .bundled()
51- private var dependencies: EditorDependencies ? = null
53+ private val configuration: EditorConfiguration
54+ private lateinit var dependencies: EditorDependencies
5255
5356 private val handler = Handler (Looper .getMainLooper())
5457 var filePathCallback: ValueCallback <Array <Uri ?>? > ? = null
@@ -68,14 +71,14 @@ class GutenbergView : WebView {
6871 private var networkRequestListener: NetworkRequestListener ? = null
6972 private var loadingListener: EditorLoadingListener ? = null
7073
71- private val coroutineScope = CoroutineScope (Dispatchers .Main + SupervisorJob ())
72-
7374 /* *
7475 * Stores the contextId from the most recent openMediaLibrary call
7576 * to pass back to JavaScript when media is selected
7677 */
7778 private var currentMediaContextId: String? = null
7879
80+ private val coroutineScope: CoroutineScope
81+
7982 var textEditorEnabled: Boolean = false
8083 set(value) {
8184 field = value
@@ -129,16 +132,23 @@ class GutenbergView : WebView {
129132 loadingListener = listener
130133 }
131134
132- constructor (context: Context ) : super (context)
133- constructor (context: Context , attrs: AttributeSet ) : super (context, attrs)
134- constructor (context: Context , attrs: AttributeSet , defStyle: Int ) : super (
135- context,
136- attrs,
137- defStyle
138- )
135+ constructor (configuration: EditorConfiguration , dependencies: EditorDependencies ? , coroutineScope: CoroutineScope , context: Context ) : super (context) {
136+ this .configuration = configuration
137+ this .coroutineScope = coroutineScope
138+
139+ if (dependencies != null ) {
140+ this .dependencies = dependencies
141+
142+ // FAST PATH: Dependencies were provided - load immediately
143+ loadEditor(dependencies)
144+ } else {
145+ // ASYNC FLOW: No dependencies - fetch them asynchronously
146+ prepareAndLoadEditor()
147+ }
148+ }
139149
140150 @SuppressLint(" SetJavaScriptEnabled" ) // Without JavaScript we have no Gutenberg
141- fun initializeWebView () {
151+ private fun initializeWebView () {
142152 this .settings.javaScriptCanOpenWindowsAutomatically = true
143153 this .settings.javaScriptEnabled = true
144154 this .settings.domStorageEnabled = true
@@ -272,38 +282,6 @@ class GutenbergView : WebView {
272282 }
273283 }
274284
275- /* *
276- * Starts the editor with the given configuration and optional dependencies.
277- *
278- * ## Loading Flows
279- *
280- * **When dependencies are provided (Fast Path):**
281- * The editor loads immediately using the pre-fetched dependencies.
282- * Only `onDependencyLoadingFinished()` and `onEditorReady()` callbacks are invoked.
283- *
284- * **When dependencies are null (Async Flow):**
285- * Dependencies are fetched asynchronously with progress reporting.
286- * All loading callbacks are invoked in order:
287- * 1. `onDependencyLoadingStarted()`
288- * 2. `onDependencyLoadingProgress()` (multiple times)
289- * 3. `onDependencyLoadingFinished()`
290- * 4. `onEditorReady()`
291- *
292- * @param configuration The editor configuration.
293- * @param dependencies Pre-fetched dependencies, or null to fetch them asynchronously.
294- */
295- fun start (configuration : EditorConfiguration , dependencies : EditorDependencies ? = null) {
296- this .configuration = configuration
297-
298- if (dependencies != null ) {
299- // FAST PATH: Dependencies were provided - load immediately
300- loadEditor(dependencies)
301- } else {
302- // ASYNC FLOW: No dependencies - fetch them asynchronously
303- prepareAndLoadEditor()
304- }
305- }
306-
307285 /* *
308286 * Fetches all required dependencies and then loads the editor.
309287 *
@@ -312,17 +290,25 @@ class GutenbergView : WebView {
312290 private fun prepareAndLoadEditor () {
313291 loadingListener?.onDependencyLoadingStarted()
314292
293+ Log .i(" GutenbergView" , " Fetching dependencies..." )
294+
315295 coroutineScope.launch {
296+ Log .i(" GutenbergView" , " In coroutine scope" )
297+ Log .i(" GutenbergView" , " Fetching dependencies in IO context" )
316298 try {
317299 val editorService = EditorService .create(
318300 context = context,
319301 configuration = configuration
320302 )
321-
303+ Log .i( " GutenbergView " , " Created editor service " )
322304 val fetchedDependencies = editorService.prepare { progress ->
323305 loadingListener?.onDependencyLoadingProgress(progress)
306+
307+ Log .i(" GutenbergView" , " Progress: $progress " )
324308 }
325309
310+ Log .i(" GutenbergView" , " Finished fetching dependencies" )
311+
326312 // Store dependencies and load the editor
327313 loadEditor(fetchedDependencies)
328314 } catch (e: Exception ) {
@@ -759,7 +745,6 @@ class GutenbergView : WebView {
759745
760746 override fun onDetachedFromWindow () {
761747 super .onDetachedFromWindow()
762- coroutineScope.cancel()
763748 clearConfig()
764749 this .stopLoading()
765750 FileCache .clearCache(context)
@@ -785,40 +770,6 @@ class GutenbergView : WebView {
785770 private var warmupRunnable: Runnable ? = null
786771 private var warmupWebView: GutenbergView ? = null
787772
788- /* *
789- * Warmup the editor by preloading assets in a temporary WebView.
790- * This pre-caches assets to improve editor launch speed.
791- */
792- @JvmStatic
793- fun warmup (context : Context , configuration : EditorConfiguration ) {
794- // Cancel any existing warmup
795- cancelWarmup()
796-
797- // Create dedicated warmup WebView
798- val webView = GutenbergView (context)
799- webView.initializeWebView()
800- webView.start(configuration, EditorDependencies .empty)
801- warmupWebView = webView
802-
803- // Schedule cleanup after assets are loaded
804- warmupHandler = Handler (Looper .getMainLooper())
805- warmupRunnable = Runnable {
806- cleanupWarmup()
807- }
808- warmupHandler?.postDelayed(warmupRunnable!! , ASSET_LOADING_TIMEOUT_MS )
809- }
810-
811- /* *
812- * Cancel any pending warmup and clean up resources.
813- */
814- @JvmStatic
815- fun cancelWarmup () {
816- warmupRunnable?.let { runnable ->
817- warmupHandler?.removeCallbacks(runnable)
818- }
819- cleanupWarmup()
820- }
821-
822773 /* *
823774 * Clean up warmup resources.
824775 */
@@ -832,21 +783,6 @@ class GutenbergView : WebView {
832783 warmupHandler = null
833784 warmupRunnable = null
834785 }
835-
836- /* *
837- * Create a new GutenbergView for the editor.
838- * Cancels any pending warmup to free resources.
839- */
840- @JvmStatic
841- fun createForEditor (context : Context ): GutenbergView {
842- // Cancel any pending warmup to free resources
843- cancelWarmup()
844-
845- // Create fresh WebView for editor
846- val webView = GutenbergView (context)
847- webView.initializeWebView()
848- return webView
849- }
850786 }
851787}
852788
0 commit comments