diff --git a/components/config/ConfigList.brs b/components/config/ConfigList.brs index f2c4f49ce..4e015df0a 100644 --- a/components/config/ConfigList.brs +++ b/components/config/ConfigList.brs @@ -27,7 +27,7 @@ sub onItemSelected() i = m.top.itemSelected itemField = m.top.content.getchild(i) - show_dialog(itemField) + configListShowDialog(itemField) end sub function onDialogButton() @@ -46,7 +46,7 @@ function onDialogButton() end function -sub show_dialog(configField) +sub configListShowDialog(configField) dialog = createObject("roSGNode", "StandardKeyboardDialog") m.configField = configField dialog.title = configField.label diff --git a/components/home/HomeRows.brs b/components/home/HomeRows.brs index 4fce8fff5..68a4a9ecd 100644 --- a/components/home/HomeRows.brs +++ b/components/home/HomeRows.brs @@ -12,6 +12,10 @@ sub init() m.top.rowLabelOffset = [0, 20] m.top.showRowCounter = [true] + m.homeSectionIndexes = { + count: 0 + } + updateSize() m.top.setfocus(true) @@ -23,8 +27,8 @@ sub init() m.LoadLibrariesTask.observeField("content", "onLibrariesLoaded") ' set up tesk nodes for other rows - m.LoadContinueTask = createObject("roSGNode", "LoadItemsTask") - m.LoadContinueTask.itemsToLoad = "continue" + m.LoadContinueWatchingTask = createObject("roSGNode", "LoadItemsTask") + m.LoadContinueWatchingTask.itemsToLoad = "continue" m.LoadNextUpTask = createObject("roSGNode", "LoadItemsTask") m.LoadNextUpTask.itemsToLoad = "nextUp" @@ -61,73 +65,199 @@ sub onLibrariesLoaded() m.libraryData = m.LoadLibrariesTask.content m.LoadLibrariesTask.unobserveField("content") m.LoadLibrariesTask.content = [] - ' create My Media, Continue Watching, and Next Up rows + content = CreateObject("roSGNode", "ContentNode") + sizeArray = [] + loadedSections = 0 + + ' Add sections in order based on user settings + for i = 0 to 6 + sectionName = LCase(m.global.session.user.settings["homesection" + i.toStr()]) + sectionLoaded = addHomeSection(content, sizeArray, sectionName) + + ' Count how many sections with data are loaded + if sectionLoaded then loadedSections++ + + ' If 2 sections with data are loaded or we're at the end of the web client section data, consider the home view loaded + if loadedSections = 2 or i = 6 + if not m.global.app_loaded + m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring + m.global.app_loaded = true + end if + end if + end for + + ' Favorites isn't an option on Web settings, so we must manually add it for now + addHomeSection(content, sizeArray, "favorites") + + m.top.rowItemSize = sizeArray + m.top.content = content +end sub + +' Removes a home section from the home rows +sub removeHomeSection(sectionType as string) + sectionName = LCase(sectionType) + + removedSectionIndex = m.homeSectionIndexes[sectionName] + + if not isValid(removedSectionIndex) then return + + for each section in m.homeSectionIndexes + if m.homeSectionIndexes[section] > removedSectionIndex + m.homeSectionIndexes[section]-- + end if + end for + + m.homeSectionIndexes.Delete(sectionName) + m.homeSectionIndexes.AddReplace("count", m.homeSectionIndexes.count - 1) + + m.top.content.removeChildIndex(removedSectionIndex) +end sub + +' Adds a new home section to the home rows. +' Returns a boolean indicating whether the section was handled. +function addHomeSection(content as dynamic, sizeArray as dynamic, sectionName as string) as boolean + ' Poster size library items + if sectionName = "livetv" + createLiveTVRow(content, sizeArray) + return true + end if + + ' Poster size library items + if sectionName = "smalllibrarytiles" + createLibraryRow(content, sizeArray) + return true + end if + + ' Continue Watching items + if sectionName = "resume" + createContinueWatchingRow(content, sizeArray) + return true + end if + + ' Next Up items + if sectionName = "nextup" + createNextUpRow(content, sizeArray) + return true + end if + + ' Latest items in each library + if sectionName = "latestmedia" + createLatestInRows(content, sizeArray) + return true + end if + + ' Favorite Items + if sectionName = "favorites" + createFavoritesRow(content, sizeArray) + return true + end if + + return false +end function + +' Create a row displaying the user's libraries +sub createLibraryRow(content as dynamic, sizeArray as dynamic) + ' Ensure we have data + if not isValidAndNotEmpty(m.libraryData) then return mediaRow = content.CreateChild("HomeRow") mediaRow.title = tr("My Media") - continueRow = content.CreateChild("HomeRow") - continueRow.title = tr("Continue Watching") + m.homeSectionIndexes.AddReplace("library", m.homeSectionIndexes.count) + m.homeSectionIndexes.count++ - nextUpRow = content.CreateChild("HomeRow") - nextUpRow.title = tr("Next Up >") + sizeArray.push([464, 331]) - favoritesRow = content.CreateChild("HomeRow") - favoritesRow.title = tr("Favorites") + filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes) + for each item in filteredMedia + mediaRow.appendChild(item) + end for +end sub - sizeArray = [ - [464, 311], ' My Media - [464, 331], ' Continue Watching - [464, 331], ' Next Up - [464, 331] ' Favorites - ] - - haveLiveTV = false - - ' validate library data - if isValid(m.libraryData) and m.libraryData.count() > 0 - ' populate My Media row - filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes) - for each item in filteredMedia - mediaRow.appendChild(item) - end for +' Create a row displaying latest items in each of the user's libraries +sub createLatestInRows(content as dynamic, sizeArray as dynamic) + ' Ensure we have data + if not isValidAndNotEmpty(m.libraryData) then return - ' create a "Latest In" row for each library - filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes) - for each lib in filteredLatest - if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program" - latestInRow = content.CreateChild("HomeRow") - latestInRow.title = tr("Latest in") + " " + lib.name + " >" - sizeArray.Push([464, 331]) - else if lib.collectionType = "livetv" - ' If we have Live TV, add "On Now" - onNowRow = content.CreateChild("HomeRow") - onNowRow.title = tr("On Now") - sizeArray.Push([464, 331]) - haveLiveTV = true - end if - end for - end if + ' create a "Latest In" row for each library + filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes) + for each lib in filteredLatest + if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program" + latestInRow = content.CreateChild("HomeRow") + latestInRow.title = tr("Latest in") + " " + lib.name + " >" - m.top.rowItemSize = sizeArray - m.top.content = content + m.homeSectionIndexes.AddReplace("latestin" + LCase(lib.name).Replace(" ", ""), m.homeSectionIndexes.count) + m.homeSectionIndexes.count++ + sizeArray.Push([464, 331]) + + loadLatest = createObject("roSGNode", "LoadItemsTask") + loadLatest.itemsToLoad = "latest" + loadLatest.itemId = lib.id + + metadata = { "title": lib.name } + metadata.Append({ "contentType": lib.json.CollectionType }) + loadLatest.metadata = metadata + + loadLatest.observeField("content", "updateLatestItems") + loadLatest.control = "RUN" + end if + end for +end sub + +' Create a row displaying the live tv now on section +sub createLiveTVRow(content as dynamic, sizeArray as dynamic) + contentRow = content.CreateChild("HomeRow") + contentRow.title = tr("On Now") + m.homeSectionIndexes.AddReplace("livetv", m.homeSectionIndexes.count) + m.homeSectionIndexes.count++ + sizeArray.push([464, 331]) + + m.LoadOnNowTask.observeField("content", "updateOnNowItems") + m.LoadOnNowTask.control = "RUN" +end sub + +' Create a row displaying items the user can continue watching +sub createContinueWatchingRow(content as dynamic, sizeArray as dynamic) + continueWatchingRow = content.CreateChild("HomeRow") + continueWatchingRow.title = tr("Continue Watching") + m.homeSectionIndexes.AddReplace("resume", m.homeSectionIndexes.count) + m.homeSectionIndexes.count++ + sizeArray.push([464, 331]) ' Load the Continue Watching Data - m.LoadContinueTask.observeField("content", "updateContinueItems") - m.LoadContinueTask.control = "RUN" + m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems") + m.LoadContinueWatchingTask.control = "RUN" +end sub + +' Create a row displaying next episodes up to watch +sub createNextUpRow(content as dynamic, sizeArray as dynamic) + nextUpRow = content.CreateChild("HomeRow") + nextUpRow.title = tr("Next Up >") + m.homeSectionIndexes.AddReplace("nextup", m.homeSectionIndexes.count) + m.homeSectionIndexes.count++ + sizeArray.push([464, 331]) + + ' Load the Next Up Data + m.LoadNextUpTask.observeField("content", "updateNextUpItems") + m.LoadNextUpTask.control = "RUN" +end sub + +' Create a row displaying items from the user's favorites list +sub createFavoritesRow(content as dynamic, sizeArray as dynamic) + favoritesRow = content.CreateChild("HomeRow") + favoritesRow.title = tr("Favorites") + sizeArray.Push([464, 331]) + + m.homeSectionIndexes.AddReplace("favorites", m.homeSectionIndexes.count) + m.homeSectionIndexes.count++ ' Load the Favorites Data m.LoadFavoritesTask.observeField("content", "updateFavoritesItems") m.LoadFavoritesTask.control = "RUN" - - ' If we have Live TV access, load "On Now" data - if haveLiveTV - m.LoadOnNowTask.observeField("content", "updateOnNowItems") - m.LoadOnNowTask.control = "RUN" - end if end sub +' Update home row data sub updateHomeRows() if m.global.playstateTask.state = "run" m.global.playstateTask.observeField("state", "updateHomeRows") @@ -136,8 +266,43 @@ sub updateHomeRows() m.global.playstateTask.unobserveField("state") - m.LoadContinueTask.observeField("content", "updateContinueItems") - m.LoadContinueTask.control = "RUN" + ' If resume section exists, reload row's data + if m.homeSectionIndexes.doesExist("resume") + m.LoadContinueWatchingTask.observeField("content", "updateContinueWatchingItems") + m.LoadContinueWatchingTask.control = "RUN" + end if + + ' If next up section exists, reload row's data + if m.homeSectionIndexes.doesExist("nextup") + m.LoadNextUpTask.observeField("content", "updateNextUpItems") + m.LoadNextUpTask.control = "RUN" + end if + + ' If favorites section exists, reload row's data + if m.homeSectionIndexes.doesExist("favorites") + m.LoadFavoritesTask.observeField("content", "updateFavoritesItems") + m.LoadFavoritesTask.control = "RUN" + end if + + ' If live tv's on now section exists, reload row's data + if m.homeSectionIndexes.doesExist("livetv") + m.LoadOnNowTask.observeField("content", "updateOnNowItems") + m.LoadOnNowTask.control = "RUN" + end if + + ' If latest in library section exists, reload row's data + hasLatestHomeSection = false + + for each section in m.homeSectionIndexes + if LCase(Left(section, 6)) = "latest" + hasLatestHomeSection = true + exit for + end if + end for + + if hasLatestHomeSection + updateLatestInRows() + end if end sub sub updateFavoritesItems() @@ -147,20 +312,15 @@ sub updateFavoritesItems() if itemData = invalid then return - homeRows = m.top.content - rowIndex = getRowIndex("Favorites") + rowIndex = m.homeSectionIndexes.favorites if itemData.count() < 1 - if isValid(rowIndex) - ' remove the row - deleteFromSizeArray(rowIndex) - homeRows.removeChildIndex(rowIndex) - end if + removeHomeSection("favorites") + return else ' remake row using the new data row = CreateObject("roSGNode", "HomeRow") row.title = tr("Favorites") - itemSize = [464, 331] for each item in itemData usePoster = true @@ -174,60 +334,40 @@ sub updateFavoritesItems() row.appendChild(item) end for - if rowIndex = invalid - ' insert new row under "My Media" - updateSizeArray(itemSize, 1) - homeRows.insertChild(row, 1) - else - ' replace the old row - homeRows.replaceChild(row, rowIndex) - end if + ' replace the old row + m.top.content.replaceChild(row, rowIndex) + end if end sub -sub updateContinueItems() - itemData = m.LoadContinueTask.content - m.LoadContinueTask.unobserveField("content") - m.LoadContinueTask.content = [] +sub updateContinueWatchingItems() + itemData = m.LoadContinueWatchingTask.content + m.LoadContinueWatchingTask.unobserveField("content") + m.LoadContinueWatchingTask.content = [] if itemData = invalid then return - homeRows = m.top.content - continueRowIndex = getRowIndex("Continue Watching") - if itemData.count() < 1 - if isValid(continueRowIndex) - ' remove the row - deleteFromSizeArray(continueRowIndex) - homeRows.removeChildIndex(continueRowIndex) - end if - else - ' remake row using the new data - row = CreateObject("roSGNode", "HomeRow") - row.title = tr("Continue Watching") - itemSize = [464, 331] - for each item in itemData - if isValid(item.json) and isValid(item.json.UserData) and isValid(item.json.UserData.PlayedPercentage) - item.PlayedPercentage = item.json.UserData.PlayedPercentage - end if + removeHomeSection("resume") + return + end if - item.usePoster = row.usePoster - item.imageWidth = row.imageWidth - row.appendChild(item) - end for + ' remake row using the new data + row = CreateObject("roSGNode", "HomeRow") + row.title = tr("Continue Watching") - if continueRowIndex = invalid - ' insert new row under "My Media" - updateSizeArray(itemSize, 1) - homeRows.insertChild(row, 1) - else - ' replace the old row - homeRows.replaceChild(row, continueRowIndex) + for each item in itemData + if isValid(item.json) and isValid(item.json.UserData) and isValid(item.json.UserData.PlayedPercentage) + item.PlayedPercentage = item.json.UserData.PlayedPercentage end if - end if - m.LoadNextUpTask.observeField("content", "updateNextUpItems") - m.LoadNextUpTask.control = "RUN" + item.usePoster = row.usePoster + item.imageWidth = row.imageWidth + row.appendChild(item) + end for + + ' replace the old row + m.top.content.replaceChild(row, m.homeSectionIndexes.resume) end sub sub updateNextUpItems() @@ -237,53 +377,33 @@ sub updateNextUpItems() if itemData = invalid then return - homeRows = m.top.content - nextUpRowIndex = getRowIndex("Next Up >") - if itemData.count() < 1 - if isValid(nextUpRowIndex) - ' remove the row - deleteFromSizeArray(nextUpRowIndex) - homeRows.removeChildIndex(nextUpRowIndex) - end if + removeHomeSection("nextup") + return else ' remake row using the new data row = CreateObject("roSGNode", "HomeRow") row.title = tr("Next Up") + " >" - itemSize = [464, 331] for each item in itemData item.usePoster = row.usePoster item.imageWidth = row.imageWidth row.appendChild(item) end for - if nextUpRowIndex = invalid - ' insert new row under "Continue Watching" - continueRowIndex = getRowIndex("Continue Watching") - if isValid(continueRowIndex) - updateSizeArray(itemSize, continueRowIndex + 1) - homeRows.insertChild(row, continueRowIndex + 1) - else - ' insert it under My Media - updateSizeArray(itemSize, 1) - homeRows.insertChild(row, 1) - end if - else - ' replace the old row - homeRows.replaceChild(row, nextUpRowIndex) - end if + ' replace the old row + m.top.content.replaceChild(row, m.homeSectionIndexes.nextup) end if +end sub - ' consider home screen loaded when above rows are loaded - if m.global.app_loaded = false - m.top.signalBeacon("AppLaunchComplete") ' Roku Performance monitoring - m.global.app_loaded = true - end if +' Iterate over user's libraries and update data for each Latest In section +sub updateLatestInRows() + ' Ensure we have data + if not isValidAndNotEmpty(m.libraryData) then return - ' create task nodes for "Latest In" rows + ' Load new data for each library filteredLatest = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.LatestItemsExcludes) for each lib in filteredLatest - if lib.collectionType <> "livetv" and lib.collectionType <> "boxsets" and lib.json.CollectionType <> "Program" + if lib.collectionType <> "boxsets" and lib.collectionType <> "livetv" and lib.json.CollectionType <> "Program" loadLatest = createObject("roSGNode", "LoadItemsTask") loadLatest.itemsToLoad = "latest" loadLatest.itemId = lib.id @@ -296,7 +416,6 @@ sub updateNextUpItems() loadLatest.control = "RUN" end if end for - end sub sub updateLatestItems(msg) @@ -308,15 +427,13 @@ sub updateLatestItems(msg) if itemData = invalid then return - homeRows = m.top.content - rowIndex = getRowIndex(tr("Latest in") + " " + node.metadata.title + " >") + sectionName = "latestin" + LCase(node.metadata.title).Replace(" ", "") + + rowIndex = m.homeSectionIndexes[sectionName] if itemData.count() < 1 - ' remove row - if isValid(rowIndex) - deleteFromSizeArray(rowIndex) - homeRows.removeChildIndex(rowIndex) - end if + removeHomeSection(sectionName) + return else ' remake row using new data row = CreateObject("roSGNode", "HomeRow") @@ -340,15 +457,9 @@ sub updateLatestItems(msg) row.appendChild(item) end for - if rowIndex = invalid - ' append new row - updateSizeArray(itemSize) - homeRows.appendChild(row) - else - ' replace the old row - updateSizeArray(itemSize, rowIndex, "replace") - homeRows.replaceChild(row, rowIndex) - end if + ' replace the old row + updateSizeArray(itemSize, rowIndex, "replace") + m.top.content.replaceChild(row, rowIndex) end if end sub @@ -359,50 +470,25 @@ sub updateOnNowItems() if itemData = invalid then return - homeRows = m.top.content - onNowRowIndex = getRowIndex("On Now") - if itemData.count() < 1 - if isValid(onNowRowIndex) - ' remove the row - deleteFromSizeArray(onNowRowIndex) - homeRows.removeChildIndex(onNowRowIndex) - end if + removeHomeSection("livetv") + return else ' remake row using the new data row = CreateObject("roSGNode", "HomeRow") row.title = tr("On Now") - itemSize = [464, 331] for each item in itemData item.usePoster = row.usePoster item.imageWidth = row.imageWidth row.appendChild(item) end for - if onNowRowIndex = invalid - ' insert new row under "My Media" - updateSizeArray(itemSize, 1) - homeRows.insertChild(row, 1) - else - ' replace the old row - homeRows.replaceChild(row, onNowRowIndex) - end if + ' replace the old row + m.top.content.replaceChild(row, m.homeSectionIndexes.livetv) + end if end sub -function getRowIndex(rowTitle as string) - rowIndex = invalid - for i = 1 to m.top.content.getChildCount() - 1 - ' skip row 0 since it's always "My Media" - tmpRow = m.top.content.getChild(i) - if tmpRow.title = rowTitle - rowIndex = i - exit for - end if - end for - return rowIndex -end function - sub updateSizeArray(rowItemSize, rowIndex = invalid, action = "insert") sizeArray = m.top.rowItemSize ' append by default @@ -428,10 +514,6 @@ sub updateSizeArray(rowItemSize, rowIndex = invalid, action = "insert") m.top.rowItemSize = newSizeArray end sub -sub deleteFromSizeArray(rowIndex) - updateSizeArray([0, 0], rowIndex, "delete") -end sub - sub itemSelected() m.top.selectedItem = m.top.content.getChild(m.top.rowItemSelected[0]).getChild(m.top.rowItemSelected[1]) diff --git a/components/quickConnect/QuickConnectDialog.brs b/components/quickConnect/QuickConnectDialog.brs index c646b1463..defb80d91 100644 --- a/components/quickConnect/QuickConnectDialog.brs +++ b/components/quickConnect/QuickConnectDialog.brs @@ -34,7 +34,7 @@ sub OnAuthenticated() if authenticated <> invalid and authenticated = true currentUser = AboutMe() session.user.Login(currentUser) - LoadUserPreferences() + session.user.LoadUserPreferences() LoadUserAbilities() m.top.close = true m.top.authenticated = true diff --git a/source/ShowScenes.brs b/source/ShowScenes.brs index 48a1853db..055df3945 100644 --- a/source/ShowScenes.brs +++ b/source/ShowScenes.brs @@ -90,7 +90,7 @@ function LoginFlow() else print "Success! Auth token is still valid" session.user.Login(currentUser) - LoadUserPreferences() + session.user.LoadUserPreferences() LoadUserAbilities() return true end if @@ -103,7 +103,7 @@ function LoginFlow() if isValid(userData) print "login success!" session.user.Login(userData) - LoadUserPreferences() + session.user.LoadUserPreferences() LoadUserAbilities() return true else @@ -146,7 +146,7 @@ function LoginFlow() if isValid(userData) print "login success!" session.user.Login(userData) - LoadUserPreferences() + session.user.LoadUserPreferences() LoadUserAbilities() return true else @@ -172,7 +172,7 @@ function LoginFlow() goto start_login end if - LoadUserPreferences() + session.user.LoadUserPreferences() LoadUserAbilities() m.global.sceneManager.callFunc("clearScenes") diff --git a/source/api/userauth.brs b/source/api/userauth.brs index ce00984b9..33f32252e 100644 --- a/source/api/userauth.brs +++ b/source/api/userauth.brs @@ -1,5 +1,6 @@ ' needed for SignOut() and ServerInfo() import "pkg:/source/utils/session.bs" +import "pkg:/source/utils/misc.brs" function get_token(user as string, password as string) url = "Users/AuthenticateByName?format=json" @@ -109,22 +110,6 @@ function GetPublicUsers() return getJson(resp) end function -' Load and parse Display Settings from server -sub LoadUserPreferences() - id = m.global.session.user.id - ' Currently using client "emby", which is what website uses so we get same Display prefs as web. - ' May want to change to specific Roku display settings - url = Substitute("DisplayPreferences/usersettings?userId={0}&client=emby", id) - resp = APIRequest(url) - jsonResponse = getJson(resp) - - if jsonResponse <> invalid and jsonResponse.CustomPrefs <> invalid and jsonResponse.CustomPrefs["landing-livetv"] <> invalid - set_user_setting("display.livetv.landing", jsonResponse.CustomPrefs["landing-livetv"]) - else - unset_user_setting("display.livetv.landing") - end if -end sub - sub LoadUserAbilities() if m.global.session.user.Policy.EnableLiveTvManagement = true set_user_setting("livetv.canrecord", "true") diff --git a/source/utils/session.bs b/source/utils/session.bs index 01c5712da..9ec9e4df3 100644 --- a/source/utils/session.bs +++ b/source/utils/session.bs @@ -162,6 +162,59 @@ namespace session end if end sub + ' Load and parse Display Settings from server + sub LoadUserPreferences() + id = m.global.session.user.id + ' Currently using client "emby", which is what website uses so we get same Display prefs as web. + ' May want to change to specific Roku display settings + url = Substitute("DisplayPreferences/usersettings?userId={0}&client=emby", id) + resp = APIRequest(url) + jsonResponse = getJson(resp) + + if isValid(jsonResponse) and isValid(jsonResponse.CustomPrefs) + session.user.SaveUserHomeSections(jsonResponse.CustomPrefs) + + if isValid(jsonResponse.CustomPrefs["landing-livetv"]) + set_user_setting("display.livetv.landing", jsonResponse.CustomPrefs["landing-livetv"]) + else + unset_user_setting("display.livetv.landing") + end if + else + unset_user_setting("display.livetv.landing") + end if + end sub + + ' Saves user's web client home sections as Roku user settings. + ' Handles unsupported sections and ignores duplicates. + sub SaveUserHomeSections(customPrefs as object) + rowTypes = [] + + for i = 0 to 6 + homeSectionKey = "homesection" + i.toStr() + rowType = LCase(customPrefs[homeSectionKey]) + + ' Just in case we get invalid data + if not isValid(rowType) then rowType = "none" + + ' Small size library item buttons - Currently unsupported, use small library titles + if rowType = "librarybuttons" + rowType = "smalllibrarytiles" + end if + + ' None is the only section type allowed to have duplicates + ' For all other types, only accept the 1st entry + if inArray(rowTypes, rowType) + set_user_setting(homeSectionKey, "none") + else + set_user_setting(homeSectionKey, rowType) + + if rowType <> "none" + rowTypes.push(rowType) + end if + end if + end for + end sub + ' Empty the global user session array and reload defaults sub Logout() session.Update("user", {