Merge remote-tracking branch 'upstream/unstable' into update-device-profile
This commit is contained in:
commit
90ca547020
|
@ -7,7 +7,7 @@ end sub
|
|||
|
||||
sub getNextEpisodeTask()
|
||||
m.nextEpisodeData = api.shows.GetEpisodes(m.top.showID, {
|
||||
UserId: get_setting("active_user"),
|
||||
UserId: m.global.session.user.id,
|
||||
StartItemId: m.top.videoID,
|
||||
Limit: 2
|
||||
})
|
||||
|
|
|
@ -16,7 +16,7 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
|
|||
"DeviceProfile": getDeviceProfile()
|
||||
}
|
||||
params = {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"StartTimeTicks": currentItem.startingPoint,
|
||||
"IsPlayback": true,
|
||||
"AutoOpenLiveStream": true,
|
||||
|
@ -46,15 +46,15 @@ sub getPlaybackInfoTask()
|
|||
end if
|
||||
end sub
|
||||
|
||||
function GetTranscodingStats(session)
|
||||
function GetTranscodingStats(deviceSession)
|
||||
sessionStats = { data: [] }
|
||||
|
||||
if isValid(session.TranscodingInfo) and session.TranscodingInfo.Count() > 0
|
||||
transcodingReasons = session.TranscodingInfo.TranscodeReasons
|
||||
videoCodec = session.TranscodingInfo.VideoCodec
|
||||
audioCodec = session.TranscodingInfo.AudioCodec
|
||||
totalBitrate = session.TranscodingInfo.Bitrate
|
||||
audioChannels = session.TranscodingInfo.AudioChannels
|
||||
if isValid(deviceSession.TranscodingInfo) and deviceSession.TranscodingInfo.Count() > 0
|
||||
transcodingReasons = deviceSession.TranscodingInfo.TranscodeReasons
|
||||
videoCodec = deviceSession.TranscodingInfo.VideoCodec
|
||||
audioCodec = deviceSession.TranscodingInfo.AudioCodec
|
||||
totalBitrate = deviceSession.TranscodingInfo.Bitrate
|
||||
audioChannels = deviceSession.TranscodingInfo.AudioChannels
|
||||
|
||||
if isValid(transcodingReasons) and transcodingReasons.Count() > 0
|
||||
sessionStats.data.push("<header>" + tr("Transcoding Information") + "</header>")
|
||||
|
@ -65,7 +65,7 @@ function GetTranscodingStats(session)
|
|||
|
||||
if isValid(videoCodec)
|
||||
data = "<b>• " + tr("Video Codec") + ":</b> " + videoCodec
|
||||
if session.TranscodingInfo.IsVideoDirect
|
||||
if deviceSession.TranscodingInfo.IsVideoDirect
|
||||
data = data + " (" + tr("direct") + ")"
|
||||
end if
|
||||
sessionStats.data.push(data)
|
||||
|
@ -73,7 +73,7 @@ function GetTranscodingStats(session)
|
|||
|
||||
if isValid(audioCodec)
|
||||
data = "<b>• " + tr("Audio Codec") + ":</b> " + audioCodec
|
||||
if session.TranscodingInfo.IsAudioDirect
|
||||
if deviceSession.TranscodingInfo.IsAudioDirect
|
||||
data = data + " (" + tr("direct") + ")"
|
||||
end if
|
||||
sessionStats.data.push(data)
|
||||
|
|
|
@ -7,7 +7,7 @@ end sub
|
|||
|
||||
sub getShuffleEpisodesTask()
|
||||
data = api.shows.GetEpisodes(m.top.showID, {
|
||||
UserId: get_setting("active_user"),
|
||||
UserId: m.global.session.user.id,
|
||||
SortBy: "Random",
|
||||
Limit: 200
|
||||
})
|
||||
|
|
|
@ -18,7 +18,7 @@ sub init()
|
|||
|
||||
m.itemText.translation = [0, m.itemPoster.height + 7]
|
||||
|
||||
m.gridTitles = get_user_setting("itemgrid.gridTitles")
|
||||
m.gridTitles = m.global.session.user.settings["itemgrid.gridTitles"]
|
||||
m.itemText.visible = m.gridTitles = "showalways"
|
||||
|
||||
' Add some padding space when Item Titles are always showing
|
||||
|
@ -48,7 +48,7 @@ sub itemContentChanged()
|
|||
m.itemIcon.uri = itemData.iconUrl
|
||||
m.itemText.text = itemData.Title
|
||||
else if itemData.type = "Series"
|
||||
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
|
||||
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
|
||||
if isValid(itemData.json) and isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
|
||||
if itemData.json.UserData.UnplayedItemCount > 0
|
||||
m.unplayedCount.visible = true
|
||||
|
|
|
@ -8,7 +8,7 @@ sub init()
|
|||
m.log = log.Logger("ItemGrid")
|
||||
m.options = m.top.findNode("options")
|
||||
|
||||
m.showItemCount = get_user_setting("itemgrid.showItemCount") = "true"
|
||||
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
|
||||
|
||||
m.tvGuide = invalid
|
||||
m.channelFocused = invalid
|
||||
|
@ -71,7 +71,7 @@ sub init()
|
|||
m.AlphaSelected = m.top.findNode("AlphaSelected")
|
||||
|
||||
'Get reset folder setting
|
||||
m.resetGrid = get_user_setting("itemgrid.reset") = "true"
|
||||
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
|
||||
|
||||
m.micButton = m.top.findNode("micButton")
|
||||
m.micButtonText = m.top.findNode("micButtonText")
|
||||
|
@ -105,7 +105,7 @@ sub loadInitialItems()
|
|||
' Read view/sort/filter settings
|
||||
if m.top.parentItem.collectionType = "livetv"
|
||||
' Translate between app and server nomenclature
|
||||
viewSetting = get_user_setting("display.livetv.landing")
|
||||
viewSetting = m.global.session.user.settings["display.livetv.landing"]
|
||||
'Move mic to be visiable on TV Guide screen
|
||||
if m.global.device.hasVoiceRemote = true
|
||||
m.micButton.translation = "[1540, 92]"
|
||||
|
@ -119,19 +119,19 @@ sub loadInitialItems()
|
|||
else
|
||||
m.view = "livetv"
|
||||
end if
|
||||
m.sortField = get_user_setting("display.livetv.sortField")
|
||||
sortAscendingStr = get_user_setting("display.livetv.sortAscending")
|
||||
m.filter = get_user_setting("display.livetv.filter")
|
||||
m.sortField = m.global.session.user.settings["display.livetv.sortField"]
|
||||
sortAscendingStr = m.global.session.user.settings["display.livetv.sortAscending"]
|
||||
m.filter = m.global.session.user.settings["display.livetv.filter"]
|
||||
else if m.top.parentItem.collectionType = "music"
|
||||
m.view = get_user_setting("display.music.view")
|
||||
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
|
||||
sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
|
||||
m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
|
||||
m.view = m.global.session.user.settings["display.music.view"]
|
||||
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
|
||||
sortAscendingStr = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
|
||||
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
|
||||
else
|
||||
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
|
||||
sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
|
||||
m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
|
||||
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
|
||||
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
|
||||
sortAscendingStr = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
|
||||
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
|
||||
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
|
||||
end if
|
||||
|
||||
if m.sortField = invalid then m.sortField = "SortName"
|
||||
|
@ -183,7 +183,7 @@ sub loadInitialItems()
|
|||
m.loadItemsTask.itemType = "MusicArtist"
|
||||
m.loadItemsTask.itemId = m.top.parentItem.Id
|
||||
|
||||
m.view = get_user_setting("display.music.view")
|
||||
m.view = m.global.session.user.settings["display.music.view"]
|
||||
|
||||
if m.view = "music-album"
|
||||
m.loadItemsTask.itemType = "MusicAlbum"
|
||||
|
@ -194,7 +194,7 @@ sub loadInitialItems()
|
|||
' For LiveTV, we want to "Fit" the item images, not zoom
|
||||
m.top.imageDisplayMode = "scaleToFit"
|
||||
|
||||
if get_user_setting("display.livetv.landing") = "guide" and m.options.view <> "livetv"
|
||||
if m.global.session.user.settings["display.livetv.landing"] = "guide" and m.options.view <> "livetv"
|
||||
showTvGuide()
|
||||
end if
|
||||
else if m.top.parentItem.collectionType = "CollectionFolder" or m.top.parentItem.type = "CollectionFolder" or m.top.parentItem.collectionType = "boxsets" or m.top.parentItem.Type = "Boxset" or m.top.parentItem.Type = "Boxsets" or m.top.parentItem.Type = "Folder" or m.top.parentItem.Type = "Channel"
|
||||
|
@ -650,7 +650,7 @@ sub optionsClosed()
|
|||
reload = true
|
||||
end if
|
||||
else
|
||||
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
|
||||
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
|
||||
if m.options.view <> m.view
|
||||
'reload and store new view setting
|
||||
m.view = m.options.view
|
||||
|
|
|
@ -12,7 +12,7 @@ sub init()
|
|||
m.top.functionName = "loadItems"
|
||||
|
||||
m.top.limit = 60
|
||||
usersettingLimit = get_user_setting("itemgrid.Limit")
|
||||
usersettingLimit = m.global.session.user.settings["itemgrid.Limit"]
|
||||
|
||||
if usersettingLimit <> invalid
|
||||
m.top.limit = usersettingLimit
|
||||
|
@ -105,33 +105,33 @@ sub loadItems()
|
|||
|
||||
if m.top.ItemType = "LiveTV"
|
||||
url = "LiveTv/Channels"
|
||||
params.append({ UserId: get_setting("active_user") })
|
||||
params.append({ UserId: m.global.session.user.id })
|
||||
else if m.top.view = "Networks"
|
||||
url = "Studios"
|
||||
params.append({ UserId: get_setting("active_user") })
|
||||
params.append({ UserId: m.global.session.user.id })
|
||||
else if m.top.view = "Genres"
|
||||
url = "Genres"
|
||||
params.append({ UserId: get_setting("active_user"), includeItemTypes: m.top.itemType })
|
||||
params.append({ UserId: m.global.session.user.id, includeItemTypes: m.top.itemType })
|
||||
else if m.top.ItemType = "MusicArtist"
|
||||
url = "Artists"
|
||||
params.append({
|
||||
UserId: get_setting("active_user"),
|
||||
UserId: m.global.session.user.id,
|
||||
Fields: "Genres"
|
||||
})
|
||||
params.IncludeItemTypes = "MusicAlbum,Audio"
|
||||
else if m.top.ItemType = "AlbumArtists"
|
||||
url = "Artists/AlbumArtists"
|
||||
params.append({
|
||||
UserId: get_setting("active_user"),
|
||||
UserId: m.global.session.user.id,
|
||||
Fields: "Genres"
|
||||
})
|
||||
params.IncludeItemTypes = "MusicAlbum,Audio"
|
||||
else if m.top.ItemType = "MusicAlbum"
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
params.append({ ImageTypeLimit: 1 })
|
||||
params.append({ EnableImageTypes: "Primary,Backdrop,Banner,Thumb" })
|
||||
else
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
end if
|
||||
|
||||
resp = APIRequest(url, params)
|
||||
|
@ -168,7 +168,7 @@ sub loadItems()
|
|||
tmp = CreateObject("roSGNode", "ContentNode")
|
||||
tmp.title = item.name
|
||||
|
||||
genreData = api.users.GetItemsByQuery(get_setting("active_user"), {
|
||||
genreData = api.users.GetItemsByQuery(m.global.session.user.id, {
|
||||
SortBy: "Random",
|
||||
SortOrder: "Ascending",
|
||||
IncludeItemTypes: m.top.itemType,
|
||||
|
|
|
@ -152,8 +152,8 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
|
|||
' transcode is that the Encoding Level is not supported, then try to direct play but silently
|
||||
' fall back to the transcode if that fails.
|
||||
if m.playbackInfo.MediaSources[0].MediaStreams.Count() > 0 and meta.live = false
|
||||
tryDirectPlay = get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
|
||||
tryDirectPlay = tryDirectPlay or (get_user_setting("playback.tryDirect.hevcProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
|
||||
tryDirectPlay = m.global.session.user.settings["playback.tryDirect.h264ProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
|
||||
tryDirectPlay = tryDirectPlay or (m.global.session.user.settings["playback.tryDirect.hevcProfileLevel"] and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
|
||||
if tryDirectPlay and isValid(m.playbackInfo.MediaSources[0].TranscodingUrl) and forceTranscoding = false
|
||||
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
|
||||
|
@ -231,7 +231,7 @@ sub addSubtitlesToVideo(video, meta)
|
|||
safesubs = subtitles["all"]
|
||||
subtitleTracks = []
|
||||
|
||||
if get_user_setting("playback.subs.onlytext") = "true"
|
||||
if m.global.session.user.settings["playback.subs.onlytext"] = true
|
||||
safesubs = subtitles["text"]
|
||||
end if
|
||||
|
||||
|
@ -330,7 +330,7 @@ sub addNextEpisodesToQueue(showID)
|
|||
end if
|
||||
|
||||
url = Substitute("Shows/{0}/Episodes", showID)
|
||||
urlParams = { "UserId": get_setting("active_user") }
|
||||
urlParams = { "UserId": m.global.session.user.id }
|
||||
urlParams.Append({ "StartItemId": videoID })
|
||||
urlParams.Append({ "Limit": 50 })
|
||||
resp = APIRequest(url, urlParams)
|
||||
|
@ -347,7 +347,7 @@ end sub
|
|||
function sortSubtitles(id as string, MediaStreams)
|
||||
tracks = { "forced": [], "default": [], "normal": [], "text": [] }
|
||||
'Too many args for using substitute
|
||||
prefered_lang = m.user.Configuration.SubtitleLanguagePreference
|
||||
prefered_lang = m.global.session.user.configuration.SubtitleLanguagePreference
|
||||
for each stream in MediaStreams
|
||||
if stream.type = "Subtitle"
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ sub init()
|
|||
|
||||
m.overhang.isVisible = false
|
||||
|
||||
m.showItemCount = get_user_setting("itemgrid.showItemCount") = "true"
|
||||
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
|
||||
|
||||
m.swapAnimation.observeField("state", "swapDone")
|
||||
|
||||
|
@ -86,7 +86,7 @@ sub init()
|
|||
m.spinner.visible = true
|
||||
|
||||
'Get reset folder setting
|
||||
m.resetGrid = get_user_setting("itemgrid.reset") = "true"
|
||||
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
|
||||
|
||||
'Hide voice search if device does not have voice remote
|
||||
if m.global.device.hasVoiceRemote = false
|
||||
|
@ -129,15 +129,15 @@ sub loadInitialItems()
|
|||
SetBackground("")
|
||||
end if
|
||||
|
||||
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
|
||||
m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
|
||||
m.filterOptions = get_user_setting("display." + m.top.parentItem.Id + ".filterOptions")
|
||||
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
|
||||
sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
|
||||
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
|
||||
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
|
||||
m.filterOptions = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filterOptions"]
|
||||
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
|
||||
m.sortAscending = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
|
||||
|
||||
' If user has not set a preferred view for this folder, check if they've set a default view
|
||||
if not isValid(m.view)
|
||||
m.view = get_user_setting("itemgrid.movieDefaultView")
|
||||
m.view = m.global.session.user.settings["itemgrid.movieDefaultView"]
|
||||
end if
|
||||
|
||||
if not isValid(m.sortField) then m.sortField = "SortName"
|
||||
|
@ -147,12 +147,6 @@ sub loadInitialItems()
|
|||
|
||||
m.filterOptions = ParseJson(m.filterOptions)
|
||||
|
||||
if sortAscendingStr = invalid or sortAscendingStr = "true"
|
||||
m.sortAscending = true
|
||||
else
|
||||
m.sortAscending = false
|
||||
end if
|
||||
|
||||
if m.top.parentItem.json.type = "Studio"
|
||||
m.loadItemsTask.studioIds = m.top.parentItem.id
|
||||
m.loadItemsTask.itemId = m.top.parentItem.parentFolder
|
||||
|
@ -206,7 +200,7 @@ sub loadInitialItems()
|
|||
m.itemGrid.numRows = "3"
|
||||
m.selectedMovieOverview.visible = false
|
||||
m.infoGroup.visible = false
|
||||
m.top.showItemTitles = get_user_setting("itemgrid.gridTitles")
|
||||
m.top.showItemTitles = m.global.session.user.settings["itemgrid.gridTitles"]
|
||||
if LCase(m.top.showItemTitles) = "hidealways"
|
||||
m.itemGrid.itemSize = "[230, 315]"
|
||||
m.itemGrid.rowHeights = "[315]"
|
||||
|
@ -229,7 +223,7 @@ sub loadInitialItems()
|
|||
|
||||
m.getFiltersTask.observeField("filters", "FilterDataLoaded")
|
||||
m.getFiltersTask.params = {
|
||||
userid: get_setting("active_user"),
|
||||
userid: m.global.session.user.id,
|
||||
parentid: m.top.parentItem.Id,
|
||||
includeitemtypes: "Movie"
|
||||
}
|
||||
|
@ -794,7 +788,7 @@ sub optionsClosed()
|
|||
set_user_setting("display." + m.top.parentItem.Id + ".filterOptions", FormatJson(m.options.filterOptions))
|
||||
end if
|
||||
|
||||
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
|
||||
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
|
||||
|
||||
if m.options.view <> m.view
|
||||
m.view = m.options.view
|
||||
|
|
|
@ -18,7 +18,7 @@ sub init()
|
|||
m.itemPoster.loadDisplayMode = m.topParent.imageDisplayMode
|
||||
end if
|
||||
|
||||
m.gridTitles = get_user_setting("itemgrid.gridTitles")
|
||||
m.gridTitles = m.global.session.user.settings["itemgrid.gridTitles"]
|
||||
m.posterText.visible = false
|
||||
m.postTextBackground.visible = false
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ sub init()
|
|||
|
||||
m.overhang.isVisible = false
|
||||
|
||||
m.showItemCount = get_user_setting("itemgrid.showItemCount") = "true"
|
||||
m.showItemCount = m.global.session.user.settings["itemgrid.showItemCount"]
|
||||
|
||||
m.swapAnimation.observeField("state", "swapDone")
|
||||
|
||||
|
@ -80,7 +80,7 @@ sub init()
|
|||
m.spinner.visible = true
|
||||
|
||||
'Get reset folder setting
|
||||
m.resetGrid = get_user_setting("itemgrid.reset") = "true"
|
||||
m.resetGrid = m.global.session.user.settings["itemgrid.reset"]
|
||||
|
||||
'Hide voice search if device does not have voice remote
|
||||
if m.global.device.hasVoiceRemote = false
|
||||
|
@ -123,22 +123,16 @@ sub loadInitialItems()
|
|||
SetBackground("")
|
||||
end if
|
||||
|
||||
m.sortField = get_user_setting("display." + m.top.parentItem.Id + ".sortField")
|
||||
sortAscendingStr = get_user_setting("display." + m.top.parentItem.Id + ".sortAscending")
|
||||
m.filter = get_user_setting("display." + m.top.parentItem.Id + ".filter")
|
||||
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
|
||||
m.sortField = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortField"]
|
||||
m.sortAscending = m.global.session.user.settings["display." + m.top.parentItem.Id + ".sortAscending"]
|
||||
m.filter = m.global.session.user.settings["display." + m.top.parentItem.Id + ".filter"]
|
||||
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
|
||||
|
||||
if not isValid(m.sortField) then m.sortField = "SortName"
|
||||
if not isValid(m.filter) then m.filter = "All"
|
||||
if not isValid(m.view) then m.view = "ArtistsPresentation"
|
||||
|
||||
if sortAscendingStr = invalid or LCase(sortAscendingStr) = "true"
|
||||
m.sortAscending = true
|
||||
else
|
||||
m.sortAscending = false
|
||||
end if
|
||||
|
||||
m.top.showItemTitles = get_user_setting("itemgrid.gridTitles")
|
||||
m.top.showItemTitles = m.global.session.user.settings["itemgrid.gridTitles"]
|
||||
|
||||
if LCase(m.top.parentItem.json.type) = "musicgenre"
|
||||
m.itemGrid.translation = "[96, 60]"
|
||||
|
@ -660,7 +654,7 @@ sub optionsClosed()
|
|||
set_user_setting("display." + m.top.parentItem.Id + ".filter", m.options.filter)
|
||||
end if
|
||||
|
||||
m.view = get_user_setting("display." + m.top.parentItem.Id + ".landing")
|
||||
m.view = m.global.session.user.settings["display." + m.top.parentItem.Id + ".landing"]
|
||||
|
||||
if m.options.view <> m.view
|
||||
m.view = m.options.view
|
||||
|
|
|
@ -18,7 +18,7 @@ sub init()
|
|||
m.slideDownAnimation = m.top.findNode("slideDown")
|
||||
m.slideUpAnimation = m.top.findNode("slideUp")
|
||||
' show clock based on user setting
|
||||
m.hideClock = get_user_setting("ui.design.hideclock") = "true"
|
||||
m.hideClock = m.global.session.user.settings["ui.design.hideclock"]
|
||||
if not m.hideClock
|
||||
' save node references
|
||||
m.overlayHours = m.top.findNode("overlayHours")
|
||||
|
|
|
@ -13,7 +13,7 @@ sub init()
|
|||
m.top.transcodeReasons = []
|
||||
m.bufferCheckTimer.duration = 30
|
||||
|
||||
if get_user_setting("ui.design.hideclock") = "true"
|
||||
if m.global.session.user.settings["ui.design.hideclock"] = true
|
||||
clockNode = findNodeBySubtype(m.top, "clock")
|
||||
if clockNode[0] <> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
|
||||
end if
|
||||
|
@ -22,12 +22,7 @@ sub init()
|
|||
m.nextEpisodeButton = m.top.findNode("nextEpisode")
|
||||
m.nextEpisodeButton.text = tr("Next Episode")
|
||||
m.nextEpisodeButton.setFocus(false)
|
||||
m.nextupbuttonseconds = get_user_setting("playback.nextupbuttonseconds", "30")
|
||||
if isValid(m.nextupbuttonseconds)
|
||||
m.nextupbuttonseconds = val(m.nextupbuttonseconds)
|
||||
else
|
||||
m.nextupbuttonseconds = 30
|
||||
end if
|
||||
m.nextupbuttonseconds = m.global.session.user.settings["playback.nextupbuttonseconds"]
|
||||
|
||||
m.showNextEpisodeButtonAnimation = m.top.findNode("showNextEpisodeButton")
|
||||
m.hideNextEpisodeButtonAnimation = m.top.findNode("hideNextEpisodeButton")
|
||||
|
@ -49,7 +44,7 @@ sub onAllowCaptionsChange()
|
|||
m.captionTask.observeField("useThis", "checkCaptionMode")
|
||||
m.top.observeField("currentSubtitleTrack", "loadCaption")
|
||||
m.top.observeField("globalCaptionMode", "toggleCaption")
|
||||
if get_user_setting("playback.subs.custom") = "false"
|
||||
if m.global.session.user.settings["playback.subs.custom"] = false
|
||||
m.top.suppressCaptions = false
|
||||
else
|
||||
m.top.suppressCaptions = true
|
||||
|
@ -95,7 +90,7 @@ end sub
|
|||
'
|
||||
' Runs Next Episode button animation and sets focus to button
|
||||
sub showNextEpisodeButton()
|
||||
if m.global.userConfig.EnableNextEpisodeAutoPlay and not m.nextEpisodeButton.visible
|
||||
if m.global.session.user.configuration.EnableNextEpisodeAutoPlay and not m.nextEpisodeButton.visible
|
||||
m.showNextEpisodeButtonAnimation.control = "start"
|
||||
m.nextEpisodeButton.setFocus(true)
|
||||
m.nextEpisodeButton.visible = true
|
||||
|
|
|
@ -56,7 +56,7 @@ sub itemContentChanged() as void
|
|||
itemData = m.top.itemContent
|
||||
m.title.text = itemData.title
|
||||
|
||||
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
|
||||
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
|
||||
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
|
||||
if itemData.json.UserData.UnplayedItemCount > 0
|
||||
m.unplayedCount.visible = true
|
||||
|
@ -80,7 +80,7 @@ sub itemContentChanged() as void
|
|||
|
||||
imageUrl = itemData.posterURL
|
||||
|
||||
if get_user_setting("ui.tvshows.blurunwatched") = "true"
|
||||
if m.global.session.user.settings["ui.tvshows.blurunwatched"] = true
|
||||
if itemData.json.lookup("Type") = "Episode" and isValid(itemData.json.userdata)
|
||||
if not itemData.json.userdata.played
|
||||
imageUrl = imageUrl + "&blur=15"
|
||||
|
|
|
@ -32,7 +32,7 @@ sub saveToRegistry()
|
|||
users.push({
|
||||
id: m.top.id,
|
||||
username: m.top.username,
|
||||
server: get_setting("server")
|
||||
server: m.global.session.server.url
|
||||
})
|
||||
set_setting("available_users", formatJson(users))
|
||||
end if
|
||||
|
@ -48,8 +48,8 @@ sub removeFromRegistry()
|
|||
set_setting("available_users", formatJson(new_users))
|
||||
end sub
|
||||
|
||||
function getPreference(key as string, default as string)
|
||||
return get_user_setting("pref-" + key, default)
|
||||
function getPreference(key as string)
|
||||
return get_user_setting("pref-" + key)
|
||||
end function
|
||||
|
||||
function setPreference(key as string, value as string)
|
||||
|
|
|
@ -5,7 +5,7 @@ import "pkg:/source/utils/misc.brs"
|
|||
sub init()
|
||||
m.top.overhangTitle = "Home"
|
||||
m.top.optionsAvailable = true
|
||||
if get_user_setting("ui.home.splashBackground") = "true"
|
||||
if m.global.session.user.settings["ui.home.splashBackground"] = true
|
||||
m.backdrop = m.top.findNode("backdrop")
|
||||
m.backdrop.uri = buildURL("/Branding/Splashscreen?format=jpg&foregroundLayer=0.15&fillWidth=1280&width=1280&fillHeight=720&height=720&tag=splash")
|
||||
end if
|
||||
|
|
|
@ -50,7 +50,7 @@ sub itemContentChanged()
|
|||
m.playedIndicator.visible = false
|
||||
|
||||
if LCase(itemData.type) = "series"
|
||||
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
|
||||
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
|
||||
if isValid(itemData.json.UserData) and isValid(itemData.json.UserData.UnplayedItemCount)
|
||||
if itemData.json.UserData.UnplayedItemCount > 0
|
||||
m.unplayedCount.visible = true
|
||||
|
|
|
@ -87,16 +87,14 @@ sub onLibrariesLoaded()
|
|||
|
||||
' validate library data
|
||||
if isValid(m.libraryData) and m.libraryData.count() > 0
|
||||
userConfig = m.global.userConfig
|
||||
|
||||
' populate My Media row
|
||||
filteredMedia = filterNodeArray(m.libraryData, "id", userConfig.MyMediaExcludes)
|
||||
filteredMedia = filterNodeArray(m.libraryData, "id", m.global.session.user.configuration.MyMediaExcludes)
|
||||
for each item in filteredMedia
|
||||
mediaRow.appendChild(item)
|
||||
end for
|
||||
|
||||
' create a "Latest In" row for each library
|
||||
filteredLatest = filterNodeArray(m.libraryData, "id", userConfig.LatestItemsExcludes)
|
||||
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")
|
||||
|
@ -283,8 +281,7 @@ sub updateNextUpItems()
|
|||
end if
|
||||
|
||||
' create task nodes for "Latest In" rows
|
||||
userConfig = m.global.userConfig
|
||||
filteredLatest = filterNodeArray(m.libraryData, "id", userConfig.LatestItemsExcludes)
|
||||
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"
|
||||
loadLatest = createObject("roSGNode", "LoadItemsTask")
|
||||
|
|
|
@ -17,7 +17,7 @@ sub loadItems()
|
|||
' Load Libraries
|
||||
if m.top.itemsToLoad = "libraries"
|
||||
|
||||
url = Substitute("Users/{0}/Views/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Views/", m.global.session.user.id)
|
||||
resp = APIRequest(url)
|
||||
data = getJson(resp)
|
||||
if isValid(data) and isValid(data.Items)
|
||||
|
@ -33,7 +33,7 @@ sub loadItems()
|
|||
|
||||
' Load Latest Additions to Libraries
|
||||
else if m.top.itemsToLoad = "latest"
|
||||
activeUser = get_setting("active_user")
|
||||
activeUser = m.global.session.user.id
|
||||
if isValid(activeUser)
|
||||
url = Substitute("Users/{0}/Items/Latest", activeUser)
|
||||
params = {}
|
||||
|
@ -67,15 +67,14 @@ sub loadItems()
|
|||
params["SortBy"] = "DatePlayed"
|
||||
params["SortOrder"] = "Descending"
|
||||
params["ImageTypeLimit"] = 1
|
||||
params["UserId"] = get_setting("active_user")
|
||||
params["UserId"] = m.global.session.user.id
|
||||
params["EnableRewatching"] = false
|
||||
params["DisableFirstEpisode"] = false
|
||||
params["limit"] = 24
|
||||
params["EnableTotalRecordCount"] = false
|
||||
|
||||
maxDaysInNextUp = get_user_setting("ui.details.maxdaysnextup", "365")
|
||||
maxDaysInNextUp = m.global.session.user.settings["ui.details.maxdaysnextup"]
|
||||
if isValid(maxDaysInNextUp)
|
||||
maxDaysInNextUp = Val(maxDaysInNextUp)
|
||||
if maxDaysInNextUp > 0
|
||||
dateToday = CreateObject("roDateTime")
|
||||
dateCutoff = CreateObject("roDateTime")
|
||||
|
@ -97,7 +96,7 @@ sub loadItems()
|
|||
end if
|
||||
' Load Continue Watching
|
||||
else if m.top.itemsToLoad = "continue"
|
||||
activeUser = get_setting("active_user")
|
||||
activeUser = m.global.session.user.id
|
||||
if isValid(activeUser)
|
||||
url = Substitute("Users/{0}/Items/Resume", activeUser)
|
||||
|
||||
|
@ -124,7 +123,7 @@ sub loadItems()
|
|||
|
||||
else if m.top.itemsToLoad = "favorites"
|
||||
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id)
|
||||
|
||||
params = {}
|
||||
params["Filters"] = "IsFavorite"
|
||||
|
@ -155,7 +154,7 @@ sub loadItems()
|
|||
else if m.top.itemsToLoad = "onNow"
|
||||
url = "LiveTv/Programs/Recommended"
|
||||
params = {}
|
||||
params["userId"] = get_setting("active_user")
|
||||
params["userId"] = m.global.session.user.id
|
||||
params["isAiring"] = true
|
||||
params["limit"] = 16 ' 16 to be consistent with "Latest In"
|
||||
params["imageTypeLimit"] = 1
|
||||
|
@ -190,7 +189,7 @@ sub loadItems()
|
|||
end for
|
||||
else if m.top.itemsToLoad = "specialfeatures"
|
||||
params = {}
|
||||
url = Substitute("Users/{0}/Items/{1}/SpecialFeatures", get_setting("active_user"), m.top.itemId)
|
||||
url = Substitute("Users/{0}/Items/{1}/SpecialFeatures", m.global.session.user.id, m.top.itemId)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
if data <> invalid and data.count() > 0
|
||||
|
@ -220,7 +219,7 @@ sub loadItems()
|
|||
end for
|
||||
end if
|
||||
else if m.top.itemsToLoad = "likethis"
|
||||
params = { "userId": get_setting("active_user"), "limit": 16 }
|
||||
params = { "userId": m.global.session.user.id, "limit": 16 }
|
||||
url = Substitute("Items/{0}/Similar", m.top.itemId)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
|
@ -252,7 +251,7 @@ end sub
|
|||
|
||||
sub getPersonVideos(videoType, dest, dimens)
|
||||
params = { personIds: m.top.itemId, recursive: true, includeItemTypes: videoType, Limit: 50, SortBy: "Random" }
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
if data <> invalid and data.count() > 0
|
||||
|
|
|
@ -22,7 +22,7 @@ sub loadChannels()
|
|||
SortBy: sort_field,
|
||||
SortOrder: sort_order,
|
||||
recursive: m.top.recursive,
|
||||
UserId: get_setting("active_user")
|
||||
UserId: m.global.session.user.id
|
||||
}
|
||||
|
||||
' Handle special case when getting names starting with numeral
|
||||
|
@ -43,7 +43,7 @@ sub loadChannels()
|
|||
params.append({ isFavorite: true })
|
||||
end if
|
||||
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
|
|
|
@ -12,7 +12,7 @@ sub loadProgramDetails()
|
|||
programIndex = m.top.ProgramIndex
|
||||
|
||||
params = {
|
||||
UserId: get_setting("active_user")
|
||||
UserId: m.global.session.user.id
|
||||
}
|
||||
|
||||
url = Substitute("LiveTv/Programs/{0}", m.top.programId)
|
||||
|
|
|
@ -10,7 +10,7 @@ sub loadSchedule()
|
|||
results = []
|
||||
|
||||
params = {
|
||||
UserId: get_setting("active_user"),
|
||||
UserId: m.global.session.user.id,
|
||||
SortBy: "startDate",
|
||||
EnableImages: false,
|
||||
EnableTotalRecordCount: false,
|
||||
|
|
|
@ -91,7 +91,7 @@ sub setupLabels()
|
|||
m.recordSeriesOutline.width = recordSeriesButtonBackground.width
|
||||
m.recordSeriesOutline.height = recordSeriesButtonBackground.height
|
||||
|
||||
m.userCanRecord = get_user_setting("livetv.canrecord")
|
||||
m.userCanRecord = m.global.session.user.settings["livetv.canrecord"]
|
||||
if m.userCanRecord = "false"
|
||||
m.recordButton.visible = false
|
||||
m.recordSeriesButton.visible = false
|
||||
|
|
|
@ -12,7 +12,7 @@ sub init()
|
|||
m.originalQueue = []
|
||||
m.queueTypes = []
|
||||
' Preroll videos only play if user has cinema mode setting enabled
|
||||
m.isPrerollActive = (get_user_setting("playback.cinemamode") = "true")
|
||||
m.isPrerollActive = m.global.session.user.settings["playback.cinemamode"]
|
||||
m.position = 0
|
||||
m.shuffleEnabled = false
|
||||
end sub
|
||||
|
@ -21,7 +21,7 @@ end sub
|
|||
sub clear()
|
||||
m.queue = []
|
||||
m.queueTypes = []
|
||||
m.isPrerollActive = (get_user_setting("playback.cinemamode") = "true")
|
||||
m.isPrerollActive = m.global.session.user.settings["playback.cinemamode"]
|
||||
setPosition(0)
|
||||
end sub
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ sub itemContentChanged()
|
|||
|
||||
if type(itemData.RunTimeTicks) = "LongInteger"
|
||||
setFieldText("runtime", stri(getRuntime()) + " mins")
|
||||
if get_user_setting("ui.design.hideclock") <> "true"
|
||||
if m.global.session.user.settings["ui.design.hideclock"] <> true
|
||||
setFieldText("ends-at", tr("Ends at %1").Replace("%1", getEndTime()))
|
||||
end if
|
||||
end if
|
||||
|
@ -120,7 +120,7 @@ sub itemContentChanged()
|
|||
m.top.findNode("details").removeChild(m.top.findNode("director"))
|
||||
end if
|
||||
|
||||
if get_user_setting("ui.details.hidetagline") = "false"
|
||||
if m.global.session.user.settings["ui.details.hidetagline"] = false
|
||||
if itemData.taglines.count() > 0
|
||||
setFieldText("tagline", itemData.taglines[0])
|
||||
end if
|
||||
|
|
|
@ -10,8 +10,8 @@ sub init()
|
|||
m.textBackground = m.top.findNode("background")
|
||||
m.statusTimer = m.top.findNode("statusTimer")
|
||||
m.statusTimer.observeField("fire", "statusUpdate")
|
||||
m.slideshow = get_user_setting("photos.slideshow")
|
||||
m.random = get_user_setting("photos.random")
|
||||
m.slideshow = m.global.session.user.settings["photos.slideshow"]
|
||||
m.random = m.global.session.user.settings["photos.random"]
|
||||
|
||||
m.showStatusAnimation = m.top.findNode("showStatusAnimation")
|
||||
m.hideStatusAnimation = m.top.findNode("hideStatusAnimation")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import "pkg:/source/api/userauth.brs"
|
||||
import "pkg:/source/api/baserequest.brs"
|
||||
import "pkg:/source/utils/config.brs"
|
||||
import "pkg:/source/utils/session.bs"
|
||||
|
||||
sub init()
|
||||
m.quickConnectTimer = m.top.findNode("quickConnectTimer")
|
||||
|
@ -31,9 +32,10 @@ sub OnAuthenticated()
|
|||
' We've been given the go ahead, try to authenticate via Quick Connect...
|
||||
authenticated = AuthenticateViaQuickConnect(m.top.quickConnectJson.secret)
|
||||
if authenticated <> invalid and authenticated = true
|
||||
m.user = AboutMe()
|
||||
currentUser = AboutMe()
|
||||
session.user.Login(currentUser)
|
||||
LoadUserPreferences()
|
||||
LoadUserAbilities(m.user)
|
||||
LoadUserAbilities()
|
||||
m.top.close = true
|
||||
m.top.authenticated = true
|
||||
else
|
||||
|
|
|
@ -95,20 +95,20 @@ sub settingFocused()
|
|||
|
||||
m.boolSetting.visible = true
|
||||
|
||||
if get_user_setting(selectedSetting.settingName) = "true"
|
||||
if m.global.session.user.settings[selectedSetting.settingName] = true
|
||||
m.boolSetting.checkedItem = 1
|
||||
else
|
||||
m.boolSetting.checkedItem = 0
|
||||
end if
|
||||
else if selectedSetting.type = "integer"
|
||||
integerValue = get_user_setting(selectedSetting.settingName, selectedSetting.default)
|
||||
integerValue = m.global.session.user.settings[selectedSetting.settingName].ToStr()
|
||||
if isValid(integerValue)
|
||||
m.integerSetting.text = integerValue
|
||||
end if
|
||||
m.integerSetting.visible = true
|
||||
else if LCase(selectedSetting.type) = "radio"
|
||||
|
||||
selectedValue = get_user_setting(selectedSetting.settingName, selectedSetting.default)
|
||||
selectedValue = m.global.session.user.settings[selectedSetting.settingName]
|
||||
|
||||
radioContent = CreateObject("roSGNode", "ContentNode")
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ sub setSeasonLoading()
|
|||
end sub
|
||||
|
||||
sub updateSeason()
|
||||
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
|
||||
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
|
||||
if isValid(m.top.seasonData) and isValid(m.top.seasonData.UserData) and isValid(m.top.seasonData.UserData.UnplayedItemCount)
|
||||
if m.top.seasonData.UserData.UnplayedItemCount > 0
|
||||
m.unplayedCount.visible = true
|
||||
|
|
|
@ -36,7 +36,7 @@ sub itemContentChanged()
|
|||
|
||||
imageUrl = item.posterURL
|
||||
|
||||
if get_user_setting("ui.tvshows.blurunwatched") = "true"
|
||||
if m.global.session.user.settings["ui.tvshows.blurunwatched"] = true
|
||||
if itemData.lookup("Type") = "Episode"
|
||||
if not itemData.userdata.played
|
||||
imageUrl = imageUrl + "&blur=15"
|
||||
|
@ -54,12 +54,12 @@ sub itemContentChanged()
|
|||
m.top.findNode("runtime").text = stri(runTime).trim() + " mins"
|
||||
end if
|
||||
|
||||
if get_user_setting("ui.design.hideclock") <> "true"
|
||||
if m.global.session.user.settings["ui.design.hideclock"] <> true
|
||||
m.top.findNode("endtime").text = tr("Ends at %1").Replace("%1", getEndTime())
|
||||
end if
|
||||
end if
|
||||
|
||||
if get_user_setting("ui.tvshows.disableCommunityRating") = "false"
|
||||
if m.global.session.user.settings["ui.tvshows.disableCommunityRating"] = false
|
||||
if isValid(itemData.communityRating)
|
||||
m.top.findNode("star").visible = true
|
||||
m.top.findNode("communityRating").text = str(int(itemData.communityRating * 10) / 10)
|
||||
|
|
|
@ -19,7 +19,7 @@ sub itemContentChanged()
|
|||
item = m.top.itemContent
|
||||
itemData = item.json
|
||||
|
||||
if get_user_setting("ui.tvshows.disableUnwatchedEpisodeCount", "false") = "false"
|
||||
if m.global.session.user.settings["ui.tvshows.disableUnwatchedEpisodeCount"] = false
|
||||
if isValid(itemData.UserData) and isValid(itemData.UserData.UnplayedItemCount)
|
||||
if itemData.UserData.UnplayedItemCount > 0
|
||||
m.unplayedCount.visible = true
|
||||
|
|
|
@ -29,7 +29,7 @@ sub init()
|
|||
m.top.transcodeReasons = []
|
||||
m.bufferCheckTimer.duration = 30
|
||||
|
||||
if get_user_setting("ui.design.hideclock") = "true"
|
||||
if m.global.session.user.settings["ui.design.hideclock"] = true
|
||||
clockNode = findNodeBySubtype(m.top, "clock")
|
||||
if clockNode[0] <> invalid then clockNode[0].parent.removeChild(clockNode[0].node)
|
||||
end if
|
||||
|
@ -152,7 +152,7 @@ end sub
|
|||
'
|
||||
' Runs Next Episode button animation and sets focus to button
|
||||
sub showNextEpisodeButton()
|
||||
if m.global.userConfig.EnableNextEpisodeAutoPlay and not m.nextEpisodeButton.visible
|
||||
if m.global.session.user.configuration.EnableNextEpisodeAutoPlay and not m.nextEpisodeButton.visible
|
||||
m.showNextEpisodeButtonAnimation.control = "start"
|
||||
m.nextEpisodeButton.setFocus(true)
|
||||
m.nextEpisodeButton.visible = true
|
||||
|
|
|
@ -6365,5 +6365,18 @@
|
|||
<translation>Sélectionnez un serveur disponible sur votre réseau local:</translation>
|
||||
<extracomment>Instructions on initial app launch when the user is asked to pick a server from a list</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cinema Mode</source>
|
||||
<translation>Mode cinéma</translation>
|
||||
<extracomment>Settings Menu - Title for option</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Playback Information</source>
|
||||
<translation>Informations de lecture</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Play Trailer</source>
|
||||
<translation>Lire la bande annonce</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
|
@ -10179,5 +10179,137 @@
|
|||
<source>Unplayed</source>
|
||||
<translation>Nem játszott</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Age</source>
|
||||
<translation>Életkór</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Mented a hitelesítő adatokat?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Died</source>
|
||||
<translation>Meghalt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Monday</source>
|
||||
<translation>Hétfő</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starts at</source>
|
||||
<translation>Kezdődik majd</translation>
|
||||
<extracomment>(Future Tense) For defining time when a program will start today (e.g. Starts at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ends at</source>
|
||||
<translation>Vége volt</translation>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program ended (e.g. Ended Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Wednesday</source>
|
||||
<translation>Szerda</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Started</source>
|
||||
<translation>Kezdődött</translation>
|
||||
<extracomment>(Past Tense) For defining a day and time when a program started (e.g. Started Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Born</source>
|
||||
<translation>Született</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cast & Crew</source>
|
||||
<translation>Szereplők és stáb</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Mentés Törölése</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation>Mostantól</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>today</source>
|
||||
<translation>ma</translation>
|
||||
<extracomment>Current day</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Sunday</source>
|
||||
<translation>Vasárnap</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Tuesday</source>
|
||||
<translation>Kedd</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Thursday</source>
|
||||
<translation>Csütörtök</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Saturday</source>
|
||||
<translation>Szombat</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Started at</source>
|
||||
<translation>Ekkor kezdődött</translation>
|
||||
<extracomment>(Past Tense) For defining time when a program started today (e.g. Started at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starts</source>
|
||||
<translation>Kezdődni fog</translation>
|
||||
<extracomment>(Future Tense) For defining a day and time when a program will start (e.g. Starts Wednesday, 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Live</source>
|
||||
<translation>Élő</translation>
|
||||
<extracomment>If TV Show is being broadcast live (not pre-recorded)</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ended at</source>
|
||||
<translation>Vége lett</translation>
|
||||
<extracomment>(Past Tense) For defining time when a program will ended (e.g. Ended at 08:00) </extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>TV Guide</source>
|
||||
<translation>Műsorújság</translation>
|
||||
<extracomment>Menu option for showing Live TV Guide / Schedule</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Friday</source>
|
||||
<translation>Péntek</translation>
|
||||
<extracomment>Day of Week</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>yesterday</source>
|
||||
<translation>tegnap</translation>
|
||||
<extracomment>Previous day</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>tomorrow</source>
|
||||
<translation>holnap</translation>
|
||||
<extracomment>Next day</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Repeat</source>
|
||||
<translation>Ismétlés</translation>
|
||||
<extracomment>If TV Shows has previously been broadcasted</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Channels</source>
|
||||
<translation>Csatornák</translation>
|
||||
<extracomment>Menu option for showing Live TV Channel List</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>View Channel</source>
|
||||
<translation>Csatorna Megtekintése</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
|
@ -382,5 +382,98 @@
|
|||
<source>Save Credentials?</source>
|
||||
<translation>Saglabāt akreditācijas datus?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Save Credentials?</source>
|
||||
<translation>Saglabāt akreditācijas datus?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Delete Saved</source>
|
||||
<translation>Izdzēst Saglabātos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>On Now</source>
|
||||
<translation>Tagad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error Retrieving Content</source>
|
||||
<translation>Kļūda Saņemot Saturu</translation>
|
||||
<extracomment>Dialog title when unable to load Content from Server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>Error During Playback</source>
|
||||
<translation>Kļūda Atskaņošanas Laikā</translation>
|
||||
<extracomment>Dialog title when error occurs during playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>An error was encountered while playing this item.</source>
|
||||
<translation>Notika kļūda, atskaņojot šo vienumu.</translation>
|
||||
<extracomment>Dialog detail when error occurs during playback</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Message displayed in Item Grid when no item to display. %1 is container type (e.g. Boxset, Collection, Folder, etc)</comment>
|
||||
<source>NO_ITEMS</source>
|
||||
<translation>%1 nesatur vienumus</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Name or Title field of media item</comment>
|
||||
<source>TITLE</source>
|
||||
<translation>Nosaukums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DATE_ADDED</source>
|
||||
<translation>Pievienošanas Datums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Title of Tab for options to filter library content</comment>
|
||||
<source>TAB_FILTER</source>
|
||||
<translation>Filtrēt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Title of Tab for options to sort library content</comment>
|
||||
<source>TAB_SORT</source>
|
||||
<translation>Kārtot</translation>
|
||||
</message>
|
||||
<message>
|
||||
<comment>Title of Tab for switching "views" when looking at a library</comment>
|
||||
<source>TAB_VIEW</source>
|
||||
<translation>Izkārtojums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>RUNTIME</source>
|
||||
<translation>Ilgums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>DATE_PLAYED</source>
|
||||
<translation>Atskaņošanas Datums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>There was an error retrieving the data for this item from the server.</source>
|
||||
<translation>Notika kļūda, no servera saņemot datus par šo vienumu.</translation>
|
||||
<extracomment>Dialog detail when unable to load Content from Server</extracomment>
|
||||
</message>
|
||||
<message>
|
||||
<source>RELEASE_DATE</source>
|
||||
<translation>Izlaiduma Datums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>IMDB_RATING</source>
|
||||
<translation>IMDb Vērtējums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Born</source>
|
||||
<translation>Dzimšanas datums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Died</source>
|
||||
<translation>Nāves datums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Age</source>
|
||||
<translation>Vecums</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>CRITIC_RATING</source>
|
||||
<translation>Kritiķu Vērtējums</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -25,7 +25,7 @@
|
|||
"rimraf": "5.0.1",
|
||||
"roku-deploy": "3.10.2",
|
||||
"roku-log-bsc-plugin": "0.8.1",
|
||||
"rooibos-roku": "5.5.2",
|
||||
"rooibos-roku": "5.5.3",
|
||||
"ropm": "0.10.15",
|
||||
"spellchecker-cli": "6.1.1",
|
||||
"undent": "0.1.0"
|
||||
|
@ -4376,9 +4376,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/rooibos-roku": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/rooibos-roku/-/rooibos-roku-5.5.2.tgz",
|
||||
"integrity": "sha512-KBHdQb2qSD1WCzs7P9qxQt4YgPf3hc1CA4nIq9nHeW09+77Ksw9+GW1pjVABW+ip1kZ3Tf8+Bimb8pa4FN5Zmw==",
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/rooibos-roku/-/rooibos-roku-5.5.3.tgz",
|
||||
"integrity": "sha512-h6iDQPlxEguyBp5bO0mm9qPuckWEH2+h7KDzSgO0ue2pNzwKcAm+tf0wH5gwXFTu9vHgEctpdbv0gr71FZSw1w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"source-map": "^0.7.3",
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"rimraf": "5.0.1",
|
||||
"roku-deploy": "3.10.2",
|
||||
"roku-log-bsc-plugin": "0.8.1",
|
||||
"rooibos-roku": "5.5.2",
|
||||
"rooibos-roku": "5.5.3",
|
||||
"ropm": "0.10.15",
|
||||
"spellchecker-cli": "6.1.1",
|
||||
"undent": "0.1.0"
|
||||
|
|
|
@ -13,6 +13,7 @@ sub Main (args as dynamic) as void
|
|||
m.global = m.screen.getGlobalNode()
|
||||
SaveAppToGlobal()
|
||||
SaveDeviceToGlobal()
|
||||
session.Init()
|
||||
|
||||
m.scene = m.screen.CreateScene("JFScene")
|
||||
m.screen.show() ' vscode_rale_tracker_entry
|
||||
|
@ -34,10 +35,9 @@ sub Main (args as dynamic) as void
|
|||
PostDeviceProfile()
|
||||
' remove previous scenes from the stack
|
||||
sceneManager.callFunc("clearScenes")
|
||||
' save user config
|
||||
m.global.addFields({ userConfig: m.user.configuration })
|
||||
|
||||
' load home page
|
||||
sceneManager.currentUser = m.user.Name
|
||||
sceneManager.currentUser = m.global.session.user.name
|
||||
group = CreateHomeGroup()
|
||||
group.callFunc("loadLibraries")
|
||||
sceneManager.callFunc("pushScene", group)
|
||||
|
@ -64,7 +64,7 @@ sub Main (args as dynamic) as void
|
|||
' Only show the Whats New popup the first time a user runs a new client version.
|
||||
if m.global.app.version <> get_setting("LastRunVersion")
|
||||
' Ensure the user hasn't disabled Whats New popups
|
||||
if get_user_setting("load.allowwhatsnew") = "true"
|
||||
if m.global.session.user.settings["load.allowwhatsnew"] = true
|
||||
set_setting("LastRunVersion", m.global.app.version)
|
||||
dialog = createObject("roSGNode", "WhatsNewDialog")
|
||||
m.scene.dialog = dialog
|
||||
|
@ -460,7 +460,7 @@ sub Main (args as dynamic) as void
|
|||
dialog.title = tr("Loading trailer")
|
||||
m.scene.dialog = dialog
|
||||
|
||||
trailerData = api.users.GetLocalTrailers(get_setting("active_user"), group.id)
|
||||
trailerData = api.users.GetLocalTrailers(m.global.session.user.id, group.id)
|
||||
|
||||
if isValid(trailerData) and isValid(trailerData[0]) and isValid(trailerData[0].id)
|
||||
m.global.queueManager.callFunc("clear")
|
||||
|
|
|
@ -2,7 +2,14 @@ function LoginFlow(startOver = false as boolean)
|
|||
'Collect Jellyfin server and user information
|
||||
start_login:
|
||||
|
||||
if get_setting("server") = invalid then startOver = true
|
||||
serverUrl = get_setting("server")
|
||||
if isValid(serverUrl)
|
||||
print "Previous server connection saved to registry"
|
||||
session.server.UpdateURL(serverUrl)
|
||||
else
|
||||
startOver = true
|
||||
print "No previous server connection saved to registry"
|
||||
end if
|
||||
|
||||
invalidServer = true
|
||||
if not startOver
|
||||
|
@ -28,7 +35,9 @@ function LoginFlow(startOver = false as boolean)
|
|||
SaveServerList()
|
||||
end if
|
||||
|
||||
if get_setting("active_user") = invalid
|
||||
activeUser = get_setting("active_user")
|
||||
if activeUser = invalid
|
||||
print "No active user found in registry"
|
||||
SendPerformanceBeacon("AppDialogInitiate") ' Roku Performance monitoring - Dialog Starting
|
||||
publicUsers = GetPublicUsers()
|
||||
if publicUsers.count()
|
||||
|
@ -37,7 +46,7 @@ function LoginFlow(startOver = false as boolean)
|
|||
user = CreateObject("roSGNode", "PublicUserData")
|
||||
user.id = item.Id
|
||||
user.name = item.Name
|
||||
if item.PrimaryImageTag <> invalid
|
||||
if isValid(item.PrimaryImageTag)
|
||||
user.ImageURL = UserImageURL(user.id, { "tag": item.PrimaryImageTag })
|
||||
end if
|
||||
publicUsersNodes.push(user)
|
||||
|
@ -48,11 +57,11 @@ function LoginFlow(startOver = false as boolean)
|
|||
return LoginFlow(true)
|
||||
else
|
||||
'Try to login without password. If the token is valid, we're done
|
||||
get_token(userSelected, "")
|
||||
if get_setting("active_user") <> invalid
|
||||
m.user = AboutMe()
|
||||
userData = get_token(userSelected, "")
|
||||
if isValid(userData)
|
||||
session.user.Login(userData)
|
||||
LoadUserPreferences()
|
||||
LoadUserAbilities(m.user)
|
||||
LoadUserAbilities()
|
||||
SendPerformanceBeacon("AppDialogComplete") ' Roku Performance monitoring - Dialog Closed
|
||||
return true
|
||||
end if
|
||||
|
@ -66,17 +75,74 @@ function LoginFlow(startOver = false as boolean)
|
|||
m.global.sceneManager.callFunc("clearScenes")
|
||||
return LoginFlow(true)
|
||||
end if
|
||||
else
|
||||
print "Active user found in registry"
|
||||
session.user.Update("id", activeUser)
|
||||
|
||||
myAuthToken = get_user_setting("token")
|
||||
if isValid(myAuthToken)
|
||||
print "Auth token found in registry"
|
||||
session.user.Update("authToken", myAuthToken)
|
||||
print "Attempting to use API with auth token"
|
||||
currentUser = AboutMe()
|
||||
if currentUser = invalid
|
||||
print "Auth token is no longer valid - restart login flow"
|
||||
unset_user_setting("token")
|
||||
unset_setting("active_user")
|
||||
session.user.Logout()
|
||||
goto start_login
|
||||
else
|
||||
print "Success! Auth token is still valid"
|
||||
session.user.Login(currentUser)
|
||||
end if
|
||||
else
|
||||
print "No auth token found in registry"
|
||||
myUsername = get_setting("username")
|
||||
myPassword = get_setting("password")
|
||||
userData = invalid
|
||||
|
||||
if isValid(myUsername) and isValid(myPassword)
|
||||
if myUsername <> ""
|
||||
print "Username and password found in registry. Attempting to login"
|
||||
userData = get_token(myUsername, myPassword)
|
||||
else
|
||||
print "Username in registry is an empty string"
|
||||
unset_setting("username")
|
||||
unset_setting("password")
|
||||
end if
|
||||
else if isValid(myUsername) and not isValid(myPassword)
|
||||
print "Username found in registry but no password"
|
||||
if myUsername <> ""
|
||||
print "Attempting to login with no password"
|
||||
userData = get_token(myUsername, "")
|
||||
else
|
||||
print "Username in registry is an empty string"
|
||||
unset_setting("username")
|
||||
end if
|
||||
|
||||
m.user = AboutMe()
|
||||
if m.user = invalid or m.user.id <> get_setting("active_user")
|
||||
else if not isValid(myUsername) and not isValid(myPassword)
|
||||
print "Neither username nor password found in registry - restart login flow"
|
||||
unset_setting("active_user")
|
||||
session.user.Logout()
|
||||
goto start_login
|
||||
end if
|
||||
|
||||
if isValid(userData)
|
||||
print "login success!"
|
||||
session.user.Login(userData)
|
||||
end if
|
||||
end if
|
||||
end if
|
||||
|
||||
if m.global.session.user.id = invalid or m.global.session.user.authToken = invalid
|
||||
print "Login failed, restart flow"
|
||||
unset_setting("active_user")
|
||||
session.user.Logout()
|
||||
goto start_login
|
||||
end if
|
||||
|
||||
LoadUserPreferences()
|
||||
LoadUserAbilities(m.user)
|
||||
LoadUserAbilities()
|
||||
m.global.sceneManager.callFunc("clearScenes")
|
||||
|
||||
return true
|
||||
|
@ -84,18 +150,18 @@ end function
|
|||
|
||||
sub SaveServerList()
|
||||
'Save off this server to our list of saved servers for easier navigation between servers
|
||||
server = get_setting("server")
|
||||
server = m.global.session.server.url
|
||||
saved = get_setting("saved_servers")
|
||||
if server <> invalid
|
||||
if isValid(server)
|
||||
server = LCase(server)'Saved server data is always lowercase
|
||||
end if
|
||||
entryCount = 0
|
||||
addNewEntry = true
|
||||
savedServers = { serverList: [] }
|
||||
if saved <> invalid
|
||||
if isValid(saved)
|
||||
savedServers = ParseJson(saved)
|
||||
entryCount = savedServers.serverList.Count()
|
||||
if savedServers.serverList <> invalid and entryCount > 0
|
||||
if isValid(savedServers.serverList) and entryCount > 0
|
||||
for each item in savedServers.serverList
|
||||
if item.baseUrl = server
|
||||
addNewEntry = false
|
||||
|
@ -117,10 +183,10 @@ end sub
|
|||
|
||||
sub DeleteFromServerList(urlToDelete)
|
||||
saved = get_setting("saved_servers")
|
||||
if urlToDelete <> invalid
|
||||
if isValid(urlToDelete)
|
||||
urlToDelete = LCase(urlToDelete)
|
||||
end if
|
||||
if saved <> invalid
|
||||
if isValid(saved)
|
||||
savedServers = ParseJson(saved)
|
||||
newServers = { serverList: [] }
|
||||
for each item in savedServers.serverList
|
||||
|
@ -146,8 +212,8 @@ function CreateServerGroup()
|
|||
port = CreateObject("roMessagePort")
|
||||
m.colors = {}
|
||||
|
||||
if get_setting("server") <> invalid
|
||||
screen.serverUrl = get_setting("server")
|
||||
if isValid(m.global.session.server.url)
|
||||
screen.serverUrl = m.global.session.server.url
|
||||
end if
|
||||
m.viewModel = {}
|
||||
button = screen.findNode("submit")
|
||||
|
@ -181,43 +247,45 @@ function CreateServerGroup()
|
|||
if node = "submit"
|
||||
serverUrl = standardize_jellyfin_url(screen.serverUrl)
|
||||
'If this is a different server from what we know, reset username/password setting
|
||||
if get_setting("server") <> serverUrl
|
||||
if m.global.session.server.url <> serverUrl
|
||||
set_setting("username", "")
|
||||
set_setting("password", "")
|
||||
end if
|
||||
set_setting("server", serverUrl)
|
||||
session.server.UpdateURL(serverUrl)
|
||||
' Show Connecting to Server spinner
|
||||
dialog = createObject("roSGNode", "ProgressDialog")
|
||||
dialog.title = tr("Connecting to Server")
|
||||
m.scene.dialog = dialog
|
||||
|
||||
m.serverInfoResult = ServerInfo()
|
||||
serverInfoResult = ServerInfo()
|
||||
|
||||
dialog.close = true
|
||||
|
||||
if m.serverInfoResult = invalid
|
||||
if serverInfoResult = invalid
|
||||
' Maybe don't unset setting, but offer as a prompt
|
||||
' Server not found, is it online? New values / Retry
|
||||
print "Server not found, is it online? New values / Retry"
|
||||
screen.errorMessage = tr("Server not found, is it online?")
|
||||
SignOut(false)
|
||||
else if m.serverInfoResult.Error <> invalid and m.serverInfoResult.Error
|
||||
else if isValid(serverInfoResult.Error) and serverInfoResult.Error
|
||||
' If server redirected received, update the URL
|
||||
if m.serverInfoResult.UpdatedUrl <> invalid
|
||||
serverUrl = m.serverInfoResult.UpdatedUrl
|
||||
if isValid(serverInfoResult.UpdatedUrl)
|
||||
serverUrl = serverInfoResult.UpdatedUrl
|
||||
set_setting("server", serverUrl)
|
||||
session.server.UpdateURL(serverUrl)
|
||||
end if
|
||||
' Display Error Message to user
|
||||
message = tr("Error: ")
|
||||
if m.serverInfoResult.ErrorCode <> invalid
|
||||
message = message + "[" + m.serverInfoResult.ErrorCode.toStr() + "] "
|
||||
if isValid(serverInfoResult.ErrorCode)
|
||||
message = message + "[" + serverInfoResult.ErrorCode.toStr() + "] "
|
||||
end if
|
||||
screen.errorMessage = message + tr(m.serverInfoResult.ErrorMessage)
|
||||
screen.errorMessage = message + tr(serverInfoResult.ErrorMessage)
|
||||
SignOut(false)
|
||||
else
|
||||
screen.visible = false
|
||||
if m.serverInfoResult.serverName <> invalid
|
||||
return m.serverInfoResult.ServerName + " (Saved)"
|
||||
if isValid(serverInfoResult.serverName)
|
||||
return serverInfoResult.ServerName + " (Saved)"
|
||||
else
|
||||
return "Saved"
|
||||
end if
|
||||
|
@ -226,7 +294,7 @@ function CreateServerGroup()
|
|||
serverPicker = screen.findNode("serverPicker")
|
||||
itemToDelete = serverPicker.content.getChild(serverPicker.itemFocused)
|
||||
urlToDelete = itemToDelete.baseUrl
|
||||
if urlToDelete <> invalid
|
||||
if isValid(urlToDelete)
|
||||
DeleteFromServerList(urlToDelete)
|
||||
serverPicker.content.removeChild(itemToDelete)
|
||||
sidepanel.visible = false
|
||||
|
@ -283,17 +351,18 @@ function CreateSigninGroup(user = "")
|
|||
group.findNode("prompt").text = tr("Sign In")
|
||||
|
||||
'Load in any saved server data and see if we can just log them in...
|
||||
server = get_setting("server")
|
||||
if server <> invalid
|
||||
server = m.global.session.server.url
|
||||
if isValid(server)
|
||||
server = LCase(server)'Saved server data is always lowercase
|
||||
end if
|
||||
saved = get_setting("saved_servers")
|
||||
if saved <> invalid
|
||||
if isValid(saved)
|
||||
savedServers = ParseJson(saved)
|
||||
for each item in savedServers.serverList
|
||||
if item.baseUrl = server and item.username <> invalid and item.password <> invalid
|
||||
get_token(item.username, item.password)
|
||||
if get_setting("active_user") <> invalid
|
||||
if item.baseUrl = server and isValid(item.username) and isValid(item.password)
|
||||
userData = get_token(item.username, item.password)
|
||||
if isValid(userData)
|
||||
session.user.Login(userData)
|
||||
return "true"
|
||||
end if
|
||||
end if
|
||||
|
@ -314,8 +383,9 @@ function CreateSigninGroup(user = "")
|
|||
password_field.label = tr("Password")
|
||||
password_field.field = "password"
|
||||
password_field.type = "password"
|
||||
if get_setting("password") <> invalid
|
||||
password_field.value = get_setting("password")
|
||||
registryPassword = get_setting("password")
|
||||
if isValid(registryPassword)
|
||||
password_field.value = registryPassword
|
||||
end if
|
||||
' Add checkbox for saving credentials
|
||||
checkbox = group.findNode("onOff")
|
||||
|
@ -327,11 +397,8 @@ function CreateSigninGroup(user = "")
|
|||
checkbox.content = items
|
||||
checkbox.checkedState = [true]
|
||||
quickConnect = group.findNode("quickConnect")
|
||||
if m.serverInfoResult = invalid
|
||||
m.serverInfoResult = ServerInfo()
|
||||
end if
|
||||
' Quick Connect only supported for server version 10.8+ right now...
|
||||
if versionChecker(m.serverInfoResult.Version, "10.8.0")
|
||||
if versionChecker(m.global.session.server.version, "10.8.0")
|
||||
' Add option for Quick Connect
|
||||
quickConnect.text = tr("Quick Connect")
|
||||
quickConnect.observeField("buttonSelected", port)
|
||||
|
@ -365,8 +432,9 @@ function CreateSigninGroup(user = "")
|
|||
node = msg.getNode()
|
||||
if node = "submit"
|
||||
' Validate credentials
|
||||
get_token(username.value, password.value)
|
||||
if get_setting("active_user") <> invalid
|
||||
activeUser = get_token(username.value, password.value)
|
||||
if isValid(activeUser)
|
||||
session.user.Login(activeUser)
|
||||
set_setting("username", username.value)
|
||||
set_setting("password", password.value)
|
||||
if checkbox.checkedState[0] = true
|
||||
|
@ -463,7 +531,7 @@ function CreateHomeGroup()
|
|||
user_options.push({ display: user.username + "@" + user.server, value: user.id })
|
||||
end for
|
||||
user_node.choices = user_options
|
||||
user_node.value = get_setting("active_user")
|
||||
user_node.value = m.global.session.user.id
|
||||
new_options.push(user_node)
|
||||
|
||||
sidepanel.options = new_options
|
||||
|
@ -492,7 +560,7 @@ function CreateMovieDetailsGroup(movie as object) as dynamic
|
|||
m.global.sceneManager.callFunc("pushScene", group)
|
||||
group.itemContent = movieMetaData
|
||||
' local trailers
|
||||
trailerData = api.users.GetLocalTrailers(get_setting("active_user"), movie.id)
|
||||
trailerData = api.users.GetLocalTrailers(m.global.session.user.id, movie.id)
|
||||
if isValid(trailerData)
|
||||
group.trailerAvailable = trailerData.Count() > 0
|
||||
end if
|
||||
|
@ -525,7 +593,7 @@ function CreateSeriesDetailsGroup(seriesID as string) as dynamic
|
|||
' Get season data early in the function so we can check number of seasons.
|
||||
seasonData = TVSeasons(seriesID)
|
||||
' Divert to season details if user setting goStraightToEpisodeListing is enabled and only one season exists.
|
||||
if get_user_setting("ui.tvshows.goStraightToEpisodeListing") = "true" and seasonData.Items.Count() = 1
|
||||
if m.global.session.user.settings["ui.tvshows.goStraightToEpisodeListing"] = true and seasonData.Items.Count() = 1
|
||||
stopLoadingSpinner()
|
||||
return CreateSeasonDetailsGroupByID(seriesID, seasonData.Items[0].id)
|
||||
end if
|
||||
|
@ -783,7 +851,7 @@ function CreatePersonView(personData as object) as dynamic
|
|||
end function
|
||||
|
||||
sub UpdateSavedServerList()
|
||||
server = get_setting("server")
|
||||
server = m.global.session.server.url
|
||||
username = get_setting("username")
|
||||
password = get_setting("password")
|
||||
|
||||
|
@ -794,9 +862,9 @@ sub UpdateSavedServerList()
|
|||
server = LCase(server)'Saved server data is always lowercase
|
||||
|
||||
saved = get_setting("saved_servers")
|
||||
if saved <> invalid
|
||||
if isValid(saved)
|
||||
savedServers = ParseJson(saved)
|
||||
if savedServers.serverList <> invalid and savedServers.serverList.Count() > 0
|
||||
if isValid(savedServers.serverList) and savedServers.serverList.Count() > 0
|
||||
newServers = { serverList: [] }
|
||||
for each item in savedServers.serverList
|
||||
if item.baseUrl = server
|
||||
|
|
|
@ -82,7 +82,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
params = {
|
||||
ids: video.Id
|
||||
}
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
for each item in data.Items
|
||||
|
@ -92,7 +92,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
params = {
|
||||
ids: m.series_id
|
||||
}
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
for each item in data.Items
|
||||
|
@ -109,7 +109,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
params = {
|
||||
ids: video.Id
|
||||
}
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
for each item in data.Items
|
||||
|
@ -120,7 +120,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
params = {
|
||||
ids: m.season_id
|
||||
}
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
for each item in data.Items
|
||||
|
@ -130,7 +130,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
params = {
|
||||
ids: m.series_id
|
||||
}
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
for each item in data.Items
|
||||
|
@ -147,7 +147,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
params = {
|
||||
ids: video.Id
|
||||
}
|
||||
url = Substitute("Users/{0}/Items/", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
|
||||
resp = APIRequest(url, params)
|
||||
data = getJson(resp)
|
||||
for each item in data.Items
|
||||
|
@ -217,7 +217,7 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
end if
|
||||
|
||||
subtitles = sortSubtitles(meta.id, m.playbackInfo.MediaSources[0].MediaStreams)
|
||||
if get_user_setting("playback.subs.onlytext") = "true"
|
||||
if m.global.session.user.settings["playback.subs.onlytext"] = true
|
||||
safesubs = []
|
||||
for each subtitle in subtitles["all"]
|
||||
if subtitle["IsTextSubtitleStream"]
|
||||
|
@ -249,8 +249,8 @@ sub AddVideoContent(video as object, mediaSourceId as dynamic, audio_stream_idx
|
|||
' transcode is that the Encoding Level is not supported, then try to direct play but silently
|
||||
' fall back to the transcode if that fails.
|
||||
if m.playbackInfo.MediaSources[0].MediaStreams.Count() > 0 and meta.live = false
|
||||
tryDirectPlay = get_user_setting("playback.tryDirect.h264ProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
|
||||
tryDirectPlay = tryDirectPlay or (get_user_setting("playback.tryDirect.hevcProfileLevel") = "true" and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
|
||||
tryDirectPlay = m.global.session.user.settings["playback.tryDirect.h264ProfileLevel"] = true and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "h264"
|
||||
tryDirectPlay = tryDirectPlay or (m.global.session.user.settings["playback.tryDirect.hevcProfileLevel"] = true and m.playbackInfo.MediaSources[0].MediaStreams[0].codec = "hevc")
|
||||
if tryDirectPlay and isValid(m.playbackInfo.MediaSources[0].TranscodingUrl) and forceTranscoding = false
|
||||
transcodingReasons = getTranscodeReasons(m.playbackInfo.MediaSources[0].TranscodingUrl)
|
||||
if transcodingReasons.Count() = 1 and transcodingReasons[0] = "VideoLevelNotSupported"
|
||||
|
@ -318,7 +318,7 @@ end sub
|
|||
|
||||
function PlayIntroVideo(video_id, audio_stream_idx) as boolean
|
||||
' Intro videos only play if user has cinema mode setting enabled
|
||||
if get_user_setting("playback.cinemamode") = "true"
|
||||
if m.global.session.user.settings["playback.cinemamode"] = true
|
||||
' Check if server has intro videos setup and available
|
||||
introVideos = GetIntroVideos(video_id)
|
||||
|
||||
|
@ -441,10 +441,10 @@ end function
|
|||
|
||||
sub autoPlayNextEpisode(videoID as string, showID as string)
|
||||
' use web client setting
|
||||
if m.user.Configuration.EnableNextEpisodeAutoPlay
|
||||
if m.global.session.user.configuration.EnableNextEpisodeAutoPlay
|
||||
' query API for next episode ID
|
||||
url = Substitute("Shows/{0}/Episodes", showID)
|
||||
urlParams = { "UserId": get_setting("active_user") }
|
||||
urlParams = { "UserId": m.global.session.user.id }
|
||||
urlParams.Append({ "StartItemId": videoID })
|
||||
urlParams.Append({ "Limit": 2 })
|
||||
resp = APIRequest(url, urlParams)
|
||||
|
@ -481,15 +481,15 @@ function GetPlaybackInfo()
|
|||
return [errMsg]
|
||||
end function
|
||||
|
||||
function GetTranscodingStats(session)
|
||||
function GetTranscodingStats(deviceSession)
|
||||
sessionStats = []
|
||||
|
||||
if isValid(session.TranscodingInfo) and session.TranscodingInfo.Count() > 0
|
||||
transcodingReasons = session.TranscodingInfo.TranscodeReasons
|
||||
videoCodec = session.TranscodingInfo.VideoCodec
|
||||
audioCodec = session.TranscodingInfo.AudioCodec
|
||||
totalBitrate = session.TranscodingInfo.Bitrate
|
||||
audioChannels = session.TranscodingInfo.AudioChannels
|
||||
if isValid(deviceSession.TranscodingInfo) and deviceSession.TranscodingInfo.Count() > 0
|
||||
transcodingReasons = deviceSession.TranscodingInfo.TranscodeReasons
|
||||
videoCodec = deviceSession.TranscodingInfo.VideoCodec
|
||||
audioCodec = deviceSession.TranscodingInfo.AudioCodec
|
||||
totalBitrate = deviceSession.TranscodingInfo.Bitrate
|
||||
audioChannels = deviceSession.TranscodingInfo.AudioChannels
|
||||
|
||||
if isValid(transcodingReasons) and transcodingReasons.Count() > 0
|
||||
sessionStats.push("** " + tr("Transcoding Information") + " **")
|
||||
|
@ -500,7 +500,7 @@ function GetTranscodingStats(session)
|
|||
|
||||
if isValid(videoCodec)
|
||||
data = tr("Video Codec") + ": " + videoCodec
|
||||
if session.TranscodingInfo.IsVideoDirect
|
||||
if deviceSession.TranscodingInfo.IsVideoDirect
|
||||
data = data + " (" + tr("direct") + ")"
|
||||
end if
|
||||
sessionStats.push(data)
|
||||
|
@ -508,7 +508,7 @@ function GetTranscodingStats(session)
|
|||
|
||||
if isValid(audioCodec)
|
||||
data = tr("Audio Codec") + ": " + audioCodec
|
||||
if session.TranscodingInfo.IsAudioDirect
|
||||
if deviceSession.TranscodingInfo.IsAudioDirect
|
||||
data = data + " (" + tr("direct") + ")"
|
||||
end if
|
||||
sessionStats.push(data)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
function ItemGetPlaybackInfo(id as string, startTimeTicks = 0 as longinteger)
|
||||
params = {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"StartTimeTicks": startTimeTicks,
|
||||
"IsPlayback": true,
|
||||
"AutoOpenLiveStream": true,
|
||||
|
@ -15,7 +15,7 @@ function ItemPostPlaybackInfo(id as string, mediaSourceId = "" as string, audioT
|
|||
"DeviceProfile": getDeviceProfile()
|
||||
}
|
||||
params = {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"StartTimeTicks": startTimeTicks,
|
||||
"IsPlayback": true,
|
||||
"AutoOpenLiveStream": true,
|
||||
|
@ -39,7 +39,7 @@ function searchMedia(query as string)
|
|||
' For each potential type, a separate query is done:
|
||||
' varying item types, and artists, and people
|
||||
if query <> ""
|
||||
resp = APIRequest(Substitute("Search/Hints", get_setting("active_user")), {
|
||||
resp = APIRequest(Substitute("Search/Hints", m.global.session.user.id), {
|
||||
"searchTerm": query,
|
||||
"IncludePeople": true,
|
||||
"IncludeMedia": true,
|
||||
|
@ -70,7 +70,7 @@ end function
|
|||
|
||||
' MetaData about an item
|
||||
function ItemMetaData(id as string)
|
||||
url = Substitute("Users/{0}/Items/{1}", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/Items/{1}", m.global.session.user.id, id)
|
||||
resp = APIRequest(url)
|
||||
data = getJson(resp)
|
||||
if data = invalid then return invalid
|
||||
|
@ -178,7 +178,7 @@ end function
|
|||
|
||||
' Get list of albums belonging to an artist
|
||||
function MusicAlbumList(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id)
|
||||
resp = APIRequest(url, {
|
||||
"AlbumArtistIds": id,
|
||||
"includeitemtypes": "MusicAlbum",
|
||||
|
@ -200,7 +200,7 @@ end function
|
|||
|
||||
' Get list of albums an artist appears on
|
||||
function AppearsOnList(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id)
|
||||
resp = APIRequest(url, {
|
||||
"ContributingArtistIds": id,
|
||||
"ExcludeItemIds": id,
|
||||
|
@ -224,7 +224,7 @@ end function
|
|||
|
||||
' Get list of songs belonging to an artist
|
||||
function GetSongsByArtist(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id)
|
||||
resp = APIRequest(url, {
|
||||
"AlbumArtistIds": id,
|
||||
"includeitemtypes": "Audio",
|
||||
|
@ -253,7 +253,7 @@ end function
|
|||
function PlaylistItemList(id as string)
|
||||
url = Substitute("Playlists/{0}/Items", id)
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user")
|
||||
"UserId": m.global.session.user.id
|
||||
})
|
||||
|
||||
results = []
|
||||
|
@ -275,9 +275,9 @@ end function
|
|||
|
||||
' Get Songs that are on an Album
|
||||
function MusicSongList(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id, id)
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"parentId": id,
|
||||
"includeitemtypes": "Audio",
|
||||
"sortBy": "SortName"
|
||||
|
@ -302,9 +302,9 @@ end function
|
|||
|
||||
' Get Songs that are on an Album
|
||||
function AudioItem(id as string)
|
||||
url = Substitute("Users/{0}/Items/{1}", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/Items/{1}", m.global.session.user.id, id)
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"includeitemtypes": "Audio",
|
||||
"sortBy": "SortName"
|
||||
})
|
||||
|
@ -316,7 +316,7 @@ end function
|
|||
function CreateInstantMix(id as string)
|
||||
url = Substitute("/Items/{0}/InstantMix", id)
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"Limit": 201
|
||||
})
|
||||
|
||||
|
@ -325,7 +325,7 @@ end function
|
|||
|
||||
' Get Instant Mix based on item
|
||||
function CreateArtistMix(id as string)
|
||||
url = Substitute("Users/{0}/Items", get_setting("active_user"))
|
||||
url = Substitute("Users/{0}/Items", m.global.session.user.id)
|
||||
resp = APIRequest(url, {
|
||||
"ArtistIds": id,
|
||||
"Recursive": "true",
|
||||
|
@ -344,9 +344,9 @@ end function
|
|||
|
||||
' Get Intro Videos for an item
|
||||
function GetIntroVideos(id as string)
|
||||
url = Substitute("Users/{0}/Items/{1}/Intros", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/Items/{1}/Intros", m.global.session.user.id, id)
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user")
|
||||
"UserId": m.global.session.user.id
|
||||
})
|
||||
|
||||
return getJson(resp)
|
||||
|
@ -399,7 +399,8 @@ end function
|
|||
' Seasons for a TV Show
|
||||
function TVSeasons(id as string) as dynamic
|
||||
url = Substitute("Shows/{0}/Seasons", id)
|
||||
resp = APIRequest(url, { "UserId": get_setting("active_user") })
|
||||
resp = APIRequest(url, { "UserId": m.global.session.user.id })
|
||||
|
||||
data = getJson(resp)
|
||||
' validate data
|
||||
if data = invalid or data.Items = invalid then return invalid
|
||||
|
@ -418,7 +419,7 @@ end function
|
|||
|
||||
function TVEpisodes(show_id as string, season_id as string) as dynamic
|
||||
url = Substitute("Shows/{0}/Episodes", show_id)
|
||||
resp = APIRequest(url, { "seasonId": season_id, "UserId": get_setting("active_user"), "fields": "MediaStreams" })
|
||||
resp = APIRequest(url, { "seasonId": season_id, "UserId": m.global.session.user.id, "fields": "MediaStreams" })
|
||||
|
||||
data = getJson(resp)
|
||||
' validate data
|
||||
|
@ -447,7 +448,7 @@ end function
|
|||
function TVEpisodeShuffleList(show_id as string)
|
||||
url = Substitute("Shows/{0}/Episodes", show_id)
|
||||
resp = APIRequest(url, {
|
||||
"UserId": get_setting("active_user"),
|
||||
"UserId": m.global.session.user.id,
|
||||
"Limit": 200,
|
||||
"sortBy": "Random"
|
||||
})
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
function MarkItemFavorite(id as string)
|
||||
url = Substitute("Users/{0}/FavoriteItems/{1}", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/FavoriteItems/{1}", m.global.session.user.id, id)
|
||||
resp = APIRequest(url)
|
||||
return postJson(resp)
|
||||
end function
|
||||
|
||||
function UnmarkItemFavorite(id as string)
|
||||
url = Substitute("Users/{0}/FavoriteItems/{1}", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/FavoriteItems/{1}", m.global.session.user.id, id)
|
||||
resp = APIRequest(url)
|
||||
resp.setRequest("DELETE")
|
||||
return getJson(resp)
|
||||
|
@ -14,13 +14,13 @@ end function
|
|||
sub MarkItemWatched(id as string)
|
||||
date = CreateObject("roDateTime")
|
||||
dateStr = date.ToISOString()
|
||||
url = Substitute("Users/{0}/PlayedItems/{1}", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/PlayedItems/{1}", m.global.session.user.id, id)
|
||||
req = APIRequest(url)
|
||||
postVoid(req, FormatJson({ "DatePlayed": dateStr }))
|
||||
end sub
|
||||
|
||||
function UnmarkItemWatched(id as string)
|
||||
url = Substitute("Users/{0}/PlayedItems/{1}", get_setting("active_user"), id)
|
||||
url = Substitute("Users/{0}/PlayedItems/{1}", m.global.session.user.id, id)
|
||||
resp = APIRequest(url)
|
||||
resp.setRequest("DELETE")
|
||||
return getJson(resp)
|
||||
|
|
|
@ -57,12 +57,14 @@ function APIRequest(url as string, params = {} as object) as dynamic
|
|||
full_url = buildURL(url, params)
|
||||
if full_url = invalid then return invalid
|
||||
|
||||
serverURL = m.global.session.server.url
|
||||
if serverURL = invalid then return invalid
|
||||
|
||||
req = createObject("roUrlTransfer")
|
||||
req.setUrl(full_url)
|
||||
req = authorize_request(req)
|
||||
' SSL cert
|
||||
serverURL = get_setting("server")
|
||||
if serverURL <> invalid and serverURL.left(8) = "https://"
|
||||
if serverURL.left(8) = "https://"
|
||||
req.setCertificatesFile("common:/certs/ca-bundle.crt")
|
||||
end if
|
||||
|
||||
|
@ -156,9 +158,8 @@ function deleteVoid(req)
|
|||
end function
|
||||
|
||||
function get_url()
|
||||
serverURL = get_setting("server")
|
||||
if serverURL = invalid then return invalid
|
||||
|
||||
serverURL = m.global.session.server.url
|
||||
if serverURL <> invalid
|
||||
if serverURL.right(1) = "/"
|
||||
serverURL = serverURL.left(serverURL.len() - 1)
|
||||
end if
|
||||
|
@ -167,6 +168,7 @@ function get_url()
|
|||
if serverURL.left(7) <> "http://" and serverURL.left(8) <> "https://"
|
||||
serverURL = "http://" + serverURL
|
||||
end if
|
||||
end if
|
||||
return serverURL
|
||||
end function
|
||||
|
||||
|
@ -188,23 +190,18 @@ function postString(req, data = "" as string)
|
|||
end function
|
||||
|
||||
function authorize_request(request)
|
||||
user = get_setting("active_user")
|
||||
|
||||
auth = "MediaBrowser" + " Client=" + Chr(34) + "Jellyfin Roku" + Chr(34)
|
||||
auth = auth + ", Device=" + Chr(34) + m.global.device.name + " (" + m.global.device.friendlyName + ")" + Chr(34)
|
||||
|
||||
if user <> invalid and user <> ""
|
||||
auth = auth + ", DeviceId=" + Chr(34) + m.global.device.id + Chr(34)
|
||||
auth = auth + ", UserId=" + Chr(34) + user + Chr(34)
|
||||
else
|
||||
auth = auth + ", DeviceId=" + Chr(34) + m.global.device.uuid + Chr(34)
|
||||
end if
|
||||
|
||||
auth = auth + ", Version=" + Chr(34) + m.global.app.version + Chr(34)
|
||||
|
||||
token = get_user_setting("token")
|
||||
if token <> invalid and token <> ""
|
||||
auth = auth + ", Token=" + Chr(34) + token + Chr(34)
|
||||
if m.global.session.user.id <> invalid
|
||||
auth = auth + ", DeviceId=" + Chr(34) + m.global.device.id + Chr(34)
|
||||
auth = auth + ", UserId=" + Chr(34) + m.global.session.user.id + Chr(34)
|
||||
if m.global.session.user.authToken <> invalid
|
||||
auth = auth + ", Token=" + Chr(34) + m.global.session.user.authToken + Chr(34)
|
||||
end if
|
||||
else
|
||||
auth = auth + ", DeviceId=" + Chr(34) + m.global.device.uuid + Chr(34)
|
||||
end if
|
||||
|
||||
request.AddHeader("Authorization", auth)
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
' needed for SignOut() and ServerInfo()
|
||||
import "pkg:/source/utils/session.bs"
|
||||
|
||||
function get_token(user as string, password as string)
|
||||
url = "Users/AuthenticateByName?format=json"
|
||||
req = APIRequest(url)
|
||||
|
@ -14,22 +17,29 @@ function get_token(user as string, password as string)
|
|||
return userdata
|
||||
end function
|
||||
|
||||
function AboutMe()
|
||||
id = get_setting("active_user")
|
||||
function AboutMe(id = "" as string)
|
||||
if id = ""
|
||||
if m.global.session.user.id <> invalid
|
||||
id = m.global.session.user.id
|
||||
else
|
||||
return invalid
|
||||
end if
|
||||
end if
|
||||
|
||||
url = Substitute("Users/{0}", id)
|
||||
resp = APIRequest(url)
|
||||
return getJson(resp)
|
||||
end function
|
||||
|
||||
sub SignOut(deleteSavedEntry = true as boolean)
|
||||
if get_setting("active_user") <> invalid
|
||||
if m.global.session.user.id <> invalid
|
||||
unset_user_setting("token")
|
||||
unset_setting("username")
|
||||
unset_setting("password")
|
||||
if deleteSavedEntry = true
|
||||
'Also delete any credentials in the "saved servers" list
|
||||
saved = get_setting("saved_servers")
|
||||
server = get_setting("server")
|
||||
server = m.global.session.server.url
|
||||
if server <> invalid
|
||||
server = LCase(server)
|
||||
savedServers = ParseJson(saved)
|
||||
|
@ -46,6 +56,7 @@ sub SignOut(deleteSavedEntry = true as boolean)
|
|||
end if
|
||||
end if
|
||||
unset_setting("active_user")
|
||||
session.user.Logout()
|
||||
m.global.sceneManager.currentUser = ""
|
||||
group = m.global.sceneManager.callFunc("getActiveScene")
|
||||
group.optionsAvailable = false
|
||||
|
@ -56,24 +67,6 @@ function AvailableUsers()
|
|||
return users
|
||||
end function
|
||||
|
||||
sub PickUser(id as string)
|
||||
this_user = invalid
|
||||
for each user in AvailableUsers()
|
||||
if user.id = id then this_user = user
|
||||
end for
|
||||
if this_user = invalid then return
|
||||
set_setting("active_user", this_user.id)
|
||||
set_setting("server", this_user.server)
|
||||
end sub
|
||||
|
||||
sub RemoveUser(id as string)
|
||||
user = CreateObject("roSGNode", "UserData")
|
||||
user.id = id
|
||||
user.callFunc("removeFromRegistry")
|
||||
|
||||
if get_setting("active_user") = id then SignOut(false)
|
||||
end sub
|
||||
|
||||
function ServerInfo()
|
||||
url = "System/Info/Public"
|
||||
req = APIRequest(url)
|
||||
|
@ -97,6 +90,7 @@ function ServerInfo()
|
|||
' set the server to new location and try again
|
||||
if right(headers.location, 19) = "/System/Info/Public"
|
||||
set_setting("server", left(headers.location, len(headers.location) - 19))
|
||||
session.server.UpdateURL(left(headers.location, len(headers.location) - 19))
|
||||
info = ServerInfo()
|
||||
if info.Error
|
||||
info.UpdatedUrl = left(headers.location, len(headers.location) - 19)
|
||||
|
@ -134,7 +128,7 @@ end function
|
|||
|
||||
' Load and parse Display Settings from server
|
||||
sub LoadUserPreferences()
|
||||
id = get_setting("active_user")
|
||||
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)
|
||||
|
@ -148,14 +142,13 @@ sub LoadUserPreferences()
|
|||
end if
|
||||
end sub
|
||||
|
||||
sub LoadUserAbilities(user)
|
||||
' Only have one thing we're checking now, but in the future it could be more...
|
||||
if user.Policy.EnableLiveTvManagement = true
|
||||
sub LoadUserAbilities()
|
||||
if m.global.session.user.Policy.EnableLiveTvManagement = true
|
||||
set_user_setting("livetv.canrecord", "true")
|
||||
else
|
||||
set_user_setting("livetv.canrecord", "false")
|
||||
end if
|
||||
if user.Policy.EnableContentDeletion = true
|
||||
if m.global.session.user.Policy.EnableContentDeletion = true
|
||||
set_user_setting("content.candelete", "true")
|
||||
else
|
||||
set_user_setting("content.candelete", "false")
|
||||
|
@ -197,9 +190,11 @@ function AuthenticateViaQuickConnect(secret)
|
|||
}
|
||||
req = APIRequest("Users/AuthenticateWithQuickConnect")
|
||||
jsonResponse = postJson(req, FormatJson(params))
|
||||
if jsonResponse <> invalid and jsonResponse.AccessToken <> invalid
|
||||
if jsonResponse <> invalid and jsonResponse.AccessToken <> invalid and jsonResponse.User <> invalid
|
||||
userdata = CreateObject("roSGNode", "UserData")
|
||||
userdata.json = jsonResponse
|
||||
session.user.Update("id", jsonResponse.User.Id)
|
||||
session.user.Update("authToken", jsonResponse.AccessToken)
|
||||
userdata.callFunc("setActive")
|
||||
userdata.callFunc("saveToRegistry")
|
||||
return true
|
||||
|
|
|
@ -27,7 +27,7 @@ function defaultSubtitleTrackFromVid(video_id) as integer
|
|||
if default_text_subs <> -1
|
||||
return default_text_subs
|
||||
else
|
||||
if get_user_setting("playback.subs.onlytext") = "false"
|
||||
if m.global.session.user.settings["playback.subs.onlytext"] = false
|
||||
return defaultSubtitleTrack(subtitles["all"]) ' if no appropriate text subs exist, allow non-text
|
||||
else
|
||||
return -1
|
||||
|
@ -44,23 +44,23 @@ end function
|
|||
' This allows forcing text subs, since roku requires transcoding of non-text subs
|
||||
' returns the server-side track index for the appriate subtitle
|
||||
function defaultSubtitleTrack(sorted_subtitles, require_text = false) as integer
|
||||
if m.user.Configuration.SubtitleMode = "None"
|
||||
if m.global.session.user.configuration.SubtitleMode = "None"
|
||||
return -1 ' No subtitles desired: select none
|
||||
end if
|
||||
|
||||
for each item in sorted_subtitles
|
||||
' Only auto-select subtitle if language matches preference
|
||||
languageMatch = (m.user.Configuration.SubtitleLanguagePreference = item.Track.Language)
|
||||
languageMatch = (m.global.session.user.configuration.SubtitleLanguagePreference = item.Track.Language)
|
||||
' Ensure textuality of subtitle matches preferenced passed as arg
|
||||
matchTextReq = ((require_text and item.IsTextSubtitleStream) or not require_text)
|
||||
if languageMatch and matchTextReq
|
||||
if m.user.Configuration.SubtitleMode = "Default" and (item.isForced or item.IsDefault or item.IsExternal)
|
||||
if m.global.session.user.configuration.SubtitleMode = "Default" and (item.isForced or item.IsDefault or item.IsExternal)
|
||||
return item.Index ' Finds first forced, or default, or external subs in sorted list
|
||||
else if m.user.Configuration.SubtitleMode = "Always" and not item.IsForced
|
||||
else if m.global.session.user.configuration.SubtitleMode = "Always" and not item.IsForced
|
||||
return item.Index ' Select the first non-forced subtitle option in the sorted list
|
||||
else if m.user.Configuration.SubtitleMode = "OnlyForced" and item.IsForced
|
||||
else if m.global.session.user.configuration.SubtitleMode = "OnlyForced" and item.IsForced
|
||||
return item.Index ' Select the first forced subtitle option in the sorted list
|
||||
else if m.user.Configuration.SubtitlePlaybackMode = "Smart" and (item.isForced or item.IsDefault or item.IsExternal)
|
||||
else if m.global.session.user.configuration.SubtitlePlaybackMode = "Smart" and (item.isForced or item.IsDefault or item.IsExternal)
|
||||
' Simplified "Smart" logic here mimics Default (as that is fallback behavior normally)
|
||||
' Avoids detecting preferred audio language (as is utilized in main client)
|
||||
return item.Index
|
||||
|
@ -192,7 +192,7 @@ end sub
|
|||
function sortSubtitles(id as string, MediaStreams)
|
||||
tracks = { "forced": [], "default": [], "normal": [] }
|
||||
'Too many args for using substitute
|
||||
prefered_lang = m.user.Configuration.SubtitleLanguagePreference
|
||||
prefered_lang = m.global.session.user.configuration.SubtitleLanguagePreference
|
||||
for each stream in MediaStreams
|
||||
if stream.type = "Subtitle"
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
' "Registry" is where Roku stores config
|
||||
' needed for set_user_setting() and unset_user_setting()
|
||||
import "pkg:/source/utils/session.bs"
|
||||
|
||||
' Read config tree from json config file and return
|
||||
function GetConfigTree()
|
||||
return ParseJSON(ReadAsciiFile("pkg:/settings/settings.json"))
|
||||
end function
|
||||
|
||||
|
||||
' Generic registry accessors
|
||||
function registry_read(key, section = invalid)
|
||||
if section = invalid then return invalid
|
||||
|
@ -28,6 +28,24 @@ sub registry_delete(key, section = invalid)
|
|||
reg.flush()
|
||||
end sub
|
||||
|
||||
' Return all data found inside a registry section
|
||||
function RegistryReadAll(section as string) as dynamic
|
||||
if section = "" then return invalid
|
||||
|
||||
registry = CreateObject("roRegistrySection", section)
|
||||
regKeyList = registry.GetKeyList()
|
||||
registryData = {}
|
||||
for each item in regKeyList
|
||||
' ignore session related tokens
|
||||
if item <> "token" and item <> "username" and item <> "password"
|
||||
if registry.Exists(item)
|
||||
registryData.AddReplace(item, registry.Read(item))
|
||||
end if
|
||||
end if
|
||||
end for
|
||||
|
||||
return registryData
|
||||
end function
|
||||
|
||||
' "Jellyfin" registry accessors for the default global settings
|
||||
function get_setting(key, default = invalid)
|
||||
|
@ -44,38 +62,25 @@ sub unset_setting(key)
|
|||
registry_delete(key, "Jellyfin")
|
||||
end sub
|
||||
|
||||
|
||||
' User registry accessors for the currently active user
|
||||
function get_user_setting(key, default = invalid)
|
||||
if get_setting("active_user") = invalid then return default
|
||||
value = registry_read(key, get_setting("active_user"))
|
||||
if value = invalid
|
||||
|
||||
' Check for default in Config Tree
|
||||
configTree = GetConfigTree()
|
||||
configKey = findConfigTreeKey(key, configTree)
|
||||
|
||||
if configKey <> invalid and configKey.default <> invalid
|
||||
set_user_setting(key, configKey.default) ' Set user setting to default
|
||||
return configKey.default
|
||||
end if
|
||||
|
||||
return default
|
||||
end if
|
||||
function get_user_setting(key as string) as dynamic
|
||||
if key = "" or m.global.session.user.id = invalid then return invalid
|
||||
value = registry_read(key, m.global.session.user.id)
|
||||
return value
|
||||
end function
|
||||
|
||||
sub set_user_setting(key, value)
|
||||
if get_setting("active_user") = invalid then return
|
||||
registry_write(key, value, get_setting("active_user"))
|
||||
sub set_user_setting(key as string, value as dynamic)
|
||||
if m.global.session.user.id = invalid then return
|
||||
session.user.settings.Save(key, value)
|
||||
registry_write(key, value, m.global.session.user.id)
|
||||
end sub
|
||||
|
||||
sub unset_user_setting(key)
|
||||
if get_setting("active_user") = invalid then return
|
||||
registry_delete(key, get_setting("active_user"))
|
||||
sub unset_user_setting(key as string)
|
||||
if m.global.session.user.id = invalid then return
|
||||
session.user.settings.Delete(key)
|
||||
registry_delete(key, m.global.session.user.id)
|
||||
end sub
|
||||
|
||||
|
||||
' Recursivly search the config tree for entry with settingname equal to key
|
||||
function findConfigTreeKey(key as string, tree)
|
||||
for each item in tree
|
||||
|
@ -89,5 +94,3 @@ function findConfigTreeKey(key as string, tree)
|
|||
|
||||
return invalid
|
||||
end function
|
||||
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ sub PostDeviceProfile()
|
|||
end sub
|
||||
|
||||
function getDeviceProfile() as object
|
||||
playMpeg2 = get_user_setting("playback.mpeg2") = "true"
|
||||
playAv1 = get_user_setting("playback.av1") = "true"
|
||||
playMpeg2 = m.global.session.user.settings["playback.mpeg2"]
|
||||
playAv1 = m.global.session.user.settings["playback.av1"]
|
||||
di = CreateObject("roDeviceInfo")
|
||||
|
||||
maxAudioChannels = "2" ' Currently Jellyfin server expects this as a string
|
||||
|
@ -390,10 +390,10 @@ function GetDirectPlayProfiles() as object
|
|||
videoCodecs = ["h264", "vp8", "hevc", "vp9"]
|
||||
audioCodecs = ["mp3", "pcm", "lpcm", "wav", "ac3", "wma", "flac", "alac", "aac", "opus", "dts", "wmapro", "vorbis", "eac3"]
|
||||
' respect user settings
|
||||
if get_user_setting("playback.mpeg4") = "true"
|
||||
if m.global.session.user.settings["playback.mpeg4"]
|
||||
videoCodecs.push("mpeg4")
|
||||
end if
|
||||
if get_user_setting("playback.mpeg2") = "true"
|
||||
if m.global.session.user.settings["playback.mpeg2"]
|
||||
videoCodecs.push("mpeg2")
|
||||
end if
|
||||
' check video codecs for each container
|
||||
|
@ -449,8 +449,8 @@ function GetDirectPlayProfiles() as object
|
|||
end function
|
||||
|
||||
function GetBitRateLimit(codec as string)
|
||||
if get_user_setting("playback.bitrate.maxlimited") = "true"
|
||||
userSetLimit = get_user_setting("playback.bitrate.limit").ToInt()
|
||||
if m.global.session.user.settings["playback.bitrate.maxlimited"] = true
|
||||
userSetLimit = m.global.session.user.settings["playback.bitrate.limit"]
|
||||
userSetLimit *= 1000000
|
||||
|
||||
if userSetLimit > 0
|
||||
|
|
255
source/utils/session.bs
Normal file
255
source/utils/session.bs
Normal file
|
@ -0,0 +1,255 @@
|
|||
' these are needed for ServerInfo() inside session.server.Populate()
|
||||
import "pkg:/source/api/userauth.brs"
|
||||
import "pkg:/source/api/baserequest.brs"
|
||||
|
||||
namespace session
|
||||
' Initialize the global session array
|
||||
sub Init()
|
||||
m.global.addFields({
|
||||
session: {
|
||||
server: {},
|
||||
user: {
|
||||
Configuration: {},
|
||||
Policy: {},
|
||||
settings: {}
|
||||
}
|
||||
}
|
||||
})
|
||||
session.user.settings.SaveDefaults()
|
||||
end sub
|
||||
|
||||
' Empty the global session array
|
||||
sub Delete()
|
||||
session.server.Delete()
|
||||
session.user.Logout()
|
||||
end sub
|
||||
|
||||
' Update one value from the global session array (m.global.session)
|
||||
sub Update(key as string, value = {} as object)
|
||||
' validate parameters
|
||||
if key = "" or (key <> "user" and key <> "server") or value = invalid
|
||||
print "Error in session.Update(): Invalid parameters provided"
|
||||
return
|
||||
end if
|
||||
' make copy of global session array
|
||||
tmpSession = m.global.session
|
||||
' update the temp session array
|
||||
tmpSession.AddReplace(key, value)
|
||||
' use the temp session array to update the global node
|
||||
m.global.setFields({ session: tmpSession })
|
||||
' print "m.global.session." + key + " = ", m.global.session[key]
|
||||
end sub
|
||||
|
||||
namespace server
|
||||
' Empty the global server session array
|
||||
sub Delete()
|
||||
session.Update("server")
|
||||
end sub
|
||||
|
||||
' Add or update one value from the global server session array (m.global.session.server)
|
||||
sub Update(key as string, value as dynamic)
|
||||
' validate parameters
|
||||
if key = "" or value = invalid then return
|
||||
' make copy of global server session array
|
||||
tmpSessionServer = m.global.session.server
|
||||
' update the temp server array
|
||||
tmpSessionServer[key] = value
|
||||
|
||||
session.Update("server", tmpSessionServer)
|
||||
end sub
|
||||
|
||||
' Add or update the jellyfin server URL from the global server session array (m.global.session.server)
|
||||
sub UpdateURL(value as string)
|
||||
' validate parameters
|
||||
if value = "" then return
|
||||
session.server.Update("url", value)
|
||||
session.server.Populate()
|
||||
end sub
|
||||
|
||||
' Use the saved server url to populate the global server session array (m.global.session.server)
|
||||
sub Populate()
|
||||
' validate server url
|
||||
if m.global.session.server.url = invalid or m.global.session.server.url = "" then return
|
||||
' get server info using API
|
||||
myServerInfo = ServerInfo()
|
||||
' validate data returned from API
|
||||
if myServerInfo.id = invalid then return
|
||||
' make copy of global server session
|
||||
tmpSessionServer = m.global.session.server
|
||||
' update the temp array
|
||||
tmpSessionServer.AddReplace("id", myServerInfo.Id)
|
||||
tmpSessionServer.AddReplace("name", myServerInfo.ServerName)
|
||||
tmpSessionServer.AddReplace("localURL", myServerInfo.LocalAddress)
|
||||
tmpSessionServer.AddReplace("os", myServerInfo.OperatingSystem)
|
||||
tmpSessionServer.AddReplace("startupWizardCompleted", myServerInfo.StartupWizardCompleted)
|
||||
tmpSessionServer.AddReplace("version", myServerInfo.Version)
|
||||
tmpSessionServer.AddReplace("hasError", myServerInfo.error)
|
||||
' check urls for https
|
||||
isServerHTTPS = false
|
||||
if tmpSessionServer.url.left(8) = "https://" then isServerHTTPS = true
|
||||
tmpSessionServer.AddReplace("isHTTPS", isServerHTTPS)
|
||||
isLocalServerHTTPS = false
|
||||
if myServerInfo.LocalAddress <> invalid and myServerInfo.LocalAddress.left(8) = "https://" then isLocalServerHTTPS = true
|
||||
tmpSessionServer.AddReplace("isLocalHTTPS", isLocalServerHTTPS)
|
||||
' update global server session using the temp array
|
||||
session.Update("server", tmpSessionServer)
|
||||
end sub
|
||||
end namespace
|
||||
|
||||
namespace user
|
||||
|
||||
' Add or update one value from the global user session array (m.global.session.user)
|
||||
sub Update(key as string, value as dynamic)
|
||||
' validate parameters
|
||||
if key = "" or value = invalid then return
|
||||
' make copy of global user session
|
||||
tmpSessionUser = m.global.session.user
|
||||
' update the temp user array
|
||||
tmpSessionUser[key] = value
|
||||
' update global user session using the temp array
|
||||
session.Update("user", tmpSessionUser)
|
||||
end sub
|
||||
|
||||
' Update the global session after user is authenticated.
|
||||
' Accepts a UserData.xml object from get_token() or an assocArray from AboutMe()
|
||||
sub Login(userData as object)
|
||||
' validate parameters
|
||||
if userData = invalid or userData.id = invalid then return
|
||||
' make copy of global user session array
|
||||
tmpSession = m.global.session
|
||||
oldUserSettings = tmpSession.user.settings
|
||||
if userData.json = invalid
|
||||
' we were passed data from AboutMe()
|
||||
myAuthToken = tmpSession.user.authToken
|
||||
tmpSession.AddReplace("user", userData)
|
||||
tmpSession.user.AddReplace("authToken", myAuthToken)
|
||||
else
|
||||
' we were passed data from a UserData object
|
||||
tmpSession.AddReplace("user", userData.json.User)
|
||||
tmpSession.user.AddReplace("authToken", userData.json.AccessToken)
|
||||
end if
|
||||
|
||||
tmpSession.user.AddReplace("settings", oldUserSettings)
|
||||
' update global user session
|
||||
session.Update("user", tmpSession.user)
|
||||
|
||||
' update user session settings with values from registry
|
||||
userSettings = RegistryReadAll(tmpSession.user.id)
|
||||
for each setting in userSettings
|
||||
session.user.settings.Save(setting, userSettings[setting])
|
||||
end for
|
||||
|
||||
if m.global.app.isDev
|
||||
print "m.global.session.user.settings = ", m.global.session.user.settings
|
||||
end if
|
||||
' ensure registry is updated
|
||||
set_user_setting("username", tmpSession.user.name)
|
||||
set_user_setting("token", tmpSession.user.authToken)
|
||||
end sub
|
||||
|
||||
' Empty the global user session array and reload defaults
|
||||
sub Logout()
|
||||
session.Update("user", {
|
||||
Configuration: {},
|
||||
Policy: {},
|
||||
settings: {}
|
||||
})
|
||||
' reload default user settings
|
||||
session.user.settings.SaveDefaults()
|
||||
end sub
|
||||
|
||||
namespace settings
|
||||
' Delete the user setting from the global session (m.global.session.user.settings)
|
||||
sub Delete(name as string)
|
||||
' validate parameters
|
||||
if name = "" then return
|
||||
tmpSettingArray = m.global.session.user.settings
|
||||
' update the temp user array
|
||||
tmpSettingArray.Delete(name)
|
||||
' update global user session using the temp array
|
||||
session.user.Update("settings", tmpSettingArray)
|
||||
end sub
|
||||
|
||||
' Read the user setting from the global session (m.global.session.user.settings)
|
||||
function Read(name as string) as dynamic
|
||||
' validate parameters
|
||||
if name = "" then return invalid
|
||||
|
||||
if m.global.session.user.settings[name] <> invalid
|
||||
return m.global.session.user.settings[name]
|
||||
else
|
||||
return invalid
|
||||
end if
|
||||
end function
|
||||
|
||||
' retrieve all default user settings from Config Tree
|
||||
sub SaveDefaults()
|
||||
configTree = GetConfigTree()
|
||||
if configTree = invalid then return
|
||||
|
||||
for each item in configTree
|
||||
if item.default <> invalid and item.settingName <> invalid
|
||||
session.user.settings.Save(item.settingName, item.default)
|
||||
else if item.children <> invalid and item.children.Count() > 0
|
||||
for each child in item.children
|
||||
if child.default <> invalid and child.settingName <> invalid
|
||||
session.user.settings.Save(child.settingName, child.default)
|
||||
else if child.children <> invalid and child.children.Count() > 0
|
||||
for each child in child.children
|
||||
if child.default <> invalid and child.settingName <> invalid
|
||||
session.user.settings.Save(child.settingName, child.default)
|
||||
else if child.children <> invalid and child.children.Count() > 0
|
||||
for each child in child.children
|
||||
if child.default <> invalid and child.settingName <> invalid
|
||||
session.user.settings.Save(child.settingName, child.default)
|
||||
else if child.children <> invalid and child.children.Count() > 0
|
||||
for each child in child.children
|
||||
if child.default <> invalid and child.settingName <> invalid
|
||||
session.user.settings.Save(child.settingName, child.default)
|
||||
else if child.children <> invalid and child.children.Count() > 0
|
||||
for each child in child.children
|
||||
if child.default <> invalid and child.settingName <> invalid
|
||||
session.user.settings.Save(child.settingName, child.default)
|
||||
end if
|
||||
end for
|
||||
end if
|
||||
end for
|
||||
end if
|
||||
end for
|
||||
end if
|
||||
end for
|
||||
end if
|
||||
end for
|
||||
end if
|
||||
end for
|
||||
end sub
|
||||
|
||||
' Saves the user setting to the global session.
|
||||
' This also converts strings to boolean and integer as necessary before saving to global session
|
||||
sub Save(name as string, value as string)
|
||||
if name = invalid or value = invalid then return
|
||||
tmpSettingArray = m.global.session.user.settings
|
||||
convertedValue = value
|
||||
|
||||
' convert to int
|
||||
valueInteger = value.ToInt()
|
||||
if value = "0" or valueInteger <> 0
|
||||
convertedValue = valueInteger
|
||||
end if
|
||||
|
||||
' convert to boolean
|
||||
if type(value) = "String"
|
||||
if value = "true"
|
||||
convertedValue = true
|
||||
else if value = "false"
|
||||
convertedValue = false
|
||||
end if
|
||||
end if
|
||||
|
||||
tmpSettingArray[name] = convertedValue
|
||||
|
||||
session.user.Update("settings", tmpSettingArray)
|
||||
end sub
|
||||
end namespace
|
||||
end namespace
|
||||
end namespace
|
Loading…
Reference in New Issue
Block a user