diff --git a/.github/workflows/auto-close-stale-pr.yml b/.github/workflows/auto-close-stale-pr.yml
index 5cdd7447f..00892eec5 100644
--- a/.github/workflows/auto-close-stale-pr.yml
+++ b/.github/workflows/auto-close-stale-pr.yml
@@ -15,9 +15,9 @@ jobs:
days-before-issue-stale: -1
days-before-issue-close: -1
stale-pr-label: stale
- stale-pr-message: "This pull request has been inactive for 21 days and will be automatically closed in 7 days if there is no further activity."
- close-pr-message: "This pull request has been closed because it has been inactive for 28 days. You may submit a new pull request if desired."
- days-before-pr-stale: 21
- days-before-pr-close: 7
+ stale-pr-message: "This pull request has been inactive for 30 days and will be automatically closed in 15 days if there is no further activity."
+ close-pr-message: "This pull request has been closed because it has been inactive for 45 days. You may submit a new pull request if desired."
+ days-before-pr-stale: 30
+ days-before-pr-close: 15
exempt-draft-pr: true
repo-token: ${{ secrets.JF_BOT_TOKEN }}
diff --git a/.github/workflows/automations.yml b/.github/workflows/automations.yml
index a29a73f4d..3f167cb54 100644
--- a/.github/workflows/automations.yml
+++ b/.github/workflows/automations.yml
@@ -10,7 +10,8 @@ on:
jobs:
project:
- if: github.repository == 'jellyfin/jellyfin-roku'
+ # don't run job on forks and prevent job from running twice when a PR pushes a new commit
+ if: github.repository == 'jellyfin/jellyfin-roku' && github.event_name != 'pull_request' || github.repository == 'jellyfin/jellyfin-roku' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
name: Project board 📊
runs-on: ubuntu-latest
steps:
@@ -22,7 +23,8 @@ jobs:
column: In progress
repo-token: ${{ secrets.JF_BOT_TOKEN }}
label:
- if: github.repository == 'jellyfin/jellyfin-roku'
+ # don't run job on forks and prevent job from running twice when a PR pushes a new commit
+ if: github.repository == 'jellyfin/jellyfin-roku' && github.event_name != 'pull_request' || github.repository == 'jellyfin/jellyfin-roku' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
name: Labeling 🏷️
runs-on: ubuntu-latest
steps:
diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml
index 7dd170e12..46f97c295 100644
--- a/.github/workflows/build-dev.yml
+++ b/.github/workflows/build-dev.yml
@@ -6,10 +6,12 @@ on:
jobs:
dev:
+ # prevent job from running twice when a PR pushes a new commit
+ if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
+ - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with:
node-version: "lts/*"
cache: "npm"
@@ -19,7 +21,7 @@ jobs:
run: npm run ropm
- name: Build app
run: npm run build
- - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
+ - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
with:
name: Jellyfin-Roku-dev-${{ github.sha }}
path: ${{ github.workspace }}/build/staging
diff --git a/.github/workflows/build-prod.yml b/.github/workflows/build-prod.yml
index 63e58dbbd..d482f30d2 100644
--- a/.github/workflows/build-prod.yml
+++ b/.github/workflows/build-prod.yml
@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
+ - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with:
node-version: "lts/*"
cache: "npm"
@@ -23,7 +23,7 @@ jobs:
run: npm run ropm
- name: Build app for production
run: npm run build-prod
- - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
+ - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
with:
name: Jellyfin-Roku-v${{ env.newManVersion }}-${{ github.sha }}
path: ${{ github.workspace }}/build/staging
diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml
index 5670dc7de..1b64af00a 100644
--- a/.github/workflows/bump-version.yml
+++ b/.github/workflows/bump-version.yml
@@ -94,7 +94,7 @@ jobs:
git add .
git commit -m "Bump ${{ github.event.inputs.versionType }} version"
git push --set-upstream origin "${{ env.newBranch }}"
- gh pr create --title "Bump ${{ github.event.inputs.targetBranch }} branch to ${{ env.newVersion }}" --body "Bump version to prep for next release." --label ignore-changelog --base ${{ env.targetBranch }}
+ gh pr create --title "Bump ${{ github.event.inputs.targetBranch }} branch to ${{ env.newVersion }}" --body "Bump version to prep for next release. Generated by `.github/workflows/bump-version.yml`" --label ignore-changelog --base ${{ env.targetBranch }}
minor:
if: ${{ github.event.inputs.versionType == 'minor' }}
runs-on: ubuntu-latest
@@ -161,7 +161,7 @@ jobs:
git add .
git commit -m "Bump ${{ github.event.inputs.versionType }} version"
git push --set-upstream origin "${{ env.newBranch }}"
- gh pr create --title "Bump ${{ github.event.inputs.targetBranch }} branch to ${{ env.newVersion }}" --body "Bump version to prep for next release." --label ignore-changelog --base ${{ env.targetBranch }}
+ gh pr create --title "Bump ${{ github.event.inputs.targetBranch }} branch to ${{ env.newVersion }}" --body "Bump version to prep for next release. Generated by `.github/workflows/bump-version.yml`" --label ignore-changelog --base ${{ env.targetBranch }}
major:
if: ${{ github.event.inputs.versionType == 'major' }}
@@ -231,5 +231,5 @@ jobs:
git add .
git commit -m "Bump ${{ github.event.inputs.versionType }} version"
git push --set-upstream origin "${{ env.newBranch }}"
- gh pr create --title "Bump ${{ github.event.inputs.targetBranch }} branch to ${{ env.newVersion }}" --body "Bump version to prep for next release." --label ignore-changelog --base ${{ env.targetBranch }}
+ gh pr create --title "Bump ${{ github.event.inputs.targetBranch }} branch to ${{ env.newVersion }}" --body "Bump version to prep for next release. Generated by `.github/workflows/bump-version.yml`" --label ignore-changelog --base ${{ env.targetBranch }}
\ No newline at end of file
diff --git a/.github/workflows/lint-brightscript.yml b/.github/workflows/lint-brightscript.yml
new file mode 100644
index 000000000..560bfd8be
--- /dev/null
+++ b/.github/workflows/lint-brightscript.yml
@@ -0,0 +1,20 @@
+name: lint-brightscript
+on:
+ pull_request:
+ paths:
+ - "**/*.brs"
+ - "**/*.bs"
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@master
+ - uses: actions/setup-node@master
+ with:
+ node-version: "lts/*"
+ cache: "npm"
+ - run: npm ci
+ - run: npx ropm install
+ - run: npm run validate
+ - run: npm run check-formatting
diff --git a/.github/workflows/lint-json.yml b/.github/workflows/lint-json.yml
new file mode 100644
index 000000000..a5b9f9080
--- /dev/null
+++ b/.github/workflows/lint-json.yml
@@ -0,0 +1,23 @@
+name: lint-json
+on:
+ pull_request:
+ paths:
+ - "!docs/api/**"
+ - "**/*.json"
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Clone github repo
+ uses: actions/checkout@master
+ - uses: actions/setup-node@master
+ with:
+ node-version: "lts/*"
+ cache: "npm"
+ - name: Install npm dependencies
+ run: npm ci
+ - name: Install roku package dependencies
+ run: npx ropm install
+ - name: Validate JSON syntax
+ run: npm run lint-json
\ No newline at end of file
diff --git a/.github/workflows/lint-markdown.yml b/.github/workflows/lint-markdown.yml
new file mode 100644
index 000000000..a3a0f1a28
--- /dev/null
+++ b/.github/workflows/lint-markdown.yml
@@ -0,0 +1,23 @@
+name: lint-markdown
+on:
+ pull_request:
+ paths:
+ - "**/*.md"
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Clone github repo
+ uses: actions/checkout@master
+ - uses: actions/setup-node@master
+ with:
+ node-version: "lts/*"
+ cache: "npm"
+ - name: Install npm dependencies
+ run: npm ci
+ - name: Install roku package dependencies
+ run: npx ropm install
+ - uses: xt0rted/markdownlint-problem-matcher@1a5fabfb577370cfdf5af944d418e4be3ea06f27 # v3
+ - name: Lint markdown files
+ run: npm run lint-markdown
diff --git a/.github/workflows/lint-spelling.yml b/.github/workflows/lint-spelling.yml
new file mode 100644
index 000000000..c2c9b8545
--- /dev/null
+++ b/.github/workflows/lint-spelling.yml
@@ -0,0 +1,22 @@
+name: lint-spelling
+on:
+ pull_request:
+ paths:
+ - "**/*.md"
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Clone github repo
+ uses: actions/checkout@master
+ - uses: actions/setup-node@master
+ with:
+ node-version: "lts/*"
+ cache: "npm"
+ - name: Install npm dependencies
+ run: npm ci
+ - name: Install roku package dependencies
+ run: npx ropm install
+ - name: Check markdown files for spelling errors
+ run: npm run lint-spelling
diff --git a/.github/workflows/lint-translation-files.yml b/.github/workflows/lint-translation-files.yml
new file mode 100644
index 000000000..011547e4c
--- /dev/null
+++ b/.github/workflows/lint-translation-files.yml
@@ -0,0 +1,25 @@
+name: lint-translation-files
+on:
+ pull_request:
+ paths:
+ - "locale/*/*.ts"
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Clone github repo
+ uses: actions/checkout@master
+ - name: Install xmllint and xmlstarlet using apt (from cache)
+ uses: awalsh128/cache-apt-pkgs-action@latest
+ with:
+ packages: libxml2-utils xmlstarlet
+ - name: Validate XML syntax
+ run: xmllint --noout ./locale/en_US/translations.ts
+ - name: Save output of duplicate check
+ run: echo "tsDuplicates=$(xmlstarlet sel -t -m '/TS/context/message/source' -c '.' -nl ./locale/en_US/translations.ts | sort | uniq -d | awk '{ printf "%s", $0 }')" >> $GITHUB_ENV
+ - name: Check for duplicates
+ run: xmlstarlet sel -t -m '/TS/context/message/source' -f -o ' ' -c '.' -nl ./locale/en_US/translations.ts | sort | uniq -d
+ - name: Duplicates found
+ if: env.tsDuplicates != ''
+ run: exit 1
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
deleted file mode 100644
index a46dfa9d8..000000000
--- a/.github/workflows/lint.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-name: lint
-on:
- pull_request:
-
-jobs:
- brightscript:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@master
- - uses: actions/setup-node@master
- with:
- node-version: "lts/*"
- cache: "npm"
- - run: npm ci
- - run: npx ropm install
- - run: npm run validate
- - run: npm run check-formatting
- translation-files:
- runs-on: ubuntu-latest
- steps:
- - name: Clone github repo
- uses: actions/checkout@master
- - name: Install xmllint and xmlstarlet using apt (from cache)
- uses: awalsh128/cache-apt-pkgs-action@latest
- with:
- packages: libxml2-utils xmlstarlet
- - name: Validate XML syntax
- run: xmllint --noout ./locale/en_US/translations.ts
- - name: Save output of duplicate check
- run: echo "tsDuplicates=$(xmlstarlet sel -t -m '/TS/context/message/source' -c '.' -nl ./locale/en_US/translations.ts | sort | uniq -d | awk '{ printf "%s", $0 }')" >> $GITHUB_ENV
- - name: Check for duplicates
- run: xmlstarlet sel -t -m '/TS/context/message/source' -f -o ' ' -c '.' -nl ./locale/en_US/translations.ts | sort | uniq -d
- - name: Duplicates found
- if: env.tsDuplicates != ''
- run: exit 1
- json:
- runs-on: ubuntu-latest
- steps:
- - name: Clone github repo
- uses: actions/checkout@master
- - uses: actions/setup-node@master
- with:
- node-version: "lts/*"
- cache: "npm"
- - name: Install npm dependencies
- run: npm ci
- - name: Install roku package dependencies
- run: npx ropm install
- - name: Validate JSON syntax
- run: npm run lint-json
- markdown:
- runs-on: ubuntu-latest
- steps:
- - name: Clone github repo
- uses: actions/checkout@master
- - uses: actions/setup-node@master
- with:
- node-version: "lts/*"
- cache: "npm"
- - name: Install npm dependencies
- run: npm ci
- - name: Install roku package dependencies
- run: npx ropm install
- - uses: xt0rted/markdownlint-problem-matcher@1a5fabfb577370cfdf5af944d418e4be3ea06f27 # v3
- - name: Lint markdown files
- run: npm run lint-markdown
- spelling:
- runs-on: ubuntu-latest
- steps:
- - name: Clone github repo
- uses: actions/checkout@master
- - uses: actions/setup-node@master
- with:
- node-version: "lts/*"
- cache: "npm"
- - name: Install npm dependencies
- run: npm ci
- - name: Install roku package dependencies
- run: npx ropm install
- - name: Check markdown files for spelling errors
- run: npm run lint-spelling
diff --git a/.github/workflows/release-prep.yml b/.github/workflows/release-prep.yml
deleted file mode 100644
index 35619c328..000000000
--- a/.github/workflows/release-prep.yml
+++ /dev/null
@@ -1,80 +0,0 @@
-# All of the jobs in this workflow will only run if the PR that triggered it has a 'release-prep' label
-name: release-prep
-
-on:
- pull_request:
- types: [labeled, opened, reopened, synchronize]
-
-jobs:
- version-check:
- if: ${{ contains(github.event.pull_request.labels.*.name, 'release-prep') }}
- runs-on: ubuntu-latest
- steps:
- - name: DEBUG ${{ github.event.pull_request.base.ref }}
- run: echo ${{ github.event.pull_request.base.ref }}
- - name: Checkout the branch this PR wants to update
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- with:
- ref: ${{ github.event.pull_request.base.ref }}
- - name: Install jq to parse json
- uses: awalsh128/cache-apt-pkgs-action@latest
- with:
- packages: jq
- - name: Save old package.json version
- run: echo "oldPackVersion=$(jq -r ".version" package.json)" >> $GITHUB_ENV
- - name: Find and save old major_version from manifest
- run: awk 'BEGIN { FS="=" } /^major_version/ { print "oldMajor="$2; }' manifest >> $GITHUB_ENV
- - name: Find and save old minor_version from manifest
- run: awk 'BEGIN { FS="=" } /^minor_version/ { print "oldMinor="$2; }' manifest >> $GITHUB_ENV
- - name: Find and save old build_version from manifest
- run: awk 'BEGIN { FS="=" } /^build_version/ { print "oldBuild="$2; }' manifest >> $GITHUB_ENV
- - name: Save old manifest version
- run: echo "oldManVersion=${{ env.oldMajor }}.${{ env.oldMinor }}.${{ env.oldBuild }}" >> $GITHUB_ENV
- - name: Save old Makefile version
- run: awk 'BEGIN { FS=" := " } /^VERSION/ { print "oldMakeVersion="$2; }' Makefile >> $GITHUB_ENV
- - name: Checkout PR branch
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- - name: Save new package.json version
- run: echo "newPackVersion=$(jq -r ".version" package.json)" >> $GITHUB_ENV
- - name: package.json version must be updated
- if: env.oldPackVersion == env.newPackVersion
- run: exit 1
- - name: Find and save new major_version from manifest
- run: awk 'BEGIN { FS="=" } /^major_version/ { print "newMajor="$2; }' manifest >> $GITHUB_ENV
- - name: Find and save new minor_version from manifest
- run: awk 'BEGIN { FS="=" } /^minor_version/ { print "newMinor="$2; }' manifest >> $GITHUB_ENV
- - name: Find and save new build_version from manifest
- run: awk 'BEGIN { FS="=" } /^build_version/ { print "newBuild="$2; }' manifest >> $GITHUB_ENV
- - name: Save new manifest version
- run: echo "newManVersion=${{ env.newMajor }}.${{ env.newMinor }}.${{ env.newBuild }}" >> $GITHUB_ENV
- - name: Manifest version must be updated
- if: env.oldManVersion == env.newManVersion
- run: exit 1
- - name: Save new Makefile version
- run: awk 'BEGIN { FS=" := " } /^VERSION/ { print "newMakeVersion="$2; }' Makefile >> $GITHUB_ENV
- - name: Makefile version must be updated
- if: env.oldMakeVersion == env.newMakeVersion
- run: exit 1
- - name: All new versions must match
- if: (env.newManVersion != env.newPackVersion) || (env.newManVersion != env.newMakeVersion)
- run: exit 1
- build-prod:
- if: ${{ contains(github.event.pull_request.labels.*.name, 'release-prep') }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
- with:
- node-version: "lts/*"
- cache: "npm"
- - name: NPM install
- run: npm ci
- - name: Install roku module dependencies
- run: npm run ropm
- - name: Build app for production
- run: npm run build-prod
- - uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4
- with:
- name: Jellyfin-Roku-v${{ env.newManVersion }}-${{ github.sha }}
- path: ${{ github.workspace }}/build/staging
- if-no-files-found: error
diff --git a/.github/workflows/roku-analysis.yml b/.github/workflows/roku-analysis.yml
index 2bac16036..6027db5a1 100644
--- a/.github/workflows/roku-analysis.yml
+++ b/.github/workflows/roku-analysis.yml
@@ -2,17 +2,18 @@ name: roku-analysis
on:
pull_request:
- push:
env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
jobs:
static:
+ # don't run job on forks and prevent job from running twice when a PR pushes a new commit
+ if: github.repository == 'jellyfin/jellyfin-roku' && github.event_name != 'pull_request' || github.repository == 'jellyfin/jellyfin-roku' && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
+ - uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4
with:
node-version: "lts/*"
cache: "npm"
@@ -27,7 +28,7 @@ jobs:
if: env.BRANCH_NAME == 'master'
run: npm run build-prod
- name: Setup Java
- uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4
+ uses: actions/setup-java@b36c23c0d998641eff861008f374ee103c25ac73 # v4
with:
distribution: "temurin"
java-version: "21"
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 482f3d164..59566402d 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -2,9 +2,9 @@
"version": "0.2.0",
"configurations": [
{
+ "name": "Build and Deploy",
"type": "brightscript",
"request": "launch",
- "name": "Jellyfin Debug",
"rootDir": "${workspaceFolder}/build/staging",
"preLaunchTask": "build-dev",
"stopOnEntry": false,
@@ -18,6 +18,22 @@
//WARNING: don't edit this value. Instead, set "brightscript.debug.password": "YOUR_PASSWORD_HERE" in your vscode user settings
//"password": "${promptForPassword}",
},
+ {
+ "name": "Deploy",
+ "type": "brightscript",
+ "request": "launch",
+ "rootDir": "${workspaceFolder}/build/staging",
+ "stopOnEntry": false,
+ // To enable RALE:
+ // set "brightscript.debug.raleTrackerTaskFileLocation": "/absolute/path/to/rale/TrackerTask.xml" in your vscode user settings
+ // set the below field to true
+ "injectRaleTrackerTask": false,
+ "injectRdbOnDeviceComponent": true,
+ //WARNING: don't edit this value. Instead, set "brightscript.debug.host": "YOUR_HOST_HERE" in your vscode user settings
+ //"host": "${promptForHost}",
+ //WARNING: don't edit this value. Instead, set "brightscript.debug.password": "YOUR_PASSWORD_HERE" in your vscode user settings
+ //"password": "${promptForPassword}",
+ },
{
"name": "Run tests",
"type": "brightscript",
diff --git a/components/ItemGrid/GridItem.bs b/components/ItemGrid/GridItem.bs
index 248f43024..9f7a62ae1 100644
--- a/components/ItemGrid/GridItem.bs
+++ b/components/ItemGrid/GridItem.bs
@@ -115,6 +115,21 @@ sub itemContentChanged()
else
m.itemText.text = itemData.Title
end if
+ ' Adjust to wide posters for "View All Next Up"
+ if m.itemGrid.overhangTitle = tr("View All Next Up")
+ m.posterMask.maskUri = ""
+
+ m.itemPoster.height = 300
+ m.itemPoster.width = 400
+ m.itemPoster.loadDisplayMode = "scaleToFit"
+
+ m.backdrop.height = 300
+ m.backdrop.width = 400
+ m.backdrop.loadDisplayMode = "scaleToFit"
+
+ m.itemText.translation = [0, m.itemPoster.height + 7]
+ m.itemText.maxWidth = 400
+ end if
else if itemData.type = "MusicArtist"
m.itemPoster.uri = itemData.PosterUrl
m.itemText.text = itemData.Title
diff --git a/components/ItemGrid/ItemGrid.bs b/components/ItemGrid/ItemGrid.bs
index b67b21787..759bacd7e 100644
--- a/components/ItemGrid/ItemGrid.bs
+++ b/components/ItemGrid/ItemGrid.bs
@@ -201,6 +201,14 @@ sub loadInitialItems()
' non recursive for collections (folders, boxsets, photo albums, etc)
m.loadItemsTask.recursive = false
end if
+
+ if getCollectionType() = "nextup"
+ m.loadItemsTask.itemType = "NextUp"
+ m.itemGrid.itemSize = "[400, 300]"
+ m.top.imageDisplayMode = "scaleToFit"
+ m.itemGrid.numColumns = 4
+ m.alpha.visible = false
+ end if
else if m.top.parentItem.json.type = "Studio"
m.loadItemsTask.itemId = m.top.parentItem.parentFolder
m.loadItemsTask.itemType = "Series,Movie"
@@ -406,7 +414,6 @@ sub SetUpOptions()
setPhotoAlbumOptions(options)
else if getCollectionType() = "music"
setMusicOptions(options)
-
else
setDefaultOptions(options)
end if
@@ -804,7 +811,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
searchGrp.setFocus(false)
end if
- if key = "options"
+ if key = "options" and getCollectionType() <> "nextup"
if m.options.visible = true
m.options.visible = false
m.top.removeChild(m.options)
@@ -854,7 +861,7 @@ function onKeyEvent(key as string, press as boolean) as boolean
m.top.quickPlayNode = itemToPlay
return true
end if
- else if key = "left" and topGrp.isinFocusChain()
+ else if key = "left" and topGrp.isinFocusChain() and m.alpha.visible
m.log.debug("Now entering alpha menu")
m.top.alphaActive = true
topGrp.setFocus(false)
diff --git a/components/ItemGrid/LoadItemsTask2.bs b/components/ItemGrid/LoadItemsTask2.bs
index 2a7292d90..2290103d1 100644
--- a/components/ItemGrid/LoadItemsTask2.bs
+++ b/components/ItemGrid/LoadItemsTask2.bs
@@ -130,6 +130,11 @@ sub loadItems()
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
params.append({ ImageTypeLimit: 1 })
params.append({ EnableImageTypes: "Primary,Backdrop,Banner,Thumb" })
+ else if LCase(m.top.ItemType) = "nextup"
+ url = "Shows/NextUp"
+ params.limit = 100 ' If you have more than 100 in your Next Up queue, maybe go outside a bit more.
+ params.append({ ImageTypeLimit: 1 })
+ params.append({ EnableImageTypes: "Primary,Backdrop,Banner,Thumb" })
else
url = Substitute("Users/{0}/Items/", m.global.session.user.id)
end if
@@ -194,6 +199,10 @@ sub loadItems()
tmp.image = PosterImage(item.id, { "maxHeight": 425, "maxWidth": 290, "quality": "90" })
else if item.type = "Episode"
tmp = CreateObject("roSGNode", "TVEpisode")
+ if LCase(m.top.ItemType) = "nextup"
+ tmp.title = item.name
+ tmp.type = "Episode"
+ end if
else if LCase(item.Type) = "recording"
tmp = CreateObject("roSGNode", "RecordingData")
else if item.Type = "Genre"
@@ -281,7 +290,7 @@ sub loadItems()
end if
if tmp <> invalid
- if item.Type <> "Genre" and item.Type <> "MusicGenre"
+ if LCase(item.Type) <> "genre" and LCase(item.Type) <> "musicgenre"
tmp.parentFolder = m.top.itemId
tmp.json = item
if item.UserData <> invalid and item.UserData.isFavorite <> invalid
diff --git a/components/ItemGrid/LoadVideoContentTask.bs b/components/ItemGrid/LoadVideoContentTask.bs
index 643df4fe1..74da4f449 100644
--- a/components/ItemGrid/LoadVideoContentTask.bs
+++ b/components/ItemGrid/LoadVideoContentTask.bs
@@ -118,8 +118,9 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
video.logoImage = api.items.GetImageURL(logoLookupID, "logo", 0, { "maxHeight": 65, "maxWidth": 300, "quality": "90" })
end if
- if m.global.session.user.Configuration.EnableNextEpisodeAutoPlay
- if LCase(m.top.itemType) = "episode"
+ if LCase(m.top.itemType) = "episode"
+ userSession = m.global.session.user
+ if userSession.settings["playback.playnextepisode"] = "enabled" or userSession.settings["playback.playnextepisode"] = "webclient" and userSession.Configuration.EnableNextEpisodeAutoPlay
addNextEpisodesToQueue(video.showID)
end if
end if
diff --git a/components/JFVideo.bs b/components/JFVideo.bs
index f4dfb74e8..5be3d8537 100644
--- a/components/JFVideo.bs
+++ b/components/JFVideo.bs
@@ -92,12 +92,14 @@ end sub
sub showNextEpisodeButton()
if m.top.content.contenttype <> 4 then return ' only display when content is type "Episode"
if m.nextupbuttonseconds = 0 then return ' is the button disabled?
-
- if m.nextEpisodeButton.opacity = 0 and m.global.session.user.configuration.EnableNextEpisodeAutoPlay
- m.nextEpisodeButton.visible = true
- m.showNextEpisodeButtonAnimation.control = "start"
- m.nextEpisodeButton.setFocus(true)
- end if
+ if m.nextEpisodeButton.opacity <> 0 then return
+ userSession = m.global.session.user
+ if userSession.settings["playback.playnextepisode"] = "disabled" then return
+ if userSession.settings["playback.playnextepisode"] = "webclient" and not userSession.Configuration.EnableNextEpisodeAutoPlay then return
+
+ m.nextEpisodeButton.visible = true
+ m.showNextEpisodeButtonAnimation.control = "start"
+ m.nextEpisodeButton.setFocus(true)
end sub
'
diff --git a/components/data/HomeData.bs b/components/data/HomeData.bs
index 196274507..648cdc8e8 100644
--- a/components/data/HomeData.bs
+++ b/components/data/HomeData.bs
@@ -19,15 +19,17 @@ sub setData()
' Set appropriate Images for Wide and Tall based on type
- if datum.type = "CollectionFolder" or datum.type = "UserView"
- params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
- m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
- m.top.widePosterUrl = m.top.thumbnailURL
+ if LCase(datum.type) = "collectionfolder" or LCase(datum.type) = "userview"
+ if IsValid(datum.ImageTags)
+ params = { "Tag": datum.ImageTags.Primary, "maxHeight": 261, "maxWidth": 464 }
+ m.top.thumbnailURL = ImageURL(datum.id, "Primary", params)
+ m.top.widePosterUrl = m.top.thumbnailURL
+ end if
' Add Icon URLs for display if there is no Poster
- if datum.CollectionType = "livetv"
+ if LCase(m.top.CollectionType) = "livetv"
m.top.iconUrl = "pkg:/images/media_type_icons/live_tv_white.png"
- else if datum.CollectionType = "folders"
+ else if LCase(m.top.CollectionType) = "folders" or LCase(m.top.CollectionType) = "nextup"
m.top.iconUrl = "pkg:/images/media_type_icons/folder_white.png"
end if
@@ -58,6 +60,7 @@ sub setData()
end if
else if datum.type = "Series"
+ m.top.isWatched = datum.UserData.Played
imgParams = { "maxHeight": 261 }
imgParams.Append({ "maxWidth": 464 })
diff --git a/components/home/HomeItem.bs b/components/home/HomeItem.bs
index 797e253c1..b1ddeb2be 100644
--- a/components/home/HomeItem.bs
+++ b/components/home/HomeItem.bs
@@ -151,9 +151,16 @@ sub itemContentChanged()
drawProgressBar(itemData)
end if
- if itemData.usePoster = true
+ if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "webclient"
+ tmpSetting = localGlobal.session.user.Configuration.useEpisodeImagesInNextUpAndResume
+ if isValid(tmpSetting) and tmpSetting
+ m.itemPoster.uri = itemData.thumbnailURL
+ else
+ m.itemPoster.uri = itemData.widePosterURL
+ end if
+ else if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "show"
m.itemPoster.uri = itemData.widePosterURL
- else
+ else if localGlobal.session.user.settings["ui.general.episodeimagesnextup"] = "episode"
m.itemPoster.uri = itemData.thumbnailURL
end if
diff --git a/components/home/LoadItemsTask.bs b/components/home/LoadItemsTask.bs
index 369ce7b43..f947d1250 100644
--- a/components/home/LoadItemsTask.bs
+++ b/components/home/LoadItemsTask.bs
@@ -68,7 +68,7 @@ sub loadItems()
params["SortOrder"] = "Descending"
params["ImageTypeLimit"] = 1
params["UserId"] = m.global.session.user.id
- params["EnableRewatching"] = false
+ params["EnableRewatching"] = m.global.session.user.settings["ui.details.enablerewatchingnextup"]
params["DisableFirstEpisode"] = false
params["limit"] = 24
params["EnableTotalRecordCount"] = false
@@ -85,6 +85,9 @@ sub loadItems()
end if
end if
+ addViewAll = true ' Assume there will be a "View All" to start
+ checkViewAll = false ' Only need to check if we don't have anything in the Next Up home row
+
resp = APIRequest(url, params)
data = getJson(resp)
if isValid(data) and isValid(data.Items)
@@ -93,6 +96,36 @@ sub loadItems()
tmp.json = item
results.push(tmp)
end for
+ if data.Items.Count() = 0
+ checkViewAll = true
+ end if
+ else
+ checkViewAll = true
+ end if
+
+ ' Add "View All"
+ if checkViewAll
+ ' Nothing to show in Next Up, but are there hidden items (e.g. > 365 days old)?
+ params.Delete("NextUpDateCutoff")
+ params["limit"] = 1 ' if there is even one, then we know we need to show "View All"
+ resp = APIRequest(url, params)
+ data = getJson(resp)
+ if not isValid(data) or isValid(data) and isValid(data.Items) and data.Items.Count() = 0
+ addViewAll = false
+ end if
+ end if
+
+ if addViewAll
+ tmp = CreateObject("roSGNode", "HomeData")
+ tmp.type = "CollectionFolder"
+ tmp.usePoster = false
+ tmp.json = {
+ IsFolder: true,
+ Name: tr("View All Next Up"),
+ Type: "CollectionFolder",
+ CollectionType: "nextup"
+ }
+ results.push(tmp)
end if
' Load Continue Watching
else if m.top.itemsToLoad = "continue"
diff --git a/components/music/AlbumView.bs b/components/music/AlbumView.bs
index 57af32742..67436da95 100644
--- a/components/music/AlbumView.bs
+++ b/components/music/AlbumView.bs
@@ -136,7 +136,7 @@ sub createFullDscrDlg()
dlg.Title = tr("Press 'Back' to Close")
dlg.width = 1290
dlg.palette = m.dlgPalette
- dlg.overview = [m.dscr.text]
+ dlg.overview = m.dscr.text
m.fullDscrDlg = dlg
m.top.getScene().dialog = dlg
border = createObject("roSGNode", "Poster")
diff --git a/components/music/ArtistView.bs b/components/music/ArtistView.bs
index 995b803bb..3ad015e89 100644
--- a/components/music/ArtistView.bs
+++ b/components/music/ArtistView.bs
@@ -223,7 +223,7 @@ sub createFullDscrDlg()
dlg.Title = tr("Press 'Back' to Close")
dlg.width = 1290
dlg.palette = m.dlgPalette
- dlg.overview = [m.dscr.text]
+ dlg.overview = m.dscr.text
m.fullDscrDlg = dlg
m.top.getScene().dialog = dlg
border = createObject("roSGNode", "Poster")
diff --git a/components/music/PlaylistView.bs b/components/music/PlaylistView.bs
index 238638758..3d6588045 100644
--- a/components/music/PlaylistView.bs
+++ b/components/music/PlaylistView.bs
@@ -127,7 +127,7 @@ sub createFullDscrDlg()
dlg.Title = tr("Press 'Back' to Close")
dlg.width = 1290
dlg.palette = m.dlgPalette
- dlg.overview = [m.dscr.text]
+ dlg.overview = m.dscr.text
m.fullDscrDlg = dlg
m.top.getScene().dialog = dlg
border = createObject("roSGNode", "Poster")
diff --git a/components/settings/settings.xml b/components/settings/settings.xml
index 10f3a24da..ec0bc7b47 100644
--- a/components/settings/settings.xml
+++ b/components/settings/settings.xml
@@ -35,7 +35,7 @@
-
+
\ No newline at end of file
diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs
index 5850bbd94..b662cfcf9 100644
--- a/components/video/VideoPlayerView.bs
+++ b/components/video/VideoPlayerView.bs
@@ -519,12 +519,14 @@ sub showNextEpisodeButton()
if m.osd.visible then return
if m.top.content.contenttype <> 4 then return ' only display when content is type "Episode"
if m.nextupbuttonseconds = 0 then return ' is the button disabled?
-
- if m.nextEpisodeButton.opacity = 0 and m.global.session.user.configuration.EnableNextEpisodeAutoPlay
- m.nextEpisodeButton.visible = true
- m.showNextEpisodeButtonAnimation.control = "start"
- m.nextEpisodeButton.setFocus(true)
- end if
+ if m.nextEpisodeButton.opacity <> 0 then return
+ userSession = m.global.session.user
+ if userSession.settings["playback.playnextepisode"] = "disabled" then return
+ if userSession.settings["playback.playnextepisode"] = "webclient" and not userSession.Configuration.EnableNextEpisodeAutoPlay then return
+
+ m.nextEpisodeButton.visible = true
+ m.showNextEpisodeButtonAnimation.control = "start"
+ m.nextEpisodeButton.setFocus(true)
end sub
'
diff --git a/docs/api/components_ButtonGroupHoriz.bs.html b/docs/api/components_ButtonGroupHoriz.bs.html
index e0a8c8bbd..d02d484c5 100644
--- a/docs/api/components_ButtonGroupHoriz.bs.html
+++ b/docs/api/components_ButtonGroupHoriz.bs.html
@@ -1,6 +1,6 @@
Source: components/ButtonGroupHoriz.bscomponents_ButtonGroupHoriz.bs
sub init()
+ components_ButtonGroupHoriz.bs
sub init()
m.top.layoutDirection = "horiz"
end sub
@@ -25,4 +25,4 @@
return false
end function
-
\ No newline at end of file
+