switch from timestamps to event sequence for events
This commit is contained in:
+2
-1
@@ -11,6 +11,7 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoStateEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoStateEvents
|
||||||
import io.flutter.plugin.common.StandardMessageCodec
|
import io.flutter.plugin.common.StandardMessageCodec
|
||||||
import io.flutter.plugin.platform.PlatformView
|
import io.flutter.plugin.platform.PlatformView
|
||||||
@@ -58,7 +59,7 @@ private class NativeFragmentView(
|
|||||||
super.onFlutterViewAttached(flutterView)
|
super.onFlutterViewAttached(flutterView)
|
||||||
|
|
||||||
components.engineReportedInitialized = false
|
components.engineReportedInitialized = false
|
||||||
flutterEvents.onViewReadyStateChange(System.currentTimeMillis(), true) { _ -> }
|
flutterEvents.onViewReadyStateChange(EventSequence.next(), true) { _ -> }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getView(): View {
|
override fun getView(): View {
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
package eu.weblibre.flutter_mozilla_components.api
|
package eu.weblibre.flutter_mozilla_components.api
|
||||||
|
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.MLEngineFeature
|
import eu.weblibre.flutter_mozilla_components.feature.MLEngineFeature
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.ResultConsumer
|
import eu.weblibre.flutter_mozilla_components.feature.ResultConsumer
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoMlApi
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoMlApi
|
||||||
@@ -68,7 +69,7 @@ class GeckoMlApiImpl(
|
|||||||
)
|
)
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
stateEvents.onMlProgress(System.currentTimeMillis(), mlProgress) { result ->
|
stateEvents.onMlProgress(EventSequence.next(), mlProgress) { result ->
|
||||||
result.onFailure { error ->
|
result.onFailure { error ->
|
||||||
android.util.Log.e("GeckoMlApi", "Failed to emit progress event: ${error.message}")
|
android.util.Log.e("GeckoMlApi", "Failed to emit progress event: ${error.message}")
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -7,6 +7,7 @@
|
|||||||
package eu.weblibre.flutter_mozilla_components.api
|
package eu.weblibre.flutter_mozilla_components.api
|
||||||
|
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.PrefManagerFeature
|
import eu.weblibre.flutter_mozilla_components.feature.PrefManagerFeature
|
||||||
import eu.weblibre.flutter_mozilla_components.feature.ResultConsumer
|
import eu.weblibre.flutter_mozilla_components.feature.ResultConsumer
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoPref
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoPref
|
||||||
@@ -201,7 +202,7 @@ class GeckoPrefApiImpl : GeckoPrefApi, BrowserPrefObserverDelegate {
|
|||||||
|
|
||||||
override fun onPreferenceChange(observedPreference: BrowserPreference<*>) {
|
override fun onPreferenceChange(observedPreference: BrowserPreference<*>) {
|
||||||
components.flutterEvents.onPreferenceChange(
|
components.flutterEvents.onPreferenceChange(
|
||||||
System.currentTimeMillis(), GeckoPref(
|
EventSequence.next(), GeckoPref(
|
||||||
name = observedPreference.pref,
|
name = observedPreference.pref,
|
||||||
value = observedPreference.value,
|
value = observedPreference.value,
|
||||||
defaultValue = observedPreference.defaultValue,
|
defaultValue = observedPreference.defaultValue,
|
||||||
|
|||||||
+2
-1
@@ -7,6 +7,7 @@
|
|||||||
package eu.weblibre.flutter_mozilla_components.api
|
package eu.weblibre.flutter_mozilla_components.api
|
||||||
|
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.api.GeckoDeleteBrowsingDataControllerImpl.Companion
|
import eu.weblibre.flutter_mozilla_components.api.GeckoDeleteBrowsingDataControllerImpl.Companion
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.AutocompleteResult
|
import eu.weblibre.flutter_mozilla_components.pigeons.AutocompleteResult
|
||||||
@@ -77,7 +78,7 @@ class GeckoSuggestionApiImpl(
|
|||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
suggestionEvents.onSuggestionResult(
|
suggestionEvents.onSuggestionResult(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
provider,
|
provider,
|
||||||
mappedResults
|
mappedResults
|
||||||
) { }
|
) { }
|
||||||
|
|||||||
+14
-13
@@ -17,6 +17,7 @@ import eu.weblibre.flutter_mozilla_components.pigeons.SourceValue
|
|||||||
import eu.weblibre.flutter_mozilla_components.pigeons.WebExtensionActionType
|
import eu.weblibre.flutter_mozilla_components.pigeons.WebExtensionActionType
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.WebExtensionData
|
import eu.weblibre.flutter_mozilla_components.pigeons.WebExtensionData
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.FindResultState
|
import eu.weblibre.flutter_mozilla_components.pigeons.FindResultState
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoStateEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoStateEvents
|
||||||
@@ -135,7 +136,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
components.flutterEvents.onIconChange(
|
components.flutterEvents.onIconChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
iconBytes
|
iconBytes
|
||||||
) { }
|
) { }
|
||||||
@@ -159,7 +160,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
val bytes = it.toWebPBytes()
|
val bytes = it.toWebPBytes()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
components.flutterEvents.onThumbnailChange(
|
components.flutterEvents.onThumbnailChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
bytes
|
bytes
|
||||||
) { }
|
) { }
|
||||||
@@ -191,21 +192,21 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
|
|
||||||
if (onSelectedTabChange) {
|
if (onSelectedTabChange) {
|
||||||
components.flutterEvents.onSelectedTabChange(
|
components.flutterEvents.onSelectedTabChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
selectedTab
|
selectedTab
|
||||||
) { }
|
) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onTabListChange) {
|
if (onTabListChange) {
|
||||||
components.flutterEvents.onTabListChange(
|
components.flutterEvents.onTabListChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tabs.map { it.id }) { }
|
tabs.map { it.id }) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
tabs.forEach { tab ->
|
tabs.forEach { tab ->
|
||||||
if (onTabContentStateChange) {
|
if (onTabContentStateChange) {
|
||||||
components.flutterEvents.onTabContentStateChange(
|
components.flutterEvents.onTabContentStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
TabContentState(
|
TabContentState(
|
||||||
id = tab.id,
|
id = tab.id,
|
||||||
parentId = tab.parentId,
|
parentId = tab.parentId,
|
||||||
@@ -226,7 +227,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
|
|
||||||
if (onSecurityInfoStateChange) {
|
if (onSecurityInfoStateChange) {
|
||||||
components.flutterEvents.onSecurityInfoStateChange(
|
components.flutterEvents.onSecurityInfoStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
SecurityInfoState(
|
SecurityInfoState(
|
||||||
tab.content.securityInfo.isSecure,
|
tab.content.securityInfo.isSecure,
|
||||||
@@ -238,7 +239,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
|
|
||||||
if (onReaderableStateChange) {
|
if (onReaderableStateChange) {
|
||||||
components.flutterEvents.onReaderableStateChange(
|
components.flutterEvents.onReaderableStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
ReaderableState(
|
ReaderableState(
|
||||||
tab.readerState.readerable,
|
tab.readerState.readerable,
|
||||||
@@ -249,7 +250,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
|
|
||||||
if (onHistoryStateChange) {
|
if (onHistoryStateChange) {
|
||||||
components.flutterEvents.onHistoryStateChange(
|
components.flutterEvents.onHistoryStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
HistoryState(
|
HistoryState(
|
||||||
items = tab.content.history.items.map { item ->
|
items = tab.content.history.items.map { item ->
|
||||||
@@ -264,7 +265,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
|
|
||||||
if (onFindResults) {
|
if (onFindResults) {
|
||||||
components.flutterEvents.onFindResults(
|
components.flutterEvents.onFindResults(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
tab.content.findResults.map { result ->
|
tab.content.findResults.map { result ->
|
||||||
FindResultState(
|
FindResultState(
|
||||||
@@ -321,7 +322,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
badgeBackgroundColor = browserAction.badgeBackgroundColor?.toLong(),
|
badgeBackgroundColor = browserAction.badgeBackgroundColor?.toLong(),
|
||||||
)
|
)
|
||||||
components.addonEvents.onUpsertWebExtensionAction(
|
components.addonEvents.onUpsertWebExtensionAction(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
extension.id,
|
extension.id,
|
||||||
WebExtensionActionType.BROWSER,
|
WebExtensionActionType.BROWSER,
|
||||||
data
|
data
|
||||||
@@ -336,7 +337,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
val imageBytes = icon.toWebPBytes()
|
val imageBytes = icon.toWebPBytes()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
components.addonEvents.onUpdateWebExtensionIcon(
|
components.addonEvents.onUpdateWebExtensionIcon(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
extension.id,
|
extension.id,
|
||||||
WebExtensionActionType.BROWSER,
|
WebExtensionActionType.BROWSER,
|
||||||
imageBytes
|
imageBytes
|
||||||
@@ -362,7 +363,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
badgeBackgroundColor = pageAction.badgeBackgroundColor?.toLong(),
|
badgeBackgroundColor = pageAction.badgeBackgroundColor?.toLong(),
|
||||||
)
|
)
|
||||||
components.addonEvents.onUpsertWebExtensionAction(
|
components.addonEvents.onUpsertWebExtensionAction(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
extension.id,
|
extension.id,
|
||||||
WebExtensionActionType.PAGE,
|
WebExtensionActionType.PAGE,
|
||||||
data
|
data
|
||||||
@@ -377,7 +378,7 @@ class GeckoTabsApiImpl : GeckoTabsApi {
|
|||||||
val imageBytes = icon.toWebPBytes()
|
val imageBytes = icon.toWebPBytes()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
components.addonEvents.onUpdateWebExtensionIcon(
|
components.addonEvents.onUpdateWebExtensionIcon(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
extension.id,
|
extension.id,
|
||||||
WebExtensionActionType.PAGE,
|
WebExtensionActionType.PAGE,
|
||||||
imageBytes
|
imageBytes
|
||||||
|
|||||||
+8
-6
@@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
package eu.weblibre.flutter_mozilla_components.components
|
package eu.weblibre.flutter_mozilla_components.components
|
||||||
|
|
||||||
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
import eu.weblibre.flutter_mozilla_components.api.ReaderViewEventsImpl
|
import eu.weblibre.flutter_mozilla_components.api.ReaderViewEventsImpl
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.FindResultState
|
import eu.weblibre.flutter_mozilla_components.pigeons.FindResultState
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoAddonEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoAddonEvents
|
||||||
@@ -44,7 +46,7 @@ class Events(
|
|||||||
.debounce { 50 }
|
.debounce { 50 }
|
||||||
.collect { tabId ->
|
.collect { tabId ->
|
||||||
flutterEvents.onSelectedTabChange(
|
flutterEvents.onSelectedTabChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tabId
|
tabId
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
}
|
}
|
||||||
@@ -70,7 +72,7 @@ class Events(
|
|||||||
.collect { tab ->
|
.collect { tab ->
|
||||||
val iconBytes = tab.content.icon?.toWebPBytes()
|
val iconBytes = tab.content.icon?.toWebPBytes()
|
||||||
flutterEvents.onIconChange(
|
flutterEvents.onIconChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
iconBytes
|
iconBytes
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
@@ -85,7 +87,7 @@ class Events(
|
|||||||
.debounce(15)
|
.debounce(15)
|
||||||
.collect { tab ->
|
.collect { tab ->
|
||||||
flutterEvents.onSecurityInfoStateChange(
|
flutterEvents.onSecurityInfoStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
SecurityInfoState(
|
SecurityInfoState(
|
||||||
tab.content.securityInfo.isSecure,
|
tab.content.securityInfo.isSecure,
|
||||||
@@ -110,7 +112,7 @@ class Events(
|
|||||||
.debounce(25)
|
.debounce(25)
|
||||||
.collect { tab ->
|
.collect { tab ->
|
||||||
flutterEvents.onReaderableStateChange(
|
flutterEvents.onReaderableStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
ReaderableState(
|
ReaderableState(
|
||||||
tab.readerState.readerable,
|
tab.readerState.readerable,
|
||||||
@@ -135,7 +137,7 @@ class Events(
|
|||||||
.debounce(15)
|
.debounce(15)
|
||||||
.collect { tab ->
|
.collect { tab ->
|
||||||
flutterEvents.onHistoryStateChange(
|
flutterEvents.onHistoryStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
tab.id,
|
tab.id,
|
||||||
HistoryState(
|
HistoryState(
|
||||||
items = tab.content.history.items.map { item ->
|
items = tab.content.history.items.map { item ->
|
||||||
@@ -170,7 +172,7 @@ class Events(
|
|||||||
.debounce(15)
|
.debounce(15)
|
||||||
.collect { tab ->
|
.collect { tab ->
|
||||||
flutterEvents.onTabContentStateChange(
|
flutterEvents.onTabContentStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
TabContentState(
|
TabContentState(
|
||||||
id = tab.id,
|
id = tab.id,
|
||||||
parentId = tab.parentId,
|
parentId = tab.parentId,
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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 https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package eu.weblibre.flutter_mozilla_components.ext
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicLong
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread-safe monotonic sequence counter for event ordering.
|
||||||
|
*
|
||||||
|
* Replaces System.currentTimeMillis() for event timestamps sent to Flutter,
|
||||||
|
* guaranteeing strictly increasing values regardless of wall-clock changes
|
||||||
|
* and eliminating same-millisecond collisions.
|
||||||
|
*/
|
||||||
|
object EventSequence {
|
||||||
|
private val counter = AtomicLong(0)
|
||||||
|
|
||||||
|
fun next(): Long = counter.incrementAndGet()
|
||||||
|
}
|
||||||
+2
-1
@@ -7,6 +7,7 @@
|
|||||||
package eu.weblibre.flutter_mozilla_components.feature
|
package eu.weblibre.flutter_mozilla_components.feature
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.BrowserExtensionEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.BrowserExtensionEvents
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
@@ -86,7 +87,7 @@ object BrowserExtensionFeature {
|
|||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
extensionEvents.onFeedRequested(
|
extensionEvents.onFeedRequested(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
url
|
url
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -8,6 +8,7 @@ package eu.weblibre.flutter_mozilla_components.feature
|
|||||||
|
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.ContainerSiteAssignment
|
import eu.weblibre.flutter_mozilla_components.pigeons.ContainerSiteAssignment
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoStateEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoStateEvents
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -115,7 +116,7 @@ object ContainerProxyFeature {
|
|||||||
if (status == "success") {
|
if (status == "success") {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
events.onContainerSiteAssignment(
|
events.onContainerSiteAssignment(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
ContainerSiteAssignment(
|
ContainerSiteAssignment(
|
||||||
requestId = requestId,
|
requestId = requestId,
|
||||||
tabId = components.core.store.state.selectedTabId,
|
tabId = components.core.store.state.selectedTabId,
|
||||||
|
|||||||
+2
-1
@@ -14,6 +14,7 @@ import androidx.core.graphics.Insets
|
|||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsAnimationCompat
|
import androidx.core.view.WindowInsetsAnimationCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoViewportEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoViewportEvents
|
||||||
import mozilla.components.support.base.log.logger.Logger
|
import mozilla.components.support.base.log.logger.Logger
|
||||||
import org.mozilla.gecko.util.ThreadUtils.runOnUiThread
|
import org.mozilla.gecko.util.ThreadUtils.runOnUiThread
|
||||||
@@ -185,7 +186,7 @@ class KeyboardVisibilityFeature(
|
|||||||
lastKeyboardHeight = heightPx
|
lastKeyboardHeight = heightPx
|
||||||
lastKeyboardVisible = isVisible
|
lastKeyboardVisible = isVisible
|
||||||
|
|
||||||
val timestamp = System.currentTimeMillis()
|
val timestamp = EventSequence.next()
|
||||||
|
|
||||||
logger.debug("$TAG: Keyboard change - height=$heightPx, visible=$isVisible, animating=$isAnimating")
|
logger.debug("$TAG: Keyboard change - height=$heightPx, visible=$isVisible, animating=$isAnimating")
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package eu.weblibre.flutter_mozilla_components.feature
|
package eu.weblibre.flutter_mozilla_components.feature
|
||||||
|
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoTabContentEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoTabContentEvents
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.TabContent
|
import eu.weblibre.flutter_mozilla_components.pigeons.TabContent
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -50,7 +51,7 @@ class ReadabilityExtractFeature(
|
|||||||
override fun onPortMessage(message: Any, port: Port) {
|
override fun onPortMessage(message: Any, port: Port) {
|
||||||
if (message is JSONObject) {
|
if (message is JSONObject) {
|
||||||
tabContentEvents.onContentUpdate(
|
tabContentEvents.onContentUpdate(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
contentArg = TabContent(
|
contentArg = TabContent(
|
||||||
tabId = tabId,
|
tabId = tabId,
|
||||||
fullContentMarkdown = message.tryGetString("fullContentMarkdown"),
|
fullContentMarkdown = message.tryGetString("fullContentMarkdown"),
|
||||||
|
|||||||
+9
-8
@@ -7,6 +7,7 @@ package eu.weblibre.flutter_mozilla_components.feature
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoAddonEvents
|
import eu.weblibre.flutter_mozilla_components.pigeons.GeckoAddonEvents
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.WebExtensionActionType
|
import eu.weblibre.flutter_mozilla_components.pigeons.WebExtensionActionType
|
||||||
@@ -66,7 +67,7 @@ class WebExtensionToolbarFeature(
|
|||||||
.filter { !store.state.extensions.containsKey(it) || store.state.extensions[it]?.enabled == false }
|
.filter { !store.state.extensions.containsKey(it) || store.state.extensions[it]?.enabled == false }
|
||||||
.forEach { extensionId ->
|
.forEach { extensionId ->
|
||||||
addonEvents.onRemoveWebExtensionAction(
|
addonEvents.onRemoveWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extensionId,
|
extensionIdArg = extensionId,
|
||||||
actionTypeArg = WebExtensionActionType.BROWSER,
|
actionTypeArg = WebExtensionActionType.BROWSER,
|
||||||
) {}
|
) {}
|
||||||
@@ -77,7 +78,7 @@ class WebExtensionToolbarFeature(
|
|||||||
.filter { !store.state.extensions.containsKey(it) || store.state.extensions[it]?.enabled == false }
|
.filter { !store.state.extensions.containsKey(it) || store.state.extensions[it]?.enabled == false }
|
||||||
.forEach { extensionId ->
|
.forEach { extensionId ->
|
||||||
addonEvents.onRemoveWebExtensionAction(
|
addonEvents.onRemoveWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extensionId,
|
extensionIdArg = extensionId,
|
||||||
actionTypeArg = WebExtensionActionType.PAGE,
|
actionTypeArg = WebExtensionActionType.PAGE,
|
||||||
) {}
|
) {}
|
||||||
@@ -106,7 +107,7 @@ class WebExtensionToolbarFeature(
|
|||||||
webExtensionBrowserActions.keys.toList().forEach { extensionId ->
|
webExtensionBrowserActions.keys.toList().forEach { extensionId ->
|
||||||
if (extensionId !in enabledExtensionIds) {
|
if (extensionId !in enabledExtensionIds) {
|
||||||
addonEvents.onRemoveWebExtensionAction(
|
addonEvents.onRemoveWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extensionId,
|
extensionIdArg = extensionId,
|
||||||
actionTypeArg = WebExtensionActionType.BROWSER,
|
actionTypeArg = WebExtensionActionType.BROWSER,
|
||||||
) {}
|
) {}
|
||||||
@@ -117,7 +118,7 @@ class WebExtensionToolbarFeature(
|
|||||||
webExtensionPageActions.keys.toList().forEach { extensionId ->
|
webExtensionPageActions.keys.toList().forEach { extensionId ->
|
||||||
if (extensionId !in enabledExtensionIds) {
|
if (extensionId !in enabledExtensionIds) {
|
||||||
addonEvents.onRemoveWebExtensionAction(
|
addonEvents.onRemoveWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extensionId,
|
extensionIdArg = extensionId,
|
||||||
actionTypeArg = WebExtensionActionType.PAGE,
|
actionTypeArg = WebExtensionActionType.PAGE,
|
||||||
) {}
|
) {}
|
||||||
@@ -130,7 +131,7 @@ class WebExtensionToolbarFeature(
|
|||||||
if (extensionNotAllowedInTab(extension, tab)) {
|
if (extensionNotAllowedInTab(extension, tab)) {
|
||||||
webExtensionPageActions[extension.id]?.let {
|
webExtensionPageActions[extension.id]?.let {
|
||||||
addonEvents.onRemoveWebExtensionAction(
|
addonEvents.onRemoveWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extension.id,
|
extensionIdArg = extension.id,
|
||||||
actionTypeArg = WebExtensionActionType.PAGE,
|
actionTypeArg = WebExtensionActionType.PAGE,
|
||||||
) {}
|
) {}
|
||||||
@@ -138,7 +139,7 @@ class WebExtensionToolbarFeature(
|
|||||||
}
|
}
|
||||||
webExtensionBrowserActions[extension.id]?.let {
|
webExtensionBrowserActions[extension.id]?.let {
|
||||||
addonEvents.onRemoveWebExtensionAction(
|
addonEvents.onRemoveWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extension.id,
|
extensionIdArg = extension.id,
|
||||||
actionTypeArg = WebExtensionActionType.BROWSER,
|
actionTypeArg = WebExtensionActionType.BROWSER,
|
||||||
) {}
|
) {}
|
||||||
@@ -220,7 +221,7 @@ class WebExtensionToolbarFeature(
|
|||||||
)
|
)
|
||||||
|
|
||||||
addonEvents.onUpsertWebExtensionAction(
|
addonEvents.onUpsertWebExtensionAction(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extension.id,
|
extensionIdArg = extension.id,
|
||||||
actionTypeArg = if (isPageAction) WebExtensionActionType.PAGE else WebExtensionActionType.BROWSER,
|
actionTypeArg = if (isPageAction) WebExtensionActionType.PAGE else WebExtensionActionType.BROWSER,
|
||||||
extensionDataArg = data
|
extensionDataArg = data
|
||||||
@@ -235,7 +236,7 @@ class WebExtensionToolbarFeature(
|
|||||||
val imageBytes = icon.toWebPBytes()
|
val imageBytes = icon.toWebPBytes()
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
addonEvents.onUpdateWebExtensionIcon(
|
addonEvents.onUpdateWebExtensionIcon(
|
||||||
timestampArg = System.currentTimeMillis(),
|
timestampArg = EventSequence.next(),
|
||||||
extensionIdArg = extensionId,
|
extensionIdArg = extensionId,
|
||||||
actionTypeArg = if (isPageAction) WebExtensionActionType.PAGE else WebExtensionActionType.BROWSER,
|
actionTypeArg = if (isPageAction) WebExtensionActionType.PAGE else WebExtensionActionType.BROWSER,
|
||||||
iconArg = imageBytes
|
iconArg = imageBytes
|
||||||
|
|||||||
+3
-2
@@ -10,6 +10,7 @@ import android.content.Context
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.api.ReaderViewEventsImpl
|
import eu.weblibre.flutter_mozilla_components.api.ReaderViewEventsImpl
|
||||||
import eu.weblibre.flutter_mozilla_components.api.ReaderViewControllerListener
|
import eu.weblibre.flutter_mozilla_components.api.ReaderViewControllerListener
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.ReaderViewController
|
import eu.weblibre.flutter_mozilla_components.pigeons.ReaderViewController
|
||||||
@@ -36,12 +37,12 @@ class ReaderViewIntegration(
|
|||||||
if (enabled) {
|
if (enabled) {
|
||||||
feature.showReaderView()
|
feature.showReaderView()
|
||||||
|
|
||||||
readerViewController.appearanceButtonVisibility(System.currentTimeMillis(),true) { _ -> };
|
readerViewController.appearanceButtonVisibility(EventSequence.next(),true) { _ -> };
|
||||||
} else {
|
} else {
|
||||||
feature.hideReaderView()
|
feature.hideReaderView()
|
||||||
feature.hideControls()
|
feature.hideControls()
|
||||||
|
|
||||||
readerViewController.appearanceButtonVisibility(System.currentTimeMillis(),false) { _ -> };
|
readerViewController.appearanceButtonVisibility(EventSequence.next(),false) { _ -> };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-8
@@ -6,6 +6,7 @@ package eu.weblibre.flutter_mozilla_components.middleware
|
|||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
import eu.weblibre.flutter_mozilla_components.GlobalComponents
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.resize
|
import eu.weblibre.flutter_mozilla_components.ext.resize
|
||||||
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
import eu.weblibre.flutter_mozilla_components.ext.toWebPBytes
|
||||||
import eu.weblibre.flutter_mozilla_components.pigeons.AudioHitResult
|
import eu.weblibre.flutter_mozilla_components.pigeons.AudioHitResult
|
||||||
@@ -55,7 +56,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
val bytes = resized.toWebPBytes()
|
val bytes = resized.toWebPBytes()
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onThumbnailChange(System.currentTimeMillis(), action.sessionId, bytes) { _ -> }
|
flutterEvents.onThumbnailChange(EventSequence.next(), action.sessionId, bytes) { _ -> }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//UpdateReaderConnectRequiredAction seems to be the only event that is called predictable
|
//UpdateReaderConnectRequiredAction seems to be the only event that is called predictable
|
||||||
@@ -64,7 +65,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
if(!components.engineReportedInitialized) {
|
if(!components.engineReportedInitialized) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onEngineReadyStateChange(
|
flutterEvents.onEngineReadyStateChange(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
true
|
true
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
}
|
}
|
||||||
@@ -75,7 +76,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
is TabListAction.AddTabAction -> {
|
is TabListAction.AddTabAction -> {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onTabAdded(
|
flutterEvents.onTabAdded(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
action.tab.id
|
action.tab.id
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onIconUpdate(
|
flutterEvents.onIconUpdate(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
action.pageUrl,
|
action.pageUrl,
|
||||||
bytes
|
bytes
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
@@ -94,7 +95,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
is ContentAction.UpdateHitResultAction -> {
|
is ContentAction.UpdateHitResultAction -> {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onLongPress(
|
flutterEvents.onLongPress(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
action.sessionId,
|
action.sessionId,
|
||||||
when(val result = action.hitResult) {
|
when(val result = action.hitResult) {
|
||||||
is HitResult.AUDIO -> AudioHitResult(result.src, result.title)
|
is HitResult.AUDIO -> AudioHitResult(result.src, result.title)
|
||||||
@@ -112,7 +113,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
is ContentAction.AddFindResultAction -> {
|
is ContentAction.AddFindResultAction -> {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onFindResults(
|
flutterEvents.onFindResults(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
action.sessionId,
|
action.sessionId,
|
||||||
listOf(
|
listOf(
|
||||||
FindResultState(
|
FindResultState(
|
||||||
@@ -127,7 +128,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
is ContentAction.ClearFindResultsAction -> {
|
is ContentAction.ClearFindResultsAction -> {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
flutterEvents.onFindResults(
|
flutterEvents.onFindResults(
|
||||||
System.currentTimeMillis(),
|
EventSequence.next(),
|
||||||
action.sessionId,
|
action.sessionId,
|
||||||
listOf()
|
listOf()
|
||||||
) { _ -> }
|
) { _ -> }
|
||||||
@@ -136,7 +137,7 @@ class FlutterEventMiddleware(private val flutterEvents: GeckoStateEvents) : Midd
|
|||||||
// is ReaderAction.UpdateReaderScrollYAction -> {
|
// is ReaderAction.UpdateReaderScrollYAction -> {
|
||||||
// runOnUiThread {
|
// runOnUiThread {
|
||||||
// flutterEvents.onScrollChange(
|
// flutterEvents.onScrollChange(
|
||||||
// System.currentTimeMillis(),
|
// EventSequence.next(),
|
||||||
// action.tabId,
|
// action.tabId,
|
||||||
// action.scrollY.toLong()
|
// action.scrollY.toLong()
|
||||||
// ) { _ -> }
|
// ) { _ -> }
|
||||||
|
|||||||
@@ -51,18 +51,18 @@ class GeckoAddonService extends GeckoAddonEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onRemoveWebExtensionAction(
|
void onRemoveWebExtensionAction(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String extensionId,
|
String extensionId,
|
||||||
WebExtensionActionType actionType,
|
WebExtensionActionType actionType,
|
||||||
) {
|
) {
|
||||||
switch (actionType) {
|
switch (actionType) {
|
||||||
case WebExtensionActionType.browser:
|
case WebExtensionActionType.browser:
|
||||||
_browserExtensionSubject.addWhenMoreRecent(timestamp, extensionId, (
|
_browserExtensionSubject.addWhenMoreRecent(sequence, extensionId, (
|
||||||
extensionId: extensionId,
|
extensionId: extensionId,
|
||||||
data: null,
|
data: null,
|
||||||
));
|
));
|
||||||
case WebExtensionActionType.page:
|
case WebExtensionActionType.page:
|
||||||
_pageExtensionSubject.addWhenMoreRecent(timestamp, extensionId, (
|
_pageExtensionSubject.addWhenMoreRecent(sequence, extensionId, (
|
||||||
extensionId: extensionId,
|
extensionId: extensionId,
|
||||||
data: null,
|
data: null,
|
||||||
));
|
));
|
||||||
@@ -71,19 +71,19 @@ class GeckoAddonService extends GeckoAddonEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onUpdateWebExtensionIcon(
|
void onUpdateWebExtensionIcon(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String extensionId,
|
String extensionId,
|
||||||
WebExtensionActionType actionType,
|
WebExtensionActionType actionType,
|
||||||
Uint8List icon,
|
Uint8List icon,
|
||||||
) {
|
) {
|
||||||
switch (actionType) {
|
switch (actionType) {
|
||||||
case WebExtensionActionType.browser:
|
case WebExtensionActionType.browser:
|
||||||
_browserIconSubject.addWhenMoreRecent(timestamp, extensionId, (
|
_browserIconSubject.addWhenMoreRecent(sequence, extensionId, (
|
||||||
extensionId: extensionId,
|
extensionId: extensionId,
|
||||||
bytes: icon,
|
bytes: icon,
|
||||||
));
|
));
|
||||||
case WebExtensionActionType.page:
|
case WebExtensionActionType.page:
|
||||||
_pageIconSubject.addWhenMoreRecent(timestamp, extensionId, (
|
_pageIconSubject.addWhenMoreRecent(sequence, extensionId, (
|
||||||
extensionId: extensionId,
|
extensionId: extensionId,
|
||||||
bytes: icon,
|
bytes: icon,
|
||||||
));
|
));
|
||||||
@@ -92,19 +92,19 @@ class GeckoAddonService extends GeckoAddonEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onUpsertWebExtensionAction(
|
void onUpsertWebExtensionAction(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String extensionId,
|
String extensionId,
|
||||||
WebExtensionActionType actionType,
|
WebExtensionActionType actionType,
|
||||||
WebExtensionData extensionData,
|
WebExtensionData extensionData,
|
||||||
) {
|
) {
|
||||||
switch (actionType) {
|
switch (actionType) {
|
||||||
case WebExtensionActionType.browser:
|
case WebExtensionActionType.browser:
|
||||||
_browserExtensionSubject.addWhenMoreRecent(timestamp, extensionId, (
|
_browserExtensionSubject.addWhenMoreRecent(sequence, extensionId, (
|
||||||
extensionId: extensionId,
|
extensionId: extensionId,
|
||||||
data: extensionData,
|
data: extensionData,
|
||||||
));
|
));
|
||||||
case WebExtensionActionType.page:
|
case WebExtensionActionType.page:
|
||||||
_pageExtensionSubject.addWhenMoreRecent(timestamp, extensionId, (
|
_pageExtensionSubject.addWhenMoreRecent(sequence, extensionId, (
|
||||||
extensionId: extensionId,
|
extensionId: extensionId,
|
||||||
data: extensionData,
|
data: extensionData,
|
||||||
));
|
));
|
||||||
|
|||||||
+2
-2
@@ -58,8 +58,8 @@ class GeckoBrowserExtensionService extends BrowserExtensionEvents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onFeedRequested(int timestamp, String url) {
|
void onFeedRequested(int sequence, String url) {
|
||||||
_feedRequest.addWhenMoreRecent(timestamp, null, url);
|
_feedRequest.addWhenMoreRecent(sequence, null, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ typedef ThumbnailEvent = ({String tabId, Uint8List? bytes});
|
|||||||
typedef FindResultsEvent = ({String tabId, List<FindResultState> results});
|
typedef FindResultsEvent = ({String tabId, List<FindResultState> results});
|
||||||
typedef LongPressEvent = ({String tabId, HitResult hitResult});
|
typedef LongPressEvent = ({String tabId, HitResult hitResult});
|
||||||
typedef ScrollEvent = ({String tabId, int scrollY});
|
typedef ScrollEvent = ({String tabId, int scrollY});
|
||||||
|
typedef ManifestUpdateEvent = ({String tabId, PwaManifest? manifest});
|
||||||
|
|
||||||
class GeckoEventService extends GeckoStateEvents {
|
class GeckoEventService extends GeckoStateEvents {
|
||||||
// Stream controllers
|
// Stream controllers
|
||||||
@@ -44,6 +45,7 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
|
|
||||||
final _tabAddedSubject = PublishSubject<String>();
|
final _tabAddedSubject = PublishSubject<String>();
|
||||||
final _mlProgressSubject = PublishSubject<MlProgressData>();
|
final _mlProgressSubject = PublishSubject<MlProgressData>();
|
||||||
|
final _manifestUpdateSubject = PublishSubject<ManifestUpdateEvent>();
|
||||||
|
|
||||||
// Event streams
|
// Event streams
|
||||||
ValueStream<bool> get viewReadyStateEvents => _viewStateSubject.stream;
|
ValueStream<bool> get viewReadyStateEvents => _viewStateSubject.stream;
|
||||||
@@ -68,52 +70,46 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
|
|
||||||
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
Stream<String> get tabAddedStream => _tabAddedSubject.stream;
|
||||||
Stream<MlProgressData> get mlProgressEvents => _mlProgressSubject.stream;
|
Stream<MlProgressData> get mlProgressEvents => _mlProgressSubject.stream;
|
||||||
|
Stream<ManifestUpdateEvent> get manifestUpdateEvents =>
|
||||||
|
_manifestUpdateSubject.stream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onViewReadyStateChange(int timestamp, bool state) {
|
void onViewReadyStateChange(int sequence, bool state) {
|
||||||
_viewStateSubject.addWhenMoreRecent(timestamp, null, state);
|
_viewStateSubject.addWhenMoreRecent(sequence, null, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onEngineReadyStateChange(int timestamp, bool state) {
|
void onEngineReadyStateChange(int sequence, bool state) {
|
||||||
_engineStateSubject.addWhenMoreRecent(timestamp, null, state);
|
_engineStateSubject.addWhenMoreRecent(sequence, null, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overridden methods
|
// Overridden methods
|
||||||
@override
|
@override
|
||||||
void onTabListChange(int timestamp, List<String?> tabIds) {
|
void onTabListChange(int sequence, List<String?> tabIds) {
|
||||||
_tabListSubject.addWhenMoreRecent(
|
_tabListSubject.addWhenMoreRecent(sequence, null, tabIds.nonNulls.toList());
|
||||||
timestamp,
|
|
||||||
null,
|
|
||||||
tabIds.nonNulls.toList(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onSelectedTabChange(int timestamp, String? id) {
|
void onSelectedTabChange(int sequence, String? id) {
|
||||||
_selectedTabSubject.addWhenMoreRecent(timestamp, id, id);
|
_selectedTabSubject.addWhenMoreRecent(sequence, id, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onTabContentStateChange(int timestamp, TabContentState state) {
|
void onTabContentStateChange(int sequence, TabContentState state) {
|
||||||
_tabContentSubject.addWhenMoreRecent(timestamp, state.id, state);
|
_tabContentSubject.addWhenMoreRecent(sequence, state.id, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onHistoryStateChange(int timestamp, String id, HistoryState state) {
|
void onHistoryStateChange(int sequence, String id, HistoryState state) {
|
||||||
_historySubject.addWhenMoreRecent(timestamp, id, (
|
_historySubject.addWhenMoreRecent(sequence, id, (
|
||||||
tabId: id,
|
tabId: id,
|
||||||
history: state,
|
history: state,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onReaderableStateChange(
|
void onReaderableStateChange(int sequence, String id, ReaderableState state) {
|
||||||
int timestamp,
|
_readerableSubject.addWhenMoreRecent(sequence, id, (
|
||||||
String id,
|
|
||||||
ReaderableState state,
|
|
||||||
) {
|
|
||||||
_readerableSubject.addWhenMoreRecent(timestamp, id, (
|
|
||||||
tabId: id,
|
tabId: id,
|
||||||
readerable: state,
|
readerable: state,
|
||||||
));
|
));
|
||||||
@@ -121,87 +117,91 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onSecurityInfoStateChange(
|
void onSecurityInfoStateChange(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String id,
|
String id,
|
||||||
SecurityInfoState state,
|
SecurityInfoState state,
|
||||||
) {
|
) {
|
||||||
_securityInfoSubject.addWhenMoreRecent(timestamp, id, (
|
_securityInfoSubject.addWhenMoreRecent(sequence, id, (
|
||||||
tabId: id,
|
tabId: id,
|
||||||
securityInfo: state,
|
securityInfo: state,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onIconChange(int timestamp, String id, Uint8List? bytes) {
|
void onIconChange(int sequence, String id, Uint8List? bytes) {
|
||||||
_iconChangeSubject.addWhenMoreRecent(timestamp, id, (
|
_iconChangeSubject.addWhenMoreRecent(sequence, id, (
|
||||||
tabId: id,
|
tabId: id,
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onIconUpdate(int timestamp, String url, Uint8List bytes) {
|
void onIconUpdate(int sequence, String url, Uint8List bytes) {
|
||||||
_iconUpdateSubject.addWhenMoreRecent(timestamp, url, (
|
_iconUpdateSubject.addWhenMoreRecent(sequence, url, (
|
||||||
url: url,
|
url: url,
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onThumbnailChange(int timestamp, String id, Uint8List? bytes) {
|
void onThumbnailChange(int sequence, String id, Uint8List? bytes) {
|
||||||
_thumbnailSubject.addWhenMoreRecent(timestamp, id, (
|
_thumbnailSubject.addWhenMoreRecent(sequence, id, (
|
||||||
tabId: id,
|
tabId: id,
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onFindResults(int timestamp, String id, List<FindResultState?> results) {
|
void onFindResults(int sequence, String id, List<FindResultState?> results) {
|
||||||
_findResultsSubject.addWhenMoreRecent(timestamp, id, (
|
_findResultsSubject.addWhenMoreRecent(sequence, id, (
|
||||||
tabId: id,
|
tabId: id,
|
||||||
results: results.nonNulls.toList(),
|
results: results.nonNulls.toList(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onLongPress(int timestamp, String id, HitResult hitResult) {
|
void onLongPress(int sequence, String id, HitResult hitResult) {
|
||||||
_longPressSubject.addWhenMoreRecent(timestamp, id, (
|
_longPressSubject.addWhenMoreRecent(sequence, id, (
|
||||||
tabId: id,
|
tabId: id,
|
||||||
hitResult: hitResult,
|
hitResult: hitResult,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onTabAdded(int timestamp, String tabId) {
|
void onTabAdded(int sequence, String tabId) {
|
||||||
_tabAddedSubject.addWhenMoreRecent(timestamp, null, tabId);
|
_tabAddedSubject.addWhenMoreRecent(sequence, null, tabId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
// @override
|
||||||
// void onScrollChange(int timestamp, String tabId, int scrollY) {
|
// void onScrollChange(int sequence, String tabId, int scrollY) {
|
||||||
// _scrollEventSubject.addWhenMoreRecent(timestamp, tabId, (
|
// _scrollEventSubject.addWhenMoreRecent(sequence, tabId, (
|
||||||
// tabId: tabId,
|
// tabId: tabId,
|
||||||
// scrollY: scrollY,
|
// scrollY: scrollY,
|
||||||
// ));
|
// ));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onPreferenceChange(int timestamp, GeckoPref value) {
|
void onPreferenceChange(int sequence, GeckoPref value) {
|
||||||
_prefUpdateSubject.addWhenMoreRecent(timestamp, value.name, value);
|
_prefUpdateSubject.addWhenMoreRecent(sequence, value.name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onContainerSiteAssignment(
|
void onContainerSiteAssignment(
|
||||||
int timestamp,
|
int sequence,
|
||||||
ContainerSiteAssignment details,
|
ContainerSiteAssignment details,
|
||||||
) {
|
) {
|
||||||
_siteAssignementSubject.addWhenMoreRecent(
|
_siteAssignementSubject.addWhenMoreRecent(
|
||||||
timestamp,
|
sequence,
|
||||||
details.requestId,
|
details.requestId,
|
||||||
details,
|
details,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
void onMlProgress(int sequence, MlProgressData progress) {
|
||||||
|
_mlProgressSubject.addWhenMoreRecent(sequence, null, progress);
|
||||||
|
}
|
||||||
|
|
||||||
void onMlProgress(int timestamp, MlProgressData progress) {
|
void onMlProgress(int timestamp, MlProgressData progress) {
|
||||||
_mlProgressSubject.addWhenMoreRecent(timestamp, null, progress);
|
_mlProgressSubject.addWhenMoreRecent(timestamp, null, progress);
|
||||||
}
|
}
|
||||||
@@ -236,5 +236,6 @@ class GeckoEventService extends GeckoStateEvents {
|
|||||||
await _prefUpdateSubject.close();
|
await _prefUpdateSubject.close();
|
||||||
await _siteAssignementSubject.close();
|
await _siteAssignementSubject.close();
|
||||||
await _mlProgressSubject.close();
|
await _mlProgressSubject.close();
|
||||||
|
await _manifestUpdateSubject.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ class GeckoReaderableService extends ReaderViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void appearanceButtonVisibility(int timestamp, bool visible) {
|
void appearanceButtonVisibility(int sequence, bool visible) {
|
||||||
_appearanceVisibility.addWhenMoreRecent(timestamp, null, visible);
|
_appearanceVisibility.addWhenMoreRecent(sequence, null, visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
GeckoReaderableService.setUp({
|
GeckoReaderableService.setUp({
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ class GeckoSuggestionsService extends GeckoSuggestionEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onSuggestionResult(
|
void onSuggestionResult(
|
||||||
int timestamp,
|
int sequence,
|
||||||
GeckoSuggestionType suggestionType,
|
GeckoSuggestionType suggestionType,
|
||||||
List<GeckoSuggestion> suggestions,
|
List<GeckoSuggestion> suggestions,
|
||||||
) {
|
) {
|
||||||
_suggestionsSubject.addWhenMoreRecent(
|
_suggestionsSubject.addWhenMoreRecent(
|
||||||
timestamp,
|
sequence,
|
||||||
suggestionType,
|
suggestionType,
|
||||||
suggestions,
|
suggestions,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ class GeckoTabContentService extends GeckoTabContentEvents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onContentUpdate(int timestamp, TabContent content) {
|
void onContentUpdate(int sequence, TabContent content) {
|
||||||
_contentSubject.addWhenMoreRecent(timestamp, content.tabId, content);
|
_contentSubject.addWhenMoreRecent(sequence, content.tabId, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
|
|||||||
@@ -101,12 +101,12 @@ class GeckoViewportService extends GeckoViewportEvents {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onKeyboardVisibilityChanged(
|
void onKeyboardVisibilityChanged(
|
||||||
int timestamp,
|
int sequence,
|
||||||
int heightPx,
|
int heightPx,
|
||||||
bool isVisible,
|
bool isVisible,
|
||||||
bool isAnimating,
|
bool isAnimating,
|
||||||
) {
|
) {
|
||||||
_keyboardSubject.addWhenMoreRecent(timestamp, null, (
|
_keyboardSubject.addWhenMoreRecent(sequence, null, (
|
||||||
heightPx: heightPx,
|
heightPx: heightPx,
|
||||||
isVisible: isVisible,
|
isVisible: isVisible,
|
||||||
isAnimating: isAnimating,
|
isAnimating: isAnimating,
|
||||||
|
|||||||
@@ -9,17 +9,29 @@ import 'package:rxdart/rxdart.dart';
|
|||||||
final _lastEventTimes = <Subject, Map<dynamic, int>>{};
|
final _lastEventTimes = <Subject, Map<dynamic, int>>{};
|
||||||
|
|
||||||
extension SubjectAddRecent<T> on Subject<T> {
|
extension SubjectAddRecent<T> on Subject<T> {
|
||||||
void addWhenMoreRecent(int timestamp, dynamic identifier, T value) {
|
/// Adds [value] to this Subject only if [sequence] is greater than
|
||||||
|
/// the last sequence number for this [identifier].
|
||||||
|
///
|
||||||
|
/// Uses atomic event sequence numbers (from native EventSequence) to ensure
|
||||||
|
/// events are processed in order and prevent out-of-order updates.
|
||||||
|
/// Sequence numbers are monotonically increasing integers (0, 1, 2, ...).
|
||||||
|
void addWhenMoreRecent(int sequence, dynamic identifier, T value) {
|
||||||
_lastEventTimes[this] ??= {};
|
_lastEventTimes[this] ??= {};
|
||||||
|
|
||||||
if ((_lastEventTimes[this]?[identifier] ?? 0) < timestamp) {
|
if ((_lastEventTimes[this]?[identifier] ?? 0) < sequence) {
|
||||||
_lastEventTimes[this]![identifier] = timestamp;
|
_lastEventTimes[this]![identifier] = sequence;
|
||||||
add(value);
|
add(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates this BehaviorSubject only if [sequence] is greater than
|
||||||
|
/// the last sequence number for this [identifier].
|
||||||
|
///
|
||||||
|
/// Uses atomic event sequence numbers (from native EventSequence) to ensure
|
||||||
|
/// events are processed in order and prevent out-of-order updates.
|
||||||
|
/// Sequence numbers are monotonically increasing integers (0, 1, 2, ...).
|
||||||
void updateWhenMoreRecent(
|
void updateWhenMoreRecent(
|
||||||
int timestamp,
|
int sequence,
|
||||||
dynamic identifier,
|
dynamic identifier,
|
||||||
T Function(T? currentValue) update,
|
T Function(T? currentValue) update,
|
||||||
) {
|
) {
|
||||||
@@ -27,8 +39,8 @@ extension SubjectAddRecent<T> on Subject<T> {
|
|||||||
|
|
||||||
_lastEventTimes[this] ??= {};
|
_lastEventTimes[this] ??= {};
|
||||||
|
|
||||||
if ((_lastEventTimes[this]?[identifier] ?? 0) < timestamp) {
|
if ((_lastEventTimes[this]?[identifier] ?? 0) < sequence) {
|
||||||
_lastEventTimes[this]![identifier] = timestamp;
|
_lastEventTimes[this]![identifier] = sequence;
|
||||||
add(update((this as BehaviorSubject<T>).valueOrNull));
|
add(update((this as BehaviorSubject<T>).valueOrNull));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1392,36 +1392,35 @@ class ContainerSiteAssignment {
|
|||||||
|
|
||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class GeckoStateEvents {
|
abstract class GeckoStateEvents {
|
||||||
void onViewReadyStateChange(int timestamp, bool state);
|
void onViewReadyStateChange(int sequence, bool state);
|
||||||
void onEngineReadyStateChange(int timestamp, bool state);
|
void onEngineReadyStateChange(int sequence, bool state);
|
||||||
void onIconUpdate(int timestamp, String url, Uint8List bytes);
|
void onIconUpdate(int sequence, String url, Uint8List bytes);
|
||||||
|
|
||||||
void onTabAdded(int timestamp, String tabId);
|
void onTabAdded(int sequence, String tabId);
|
||||||
|
|
||||||
void onTabListChange(int timestamp, List<String> tabIds);
|
void onTabListChange(int sequence, List<String> tabIds);
|
||||||
void onSelectedTabChange(int timestamp, String? id);
|
void onSelectedTabChange(int sequence, String? id);
|
||||||
|
|
||||||
void onTabContentStateChange(int timestamp, TabContentState state);
|
void onTabContentStateChange(int sequence, TabContentState state);
|
||||||
void onHistoryStateChange(int timestamp, String id, HistoryState state);
|
void onHistoryStateChange(int sequence, String id, HistoryState state);
|
||||||
void onReaderableStateChange(int timestamp, String id, ReaderableState state);
|
void onReaderableStateChange(int sequence, String id, ReaderableState state);
|
||||||
void onSecurityInfoStateChange(
|
void onSecurityInfoStateChange(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String id,
|
String id,
|
||||||
SecurityInfoState state,
|
SecurityInfoState state,
|
||||||
);
|
);
|
||||||
void onIconChange(int timestamp, String id, Uint8List? bytes);
|
void onIconChange(int sequence, String id, Uint8List? bytes);
|
||||||
void onThumbnailChange(int timestamp, String id, Uint8List? bytes);
|
void onThumbnailChange(int sequence, String id, Uint8List? bytes);
|
||||||
|
|
||||||
void onFindResults(int timestamp, String id, List<FindResultState> results);
|
void onFindResults(int sequence, String id, List<FindResultState> results);
|
||||||
void onLongPress(int timestamp, String id, HitResult hitResult);
|
void onLongPress(int sequence, String id, HitResult hitResult);
|
||||||
|
|
||||||
// void onScrollChange(int timestamp, String tabId, int scrollY);
|
// void onScrollChange(int sequence, String tabId, int scrollY);
|
||||||
void onPreferenceChange(int timestamp, GeckoPref value);
|
void onPreferenceChange(int sequence, GeckoPref value);
|
||||||
|
|
||||||
void onContainerSiteAssignment(
|
void onContainerSiteAssignment(int sequence, ContainerSiteAssignment details);
|
||||||
int timestamp,
|
|
||||||
ContainerSiteAssignment details,
|
void onMlProgress(int sequence, MlProgressData progress);
|
||||||
);
|
|
||||||
|
|
||||||
void onMlProgress(int timestamp, MlProgressData progress);
|
void onMlProgress(int timestamp, MlProgressData progress);
|
||||||
}
|
}
|
||||||
@@ -1439,7 +1438,7 @@ abstract class ReaderViewEvents {
|
|||||||
|
|
||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class ReaderViewController {
|
abstract class ReaderViewController {
|
||||||
void appearanceButtonVisibility(int timestamp, bool visible);
|
void appearanceButtonVisibility(int sequence, bool visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
@@ -1465,20 +1464,20 @@ abstract class GeckoAddonsApi {
|
|||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class GeckoAddonEvents {
|
abstract class GeckoAddonEvents {
|
||||||
void onUpsertWebExtensionAction(
|
void onUpsertWebExtensionAction(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String extensionId,
|
String extensionId,
|
||||||
WebExtensionActionType actionType,
|
WebExtensionActionType actionType,
|
||||||
WebExtensionData extensionData,
|
WebExtensionData extensionData,
|
||||||
);
|
);
|
||||||
|
|
||||||
void onRemoveWebExtensionAction(
|
void onRemoveWebExtensionAction(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String extensionId,
|
String extensionId,
|
||||||
WebExtensionActionType actionType,
|
WebExtensionActionType actionType,
|
||||||
);
|
);
|
||||||
|
|
||||||
void onUpdateWebExtensionIcon(
|
void onUpdateWebExtensionIcon(
|
||||||
int timestamp,
|
int sequence,
|
||||||
String extensionId,
|
String extensionId,
|
||||||
WebExtensionActionType actionType,
|
WebExtensionActionType actionType,
|
||||||
Uint8List icon,
|
Uint8List icon,
|
||||||
@@ -1495,7 +1494,7 @@ abstract class GeckoSuggestionApi {
|
|||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class GeckoSuggestionEvents {
|
abstract class GeckoSuggestionEvents {
|
||||||
void onSuggestionResult(
|
void onSuggestionResult(
|
||||||
int timestamp,
|
int sequence,
|
||||||
GeckoSuggestionType suggestionType,
|
GeckoSuggestionType suggestionType,
|
||||||
List<GeckoSuggestion> suggestions,
|
List<GeckoSuggestion> suggestions,
|
||||||
);
|
);
|
||||||
@@ -1503,7 +1502,7 @@ abstract class GeckoSuggestionEvents {
|
|||||||
|
|
||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class GeckoTabContentEvents {
|
abstract class GeckoTabContentEvents {
|
||||||
void onContentUpdate(int timestamp, TabContent content);
|
void onContentUpdate(int sequence, TabContent content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostApi()
|
@HostApi()
|
||||||
@@ -1579,7 +1578,7 @@ abstract class GeckoDownloadsApi {
|
|||||||
|
|
||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class BrowserExtensionEvents {
|
abstract class BrowserExtensionEvents {
|
||||||
void onFeedRequested(int timestamp, String url);
|
void onFeedRequested(int sequence, String url);
|
||||||
}
|
}
|
||||||
|
|
||||||
class GeckoHeader {
|
class GeckoHeader {
|
||||||
@@ -1737,12 +1736,12 @@ abstract class GeckoViewportEvents {
|
|||||||
/// This is detected natively using WindowInsets API and provides
|
/// This is detected natively using WindowInsets API and provides
|
||||||
/// accurate keyboard height information.
|
/// accurate keyboard height information.
|
||||||
///
|
///
|
||||||
/// [timestamp] Event timestamp for ordering.
|
/// [sequence] Event sequence number for ordering.
|
||||||
/// [heightPx] Keyboard height in pixels (0 when hidden).
|
/// [heightPx] Keyboard height in pixels (0 when hidden).
|
||||||
/// [isVisible] Whether the keyboard is currently visible.
|
/// [isVisible] Whether the keyboard is currently visible.
|
||||||
/// [isAnimating] Whether the keyboard is currently animating.
|
/// [isAnimating] Whether the keyboard is currently animating.
|
||||||
void onKeyboardVisibilityChanged(
|
void onKeyboardVisibilityChanged(
|
||||||
int timestamp,
|
int sequence,
|
||||||
int heightPx,
|
int heightPx,
|
||||||
bool isVisible,
|
bool isVisible,
|
||||||
bool isAnimating,
|
bool isAnimating,
|
||||||
|
|||||||
+4
-2
@@ -22,11 +22,13 @@ package eu.weblibre.simple_intent_receiver
|
|||||||
import io.flutter.plugin.common.BinaryMessenger
|
import io.flutter.plugin.common.BinaryMessenger
|
||||||
import eu.weblibre.simple_intent_receiver.pigeons.IntentEvents
|
import eu.weblibre.simple_intent_receiver.pigeons.IntentEvents
|
||||||
import eu.weblibre.simple_intent_receiver.pigeons.Intent as PigeonIntent
|
import eu.weblibre.simple_intent_receiver.pigeons.Intent as PigeonIntent
|
||||||
|
import eu.weblibre.flutter_mozilla_components.ext.EventSequence
|
||||||
|
|
||||||
class IntentReceiver(messenger: BinaryMessenger) {
|
class IntentReceiver(messenger: BinaryMessenger) {
|
||||||
private val intentEvents: IntentEvents = IntentEvents(messenger)
|
private val intentEvents: IntentEvents = IntentEvents(messenger)
|
||||||
|
|
||||||
fun sendIntent(timestamp: Long, intent: PigeonIntent) {
|
fun sendIntent(intent: PigeonIntent) {
|
||||||
intentEvents.onIntentReceived(timestamp, intent) { }
|
intentEvents.onIntentReceived(EventSequence.next(), intent) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -114,7 +114,7 @@ class SimpleIntentReceiverPlugin: FlutterPlugin, ActivityAware, PluginRegistry.N
|
|||||||
}
|
}
|
||||||
|
|
||||||
val pigeonIntent = convertToPigeonIntent(intent)
|
val pigeonIntent = convertToPigeonIntent(intent)
|
||||||
intentReceiver?.sendIntent(System.currentTimeMillis(), pigeonIntent)
|
intentReceiver?.sendIntent(pigeonIntent)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -133,12 +133,12 @@ class IntentEvents(private val binaryMessenger: BinaryMessenger, private val mes
|
|||||||
IntentPigeonCodec()
|
IntentPigeonCodec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun onIntentReceived(timestampArg: Long, intentArg: Intent, callback: (Result<Unit>) -> Unit)
|
fun onIntentReceived(sequenceArg: Long, intentArg: Intent, callback: (Result<Unit>) -> Unit)
|
||||||
{
|
{
|
||||||
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""
|
||||||
val channelName = "dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived$separatedMessageChannelSuffix"
|
val channelName = "dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived$separatedMessageChannelSuffix"
|
||||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, channelName, codec)
|
||||||
channel.send(listOf(timestampArg, intentArg)) {
|
channel.send(listOf(sequenceArg, intentArg)) {
|
||||||
if (it is List<*>) {
|
if (it is List<*>) {
|
||||||
if (it.size > 1) {
|
if (it.size > 1) {
|
||||||
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)))
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class IntentReceiver extends IntentEvents {
|
|||||||
Stream<Intent> get events => _controller.stream;
|
Stream<Intent> get events => _controller.stream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onIntentReceived(int timestamp, Intent intent) {
|
void onIntentReceived(int sequence, Intent intent) {
|
||||||
if (_lastAdded == null || timestamp > _lastAdded!) {
|
if (_lastAdded == null || sequence > _lastAdded!) {
|
||||||
_controller.add(intent);
|
_controller.add(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ class _PigeonCodec extends StandardMessageCodec {
|
|||||||
abstract class IntentEvents {
|
abstract class IntentEvents {
|
||||||
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
|
||||||
|
|
||||||
void onIntentReceived(int timestamp, Intent intent);
|
void onIntentReceived(int sequence, Intent intent);
|
||||||
|
|
||||||
static void setUp(IntentEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
static void setUp(IntentEvents? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) {
|
||||||
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
|
||||||
@@ -143,14 +143,14 @@ abstract class IntentEvents {
|
|||||||
assert(message != null,
|
assert(message != null,
|
||||||
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null.');
|
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null.');
|
||||||
final List<Object?> args = (message as List<Object?>?)!;
|
final List<Object?> args = (message as List<Object?>?)!;
|
||||||
final int? arg_timestamp = (args[0] as int?);
|
final int? arg_sequence = (args[0] as int?);
|
||||||
assert(arg_timestamp != null,
|
assert(arg_sequence != null,
|
||||||
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null, expected non-null int.');
|
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null, expected non-null int.');
|
||||||
final Intent? arg_intent = (args[1] as Intent?);
|
final Intent? arg_intent = (args[1] as Intent?);
|
||||||
assert(arg_intent != null,
|
assert(arg_intent != null,
|
||||||
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null, expected non-null Intent.');
|
'Argument for dev.flutter.pigeon.simple_intent_receiver.IntentEvents.onIntentReceived was null, expected non-null Intent.');
|
||||||
try {
|
try {
|
||||||
api.onIntentReceived(arg_timestamp!, arg_intent!);
|
api.onIntentReceived(arg_sequence!, arg_intent!);
|
||||||
return wrapResponse(empty: true);
|
return wrapResponse(empty: true);
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
return wrapResponse(error: e);
|
return wrapResponse(error: e);
|
||||||
|
|||||||
@@ -51,5 +51,5 @@ class Intent {
|
|||||||
)
|
)
|
||||||
@FlutterApi()
|
@FlutterApi()
|
||||||
abstract class IntentEvents {
|
abstract class IntentEvents {
|
||||||
void onIntentReceived(int timestamp, Intent intent);
|
void onIntentReceived(int sequence, Intent intent);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user