restor extension pop up fragment

This commit is contained in:
Fabian Freund
2026-02-16 20:21:41 +01:00
parent 645bbb9b53
commit c6f5ef48c7
6 changed files with 178 additions and 14 deletions
@@ -22,6 +22,7 @@ import androidx.annotation.CallSuper
import androidx.core.content.edit
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionActionPopupActivity
import eu.weblibre.flutter_mozilla_components.addons.WebExtensionPromptFeature
import eu.weblibre.flutter_mozilla_components.databinding.FragmentBrowserBinding
import eu.weblibre.flutter_mozilla_components.ext.getPreferenceKey
@@ -32,12 +33,7 @@ import eu.weblibre.flutter_mozilla_components.integration.ReaderViewIntegration
import eu.weblibre.flutter_mozilla_components.activities.ExternalAppBrowserActivity
import eu.weblibre.flutter_mozilla_components.services.DownloadService
import io.flutter.Log
import mozilla.components.browser.state.action.TabListAction
import mozilla.components.browser.state.action.WebExtensionAction
import mozilla.components.browser.state.state.EngineState
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.WebExtensionState
import mozilla.components.browser.state.state.createTab
import mozilla.components.browser.thumbnails.BrowserThumbnails
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.app.links.AppLinksFeature
@@ -521,16 +517,14 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
protected open fun onEngineSetupComplete() {}
private fun openPopup(webExtensionState: WebExtensionState) {
val store = components.core.store
val popupSession = store.state.extensions[webExtensionState.id]?.popupSession ?: return
val tab = createTab(url = "", source = SessionState.Source.Internal.None)
.copy(engineState = EngineState(popupSession))
store.dispatch(TabListAction.AddTabAction(tab, select = true))
store.dispatch(
WebExtensionAction.UpdatePopupSessionAction(webExtensionState.id, popupSession = null)
val intent = Intent(
components.profileApplicationContext,
WebExtensionActionPopupActivity::class.java
)
intent.putExtra("web_extension_id", webExtensionState.id)
intent.putExtra("web_extension_name", webExtensionState.name)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent)
}
@CallSuper
@@ -0,0 +1,127 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package eu.weblibre.flutter_mozilla_components.addons
import android.content.Context
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import eu.weblibre.flutter_mozilla_components.GlobalComponents
import mozilla.components.browser.state.action.WebExtensionAction
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.engine.window.WindowRequest
import mozilla.components.lib.state.ext.consumeFrom
import eu.weblibre.flutter_mozilla_components.R
/**
* An activity to show the pop up action of a web extension.
*/
class WebExtensionActionPopupActivity : AppCompatActivity() {
private val components by lazy {
requireNotNull(GlobalComponents.components) { "Components not initialized" }
}
private lateinit var webExtensionId: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_on_settings)
webExtensionId = requireNotNull(intent.getStringExtra("web_extension_id"))
intent.getStringExtra("web_extension_name")?.let {
title = it
}
supportFragmentManager
.beginTransaction()
.replace(R.id.addonSettingsContainer, WebExtensionActionPopupFragment.create(webExtensionId))
.commit()
}
override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? =
when (name) {
EngineView::class.java.name -> components.core.engine.createView(context, attrs).asView()
else -> super.onCreateView(parent, name, context, attrs)
}
/**
* A fragment to show the web extension action popup with [EngineView].
*/
class WebExtensionActionPopupFragment : Fragment(), EngineSession.Observer {
private val components by lazy {
requireNotNull(GlobalComponents.components) { "Components not initialized" }
}
private var engineSession: EngineSession? = null
private lateinit var webExtensionId: String
private val addonSettingsEngineView: EngineView
get() = requireView().findViewById<View>(R.id.addonSettingsEngineView) as EngineView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
webExtensionId = requireNotNull(arguments?.getString("web_extension_id"))
engineSession = components.core.store.state.extensions[webExtensionId]?.popupSession
return inflater.inflate(R.layout.fragment_add_on_settings, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val session = engineSession
if (session != null) {
addonSettingsEngineView.render(session)
consumePopupSession()
} else {
consumeFrom(components.core.store) { state ->
state.extensions[webExtensionId]?.let { extState ->
extState.popupSession?.let {
if (engineSession == null) {
addonSettingsEngineView.render(it)
consumePopupSession()
engineSession = it
}
}
}
}
}
}
override fun onStart() {
super.onStart()
engineSession?.register(this)
}
override fun onStop() {
super.onStop()
engineSession?.unregister(this)
}
override fun onWindowRequest(windowRequest: WindowRequest) {
if (windowRequest.type == WindowRequest.Type.CLOSE) {
activity?.onBackPressedDispatcher?.onBackPressed()
}
}
private fun consumePopupSession() {
components.core.store.dispatch(
WebExtensionAction.UpdatePopupSessionAction(webExtensionId, popupSession = null),
)
}
companion object {
fun create(webExtensionId: String) = WebExtensionActionPopupFragment().apply {
arguments = Bundle().apply {
putString("web_extension_id", webExtensionId)
}
}
}
}
}
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/addonSettingsContainer"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="match_parent">
<mozilla.components.concept.engine.EngineView
tools:ignore="Instantiatable"
android:id="@+id/addonSettingsEngineView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>