Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Commit

Permalink
Bug 1877278 - AC Translations Check for if the Engine is Supported
Browse files Browse the repository at this point in the history
This patch supports the workflow for checking if the device architecture
supports translations.

This patch adds:
* New `isEngineSupported` on `TranslationsState`
  * New `FETCH_IS_ENGINE_SUPPORTED` to request fetching and setting the value
  * New `SetEngineSupportAction` to set the `isEngineSupported` value
* `TabListAction.AddTabAction`, `TabListAction.RestoreAction`, and
`TabListAction.SelectTabAction` to eagerly request `FETCH_IS_ENGINE_SUPPORTED`
  • Loading branch information
ohall-m committed Feb 9, 2024
1 parent ab76672 commit 1784446
Show file tree
Hide file tree
Showing 8 changed files with 347 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,17 @@ sealed class TranslationsAction : BrowserAction() {
val operation: TranslationOperation,
) : TranslationsAction(), ActionWithTab

/**
* Sets whether the device architecture supports translations or not.
*
* @property tabId The ID of the tab the [EngineSession] that requested the list.
* @property isEngineSupported If the engine supports translations on this device.
*/
data class SetEngineSupportAction(
override val tabId: String,
val isEngineSupported: Boolean,
) : TranslationsAction(), ActionWithTab

/**
* Sets the languages that are supported by the translations engine.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ package mozilla.components.browser.state.engine.middleware
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import mozilla.components.browser.state.action.BrowserAction
import mozilla.components.browser.state.action.TabListAction
import mozilla.components.browser.state.action.TranslationsAction
import mozilla.components.browser.state.selector.findTab
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.TranslationsState
import mozilla.components.concept.engine.Engine
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.translate.LanguageSetting
Expand Down Expand Up @@ -39,8 +41,52 @@ class TranslationsMiddleware(
) {
// Pre process actions
when (action) {
// Initially adding the tab
is TabListAction.AddTabAction -> {
if (translationsState(context, action.tab.id)?.isEngineSupported == null) {
context.store.dispatch(
TranslationsAction.OperationRequestedAction(
tabId = action.tab.id,
operation = TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
),
)
}
}

// Restoring a tab from a closed app
is TabListAction.RestoreAction -> {
if (translationsState(context, action.selectedTabId)?.isEngineSupported == null) {
action.selectedTabId?.let { id ->
context.store.dispatch(
TranslationsAction.OperationRequestedAction(
tabId = id,
operation = TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
),
)
}
}
}

// Switching to a new tab
is TabListAction.SelectTabAction -> {
if (translationsState(context, action.tabId)?.isEngineSupported == null) {
context.store.dispatch(
TranslationsAction.OperationRequestedAction(
tabId = action.tabId,
operation = TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
),
)
}
}

is TranslationsAction.OperationRequestedAction -> {
when (action.operation) {
TranslationOperation.FETCH_IS_ENGINE_SUPPORTED -> {
scope.launch {
requestEngineSupport(context, action.tabId)
}
}

TranslationOperation.FETCH_SUPPORTED_LANGUAGES -> {
scope.launch {
requestSupportedLanguages(context, action.tabId)
Expand Down Expand Up @@ -70,6 +116,53 @@ class TranslationsMiddleware(
next(action)
}

/**
* Convenience method to get the translations state from the store.
*
* @param context Context to use to find the state of the store.
* @param tabId Tab ID associated with the request.
*/
private fun translationsState(
context: MiddlewareContext<BrowserState, BrowserAction>,
tabId: String?,
): TranslationsState? {
return tabId?.let { context.store.state.findTab(it)?.translationsState }
}

/**
* Checks if the translations engine supports the device architecture.
*
* @param context Context to use to dispatch to the store.
* @param tabId Tab ID associated with the request.
*/
private fun requestEngineSupport(
context: MiddlewareContext<BrowserState, BrowserAction>,
tabId: String,
) {
engine.isTranslationsEngineSupported(
onSuccess = { isEngineSupported ->
context.store.dispatch(
TranslationsAction.SetEngineSupportAction(
tabId = tabId,
isEngineSupported = isEngineSupported,
),
)
logger.info("Success requesting engine support.")
},

onError = { error ->
context.store.dispatch(
TranslationsAction.TranslateExceptionAction(
tabId = tabId,
operation = TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
translationError = TranslationError.UnknownEngineSupportError(error),
),
)
logger.error("Error requesting engine support: ", error)
},
)
}

/**
* Retrieves the list of supported languages using [scope] and dispatches the result to the
* store via [TranslationsAction.TranslateSetLanguagesAction] or else dispatches the failure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ internal object TranslationsStateReducer {
}
}

TranslationOperation.FETCH_IS_ENGINE_SUPPORTED -> {
state.copyWithTranslationsState(action.tabId) {
it.copy(
isEngineSupported = true,
translationError = null,
)
}
}

TranslationOperation.FETCH_SUPPORTED_LANGUAGES -> {
// Reset the error state, and then generally expect
// [TranslationsAction.SetSupportedLanguagesAction] to update state in the
Expand Down Expand Up @@ -138,6 +147,15 @@ internal object TranslationsStateReducer {
}
}

TranslationOperation.FETCH_IS_ENGINE_SUPPORTED ->
state.copyWithTranslationsState(action.tabId) {
it.copy(
// An error here doesn't necessarily imply the device doesn't support
// the engine, so not changing [isEngineSupported] state.
translationError = action.translationError,
)
}

TranslationOperation.FETCH_SUPPORTED_LANGUAGES -> {
state.copyWithTranslationsState(action.tabId) {
it.copy(
Expand Down Expand Up @@ -167,6 +185,14 @@ internal object TranslationsStateReducer {
}
}

is TranslationsAction.SetEngineSupportAction ->
state.copyWithTranslationsState(action.tabId) {
it.copy(
isEngineSupported = action.isEngineSupported,
translationError = null,
)
}

is TranslationsAction.SetSupportedLanguagesAction ->
state.copyWithTranslationsState(action.tabId) {
it.copy(
Expand Down Expand Up @@ -213,7 +239,10 @@ internal object TranslationsStateReducer {
)
}
}
TranslationOperation.TRANSLATE, TranslationOperation.RESTORE -> {
TranslationOperation.TRANSLATE,
TranslationOperation.RESTORE,
TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
-> {
// No state change for these operations
state
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import mozilla.components.concept.engine.translate.TranslationSupport
* @property isTranslated The page is currently translated.
* @property isTranslateProcessing The page is currently attempting a translation.
* @property isRestoreProcessing The page is currently attempting a restoration.
* @property isEngineSupported The translations engine supports the device architecture.
* @property supportedLanguages Set of languages the translation engine supports.
* @property pageSettings The translation engine settings that relate to the current page.
* @property neverTranslateSites List of sites the user has opted to never translate.
Expand All @@ -33,6 +34,7 @@ data class TranslationsState(
val isTranslated: Boolean = false,
val isTranslateProcessing: Boolean = false,
val isRestoreProcessing: Boolean = false,
val isEngineSupported: Boolean? = null,
val supportedLanguages: TranslationSupport? = null,
val pageSettings: TranslationPageSettings? = null,
val neverTranslateSites: List<String>? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,4 +387,74 @@ class TranslationsActionTest {
// Action success
assertNull(tabState().translationsState.supportedLanguages)
}

@Test
fun `WHEN a TranslateSetEngineSupportAction is dispatched THEN update the store to match`() {
// Initial state
assertNull(tabState().translationsState.isEngineSupported)

// Dispatch
store.dispatch(
TranslationsAction.SetEngineSupportAction(
tabId = tab.id,
isEngineSupported = true,
),
).joinBlocking()

// Final state
assertTrue(tabState().translationsState.isEngineSupported!!)
}

@Test
fun `WHEN a OperationRequestedAction is dispatched for FETCH_IS_ENGINE_SUPPORTED THEN do NOT clear isEngineSupported`() {
// Setting first to have a more robust initial state
assertNull(tabState().translationsState.isEngineSupported)

store.dispatch(
TranslationsAction.SetEngineSupportAction(
tabId = tab.id,
isEngineSupported = true,
),
).joinBlocking()

assertTrue(tabState().translationsState.isEngineSupported!!)

// Action started
store.dispatch(
TranslationsAction.OperationRequestedAction(
tabId = tab.id,
operation = TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
),
).joinBlocking()

// Action success
assertTrue(tabState().translationsState.isEngineSupported!!)
}

@Test
fun `WHEN a TranslateExceptionAction is dispatched for FETCH_IS_ENGINE_SUPPORTED THEN do NOT clear or alter isEngineSupported`() {
// Setting first to have a more robust initial state
assertNull(tabState().translationsState.isEngineSupported)

store.dispatch(
TranslationsAction.SetEngineSupportAction(
tabId = tab.id,
isEngineSupported = true,
),
).joinBlocking()

assertTrue(tabState().translationsState.isEngineSupported!!)

// Action started
store.dispatch(
TranslationsAction.TranslateExceptionAction(
tabId = tab.id,
operation = TranslationOperation.FETCH_IS_ENGINE_SUPPORTED,
translationError = TranslationError.UnknownEngineSupportError(null),
),
).joinBlocking()

// Action success
assertTrue(tabState().translationsState.isEngineSupported!!)
}
}
Loading

1 comment on commit 1784446

@firefoxci-taskcluster
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh! Looks like an error! Details

Failed to fetch task artifact public/github/customCheckRunText.md for GitHub integration.
Make sure the artifact exists on the worker or other location.

Please sign in to comment.