source_utils_quickplayOutcome.bs
import "pkg:/source/translationKeys.bs"
import "pkg:/source/utils/misc.bs"
' What a quick play's queue build ended with, and what the viewer is told when it found nothing
' to play. QueueManager shows the message; QuickPlayTask and GetShuffleItemsTask report the
' status. Pure, so the rules are unit-tested without a network seam.
'
' A read that failed says nothing about what the item holds, so it must never read as empty:
' "failed" asks the viewer to try again, "empty" tells them there is nothing to try, and
' "unsupported" tells them this can't be played that way, which no retry changes. The text
' names what the build was (a slideshow, a trailer, a shuffle, or anything else that plays).
namespace quickplayOutcome
const STATUS_OK = "ok"
const STATUS_EMPTY = "empty"
const STATUS_FAILED = "failed"
const STATUS_UNSUPPORTED = "unsupported"
const KIND_PLAY = "play"
const KIND_SHUFFLE = "shuffle"
const KIND_TRAILER = "trailer"
const KIND_SLIDESHOW = "slideshow"
' The kind of launch a QuickPlayTask build is, from the output action its dispatch chose
' ("queue", "photo" or "trailer"), so the message follows what the build turned into: Play
' on a photo library is a slideshow. Shuffle runs on its own Task, whose caller passes
' KIND_SHUFFLE itself.
'
' @param {dynamic} outputAction - QuickPlayTask's output action
' @return {string} a KIND_ constant
function kindOf(outputAction as dynamic) as string
if not isValidAndNotEmpty(outputAction) then return quickplayOutcome.KIND_PLAY
action = LCase(outputAction)
if action = "trailer" then return quickplayOutcome.KIND_TRAILER
if action = "photo" then return quickplayOutcome.KIND_SLIDESHOW
return quickplayOutcome.KIND_PLAY
end function
' How a queue build ended: items arrived; or none did because nothing here builds this
' launch, or because a read failed, or though every read answered. Items that arrived play
' even when a fallback read failed.
'
' @param {integer} itemCount - the items the build found
' @param {boolean} anyReadFailed - a read did not answer
' @param {boolean} unsupported - no dispatch branch builds this action or type
' @return {string} a STATUS_ constant
function statusOf(itemCount as integer, anyReadFailed as boolean, unsupported as boolean) as string
if itemCount > 0 then return quickplayOutcome.STATUS_OK
if unsupported then return quickplayOutcome.STATUS_UNSUPPORTED
if anyReadFailed then return quickplayOutcome.STATUS_FAILED
return quickplayOutcome.STATUS_EMPTY
end function
' The translation key of the toast for `kind` and `status`, or "" when there is nothing to
' say (the build found items). A missing kind reads as play. A kind with no text of its own
' for a status uses play's ("Can't play this." for a trailer). A status that is none of
' these reads as failed: an answer nobody can vouch for is never told as "nothing here".
'
' @param {dynamic} kind - a KIND_ constant
' @param {dynamic} status - a STATUS_ constant
' @return {string}
function messageKey(kind as dynamic, status as dynamic) as string
status = quickplayOutcome.knownStatus(status)
if status = quickplayOutcome.STATUS_OK then return ""
messages = quickplayOutcome.messageTable()
play = messages[quickplayOutcome.KIND_PLAY]
row = invalid
if isValidAndNotEmpty(kind) then row = messages[kind]
if not isValid(row) then row = play
key = row[status]
if not isValid(key) then key = play[status]
return key
end function
' The toast's style for `status`: error for a read that failed (or a status nobody can
' vouch for, which messageKey tells as failed), info for an empty answer or a launch nothing
' builds.
'
' @param {dynamic} status - a STATUS_ constant
' @return {string} a displayToast type
function toastType(status as dynamic) as string
if quickplayOutcome.knownStatus(status) = quickplayOutcome.STATUS_FAILED then return "error"
return "info"
end function
' `status` when it is one of the STATUS_ constants, otherwise STATUS_FAILED.
function knownStatus(status as dynamic) as string
if not isValidAndNotEmpty(status) then return quickplayOutcome.STATUS_FAILED
if status = quickplayOutcome.STATUS_OK or status = quickplayOutcome.STATUS_EMPTY or status = quickplayOutcome.STATUS_UNSUPPORTED then return status
return quickplayOutcome.STATUS_FAILED
end function
' Every toast text, by kind and status. Each kind has a failed and an empty text; only the
' launches that can be asked for something nothing builds (play, shuffle) have their own
' unsupported text.
function messageTable() as object
messages = {}
messages[quickplayOutcome.KIND_PLAY] = quickplayOutcome.messageRow(translationKeys.MessageQuickPlayFailed, translationKeys.MessageQuickPlayEmpty, translationKeys.MessageQuickPlayUnsupported)
messages[quickplayOutcome.KIND_SHUFFLE] = quickplayOutcome.messageRow(translationKeys.MessageShuffleFailed, translationKeys.MessageShuffleEmpty, translationKeys.MessageShuffleUnsupported)
messages[quickplayOutcome.KIND_TRAILER] = quickplayOutcome.messageRow(translationKeys.MessageTrailerFailed, translationKeys.MessageTrailerEmpty, invalid)
messages[quickplayOutcome.KIND_SLIDESHOW] = quickplayOutcome.messageRow(translationKeys.MessageSlideshowFailed, translationKeys.MessageSlideshowEmpty, invalid)
return messages
end function
function messageRow(failed as string, empty as string, unsupported as dynamic) as object
row = {}
row[quickplayOutcome.STATUS_FAILED] = failed
row[quickplayOutcome.STATUS_EMPTY] = empty
if isValid(unsupported) then row[quickplayOutcome.STATUS_UNSUPPORTED] = unsupported
return row
end function
end namespace