From c6f5ef48c781bf0a0ed5b42b7c9ddbd3bcf24a16 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Mon, 16 Feb 2026 20:21:41 +0100 Subject: [PATCH] restor extension pop up fragment --- app/android/app/src/main/AndroidManifest.xml | 5 + .../BaseBrowserFragment.kt | 22 ++- .../addons/WebExtensionActionPopupActivity.kt | 127 ++++++++++++++++++ .../res/layout/activity_add_on_settings.xml | 15 +++ .../res/layout/fragment_add_on_settings.xml | 18 +++ .../android/app/src/main/AndroidManifest.xml | 5 + 6 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/addons/WebExtensionActionPopupActivity.kt create mode 100644 packages/flutter_mozilla_components/android/src/main/res/layout/activity_add_on_settings.xml create mode 100644 packages/flutter_mozilla_components/android/src/main/res/layout/fragment_add_on_settings.xml diff --git a/app/android/app/src/main/AndroidManifest.xml b/app/android/app/src/main/AndroidManifest.xml index b3413864..f070dce2 100644 --- a/app/android/app/src/main/AndroidManifest.xml +++ b/app/android/app/src/main/AndroidManifest.xml @@ -205,6 +205,11 @@ android:exported="false" android:theme="@style/AppTheme" /> + + diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt index ec3846f2..e7f1afe6 100644 --- a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/BaseBrowserFragment.kt @@ -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 diff --git a/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/addons/WebExtensionActionPopupActivity.kt b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/addons/WebExtensionActionPopupActivity.kt new file mode 100644 index 00000000..5e704f14 --- /dev/null +++ b/packages/flutter_mozilla_components/android/src/main/kotlin/eu/weblibre/flutter_mozilla_components/addons/WebExtensionActionPopupActivity.kt @@ -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(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) + } + } + } + } +} diff --git a/packages/flutter_mozilla_components/android/src/main/res/layout/activity_add_on_settings.xml b/packages/flutter_mozilla_components/android/src/main/res/layout/activity_add_on_settings.xml new file mode 100644 index 00000000..0a1cc218 --- /dev/null +++ b/packages/flutter_mozilla_components/android/src/main/res/layout/activity_add_on_settings.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/packages/flutter_mozilla_components/android/src/main/res/layout/fragment_add_on_settings.xml b/packages/flutter_mozilla_components/android/src/main/res/layout/fragment_add_on_settings.xml new file mode 100644 index 00000000..6f5546b3 --- /dev/null +++ b/packages/flutter_mozilla_components/android/src/main/res/layout/fragment_add_on_settings.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/packages/flutter_mozilla_components/example/android/app/src/main/AndroidManifest.xml b/packages/flutter_mozilla_components/example/android/app/src/main/AndroidManifest.xml index c6a67197..0f6233c0 100644 --- a/packages/flutter_mozilla_components/example/android/app/src/main/AndroidManifest.xml +++ b/packages/flutter_mozilla_components/example/android/app/src/main/AndroidManifest.xml @@ -91,6 +91,11 @@ android:exported="false" android:theme="@style/Theme.AppCompat.Light" /> + +