diff --git a/components/home/HSSLoadSectionTask.bs b/components/home/HSSLoadSectionTask.bs
deleted file mode 100644
index 36949305d..000000000
--- a/components/home/HSSLoadSectionTask.bs
+++ /dev/null
@@ -1,289 +0,0 @@
-import "pkg:/source/api/baserequest.bs"
-import "pkg:/source/utils/misc.bs"
-
-const HSS_ENRICH_FIELDS = "Type,UserData,Overview,Genres,CommunityRating,CriticRating,OfficialRating,RunTimeTicks,ProductionYear,SeriesName,ParentIndexNumber,IndexNumber,Status,ImageTags,BackdropImageTags,ParentBackdropItemId,ParentBackdropImageTags,ParentThumbItemId,ParentThumbImageTag,SeriesId,SeriesPrimaryImageTag,ParentLogoItemId,ParentLogoImageTag"
-
-sub init()
- m.top.functionName = "loadHomeScreenSection"
-end sub
-
-function targetAPIRequest(serverUrl as string, userId as string, authToken as string, path as string, params = {} as object) as dynamic
- if not isValidAndNotEmpty(serverUrl)
- return invalid
- end if
-
- return APIRequestForServer(serverUrl, userId, authToken, path, params)
-end function
-
-sub loadHomeScreenSection()
- results = []
-
- serverUrl = m.top.serverUrl
- userId = m.top.userId
- authToken = m.top.authToken
- sectionType = m.top.sectionType
- if not isValidAndNotEmpty(sectionType)
- m.top.content = results
- return
- end if
-
- if not isValidAndNotEmpty(userId)
- m.top.content = results
- return
- end if
-
- pathSection = sectionType.EncodeUriComponent()
- params = { userId: userId }
- params.AddReplace("Fields", HSS_ENRICH_FIELDS)
- params.AddReplace("EnableImageTypes", "Primary,Backdrop,Thumb,Logo")
- params.AddReplace("ImageTypeLimit", 1)
- params.AddReplace("EnableTotalRecordCount", false)
-
- additionalData = m.top.additionalData
- if isValidAndNotEmpty(additionalData)
- params.AddReplace("additionalData", additionalData)
- end if
-
- request = targetAPIRequest(serverUrl, userId, authToken, "/HomeScreen/Section/" + pathSection, params)
- if not isValid(request)
- m.top.content = results
- return
- end if
-
- response = getJson(request)
- itemsPayload = getItemsPayload(response)
- itemsPayload = enrichItemsPayload(itemsPayload, serverUrl, userId, authToken)
-
- for each item in itemsPayload
- homeData = createSGNode("HomeData")
- homeData.json = item
- results.push(homeData)
- end for
-
- m.top.content = results
-end sub
-
-function getItemsPayload(response as dynamic) as object
- if not isValid(response)
- return []
- end if
-
- responseType = type(response)
- if responseType = "Array" or responseType = "roArray"
- return response
- end if
-
- if isChainValid(response, "Items")
- return response.Items
- end if
-
- if isChainValid(response, "items")
- return response.items
- end if
-
- return []
-end function
-
-function enrichItemsPayload(itemsPayload as object, serverUrl as string, userId as string, authToken as string) as object
- if not isValidAndNotEmpty(itemsPayload) or not isValidAndNotEmpty(userId)
- return itemsPayload
- end if
-
- if hasOverviewOnAllItems(itemsPayload)
- return itemsPayload
- end if
-
- itemIds = collectItemIds(itemsPayload)
- if not isValidAndNotEmpty(itemIds)
- return itemsPayload
- end if
-
- request = targetAPIRequest(serverUrl, userId, authToken, "/Users/" + userId.EncodeUriComponent() + "/Items", {
- Ids: itemIds.Join(","),
- Fields: HSS_ENRICH_FIELDS,
- EnableImageTypes: "Primary,Backdrop,Thumb,Logo",
- ImageTypeLimit: 1,
- EnableTotalRecordCount: false
- })
-
- if not isValid(request)
- return itemsPayload
- end if
-
- response = getJson(request)
- enrichedPayload = getItemsPayload(response)
- if not isValidAndNotEmpty(enrichedPayload)
- return itemsPayload
- end if
-
- enrichedById = {}
- for each enrichedItem in enrichedPayload
- if not isAssociativeArrayValue(enrichedItem)
- continue for
- end if
-
- itemId = getItemLookupId(enrichedItem)
- if isValidAndNotEmpty(itemId) and not enrichedById.DoesExist(itemId)
- enrichedById.AddReplace(itemId, enrichedItem)
- end if
- end for
-
- if not isValidAndNotEmpty(enrichedById)
- return itemsPayload
- end if
-
- mergedPayload = []
- for each item in itemsPayload
- if not isAssociativeArrayValue(item)
- mergedPayload.push(item)
- continue for
- end if
-
- itemId = getItemLookupId(item)
- if not isValidAndNotEmpty(itemId) or not enrichedById.DoesExist(itemId)
- mergedPayload.push(item)
- continue for
- end if
-
- mergedPayload.push(mergeSectionItem(item, enrichedById[itemId]))
- end for
-
- return mergedPayload
-end function
-
-function hasOverviewOnAllItems(itemsPayload as object) as boolean
- for each item in itemsPayload
- if not isAssociativeArrayValue(item)
- return false
- end if
-
- overview = toNormalizedString(getValueCaseInsensitive(item, "Overview", ""))
- if not isValidAndNotEmpty(overview)
- return false
- end if
- end for
-
- return true
-end function
-
-function collectItemIds(itemsPayload as object) as object
- itemIds = []
- seenIds = {}
-
- for each item in itemsPayload
- if not isAssociativeArrayValue(item)
- continue for
- end if
-
- itemId = getItemLookupId(item)
- if not isValidAndNotEmpty(itemId) or seenIds.DoesExist(itemId)
- continue for
- end if
-
- seenIds.AddReplace(itemId, true)
- itemIds.push(itemId)
- end for
-
- return itemIds
-end function
-
-function getItemLookupId(item as object) as string
- return toNormalizedString(getValueCaseInsensitive(item, "Id", ""))
-end function
-
-function mergeSectionItem(rawItem as object, enrichedItem as object) as object
- merged = {}
-
- for each key in rawItem
- merged.AddReplace(key, rawItem[key])
- end for
-
- if isAssociativeArrayValue(enrichedItem)
- for each key in enrichedItem
- currentValue = invalid
- if merged.DoesExist(key)
- currentValue = merged[key]
- end if
-
- enrichedValue = enrichedItem[key]
- if not isMissingMergeValue(enrichedValue) or isMissingMergeValue(currentValue)
- merged.AddReplace(key, enrichedValue)
- end if
- end for
- end if
-
- rawImageTags = getValueCaseInsensitive(rawItem, "ImageTags", invalid)
- enrichedImageTags = getValueCaseInsensitive(enrichedItem, "ImageTags", invalid)
- if isAssociativeArrayValue(rawImageTags) or isAssociativeArrayValue(enrichedImageTags)
- mergedImageTags = {}
-
- if isAssociativeArrayValue(rawImageTags)
- for each key in rawImageTags
- mergedImageTags.AddReplace(key, rawImageTags[key])
- end for
- end if
-
- if isAssociativeArrayValue(enrichedImageTags)
- for each key in enrichedImageTags
- mergedImageTags.AddReplace(key, enrichedImageTags[key])
- end for
- end if
-
- merged.AddReplace("ImageTags", mergedImageTags)
- end if
-
- return merged
-end function
-
-function getValueCaseInsensitive(data as dynamic, key as string, defaultValue = invalid as dynamic) as dynamic
- if not isAssociativeArrayValue(data)
- return defaultValue
- end if
-
- if data.DoesExist(key)
- return data[key]
- end if
-
- normalizedKey = LCase(key)
- for each dataKey in data
- if LCase(dataKey) = normalizedKey
- return data[dataKey]
- end if
- end for
-
- return defaultValue
-end function
-
-function toNormalizedString(value as dynamic) as string
- if not isValid(value)
- return ""
- end if
-
- if GetInterface(value, "ifString") <> invalid
- return value.ToStr().Trim()
- end if
-
- return ""
-end function
-
-function isMissingMergeValue(value as dynamic) as boolean
- if not isValid(value)
- return true
- end if
-
- valueType = type(value)
- if valueType = "String" or valueType = "roString"
- return Len(value.Trim()) = 0
- end if
-
- if valueType = "Array" or valueType = "roArray"
- return value.Count() = 0
- end if
-
- return false
-end function
-
-function isAssociativeArrayValue(value as dynamic) as boolean
- valueType = type(value)
- return valueType = "AssociativeArray" or valueType = "roAssociativeArray"
-end function
diff --git a/components/home/HSSLoadSectionTask.xml b/components/home/HSSLoadSectionTask.xml
deleted file mode 100644
index 806e1d38c..000000000
--- a/components/home/HSSLoadSectionTask.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/components/home/HSSProbeTask.bs b/components/home/HSSProbeTask.bs
deleted file mode 100644
index 80031907a..000000000
--- a/components/home/HSSProbeTask.bs
+++ /dev/null
@@ -1,106 +0,0 @@
-import "pkg:/source/api/baserequest.bs"
-import "pkg:/source/utils/misc.bs"
-
-sub init()
- m.top.functionName = "probeHomeScreenSections"
-end sub
-
-function targetAPIRequest(path as string, params = {} as object) as dynamic
- if not isValidAndNotEmpty(m.top.serverUrl)
- return invalid
- end if
-
- return APIRequestForServer(m.top.serverUrl, m.top.userId, m.top.authToken, path, params)
-end function
-
-sub probeHomeScreenSections()
- result = {
- enabled: false,
- sections: []
- }
-
- metaRequest = targetAPIRequest("/HomeScreen/Meta")
- if not isValid(metaRequest)
- m.top.result = result
- return
- end if
-
- meta = getJson(metaRequest)
- enabled = isHssMetaEnabled(meta)
- if not enabled
- m.top.result = result
- return
- end if
-
- result.enabled = true
-
- userId = m.top.userId
- if not isValidAndNotEmpty(userId)
- m.top.result = result
- return
- end if
-
- sectionsRequest = targetAPIRequest("/HomeScreen/Sections", { userId: userId })
- if not isValid(sectionsRequest)
- m.top.result = result
- return
- end if
-
- sectionsResponse = getJson(sectionsRequest)
- sectionsPayload = getSectionsPayload(sectionsResponse)
-
- sections = []
- for each sectionItem in sectionsPayload
- sectionType = chainLookupReturn(sectionItem, "section", "")
- if not isValidAndNotEmpty(sectionType)
- continue for
- end if
-
- displayText = chainLookupReturn(sectionItem, "displayText", "")
- if not isValidAndNotEmpty(displayText)
- displayText = sectionType
- end if
-
- additionalData = chainLookupReturn(sectionItem, "additionalData", "")
-
- sections.push({
- section: sectionType,
- displayText: displayText,
- additionalData: additionalData
- })
- end for
-
- result.sections = sections
- m.top.result = result
-end sub
-
-function isHssMetaEnabled(meta as dynamic) as boolean
- enabledValue = chainLookupReturn(meta, "enabled", false)
-
- if type(enabledValue) = "Boolean" or type(enabledValue) = "roBoolean"
- return enabledValue
- end if
-
- if type(enabledValue) = "String" or type(enabledValue) = "roString"
- return LCase(enabledValue) = "true"
- end if
-
- return false
-end function
-
-function getSectionsPayload(response as dynamic) as object
- if not isValid(response)
- return []
- end if
-
- responseType = type(response)
- if responseType = "Array" or responseType = "roArray"
- return response
- end if
-
- if isChainValid(response, "Items")
- return response.Items
- end if
-
- return []
-end function
diff --git a/components/home/HSSProbeTask.xml b/components/home/HSSProbeTask.xml
deleted file mode 100644
index e2bf8d528..000000000
--- a/components/home/HSSProbeTask.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/components/home/HomeRows.bs b/components/home/HomeRows.bs
index a9eb39790..a7879924e 100644
--- a/components/home/HomeRows.bs
+++ b/components/home/HomeRows.bs
@@ -6,10 +6,6 @@ import "pkg:/source/utils/misc.bs"
import "pkg:/source/utils/multiserver.bs"
const LOADING_WAIT_TIME = 2
-const HSS_LOCAL_ROWS_SETTING = "ui.home.hssRowsLocalConfig"
-const KT_LOCAL_ROWS_SETTING = "ui.home.ktRowsLocalConfig"
-const HSS_MAX_CONCURRENT_SECTION_TASKS = 3
-const KT_MAX_CONCURRENT_SECTION_TASKS = 3
' Helper function to get poster size based on user preference
function getPosterSize(preferWide = true as boolean) as object
@@ -87,30 +83,11 @@ sub init()
m.contentTasks = {}
m.multiServerTasks = {}
m.useServerConfig = false
- m.hssProbeTask = invalid
- m.hssSections = []
- m.hssSuppressedBuiltins = {}
- m.hssSectionTasks = {}
- m.hssSectionTaskQueue = []
- m.activeHssSectionTaskCount = 0
- m.hssRowTitleByKey = {}
- m.hssRowTitles = []
- m.ktProbeTask = invalid
- m.ktSections = []
- m.ktSectionTasks = {}
- m.ktSectionTaskQueue = []
- m.activeKtSectionTaskCount = 0
- m.ktRowTitleByKey = {}
- m.ktRowTitles = []
m.serverHomeRows = []
m.serverHomeRowsSource = "legacy"
m.serverLegacyRowOrder = []
m.serverDynamicRowTitles = {}
m.hasResolvedRowsPayload = false
- m.localPluginRowFilters = {
- hss: {},
- kefintweaks: {}
- }
m.pendingProbeCount = 0
m.initialHomeRowsStarted = false
end sub
@@ -197,13 +174,6 @@ function shouldUseServerConfig() as boolean
return normalizeBooleanValue(get_user_setting("homeRows.useServerConfig"), false)
end function
-function isHssEnabled() as boolean
- return normalizeBooleanValue(get_user_setting("plugin.hss.enabled"), false)
-end function
-
-function isKtEnabled() as boolean
- return normalizeBooleanValue(get_user_setting("plugin.kefintweaks.enabled"), false)
-end function
function isPluginFeatureOptedOut(settingName as string) as boolean
settingValue = get_user_setting(settingName)
@@ -214,82 +184,6 @@ function isPluginFeatureOptedOut(settingName as string) as boolean
return not normalizeBooleanValue(settingValue, false)
end function
-function loadCachedHssProbeState() as boolean
- m.hssSections = []
- m.hssSuppressedBuiltins = {}
-
- cachedValue = get_user_setting("plugin.hss.homeCache")
- if not isValidAndNotEmpty(cachedValue)
- return false
- end if
-
- parsed = ParseJson(cachedValue)
- if not isValid(parsed)
- return false
- end if
-
- if not normalizeBooleanValue(chainLookupReturn(parsed, "loaded", false), false)
- return false
- end if
-
- if normalizeBooleanValue(chainLookupReturn(parsed, "enabled", false), false)
- cachedSections = chainLookupReturn(parsed, "sections", [])
- if isValid(cachedSections)
- m.hssSections = cachedSections
- end if
-
- cachedSuppressedBuiltins = chainLookupReturn(parsed, "suppressedBuiltins", {})
- if isValid(cachedSuppressedBuiltins)
- m.hssSuppressedBuiltins = cachedSuppressedBuiltins
- end if
- end if
-
- return true
-end function
-
-function loadCachedKtProbeState() as boolean
- m.ktSections = []
-
- cachedValue = get_user_setting("plugin.kt.homeCache")
- if not isValidAndNotEmpty(cachedValue)
- return false
- end if
-
- parsed = ParseJson(cachedValue)
- if not isValid(parsed)
- return false
- end if
-
- if not normalizeBooleanValue(chainLookupReturn(parsed, "loaded", false), false)
- return false
- end if
-
- if normalizeBooleanValue(chainLookupReturn(parsed, "enabled", false), false)
- cachedSections = chainLookupReturn(parsed, "sections", [])
- if isValid(cachedSections)
- m.ktSections = cachedSections
- end if
- end if
-
- return true
-end function
-
-sub saveHssProbeCache(enabled as boolean)
- set_user_setting("plugin.hss.homeCache", FormatJson({
- loaded: true,
- enabled: enabled,
- sections: m.hssSections,
- suppressedBuiltins: m.hssSuppressedBuiltins
- }))
-end sub
-
-sub saveKtProbeCache(enabled as boolean)
- set_user_setting("plugin.kt.homeCache", FormatJson({
- loaded: true,
- enabled: enabled,
- sections: m.ktSections
- }))
-end sub
function isArrayValue(value as dynamic) as boolean
valueType = type(value)
@@ -370,11 +264,6 @@ end function
function normalizeHomeRowsSource(sourceValue as dynamic) as string
source = LCase(toNormalizedString(sourceValue))
- if source = "kefin" or source = "kefintweak" or source = "kefintweaks"
- return "kefintweaks"
- end if
-
- if source = "hss" then return "hss"
if source = "legacy" then return "legacy"
if source = "jellyfin" then return "jellyfin"
if source = "moonfin" then return "moonfin"
@@ -457,18 +346,9 @@ function buildPluginRowsFilterMap(configRows as object) as object
return filterMap
end function
-sub refreshLocalPluginRowFilters()
- m.localPluginRowFilters = {
- hss: buildPluginRowsFilterMap(parsePluginRowsConfigSetting(HSS_LOCAL_ROWS_SETTING)),
- kefintweaks: buildPluginRowsFilterMap(parsePluginRowsConfigSetting(KT_LOCAL_ROWS_SETTING))
- }
-end sub
function getLocalPluginRowFilter(row as object) as dynamic
rowSource = normalizeHomeRowsSource(chainLookupReturn(row, "source", m.serverHomeRowsSource))
- if rowSource <> "hss" and rowSource <> "kefintweaks"
- return invalid
- end if
rowId = LCase(toNormalizedString(chainLookupReturn(row, "id", "")))
if not isValidAndNotEmpty(rowId)
@@ -643,7 +523,7 @@ sub refreshServerRowsState()
end if
m.serverLegacyRowOrder = parseHomeRowOrderSetting()
- refreshLocalPluginRowFilters()
+' refreshLocalPluginRowFilters()
m.hasResolvedRowsPayload = hasResolvedServerRowsPayload()
payload = parseResolvedRowsPayload()
@@ -727,399 +607,25 @@ function getResolvedSectionName(index as integer) as string
return getResolvedSectionNameForMode(index, m.useServerConfig)
end function
-function shouldLoadHss() as boolean
- if shouldUseResolvedServerRows()
- if m.serverHomeRowsSource = "hss" or hasServerRowsForSource("hss")
- return true
- end if
- end if
-
- if isPluginFeatureOptedOut("plugin.enabled") or isPluginFeatureOptedOut("plugin.hss.enabled")
- return false
- end if
-
- if moonfinPlugin.IsPluginInstalled()
- return true
- end if
-
- if not isHssEnabled()
- return false
- end if
-
- useServerConfig = shouldUseServerConfig()
- for i = 0 to 7
- sectionName = getResolvedSectionNameForMode(i, useServerConfig)
- if sectionName = "hss_all"
- return true
- end if
- end for
-
- return false
-end function
-
-function shouldLoadKt() as boolean
- if shouldUseResolvedServerRows()
- if m.serverHomeRowsSource = "kefintweaks" or hasServerRowsForSource("kefintweaks")
- return true
- end if
- end if
-
- if isPluginFeatureOptedOut("plugin.enabled") or isPluginFeatureOptedOut("plugin.kefintweaks.enabled")
- return false
- end if
-
- if moonfinPlugin.IsPluginInstalled()
- return true
- end if
-
- if not isKtEnabled()
- return false
- end if
-
- useServerConfig = shouldUseServerConfig()
- for i = 0 to 7
- sectionName = getResolvedSectionNameForMode(i, useServerConfig)
- if sectionName = "kt_all"
- return true
- end if
- end for
-
- return false
-end function
-
-function isSectionSuppressedByHss(sectionName as string) as boolean
- if not isValid(m.hssSuppressedBuiltins)
- return false
- end if
-
- return m.hssSuppressedBuiltins.DoesExist(sectionName)
-end function
-
-function getHssSectionKey(sectionType as string, additionalData = "" as string, sectionIndex = 0 as integer) as string
- return LCase(sectionType ?? "") + "|" + LCase(additionalData ?? "") + "|" + sectionIndex.toStr()
-end function
-
-function getKtSectionKey(sectionType as string, sectionIndex = 0 as integer) as string
- return LCase(sectionType ?? "") + "|" + sectionIndex.toStr()
-end function
-
-function getUniqueHssSectionTitle(baseTitle as string, usedTitles as object) as string
- if not isValidAndNotEmpty(baseTitle)
- baseTitle = "Home"
- end if
-
- candidate = baseTitle
- suffix = 2
-
- while sectionExists(candidate) or usedTitles.DoesExist(LCase(candidate))
- candidate = baseTitle + " (" + suffix.toStr() + ")"
- suffix++
- end while
-
- usedTitles[LCase(candidate)] = true
- return candidate
-end function
-
-function getHssBuiltinEquivalent(section as string) as string
- sectionName = LCase(section ?? "").Replace(" ", "")
-
- if sectionName = "continuewatching" then return "resume"
- if sectionName = "continuelistening" or sectionName = "resumeaudio" then return "resumeaudio"
- if sectionName = "nextup" then return "nextup"
- if sectionName = "latestmedia" then return "latestmedia"
- if sectionName = "recentlyreleased" then return "recentlyreleased"
- if sectionName = "favorites" then return "favorites"
-
- return ""
-end function
-
-sub cleanupHssTasks()
- m.hssSectionTaskQueue = []
- m.activeHssSectionTaskCount = 0
-
- if not isValid(m.hssSectionTasks)
- m.hssSectionTasks = {}
- return
- end if
-
- for each taskKey in m.hssSectionTasks
- task = m.hssSectionTasks[taskKey]
- if isValid(task)
- task.unobserveField("content")
- task.control = "STOP"
- end if
- end for
-
- m.hssSectionTasks = {}
-end sub
-
-sub resetHssRowTracking()
- m.hssRowTitleByKey = {}
- m.hssRowTitles = []
-end sub
-
-sub removeTrackedHssRows()
- if not isValid(m.hssRowTitles)
- m.hssRowTitles = []
- return
- end if
-
- didRemoveRow = false
-
- for each rowTitle in m.hssRowTitles
- while sectionExists(rowTitle)
- sectionIndex = getSectionIndex(rowTitle)
- if sectionIndex < 0
- exit while
- end if
-
- m.top.content.removeChildIndex(sectionIndex)
- didRemoveRow = true
- end while
- end for
-
- if didRemoveRow
- setRowItemSize()
- end if
-end sub
-
-sub cleanupKtTasks()
- m.ktSectionTaskQueue = []
- m.activeKtSectionTaskCount = 0
-
- if not isValid(m.ktSectionTasks)
- m.ktSectionTasks = {}
- return
- end if
-
- for each taskKey in m.ktSectionTasks
- task = m.ktSectionTasks[taskKey]
- if isValid(task)
- task.unobserveField("content")
- task.control = "STOP"
- end if
- end for
-
- m.ktSectionTasks = {}
-end sub
-
-sub resetKtRowTracking()
- m.ktRowTitleByKey = {}
- m.ktRowTitles = []
-end sub
-
-sub removeTrackedKtRows()
- if not isValid(m.ktRowTitles)
- m.ktRowTitles = []
- return
- end if
-
- didRemoveRow = false
-
- for each rowTitle in m.ktRowTitles
- while sectionExists(rowTitle)
- sectionIndex = getSectionIndex(rowTitle)
- if sectionIndex < 0
- exit while
- end if
-
- m.top.content.removeChildIndex(sectionIndex)
- didRemoveRow = true
- end while
- end for
-
- if didRemoveRow
- setRowItemSize()
- end if
-end sub
sub startHomeRowsLoading()
- cleanupHssTasks()
- cleanupKtTasks()
- removeTrackedHssRows()
- removeTrackedKtRows()
- resetHssRowTracking()
- resetKtRowTracking()
- m.hssSections = []
- m.hssSuppressedBuiltins = {}
- m.ktSections = []
m.serverDynamicRowTitles = {}
m.pendingProbeCount = 0
m.initialHomeRowsStarted = false
refreshServerRowsState()
- if isValid(m.hssProbeTask)
- m.hssProbeTask.unobserveField("result")
- m.hssProbeTask.control = "STOP"
- m.hssProbeTask = invalid
- end if
-
- if isValid(m.ktProbeTask)
- m.ktProbeTask.unobserveField("result")
- m.ktProbeTask.control = "STOP"
- m.ktProbeTask = invalid
- end if
-
- shouldProbeHss = shouldLoadHss()
- shouldProbeKt = shouldLoadKt()
-
- if shouldUseResolvedServerRows()
- if m.serverHomeRowsSource = "hss" or hasServerRowsForSource("hss")
- shouldProbeHss = false
- end if
-
- if m.serverHomeRowsSource = "kefintweaks" or hasServerRowsForSource("kefintweaks")
- shouldProbeKt = false
- end if
- end if
-
- if shouldProbeHss
- loadCachedHssProbeState()
- m.hssProbeTask = CreateObject("roSGNode", "HSSProbeTask")
- m.hssProbeTask.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- m.hssProbeTask.userId = chainLookupReturn(m.global, "session.user.id", "")
- m.hssProbeTask.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- m.hssProbeTask.observeField("result", "onHSSProbeComplete")
- m.pendingProbeCount++
- m.hssProbeTask.control = "RUN"
- end if
-
- if shouldProbeKt
- loadCachedKtProbeState()
- m.ktProbeTask = CreateObject("roSGNode", "KefinTweaksProbeTask")
- m.ktProbeTask.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- m.ktProbeTask.userId = chainLookupReturn(m.global, "session.user.id", "")
- m.ktProbeTask.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- m.ktProbeTask.observeField("result", "onKTProbeComplete")
- m.pendingProbeCount++
- m.ktProbeTask.control = "RUN"
- end if
m.initialHomeRowsStarted = true
processUserSections()
end sub
-sub onHSSProbeComplete()
- hssEnabled = false
-
- if isValid(m.hssProbeTask)
- result = m.hssProbeTask.result
-
- m.hssProbeTask.unobserveField("result")
- m.hssProbeTask = invalid
-
- m.hssSections = []
- m.hssSuppressedBuiltins = {}
-
- if isValid(result) and normalizeBooleanValue(result.enabled, false)
- hssEnabled = true
- sections = chainLookupReturn(result, "sections", [])
- if isValidAndNotEmpty(sections)
- m.hssSections = sections
-
- for each hssSection in m.hssSections
- builtinSection = getHssBuiltinEquivalent(chainLookupReturn(hssSection, "section", ""))
- if isValidAndNotEmpty(builtinSection)
- m.hssSuppressedBuiltins[builtinSection] = true
- end if
- end for
- end if
- end if
- end if
-
- saveHssProbeCache(hssEnabled)
-
- if m.pendingProbeCount > 0
- m.pendingProbeCount = m.pendingProbeCount - 1
- end if
-
- if m.initialHomeRowsStarted
- if shouldUseResolvedServerRows()
- return
- end if
-
- cleanupHssTasks()
- removeTrackedHssRows()
- resetHssRowTracking()
-
- if shouldLoadHss()
- createHssRows()
- end if
- return
- end if
-
- if not m.initialHomeRowsStarted
- m.initialHomeRowsStarted = true
- processUserSections()
- end if
-end sub
-
-sub onKTProbeComplete()
- ktEnabled = false
-
- if isValid(m.ktProbeTask)
- result = m.ktProbeTask.result
-
- m.ktProbeTask.unobserveField("result")
- m.ktProbeTask = invalid
-
- m.ktSections = []
-
- if isValid(result) and normalizeBooleanValue(result.enabled, false)
- ktEnabled = true
- sections = chainLookupReturn(result, "sections", [])
- if isValidAndNotEmpty(sections)
- m.ktSections = sections
- end if
- end if
- end if
-
- saveKtProbeCache(ktEnabled)
-
- if m.pendingProbeCount > 0
- m.pendingProbeCount = m.pendingProbeCount - 1
- end if
-
- if m.initialHomeRowsStarted
- if shouldUseResolvedServerRows()
- return
- end if
-
- cleanupKtTasks()
- removeTrackedKtRows()
- resetKtRowTracking()
-
- if shouldLoadKt()
- createKtRows()
- end if
- return
- end if
-
- if m.pendingProbeCount = 0
- m.initialHomeRowsStarted = true
- processUserSections()
- end if
-end sub
function getExpectedRowContribution(sectionName as string) as integer
if not isValidAndNotEmpty(sectionName) or sectionName = "none"
return 0
end if
- if sectionName = "hss_all"
- if isValidAndNotEmpty(m.hssSections)
- return m.hssSections.Count()
- end if
- return 0
- end if
-
- if sectionName = "kt_all"
- if isValidAndNotEmpty(m.ktSections)
- return m.ktSections.Count()
- end if
- return 0
- end if
if sectionName = "latestmedia"
if isMultiServerEnabled()
@@ -1167,13 +673,6 @@ function inferServerRowSource(row as object) as string
rowSource = m.serverHomeRowsSource
end if
- rowIdToken = normalizeSectionToken(chainLookupReturn(row, "id", ""))
- if rowSource <> "hss" and Left(rowIdToken, 3) = "hss"
- rowSource = "hss"
- end if
- if rowSource <> "kefintweaks" and (Left(rowIdToken, 5) = "kefin" or Left(rowIdToken, 2) = "kt")
- rowSource = "kefintweaks"
- end if
return rowSource
end function
@@ -1201,163 +700,20 @@ function mapBuiltinSectionFromServerRow(row as object) as string
if token = "mylist" or token = "playlists" then return "mylist"
if token = "smalllibrarytiles" or token = "librarytilessmall" or token = "librarybuttons" or token = "mymedia" then return "smalllibrarytiles"
if token = "featuredmedia" or token = "mediabar" then return "featuredmedia"
- if token = "hssall" then return "hss_all"
- if token = "ktall" or token = "kefintweaksrows" then return "kt_all"
if token = "none" then return "none"
end for
return ""
end function
-function getServerDynamicTitle(baseTitle as string) as string
- if not isValid(m.serverDynamicRowTitles)
- m.serverDynamicRowTitles = {}
- end if
-
- return getUniqueHssSectionTitle(baseTitle, m.serverDynamicRowTitles)
-end function
function parseServerAdditionalData(row as object) as dynamic
return parseJsonObjectOrArray(chainLookupReturn(row, "additionalData", invalid))
end function
-function createHssRowFromServerRow(row as object, rowIndex as integer) as boolean
- parsedAdditional = parseServerAdditionalData(row)
- sectionType = ""
- if isAssociativeArrayValue(parsedAdditional)
- sectionType = toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "section", ""))
- end if
+function addServerHomeRow(row as object) as boolean
- if not isValidAndNotEmpty(sectionType)
- rowId = toNormalizedString(chainLookupReturn(row, "id", ""))
- rowIdLower = LCase(rowId)
- if Left(rowIdLower, 4) = "hss-"
- sectionType = rowId.Mid(4)
- else
- sectionType = rowId
- end if
- end if
-
- if not isValidAndNotEmpty(sectionType)
- m.processedRowCount++
- return false
- end if
-
- sectionTitle = toNormalizedString(chainLookupReturn(row, "title", ""))
- if not isValidAndNotEmpty(sectionTitle) and isAssociativeArrayValue(parsedAdditional)
- sectionTitle = toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "displayText", sectionType))
- end if
- sectionTitle = getServerDynamicTitle(sectionTitle)
-
- additionalData = ""
- if isAssociativeArrayValue(parsedAdditional)
- additionalData = toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "additionalData", ""))
- else
- additionalData = toNormalizedString(chainLookupReturn(row, "additionalData", ""))
- end if
-
- sectionKey = getHssSectionKey(sectionType, additionalData, rowIndex)
- m.hssRowTitleByKey[sectionKey] = sectionTitle
- m.hssRowTitles.push(sectionTitle)
-
- if not sectionExists(sectionTitle)
- rowNode = m.top.content.CreateChild("HomeRow")
- rowNode.title = sectionTitle
- rowNode.imageWidth = getPosterSize(false)[0]
- rowNode.cursorSize = getPosterSize(false)
- end if
-
- enqueueHssSectionTask(sectionType, additionalData, sectionTitle, sectionKey)
-
- return true
-end function
-
-function createKtRowFromServerRow(row as object, rowIndex as integer) as boolean
- parsedAdditional = parseServerAdditionalData(row)
-
- sectionKind = toNormalizedString(chainLookupReturn(row, "route", ""))
- if not isValidAndNotEmpty(sectionKind) and isAssociativeArrayValue(parsedAdditional)
- sectionKind = toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "kind", ""))
- end if
- if not isValidAndNotEmpty(sectionKind) and isAssociativeArrayValue(parsedAdditional)
- sectionKind = toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "section", ""))
- end if
-
- if not isValidAndNotEmpty(sectionKind)
- rowId = toNormalizedString(chainLookupReturn(row, "id", ""))
- rowIdLower = LCase(rowId)
- if Left(rowIdLower, 6) = "kefin-"
- sectionKind = rowId.Mid(6)
- else if Left(rowIdLower, 3) = "kt-"
- sectionKind = rowId.Mid(3)
- else
- idParts = rowId.Split(":")
- if idParts.Count() >= 4 and LCase(idParts[0]) = "plugindynamic"
- sectionKind = idParts[3]
- else if idParts.Count() > 0
- sectionKind = idParts[idParts.Count() - 1]
- end if
- end if
- end if
-
- if not isValidAndNotEmpty(sectionKind)
- m.processedRowCount++
- return false
- end if
-
- sectionSpec = {}
- if isAssociativeArrayValue(parsedAdditional)
- parsedSpec = getCaseInsensitiveValue(parsedAdditional, "spec", invalid)
- if isAssociativeArrayValue(parsedSpec)
- sectionSpec = parsedSpec
- else
- hasSectionMetadata = isValidAndNotEmpty(toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "section", ""))) or isValidAndNotEmpty(toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "displayText", "")))
- if not hasSectionMetadata
- sectionSpec = parsedAdditional
- end if
- end if
- end if
-
- if isAssociativeArrayValue(sectionSpec)
- specKind = toNormalizedString(getCaseInsensitiveValue(sectionSpec, "kind", ""))
- if not isValidAndNotEmpty(specKind)
- sectionSpec.kind = sectionKind
- end if
- end if
-
- sectionTitle = toNormalizedString(chainLookupReturn(row, "title", ""))
- if not isValidAndNotEmpty(sectionTitle) and isAssociativeArrayValue(parsedAdditional)
- sectionTitle = toNormalizedString(getCaseInsensitiveValue(parsedAdditional, "displayText", sectionKind))
- end if
- sectionTitle = getServerDynamicTitle(sectionTitle)
-
- sectionKey = getKtSectionKey(sectionKind, rowIndex)
- m.ktRowTitleByKey[sectionKey] = sectionTitle
- m.ktRowTitles.push(sectionTitle)
-
- if not sectionExists(sectionTitle)
- rowNode = m.top.content.CreateChild("HomeRow")
- rowNode.title = sectionTitle
- rowNode.imageWidth = getPosterSize(false)[0]
- rowNode.cursorSize = getPosterSize(false)
- end if
-
- enqueueKtSectionTask(sectionKind, sectionSpec, sectionTitle, sectionKey)
-
- return true
-end function
-
-function addServerHomeRow(row as object, rowIndex as integer) as boolean
- rowSource = inferServerRowSource(row)
-
- if rowSource = "hss"
- return createHssRowFromServerRow(row, rowIndex)
- end if
-
- if rowSource = "kefintweaks"
- return createKtRowFromServerRow(row, rowIndex)
- end if
sectionType = mapBuiltinSectionFromServerRow(row)
if not isValidAndNotEmpty(sectionType) or sectionType = "none"
@@ -1373,12 +729,7 @@ sub processServerRows()
m.processedRowCount = 0
for each row in m.serverHomeRows
- rowSource = inferServerRowSource(row)
- if rowSource = "hss" or rowSource = "kefintweaks"
- m.expectedRowCount++
- continue for
- end if
sectionType = mapBuiltinSectionFromServerRow(row)
if not isValidAndNotEmpty(sectionType) or sectionType = "none"
@@ -1392,7 +743,7 @@ sub processServerRows()
loadedSections = 0
rowIndex = 0
for each row in m.serverHomeRows
- sectionLoaded = addServerHomeRow(row, rowIndex)
+ sectionLoaded = addServerHomeRow(row)
if sectionLoaded then loadedSections++
if not m.global.app_loaded
@@ -1438,9 +789,6 @@ sub processUserSections()
for i = 0 to 7
sectionName = getResolvedSectionName(i)
- if isSectionSuppressedByHss(sectionName)
- sectionName = "none"
- end if
m.expectedRowCount = m.expectedRowCount + getExpectedRowContribution(sectionName)
end for
@@ -1450,9 +798,6 @@ sub processUserSections()
for i = 0 to 7
sectionName = getResolvedSectionName(i)
- if isSectionSuppressedByHss(sectionName)
- sectionName = "none"
- end if
sectionLoaded = false
if sectionName <> "none"
@@ -1669,15 +1014,6 @@ function addHomeSection(sectionType as string) as boolean
return true
end if
- if sectionType = "hss_all"
- createHssRows()
- return isValidAndNotEmpty(m.hssSections)
- end if
-
- if sectionType = "kt_all"
- createKtRows()
- return isValidAndNotEmpty(m.ktSections)
- end if
' Featured Media Carousel - now handled by separate toggle in Moonfin settings
' Skip creating a row for it, as it's controlled by ui.home.mediaBarEnabled
@@ -1692,197 +1028,6 @@ function addHomeSection(sectionType as string) as boolean
return false
end function
-sub enqueueHssSectionTask(sectionType as string, additionalData as string, sectionTitle as string, sectionKey as string)
- if not isValid(m.hssSectionTaskQueue)
- m.hssSectionTaskQueue = []
- end if
-
- m.hssSectionTaskQueue.push({
- sectionType: sectionType,
- additionalData: additionalData,
- sectionTitle: sectionTitle,
- sectionKey: sectionKey
- })
-
- drainHssSectionTaskQueue()
-end sub
-
-sub drainHssSectionTaskQueue()
- if not isValid(m.hssSectionTaskQueue)
- m.hssSectionTaskQueue = []
- end if
-
- if not isValid(m.hssSectionTasks)
- m.hssSectionTasks = {}
- end if
-
- while m.activeHssSectionTaskCount < HSS_MAX_CONCURRENT_SECTION_TASKS and m.hssSectionTaskQueue.Count() > 0
- taskDescriptor = m.hssSectionTaskQueue.Shift()
- if not isAssociativeArrayValue(taskDescriptor)
- continue while
- end if
-
- sectionType = chainLookupReturn(taskDescriptor, "sectionType", "")
- sectionKey = chainLookupReturn(taskDescriptor, "sectionKey", "")
- if not isValidAndNotEmpty(sectionType) or not isValidAndNotEmpty(sectionKey)
- continue while
- end if
-
- task = CreateObject("roSGNode", "HSSLoadSectionTask")
- task.sectionType = sectionType
- task.additionalData = chainLookupReturn(taskDescriptor, "additionalData", "")
- task.displayText = chainLookupReturn(taskDescriptor, "sectionTitle", "")
- task.sectionKey = sectionKey
- task.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- task.userId = chainLookupReturn(m.global, "session.user.id", "")
- task.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- task.observeField("content", "onHssSectionLoaded")
- m.hssSectionTasks[sectionKey] = task
- m.activeHssSectionTaskCount++
- task.control = "RUN"
- end while
-end sub
-
-sub enqueueKtSectionTask(sectionType as string, sectionSpec as dynamic, sectionTitle as string, sectionKey as string)
- if not isValid(m.ktSectionTaskQueue)
- m.ktSectionTaskQueue = []
- end if
-
- m.ktSectionTaskQueue.push({
- sectionType: sectionType,
- sectionSpec: sectionSpec,
- sectionTitle: sectionTitle,
- sectionKey: sectionKey
- })
-
- drainKtSectionTaskQueue()
-end sub
-
-sub drainKtSectionTaskQueue()
- if not isValid(m.ktSectionTaskQueue)
- m.ktSectionTaskQueue = []
- end if
-
- if not isValid(m.ktSectionTasks)
- m.ktSectionTasks = {}
- end if
-
- while m.activeKtSectionTaskCount < KT_MAX_CONCURRENT_SECTION_TASKS and m.ktSectionTaskQueue.Count() > 0
- taskDescriptor = m.ktSectionTaskQueue.Shift()
- if not isAssociativeArrayValue(taskDescriptor)
- continue while
- end if
-
- sectionType = chainLookupReturn(taskDescriptor, "sectionType", "")
- sectionKey = chainLookupReturn(taskDescriptor, "sectionKey", "")
- if not isValidAndNotEmpty(sectionType) or not isValidAndNotEmpty(sectionKey)
- continue while
- end if
-
- task = CreateObject("roSGNode", "KefinTweaksLoadSectionTask")
- task.sectionKind = sectionType
- task.spec = chainLookupReturn(taskDescriptor, "sectionSpec", {})
- task.displayText = chainLookupReturn(taskDescriptor, "sectionTitle", "")
- task.sectionKey = sectionKey
- task.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- task.userId = chainLookupReturn(m.global, "session.user.id", "")
- task.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- task.observeField("content", "onKtSectionLoaded")
- m.ktSectionTasks[sectionKey] = task
- m.activeKtSectionTaskCount++
- task.control = "RUN"
- end while
-end sub
-
-sub createHssRows()
- if not isValidAndNotEmpty(m.hssSections)
- return
- end if
-
- if not isValid(m.hssSectionTasks)
- m.hssSectionTasks = {}
- end if
-
- usedTitles = {}
-
- sectionIndex = 0
- for each hssSection in m.hssSections
- sectionType = chainLookupReturn(hssSection, "section", "")
- if not isValidAndNotEmpty(sectionType)
- m.processedRowCount++
- sectionIndex++
- continue for
- end if
-
- sectionTitle = chainLookupReturn(hssSection, "displayText", "")
- if not isValidAndNotEmpty(sectionTitle)
- sectionTitle = sectionType
- end if
- sectionTitle = getUniqueHssSectionTitle(sectionTitle, usedTitles)
-
- additionalData = chainLookupReturn(hssSection, "additionalData", "")
- sectionKey = getHssSectionKey(sectionType, additionalData, sectionIndex)
-
- m.hssRowTitleByKey[sectionKey] = sectionTitle
- m.hssRowTitles.push(sectionTitle)
-
- if not sectionExists(sectionTitle)
- row = m.top.content.CreateChild("HomeRow")
- row.title = sectionTitle
- row.imageWidth = getPosterSize(false)[0]
- row.cursorSize = getPosterSize(false)
- end if
-
- enqueueHssSectionTask(sectionType, additionalData, sectionTitle, sectionKey)
-
- sectionIndex++
- end for
-end sub
-
-sub createKtRows()
- if not isValidAndNotEmpty(m.ktSections)
- return
- end if
-
- if not isValid(m.ktSectionTasks)
- m.ktSectionTasks = {}
- end if
-
- usedTitles = {}
-
- sectionIndex = 0
- for each ktSection in m.ktSections
- sectionType = chainLookupReturn(ktSection, "kind", "")
- if not isValidAndNotEmpty(sectionType)
- m.processedRowCount++
- sectionIndex++
- continue for
- end if
-
- sectionTitle = chainLookupReturn(ktSection, "displayText", "")
- if not isValidAndNotEmpty(sectionTitle)
- sectionTitle = sectionType
- end if
- sectionTitle = getUniqueHssSectionTitle(sectionTitle, usedTitles)
-
- sectionSpec = chainLookupReturn(ktSection, "spec", {})
- sectionKey = getKtSectionKey(sectionType, sectionIndex)
-
- m.ktRowTitleByKey[sectionKey] = sectionTitle
- m.ktRowTitles.push(sectionTitle)
-
- if not sectionExists(sectionTitle)
- row = m.top.content.CreateChild("HomeRow")
- row.title = sectionTitle
- row.imageWidth = getPosterSize(false)[0]
- row.cursorSize = getPosterSize(false)
- end if
-
- enqueueKtSectionTask(sectionType, sectionSpec, sectionTitle, sectionKey)
-
- sectionIndex++
- end for
-end sub
' createLibraryRow: Creates a row displaying the user's libraries
'
@@ -3041,137 +2186,6 @@ sub updateRecentlyReleasedItems()
setRowItemSize()
end sub
-sub onHssSectionLoaded(msg as object)
- m.processedRowCount++
-
- if m.activeHssSectionTaskCount > 0
- m.activeHssSectionTaskCount = m.activeHssSectionTaskCount - 1
- end if
-
- drainHssSectionTaskQueue()
-
- node = msg.getRoSGNode()
- if not isValid(node)
- setRowItemSize()
- return
- end if
-
- itemData = msg.getData()
-
- node.unobserveField("content")
- node.content = []
-
- sectionKey = node.sectionKey
- if isValidAndNotEmpty(sectionKey) and isValid(m.hssSectionTasks) and m.hssSectionTasks.DoesExist(sectionKey)
- m.hssSectionTasks.Delete(sectionKey)
- end if
-
- sectionTitle = ""
- if isValidAndNotEmpty(sectionKey) and isValid(m.hssRowTitleByKey) and m.hssRowTitleByKey.DoesExist(sectionKey)
- sectionTitle = m.hssRowTitleByKey[sectionKey]
- end if
-
- if not isValidAndNotEmpty(sectionTitle)
- sectionTitle = node.displayText
- end if
-
- if not isValidAndNotEmpty(sectionTitle)
- setRowItemSize()
- return
- end if
-
- if not isValidAndNotEmpty(itemData)
- removeHomeSection(sectionTitle)
- return
- end if
-
- row = CreateObject("roSGNode", "HomeRow")
- row.title = sectionTitle
- row.imageWidth = getPosterSize(false)[0]
- row.cursorSize = getPosterSize(false)
- row.usePoster = true
-
- for each item in itemData
- item.usePoster = row.usePoster
- item.imageWidth = row.imageWidth
- row.appendChild(item)
- end for
-
- if sectionExists(sectionTitle)
- m.top.content.replaceChild(row, getSectionIndex(sectionTitle))
- setRowItemSize()
- return
- end if
-
- m.top.content.insertChild(row, getOriginalSectionIndex("hss_all"))
- setRowItemSize()
-end sub
-
-sub onKtSectionLoaded(msg as object)
- m.processedRowCount++
-
- if m.activeKtSectionTaskCount > 0
- m.activeKtSectionTaskCount = m.activeKtSectionTaskCount - 1
- end if
-
- drainKtSectionTaskQueue()
-
- node = msg.getRoSGNode()
- if not isValid(node)
- setRowItemSize()
- return
- end if
-
- itemData = msg.getData()
-
- node.unobserveField("content")
- node.content = []
-
- sectionKey = node.sectionKey
- if isValidAndNotEmpty(sectionKey) and isValid(m.ktSectionTasks) and m.ktSectionTasks.DoesExist(sectionKey)
- m.ktSectionTasks.Delete(sectionKey)
- end if
-
- sectionTitle = ""
- if isValidAndNotEmpty(sectionKey) and isValid(m.ktRowTitleByKey) and m.ktRowTitleByKey.DoesExist(sectionKey)
- sectionTitle = m.ktRowTitleByKey[sectionKey]
- end if
-
- if not isValidAndNotEmpty(sectionTitle)
- sectionTitle = node.displayText
- end if
-
- if not isValidAndNotEmpty(sectionTitle)
- setRowItemSize()
- return
- end if
-
- if not isValidAndNotEmpty(itemData)
- removeHomeSection(sectionTitle)
- return
- end if
-
- row = CreateObject("roSGNode", "HomeRow")
- row.title = sectionTitle
- row.imageWidth = getPosterSize(false)[0]
- row.cursorSize = getPosterSize(false)
- row.usePoster = true
-
- for each item in itemData
- item.usePoster = row.usePoster
- item.imageWidth = row.imageWidth
- row.appendChild(item)
- end for
-
- if sectionExists(sectionTitle)
- m.top.content.replaceChild(row, getSectionIndex(sectionTitle))
- setRowItemSize()
- return
- end if
-
- m.top.content.insertChild(row, getOriginalSectionIndex("kt_all"))
- setRowItemSize()
-end sub
' updateOnNowItems: Processes LoadOnNowTask content. Removes, Creates, or Updates Recently Added in on now row as needed
'
diff --git a/components/home/KefinTweaksLoadSectionTask.bs b/components/home/KefinTweaksLoadSectionTask.bs
deleted file mode 100644
index 69e1d1c90..000000000
--- a/components/home/KefinTweaksLoadSectionTask.bs
+++ /dev/null
@@ -1,353 +0,0 @@
-import "pkg:/source/api/baserequest.bs"
-import "pkg:/source/utils/misc.bs"
-
-const DEFAULT_SECTION_LIMIT = 15
-
-sub init()
- m.top.functionName = "loadKefinSection"
-end sub
-
-function targetAPIRequest(serverUrl as string, userId as string, authToken as string, path as string, params = {} as object) as dynamic
- if not isValidAndNotEmpty(serverUrl)
- return invalid
- end if
-
- return APIRequestForServer(serverUrl, userId, authToken, path, params)
-end function
-
-sub loadKefinSection()
- results = []
-
- serverUrl = m.top.serverUrl
- userId = m.top.userId
- authToken = m.top.authToken
- sectionKind = m.top.sectionKind
- if not isValidAndNotEmpty(sectionKind)
- m.top.content = results
- return
- end if
-
- if not isValidAndNotEmpty(userId)
- m.top.content = results
- return
- end if
-
- spec = m.top.spec
- if not isAssociativeArrayValue(spec)
- spec = {}
- end if
-
- if isStringEqual(sectionKind, "recentlyAddedInLibrary")
- itemsPayload = loadRecentlyAddedInLibrary(spec, serverUrl, userId, authToken)
- else
- response = runKefinSpec(sectionKind, spec, serverUrl, userId, authToken)
- itemsPayload = getItemsPayload(response)
- end if
-
- for each item in itemsPayload
- homeData = createSGNode("HomeData")
- homeData.json = item
- results.push(homeData)
- end for
-
- m.top.content = results
-end sub
-
-function runKefinSpec(sectionKind as string, spec as object, serverUrl as string, userId as string, authToken as string) as dynamic
- sectionName = LCase(sectionKind ?? "")
- if not isValidAndNotEmpty(sectionName)
- sectionName = LCase(chainLookupReturn(spec, "kind", ""))
- end if
-
- limit = normalizeLimit(chainLookupReturn(spec, "limit", DEFAULT_SECTION_LIMIT), DEFAULT_SECTION_LIMIT)
-
- if sectionName = "recentlyreleasedmovies"
- params = getBaseItemsParams(limit)
- params.IncludeItemTypes = "Movie"
- params.SortBy = "PremiereDate"
- params.SortOrder = "Descending"
- params.MinPremiereDate = getCutoffDateIso(7)
- return requestItems(serverUrl, userId, authToken, params)
- end if
-
- if sectionName = "recentlyreleasedepisodes"
- params = getBaseItemsParams(limit)
- params.IncludeItemTypes = "Episode"
- params.SortBy = "PremiereDate"
- params.SortOrder = "Descending"
- params.MinPremiereDate = getCutoffDateIso(7)
- return requestItems(serverUrl, userId, authToken, params)
- end if
-
- if sectionName = "watchagain"
- params = getBaseItemsParams(limit)
- params.IncludeItemTypes = "Movie,Series"
- params.Filters = "IsPlayed"
- params.SortBy = "DatePlayed"
- params.SortOrder = "Descending"
- return requestItems(serverUrl, userId, authToken, params)
- end if
-
- if sectionName = "custom"
- return runCustomSpec(spec, serverUrl, userId, authToken, limit)
- end if
-
- return invalid
-end function
-
-function runCustomSpec(spec as object, serverUrl as string, userId as string, authToken as string, limit as integer) as dynamic
- sourceValue = chainLookupReturn(spec, "source", "")
- if not isValidAndNotEmpty(sourceValue)
- return invalid
- end if
-
- customType = LCase(chainLookupReturn(spec, "type", ""))
-
- params = getBaseItemsParams(limit)
- params.SortBy = mapKefinSortBy(chainLookupReturn(spec, "sortBy", "Random"))
- params.SortOrder = mapKefinSortOrder(chainLookupReturn(spec, "sortOrderDirection", "Ascending"))
- params.IncludeItemTypes = getIncludeItemTypesValue(chainLookupReturn(spec, "includeItemTypes", invalid), "Movie,Series")
-
- if customType = "tag"
- params.Tags = sourceValue
- else if customType = "genre"
- params.Genres = sourceValue
- else if customType = "parent" or customType = "collection" or customType = "playlist"
- params.ParentId = sourceValue
- else
- return invalid
- end if
-
- return requestItems(serverUrl, userId, authToken, params)
-end function
-
-function loadRecentlyAddedInLibrary(spec as object, serverUrl as string, userId as string, authToken as string) as object
- libraryIds = getStringArray(chainLookupReturn(spec, "libraryIds", []), [])
- limit = normalizeLimit(chainLookupReturn(spec, "limit", DEFAULT_SECTION_LIMIT), DEFAULT_SECTION_LIMIT)
-
- if not isValidAndNotEmpty(libraryIds)
- return []
- end if
-
- allItems = []
-
- for each libraryId in libraryIds
- if not isValidAndNotEmpty(libraryId)
- continue for
- end if
-
- request = targetAPIRequest(serverUrl, userId, authToken, "/Items/Latest", {
- ParentId: libraryId,
- Limit: limit,
- EnableImageTypes: "Primary,Backdrop,Thumb",
- ImageTypeLimit: 1,
- EnableTotalRecordCount: false
- })
-
- if not isValid(request)
- continue for
- end if
-
- response = getJson(request)
- items = getItemsPayload(response)
- if not isValidAndNotEmpty(items)
- continue for
- end if
-
- for each item in items
- allItems.push(item)
- end for
- end for
-
- if allItems.Count() <= limit
- return allItems
- end if
-
- trimmed = []
- for i = 0 to limit - 1
- trimmed.push(allItems[i])
- end for
-
- return trimmed
-end function
-
-function getBaseItemsParams(limit as integer) as object
- return {
- Recursive: true,
- Limit: limit,
- EnableImageTypes: "Primary,Backdrop,Thumb",
- ImageTypeLimit: 1,
- EnableTotalRecordCount: false
- }
-end function
-
-function requestItems(serverUrl as string, userId as string, authToken as string, params as object) as dynamic
- if not isValidAndNotEmpty(userId)
- return invalid
- end if
-
- request = targetAPIRequest(serverUrl, userId, authToken, "/Users/" + userId.EncodeUriComponent() + "/Items", params)
- if not isValid(request)
- return invalid
- end if
-
- return getJson(request)
-end function
-
-function getCutoffDateIso(days as integer) as string
- nowDate = CreateObject("roDateTime")
- cutoffDate = CreateObject("roDateTime")
- cutoffDate.FromSeconds(nowDate.AsSeconds() - (days * 86400))
- return cutoffDate.ToISOString()
-end function
-
-function mapKefinSortBy(value as dynamic) as string
- if not isValidAndNotEmpty(value)
- return "Random"
- end if
-
- normalized = LCase(value.ToStr().Replace(" ", ""))
-
- if normalized = "releasedate" or normalized = "premieredate"
- return "PremiereDate"
- end if
-
- if normalized = "dateadded" or normalized = "datecreated"
- return "DateCreated"
- end if
-
- if normalized = "name" or normalized = "sortname"
- return "SortName"
- end if
-
- if normalized = "communityrating"
- return "CommunityRating"
- end if
-
- if normalized = "datelastcontentadded"
- return "DateLastContentAdded"
- end if
-
- if normalized = "random"
- return "Random"
- end if
-
- return value.ToStr()
-end function
-
-function mapKefinSortOrder(value as dynamic) as string
- if not isValidAndNotEmpty(value)
- return "Ascending"
- end if
-
- normalized = LCase(value.ToStr())
- if normalized = "descending"
- return "Descending"
- end if
-
- return "Ascending"
-end function
-
-function getIncludeItemTypesValue(value as dynamic, defaultValue as string) as string
- includeTypes = getStringArray(value, [])
- if isValidAndNotEmpty(includeTypes)
- return includeTypes.Join(",")
- end if
-
- return defaultValue
-end function
-
-function getStringArray(value as dynamic, defaultValues as object) as object
- output = []
-
- if isArrayValue(value)
- for each item in value
- if not isValid(item)
- continue for
- end if
- itemString = item.ToStr().Trim()
- if isValidAndNotEmpty(itemString)
- output.push(itemString)
- end if
- end for
- else if type(value) = "String" or type(value) = "roString"
- for each item in value.Split(",")
- itemString = item.Trim()
- if isValidAndNotEmpty(itemString)
- output.push(itemString)
- end if
- end for
- end if
-
- if isValidAndNotEmpty(output)
- return output
- end if
-
- fallback = []
- if isArrayValue(defaultValues)
- for each item in defaultValues
- if not isValid(item)
- continue for
- end if
- itemString = item.ToStr().Trim()
- if isValidAndNotEmpty(itemString)
- fallback.push(itemString)
- end if
- end for
- end if
- return fallback
-end function
-
-function normalizeLimit(value as dynamic, defaultValue as integer) as integer
- if not isValid(value)
- return defaultValue
- end if
-
- parsed = defaultValue
- valueType = type(value)
-
- if valueType = "Integer" or valueType = "LongInteger" or valueType = "roInteger" or valueType = "roInt"
- parsed = value
- else if valueType = "Float" or valueType = "roFloat"
- parsed = Int(value)
- else if valueType = "String" or valueType = "roString"
- parsed = Int(Val(value))
- end if
-
- if parsed <= 0
- return defaultValue
- end if
-
- if parsed > 100
- return 100
- end if
-
- return parsed
-end function
-
-function getItemsPayload(response as dynamic) as object
- if not isValid(response)
- return []
- end if
-
- responseType = type(response)
- if responseType = "Array" or responseType = "roArray"
- return response
- end if
-
- if isChainValid(response, "Items")
- return response.Items
- end if
-
- return []
-end function
-
-function isArrayValue(value as dynamic) as boolean
- valueType = type(value)
- return valueType = "Array" or valueType = "roArray"
-end function
-
-function isAssociativeArrayValue(value as dynamic) as boolean
- valueType = type(value)
- return valueType = "AssociativeArray" or valueType = "roAssociativeArray"
-end function
diff --git a/components/home/KefinTweaksLoadSectionTask.xml b/components/home/KefinTweaksLoadSectionTask.xml
deleted file mode 100644
index 1930016c2..000000000
--- a/components/home/KefinTweaksLoadSectionTask.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/components/home/KefinTweaksProbeTask.bs b/components/home/KefinTweaksProbeTask.bs
deleted file mode 100644
index 34089ca96..000000000
--- a/components/home/KefinTweaksProbeTask.bs
+++ /dev/null
@@ -1,481 +0,0 @@
-import "pkg:/source/api/baserequest.bs"
-import "pkg:/source/utils/misc.bs"
-
-const DEFAULT_SECTION_LIMIT = 15
-const KEFIN_CONFIG_REQUEST_TIMEOUT_MS = 8000
-
-sub init()
- m.top.functionName = "probeKefinTweaks"
-end sub
-
-function targetAPIRequest(path as string, params = {} as object) as dynamic
- if not isValidAndNotEmpty(m.top.serverUrl)
- return invalid
- end if
-
- return APIRequestForServer(m.top.serverUrl, m.top.userId, m.top.authToken, path, params)
-end function
-
-sub probeKefinTweaks()
- result = {
- enabled: false,
- sections: []
- }
-
- source = getKefinConfigSource()
- if not isValidAndNotEmpty(source)
- m.top.result = result
- return
- end if
-
- configJson = extractKefinConfigJson(source)
- if not isValidAndNotEmpty(configJson)
- m.top.result = result
- return
- end if
-
- config = ParseJson(configJson)
- if not isValid(config)
- m.top.result = result
- return
- end if
-
- homeScreen = chainLookupReturn(config, "homeScreen", invalid)
- if not isValid(homeScreen)
- m.top.result = result
- return
- end if
-
- if not normalizeEnabled(chainLookupReturn(homeScreen, "enabled", true), true)
- m.top.result = result
- return
- end if
-
- result.enabled = true
- result.sections = buildKefinSections(homeScreen)
-
- m.top.result = result
-end sub
-
-function getKefinConfigSource() as string
- endpoints = [
- "/JavaScriptInjector/private.js",
- "/JavaScriptInjector/public.js"
- ]
-
- for each endpoint in endpoints
- req = targetAPIRequest(endpoint)
- if not isValid(req)
- continue for
- end if
-
- source = getRequestBodyWithTimeout(req, KEFIN_CONFIG_REQUEST_TIMEOUT_MS)
- if isValidAndNotEmpty(source)
- return source
- end if
- end for
-
- return ""
-end function
-
-function getRequestBodyWithTimeout(req as dynamic, timeoutMs as integer) as string
- if not isValid(req)
- return ""
- end if
-
- req.setMessagePort(CreateObject("roMessagePort"))
- req.AsyncGetToString()
-
- response = wait(timeoutMs, req.GetMessagePort())
- if type(response) <> "roUrlEvent"
- return ""
- end if
-
- if response.GetResponseCode() <> 200
- return ""
- end if
-
- return response.GetString()
-end function
-
-function extractKefinConfigJson(source as string) as string
- strictRegex = CreateObject("roRegex", "window\\.KefinTweaksConfig\\s*=\\s*(\\{[\\s\\S]*?\\});", "m")
- strictMatch = strictRegex.Match(source)
- if isValid(strictMatch) and strictMatch.Count() > 1
- return strictMatch[1]
- end if
-
- fallbackRegex = CreateObject("roRegex", "window\\.KefinTweaksConfig\\s*=\\s*(\\{[\\s\\S]*?\\})\\s*(?:;|$)", "m")
- fallbackMatch = fallbackRegex.Match(source)
- if isValid(fallbackMatch) and fallbackMatch.Count() > 1
- return fallbackMatch[1]
- end if
-
- return ""
-end function
-
-function buildKefinSections(homeScreen as dynamic) as object
- defaultLimit = normalizeLimit(chainLookupReturn(homeScreen, "defaultItemLimit", DEFAULT_SECTION_LIMIT), DEFAULT_SECTION_LIMIT)
- sections = []
-
- recentlyReleased = chainLookupReturn(homeScreen, "recentlyReleased", invalid)
- if normalizeEnabled(chainLookupReturn(recentlyReleased, "enabled", true), true)
- rrMovies = chainLookupReturn(recentlyReleased, "movies", invalid)
- if normalizeEnabled(chainLookupReturn(rrMovies, "enabled", true), true)
- moviesLimit = normalizeLimit(chainLookupReturn(rrMovies, "itemLimit", defaultLimit), defaultLimit)
- moviesOrder = normalizeOrder(chainLookupReturn(rrMovies, "order", 21), 21)
- moviesTitle = chainLookupReturn(rrMovies, "name", "Recently Released Movies")
- sections.push(buildSectionDescriptor("recentlyReleasedMovies", moviesTitle, moviesOrder, {
- kind: "recentlyReleasedMovies",
- limit: moviesLimit
- }))
- end if
-
- rrEpisodes = chainLookupReturn(recentlyReleased, "episodes", invalid)
- if normalizeEnabled(chainLookupReturn(rrEpisodes, "enabled", true), true)
- episodesLimit = normalizeLimit(chainLookupReturn(rrEpisodes, "itemLimit", defaultLimit), defaultLimit)
- episodesOrder = normalizeOrder(chainLookupReturn(rrEpisodes, "order", 22), 22)
- episodesTitle = chainLookupReturn(rrEpisodes, "name", "Recently Released Episodes")
- sections.push(buildSectionDescriptor("recentlyReleasedEpisodes", episodesTitle, episodesOrder, {
- kind: "recentlyReleasedEpisodes",
- limit: episodesLimit
- }))
- end if
- end if
-
- watchAgain = chainLookupReturn(homeScreen, "watchAgain", invalid)
- if normalizeEnabled(chainLookupReturn(watchAgain, "enabled", true), true)
- watchAgainLimit = normalizeLimit(chainLookupReturn(watchAgain, "itemLimit", defaultLimit), defaultLimit)
- watchAgainOrder = normalizeOrder(chainLookupReturn(watchAgain, "order", 50), 50)
- watchAgainTitle = chainLookupReturn(watchAgain, "name", "Watch Again")
- sections.push(buildSectionDescriptor("watchAgain", watchAgainTitle, watchAgainOrder, {
- kind: "watchAgain",
- limit: watchAgainLimit
- }))
- end if
-
- recentlyAddedInLibrary = chainLookupReturn(homeScreen, "recentlyAddedInLibrary", invalid)
- if isAssociativeArrayValue(recentlyAddedInLibrary)
- libraryIds = []
- for each libraryId in recentlyAddedInLibrary
- entry = recentlyAddedInLibrary[libraryId]
- if not normalizeEnabled(chainLookupReturn(entry, "enabled", true), true)
- continue for
- end if
- if not isValidAndNotEmpty(libraryId)
- continue for
- end if
- libraryIds.push(libraryId)
- end for
-
- if isValidAndNotEmpty(libraryIds)
- sections.push(buildSectionDescriptor("recentlyAddedInLibrary", "Recently Added", 90, {
- kind: "recentlyAddedInLibrary",
- libraryIds: libraryIds,
- limit: defaultLimit
- }))
- end if
- end if
-
- seasonal = chainLookupReturn(homeScreen, "seasonal", invalid)
- if isAssociativeArrayValue(seasonal)
- for each seasonalKey in seasonal
- entry = seasonal[seasonalKey]
- if not isAssociativeArrayValue(entry)
- continue for
- end if
-
- if not normalizeEnabled(chainLookupReturn(entry, "enabled", true), true)
- continue for
- end if
-
- startDate = chainLookupReturn(entry, "startDate", "")
- endDate = chainLookupReturn(entry, "endDate", "")
- if not isValidAndNotEmpty(startDate) or not isValidAndNotEmpty(endDate)
- continue for
- end if
-
- if not isSeasonalActive(startDate, endDate)
- continue for
- end if
-
- spec = buildCustomSectionSpec(entry, defaultLimit, ["Movie"])
- if not isValidAndNotEmpty(chainLookupReturn(spec, "source", ""))
- continue for
- end if
-
- sectionTitle = chainLookupReturn(entry, "name", seasonalKey)
- sectionOrder = normalizeOrder(chainLookupReturn(entry, "order", 60), 60)
- sections.push(buildSectionDescriptor("custom", sectionTitle, sectionOrder, spec))
- end for
- end if
-
- customSections = chainLookupReturn(homeScreen, "customSections", [])
- if isArrayValue(customSections)
- for i = 0 to customSections.Count() - 1
- entry = customSections[i]
- if not isAssociativeArrayValue(entry)
- continue for
- end if
-
- if not normalizeEnabled(chainLookupReturn(entry, "enabled", true), true)
- continue for
- end if
-
- spec = buildCustomSectionSpec(entry, defaultLimit, ["Movie", "Series"])
- if not isValidAndNotEmpty(chainLookupReturn(spec, "source", ""))
- continue for
- end if
-
- sectionTitle = chainLookupReturn(entry, "name", "Custom")
- sectionOrder = normalizeOrder(chainLookupReturn(entry, "order", 100 + i), 100 + i)
- sections.push(buildSectionDescriptor("custom", sectionTitle, sectionOrder, spec))
- end for
- end if
-
- sortedSections = sortSectionsByOrder(sections)
-
- normalized = []
- for each sectionData in sortedSections
- kind = chainLookupReturn(sectionData, "kind", "")
- if not isValidAndNotEmpty(kind)
- continue for
- end if
-
- displayText = chainLookupReturn(sectionData, "displayText", kind)
- if not isValidAndNotEmpty(displayText)
- displayText = kind
- end if
-
- sectionSpec = chainLookupReturn(sectionData, "spec", {})
- normalized.push({
- kind: kind,
- displayText: displayText,
- spec: sectionSpec
- })
- end for
-
- return normalized
-end function
-
-function buildSectionDescriptor(kind as string, displayText as string, sectionOrder as integer, spec as object) as object
- if not isValidAndNotEmpty(displayText)
- displayText = kind
- end if
-
- return {
- kind: kind,
- displayText: displayText,
- order: sectionOrder,
- spec: spec
- }
-end function
-
-function buildCustomSectionSpec(entry as dynamic, defaultLimit as integer, defaultIncludeTypes as object) as object
- return {
- kind: "custom",
- type: chainLookupReturn(entry, "type", "genre"),
- source: chainLookupReturn(entry, "source", ""),
- sortBy: chainLookupReturn(entry, "sortOrder", "Random"),
- sortOrderDirection: chainLookupReturn(entry, "sortOrderDirection", "Ascending"),
- includeItemTypes: getStringArray(chainLookupReturn(entry, "includeItemTypes", invalid), defaultIncludeTypes),
- limit: normalizeLimit(chainLookupReturn(entry, "limit", chainLookupReturn(entry, "itemLimit", defaultLimit)), defaultLimit)
- }
-end function
-
-function sortSectionsByOrder(sections as object) as object
- if not isArrayValue(sections)
- return []
- end if
-
- for i = 0 to sections.Count() - 2
- for j = i + 1 to sections.Count() - 1
- leftOrder = normalizeOrder(chainLookupReturn(sections[i], "order", i), i)
- rightOrder = normalizeOrder(chainLookupReturn(sections[j], "order", j), j)
-
- if rightOrder < leftOrder
- tmp = sections[i]
- sections[i] = sections[j]
- sections[j] = tmp
- end if
- end for
- end for
-
- return sections
-end function
-
-function getStringArray(value as dynamic, defaultValues as object) as object
- output = []
-
- if isArrayValue(value)
- for each item in value
- if not isValid(item)
- continue for
- end if
- itemString = item.ToStr().Trim()
- if isValidAndNotEmpty(itemString)
- output.push(itemString)
- end if
- end for
- else if type(value) = "String" or type(value) = "roString"
- for each item in value.Split(",")
- itemString = item.Trim()
- if isValidAndNotEmpty(itemString)
- output.push(itemString)
- end if
- end for
- end if
-
- if isValidAndNotEmpty(output)
- return output
- end if
-
- fallback = []
- if isArrayValue(defaultValues)
- for each item in defaultValues
- if not isValid(item)
- continue for
- end if
- itemString = item.ToStr().Trim()
- if isValidAndNotEmpty(itemString)
- fallback.push(itemString)
- end if
- end for
- end if
- return fallback
-end function
-
-function normalizeOrder(value as dynamic, defaultValue as integer) as integer
- if not isValid(value)
- return defaultValue
- end if
-
- parsed = defaultValue
- valueType = type(value)
-
- if valueType = "Integer" or valueType = "LongInteger" or valueType = "roInteger" or valueType = "roInt"
- parsed = value
- else if valueType = "Float" or valueType = "roFloat"
- parsed = Int(value)
- else if valueType = "String" or valueType = "roString"
- parsed = Int(Val(value))
- end if
-
- if parsed < 0
- return defaultValue
- end if
-
- return parsed
-end function
-
-function normalizeEnabled(value as dynamic, defaultValue as boolean) as boolean
- if not isValid(value)
- return defaultValue
- end if
-
- valueType = type(value)
- if valueType = "Boolean" or valueType = "roBoolean"
- return value
- end if
-
- if valueType = "String" or valueType = "roString"
- normalized = LCase(value.Trim())
- if normalized = "true" or normalized = "1" or normalized = "yes" or normalized = "on"
- return true
- end if
- if normalized = "false" or normalized = "0" or normalized = "no" or normalized = "off"
- return false
- end if
- return defaultValue
- end if
-
- return value <> 0
-end function
-
-function normalizeLimit(value as dynamic, defaultValue as integer) as integer
- if not isValid(value)
- return defaultValue
- end if
-
- parsed = defaultValue
- valueType = type(value)
-
- if valueType = "Integer" or valueType = "LongInteger" or valueType = "roInteger" or valueType = "roInt"
- parsed = value
- else if valueType = "Float" or valueType = "roFloat"
- parsed = Int(value)
- else if valueType = "String" or valueType = "roString"
- parsed = Int(Val(value))
- end if
-
- if parsed <= 0
- return defaultValue
- end if
-
- if parsed > 100
- return 100
- end if
-
- return parsed
-end function
-
-function isSeasonalActive(startMmDd as string, endMmDd as string) as boolean
- startPair = parseMonthDay(startMmDd)
- endPair = parseMonthDay(endMmDd)
-
- if not isArrayValue(startPair) or not isArrayValue(endPair)
- return false
- end if
-
- now = CreateObject("roDateTime")
- todayMonth = now.GetMonth()
- todayDay = now.GetDayOfMonth()
-
- startKey = (startPair[0] * 100) + startPair[1]
- endKey = (endPair[0] * 100) + endPair[1]
- todayKey = (todayMonth * 100) + todayDay
-
- if startKey <= endKey
- return todayKey >= startKey and todayKey <= endKey
- end if
-
- return todayKey >= startKey or todayKey <= endKey
-end function
-
-function parseMonthDay(value as dynamic) as dynamic
- if not isValidAndNotEmpty(value)
- return invalid
- end if
-
- if not (type(value) = "String" or type(value) = "roString")
- return invalid
- end if
-
- parts = value.Split("-")
- if parts.Count() < 2
- return invalid
- end if
-
- month = Int(Val(parts[0]))
- day = Int(Val(parts[1]))
-
- if month < 1 or month > 12
- return invalid
- end if
-
- if day < 1 or day > 31
- return invalid
- end if
-
- return [month, day]
-end function
-
-function isArrayValue(value as dynamic) as boolean
- valueType = type(value)
- return valueType = "Array" or valueType = "roArray"
-end function
-
-function isAssociativeArrayValue(value as dynamic) as boolean
- valueType = type(value)
- return valueType = "AssociativeArray" or valueType = "roAssociativeArray"
-end function
diff --git a/components/home/KefinTweaksProbeTask.xml b/components/home/KefinTweaksProbeTask.xml
deleted file mode 100644
index 8f613e90d..000000000
--- a/components/home/KefinTweaksProbeTask.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/components/settings/HomeRowsSourceRowsTask.bs b/components/settings/HomeRowsSourceRowsTask.bs
index 48b1927f5..f71d9e234 100644
--- a/components/settings/HomeRowsSourceRowsTask.bs
+++ b/components/settings/HomeRowsSourceRowsTask.bs
@@ -133,13 +133,7 @@ function sortRowsByOrder(rows as object) as object
end function
function normalizeHomeRowsSource(value as dynamic) as string
- source = LCase(toNormalizedString(value))
-
- if source = "kefin" or source = "kefintweak" or source = "kefintweaks"
- return "kefintweaks"
- end if
-
- return source
+ return LCase(toNormalizedString(value))
end function
function normalizeBoolean(value as dynamic, defaultValue = false as boolean) as boolean
diff --git a/components/settings/settings.bs b/components/settings/settings.bs
index f4d5943fc..6f577f065 100644
--- a/components/settings/settings.bs
+++ b/components/settings/settings.bs
@@ -10,8 +10,6 @@ import "pkg:/source/utils/JellyseerrUtils.bs"
import "pkg:/source/utils/misc.bs"
import "pkg:/source/utils/settingsSync.bs"
-const HOME_ROWS_HSS_LOCAL_SETTING = "ui.home.hssRowsLocalConfig"
-const HOME_ROWS_KT_LOCAL_SETTING = "ui.home.ktRowsLocalConfig"
sub init()
m.top.optionsAvailable = false
@@ -81,10 +79,6 @@ sub init()
m.mediaBarSelectorDialogOptions = []
m.mediaBarPickerTask = invalid
m.pendingMediaBarSettingItem = invalid
- m.hssDetected = invalid
- m.hssProbeTask = invalid
- m.ktDetected = invalid
- m.ktProbeTask = invalid
m.homeRowsSourceTask = invalid
m.pendingPluginRowsSetting = invalid
m.pendingPluginRowsSource = ""
@@ -101,11 +95,7 @@ sub init()
m.seerrLogoutTask = invalid
m.configTree = reorderSettingsForFlutter(GetConfigTree())
- updateHssSettingGate()
- updateKtSettingGate()
LoadMenu({ children: m.configTree })
- refreshHssPluginDetection()
- refreshKtPluginDetection()
end sub
sub onKeypressTimerFire()
@@ -343,30 +333,6 @@ sub onMediaBarSelectorDialogButton(event as object)
m.settingsMenu.setFocus(true)
end sub
-sub openPluginRowsManager(settingItem as object)
- sourceName = getPluginRowsManagerSource(chainLookupReturn(settingItem, "settingName", ""))
- if not isValidAndNotEmpty(sourceName)
- ShowToast("Unsupported row manager.", "error")
- m.settingsMenu.setFocus(true)
- return
- end if
-
- if isValid(m.homeRowsSourceTask)
- clearHomeRowsSourceTask()
- end if
-
- m.pendingPluginRowsSetting = settingItem
- m.pendingPluginRowsSource = sourceName
-
- m.homeRowsSourceTask = createObject("roSGNode", "HomeRowsSourceRowsTask")
- m.homeRowsSourceTask.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- m.homeRowsSourceTask.userId = chainLookupReturn(m.global, "session.user.id", "")
- m.homeRowsSourceTask.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- m.homeRowsSourceTask.source = sourceName
- m.homeRowsSourceTask.observeFieldScoped("rows", "onHomeRowsSourceRowsLoaded")
- m.homeRowsSourceTask.observeFieldScoped("errorMessage", "onHomeRowsSourceRowsError")
- m.homeRowsSourceTask.control = "RUN"
-end sub
sub onHomeRowsSourceRowsLoaded(event as object)
rows = event.getData()
@@ -440,8 +406,8 @@ sub showPluginRowsManagerDialog(settingItem as object, sourceName as string, row
return
end if
- settingKey = getPluginRowsManagerStorageKey(sourceName)
- savedRows = parsePluginRowsConfigValue(getUserSettingValue(settingKey, "[]"))
+ settingKey = ""
+ savedRows = parsePluginRowsConfigValue(getUserSettingValue("", "[]"))
savedMap = buildPluginRowsConfigMap(savedRows)
sortedRows = []
@@ -478,11 +444,6 @@ sub showPluginRowsManagerDialog(settingItem as object, sourceName as string, row
}
dialog.palette = dlgPalette
- if isStringEqual(normalizeHomeRowsSourceName(sourceName), "hss")
- dialog.title = tr("Manage HSS Rows")
- else
- dialog.title = tr("Manage KefinTweaks Rows")
- end if
dialog.message = [tr("Use Rewind/Fast-Forward to reorder rows. Press OK to toggle each row.")]
dialog.allowReorder = true
@@ -610,9 +571,6 @@ function getSettingCurrentValueLabel(settingItem as dynamic) as string
if not isValid(settingItem.type) then return ""
if not isValid(settingItem.settingName) then return ""
- if isPluginRowsManagerSetting(settingItem.settingName)
- return getPluginRowsManagerSummary(settingItem.settingName)
- end if
if isStringEqual(settingItem.settingName, "jellyseerr.accountSettings")
return GetJellyseerrAccountStatusLabel()
@@ -748,39 +706,11 @@ function getHomeSectionOrder() as object
end function
function normalizeHomeRowsSourceName(sourceValue as dynamic) as string
- source = LCase(dynamicToDisplayString(sourceValue))
-
- if isStringEqual(source, "kefin") or isStringEqual(source, "kefintweak") or isStringEqual(source, "kefintweaks")
- return "kefintweaks"
- end if
-
- return source
-end function
-
-function isPluginRowsManagerSetting(settingName as dynamic) as boolean
- if not isValid(settingName) then return false
-
- if isStringEqual(settingName, "homeRows.manageHssRows") then return true
- if isStringEqual(settingName, "homeRows.manageKtRows") then return true
- return false
+ return LCase(dynamicToDisplayString(sourceValue))
end function
-function getPluginRowsManagerSource(settingName as dynamic) as string
- if not isPluginRowsManagerSetting(settingName)
- return ""
- end if
- if isStringEqual(settingName, "homeRows.manageHssRows") then return "hss"
- return "kefintweaks"
-end function
-function getPluginRowsManagerStorageKey(sourceName as dynamic) as string
- source = normalizeHomeRowsSourceName(sourceName)
-
- if isStringEqual(source, "hss") then return HOME_ROWS_HSS_LOCAL_SETTING
- if isStringEqual(source, "kefintweaks") then return HOME_ROWS_KT_LOCAL_SETTING
- return ""
-end function
function parsePluginRowsConfigValue(value as dynamic) as object
if not isValid(value)
@@ -847,28 +777,6 @@ function buildPluginRowsConfigMap(configRows as object) as object
return configMap
end function
-function getPluginRowsManagerSummary(settingName as dynamic) as string
- sourceName = getPluginRowsManagerSource(settingName)
- settingKey = getPluginRowsManagerStorageKey(sourceName)
- if not isValidAndNotEmpty(settingKey)
- return tr("Configure")
- end if
-
- savedRows = parsePluginRowsConfigValue(getUserSettingValue(settingKey, "[]"))
- if savedRows.Count() = 0
- return tr("Configure")
- end if
-
- enabledCount = 0
- for each row in savedRows
- if normalizeBoolSettingValue(chainLookupReturn(row, "enabled", false))
- enabledCount++
- end if
- end for
-
- return enabledCount.ToStr() + "/" + savedRows.Count().ToStr() + " " + tr("enabled")
-end function
-
function buildHomeRowsV2Payload(rowOrder = invalid as dynamic) as object
rows = []
if not isValid(rowOrder)
@@ -1223,8 +1131,6 @@ sub onPluginPingComplete()
session.user.settings.Save("plugin.enabled", "false")
end if
- updateHssSettingGate()
- updateKtSettingGate()
if m.userLocation.Count() > 0
RefreshCurrentMenu()
end if
@@ -1891,21 +1797,6 @@ sub setUserBoolSetting(settingName as string, enabled as boolean, syncToServer =
end if
end sub
-function isHssPluginDetected() as boolean
- if not isValid(m.hssDetected)
- return true
- end if
-
- return m.hssDetected
-end function
-
-function isKtPluginDetected() as boolean
- if not isValid(m.ktDetected)
- return true
- end if
-
- return m.ktDetected
-end function
sub setSettingVisibilityByName(items as object, settingName as string, isVisible as boolean)
if not isValid(items)
@@ -1923,85 +1814,6 @@ sub setSettingVisibilityByName(items as object, settingName as string, isVisible
end for
end sub
-sub refreshHssPluginDetection()
- if isValid(m.hssProbeTask)
- m.hssProbeTask.unobserveField("result")
- m.hssProbeTask.control = "STOP"
- end if
-
- m.hssProbeTask = createObject("roSGNode", "HSSProbeTask")
- m.hssProbeTask.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- m.hssProbeTask.userId = chainLookupReturn(m.global, "session.user.id", "")
- m.hssProbeTask.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- m.hssProbeTask.observeField("result", "onHssPluginProbeComplete")
- m.hssProbeTask.control = "RUN"
-end sub
-
-sub onHssPluginProbeComplete()
- if not isValid(m.hssProbeTask) then return
-
- result = m.hssProbeTask.result
- m.hssProbeTask.unobserveField("result")
- m.hssProbeTask = invalid
-
- m.hssDetected = normalizeBoolSettingValue(chainLookupReturn(result, "enabled", false))
- updateHssSettingGate()
-
- if m.userLocation.Count() > 0
- RefreshCurrentMenu()
- end if
-end sub
-
-sub refreshKtPluginDetection()
- if isValid(m.ktProbeTask)
- m.ktProbeTask.unobserveField("result")
- m.ktProbeTask.control = "STOP"
- end if
-
- m.ktProbeTask = createObject("roSGNode", "KefinTweaksProbeTask")
- m.ktProbeTask.serverUrl = chainLookupReturn(m.global, "session.server.url", "")
- m.ktProbeTask.userId = chainLookupReturn(m.global, "session.user.id", "")
- m.ktProbeTask.authToken = chainLookupReturn(m.global, "session.user.authToken", "")
- m.ktProbeTask.observeField("result", "onKtPluginProbeComplete")
- m.ktProbeTask.control = "RUN"
-end sub
-
-sub onKtPluginProbeComplete()
- if not isValid(m.ktProbeTask) then return
-
- result = m.ktProbeTask.result
- m.ktProbeTask.unobserveField("result")
- m.ktProbeTask = invalid
-
- m.ktDetected = normalizeBoolSettingValue(chainLookupReturn(result, "enabled", false))
- updateKtSettingGate()
-
- if m.userLocation.Count() > 0
- RefreshCurrentMenu()
- end if
-end sub
-
-sub updateHssSettingGate()
- if not isValid(m.configTree)
- return
- end if
-
- pluginDetected = isHssPluginDetected()
- usingServerRows = shouldUseServerManagedHomeRows()
-
- setSettingVisibilityByName(m.configTree, "plugin.hss.enabled", pluginDetected and not usingServerRows)
-end sub
-
-sub updateKtSettingGate()
- if not isValid(m.configTree)
- return
- end if
-
- pluginDetected = isKtPluginDetected()
- usingServerRows = shouldUseServerManagedHomeRows()
-
- setSettingVisibilityByName(m.configTree, "plugin.kefintweaks.enabled", pluginDetected and not usingServerRows)
-end sub
function reorderSettingsForFlutter(configTree as object) as object
if not isValid(configTree) then return configTree
@@ -2027,8 +1839,6 @@ function reorderSettingsForFlutter(configTree as object) as object
enablePlugin = findSettingsChildByTitle(pluginRootSection, "Enable Plugin")
pluginSettingsSync = findSettingsChildByTitle(pluginRootSection, "Settings Sync")
- pluginHss = findSettingsChildByTitle(pluginRootSection, "Home Screen Sections")
- pluginKefinTweaks = findSettingsChildByTitle(pluginRootSection, "KefinTweaks")
mdblist = findSettingsChildByTitle(pluginRootSection, "MDBList Ratings")
tmdb = findSettingsChildByTitle(pluginRootSection, "TMDB")
jellyseerr = findSettingsChildByTitle(pluginRootSection, "Seerr")
@@ -2086,8 +1896,6 @@ function reorderSettingsForFlutter(configTree as object) as object
pluginChildren = []
pushSettingIfValid(pluginChildren, enablePlugin)
pushSettingIfValid(pluginChildren, pluginSettingsSync)
- pushSettingIfValid(pluginChildren, pluginHss)
- pushSettingIfValid(pluginChildren, pluginKefinTweaks)
integrationsChildren = []
if pluginChildren.count() > 0
@@ -2135,7 +1943,7 @@ function reorderSettingsForFlutter(configTree as object) as object
moonfinMappedTitles = ["Navigation Bar", "Home Screen", "Featured Media Bar", "Theme Music", "Shuffle", "Visual Effects", "Support Moonfin"]
pushUnmappedChildrenByTitle(additionalChildren, moonfinSettings, moonfinMappedTitles)
- pluginMappedTitles = ["Enable Plugin", "Settings Sync", "Home Screen Sections", "KefinTweaks", "MDBList Ratings", "TMDB", "Seerr", "Jellyseerr"]
+ pluginMappedTitles = ["Enable Plugin", "Settings Sync", "MDBList Ratings", "TMDB", "Seerr", "Jellyseerr"]
pushUnmappedChildrenByTitle(additionalChildren, pluginRootSection, pluginMappedTitles)
userInterfaceMappedTitles = ["Colors", "General", "Home Rows"]
@@ -2165,8 +1973,6 @@ function reorderSettingsForFlutter(configTree as object) as object
end function
sub LoadMenu(configSection, appendPath = true as boolean)
- updateHssSettingGate()
- updateKtSettingGate()
if configSection.children = invalid
' Load parent menu
@@ -2291,11 +2097,6 @@ sub settingSelected()
return
end if
- if isValid(selectedItem.settingName) and isPluginRowsManagerSetting(selectedItem.settingName)
- m.settingDesc.visible = false
- openPluginRowsManager(selectedItem)
- return
- end if
if selectedItem.type <> invalid
if isValid(selectedItem.Description)
@@ -2367,13 +2168,6 @@ sub settingSelected()
if Left(chainLookupReturn(selectedItem, "settingName", ""), 17) = "homeScreenSection"
filteredOptions = []
for each option in selectedItem.options
- optionId = chainLookupReturn(option, "id", "")
- if isStringEqual(optionId, "hss_all") and not isHssPluginDetected()
- continue for
- end if
- if isStringEqual(optionId, "kt_all") and not isKtPluginDetected()
- continue for
- end if
filteredOptions.push(option)
end for
radioOptions = filteredOptions
@@ -2436,23 +2230,6 @@ sub boolSettingChanged()
selectedSetting = getFocusedSetting()
if not isValid(selectedSetting) then return
- if selectedSetting.settingName = "plugin.hss.enabled" and m.boolSetting.checkedItem = 1 and not isHssPluginDetected()
- ShowToast("Home Screen Sections plugin was not detected on this server.", "error")
- setUserBoolSetting("plugin.hss.enabled", false)
- refreshCurrentItemValue(selectedSetting)
- hideEditingControls()
- m.settingsMenu.setFocus(true)
- return
- end if
-
- if selectedSetting.settingName = "plugin.kefintweaks.enabled" and m.boolSetting.checkedItem = 1 and not isKtPluginDetected()
- ShowToast("KefinTweaks plugin was not detected on this server.", "error")
- setUserBoolSetting("plugin.kefintweaks.enabled", false)
- refreshCurrentItemValue(selectedSetting)
- hideEditingControls()
- m.settingsMenu.setFocus(true)
- return
- end if
if m.boolSetting.checkedItem = 1
session.user.settings.Save(selectedSetting.settingName, "true")
@@ -2501,19 +2278,6 @@ sub boolSettingChanged()
hideEditingControls()
m.settingsMenu.setFocus(true)
- if selectedSetting.settingName = "plugin.enabled"
- refreshHssPluginDetection()
- refreshKtPluginDetection()
- if m.userLocation.Count() > 0
- RefreshCurrentMenu()
- end if
- else if selectedSetting.settingName = "homeRows.useServerConfig"
- updateHssSettingGate()
- updateKtSettingGate()
- if m.userLocation.Count() > 0
- RefreshCurrentMenu()
- end if
- end if
end sub
sub radioSettingChanged()
diff --git a/settings/settings.json b/settings/settings.json
index 51f328c5d..6eaa1861e 100644
--- a/settings/settings.json
+++ b/settings/settings.json
@@ -550,20 +550,6 @@
"type": "bool",
"default": "true"
},
- {
- "title": "Home Screen Sections",
- "description": "Show rows from the Home Screen Sections Jellyfin plugin.",
- "settingName": "plugin.hss.enabled",
- "type": "bool",
- "default": "false"
- },
- {
- "title": "KefinTweaks",
- "description": "Show rows from the KefinTweaks Jellyfin plugin.",
- "settingName": "plugin.kefintweaks.enabled",
- "type": "bool",
- "default": "false"
- },
{
"title": "MDBList Ratings",
"description": "Enable additional ratings from configured sources.",
@@ -1261,14 +1247,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1319,14 +1297,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1377,14 +1347,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1435,14 +1397,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1493,14 +1447,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1551,14 +1497,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1609,14 +1547,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1667,14 +1597,6 @@
{
"title": "Recently Released",
"id": "recentlyreleased"
- },
- {
- "title": "Home Screen Sections Plugin",
- "id": "hss_all"
- },
- {
- "title": "KefinTweaks Rows",
- "id": "kt_all"
}
]
},
@@ -1912,4 +1834,4 @@
}
]
}
-]
\ No newline at end of file
+]