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 12, 2024
1 parent ab76672 commit e211c10
Show file tree
Hide file tree
Showing 9 changed files with 351 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,17 @@ internal object TranslationsStateReducer {
}
}

TranslationOperation.FETCH_IS_ENGINE_SUPPORTED -> {
// Reset the error state, and then generally expect
// [TranslationsAction.SetEngineSupportAction] to update state in the
// success case.
state.copyWithTranslationsState(action.tabId) {
it.copy(
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 +149,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 +187,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 +241,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

0 comments on commit e211c10

Please sign in to comment.