Archive Project
This commit is contained in:
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# IDEA Project Files
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Node.js
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Media Assets
|
||||||
|
assets/
|
||||||
|
|
||||||
|
# Generated Files
|
||||||
|
*.ite
|
||||||
BIN
Play Button.pxm
Normal file
BIN
Play Button.pxm
Normal file
Binary file not shown.
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# iTunes Extras Template
|
||||||
|
|
||||||
|
## Asset File Structure and Naming
|
||||||
BIN
TuneKit/sounds/Exit.aif
Normal file
BIN
TuneKit/sounds/Exit.aif
Normal file
Binary file not shown.
BIN
TuneKit/sounds/Limit.aif
Normal file
BIN
TuneKit/sounds/Limit.aif
Normal file
Binary file not shown.
BIN
TuneKit/sounds/Selection.aif
Normal file
BIN
TuneKit/sounds/Selection.aif
Normal file
Binary file not shown.
BIN
TuneKit/sounds/SelectionChange.aif
Normal file
BIN
TuneKit/sounds/SelectionChange.aif
Normal file
Binary file not shown.
5941
TuneKit/src/TuneKit.js
Normal file
5941
TuneKit/src/TuneKit.js
Normal file
File diff suppressed because it is too large
Load Diff
67
compile.sh
Normal file
67
compile.sh
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
BABEL=./node_modules/babel-cli/bin/babel.js
|
||||||
|
SASS=./node_modules/node-sass/bin/node-sass
|
||||||
|
MUSTACHE=./node_modules/mustache/bin/mustache
|
||||||
|
|
||||||
|
DATA_FILE=data.json
|
||||||
|
|
||||||
|
SOURCE_ROOT=src
|
||||||
|
TARGET_DIR="iTunes Extras.ite"
|
||||||
|
|
||||||
|
rm -r "${TARGET_DIR}"
|
||||||
|
mkdir -p "${TARGET_DIR}"
|
||||||
|
|
||||||
|
cp -R TuneKit/ "${TARGET_DIR}/TuneKit/"
|
||||||
|
|
||||||
|
for file in $(find ${SOURCE_ROOT} -type f)
|
||||||
|
do
|
||||||
|
echo -n "Compiling $file..."
|
||||||
|
dir=$(dirname "$file")
|
||||||
|
filename=$(basename "$file")
|
||||||
|
extension="${filename##*.}"
|
||||||
|
filename="${filename%.*}"
|
||||||
|
filename="${filename%.*}" # For double extensions
|
||||||
|
|
||||||
|
if [[ $filename == _* ]]; then
|
||||||
|
echo -en "\033[0;33m"
|
||||||
|
echo " Skipping"
|
||||||
|
echo -en "\033[0;00m"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
targetDir="${TARGET_DIR}${dir#${SOURCE_ROOT}}"
|
||||||
|
partialTarget="${targetDir}/${filename}"
|
||||||
|
|
||||||
|
mkdir -p "$targetDir"
|
||||||
|
|
||||||
|
case "$file" in
|
||||||
|
*.xml.mustache )
|
||||||
|
${MUSTACHE} "${DATA_FILE}" "${file}" "${partialTarget}.xml"
|
||||||
|
;;
|
||||||
|
*.plist.mustache )
|
||||||
|
${MUSTACHE} "${DATA_FILE}" "${file}" "${partialTarget}.plist"
|
||||||
|
;;
|
||||||
|
*.js.mustache )
|
||||||
|
${MUSTACHE} "${DATA_FILE}" "${file}" | ${BABEL} --out-file "${partialTarget}.js" --presets env
|
||||||
|
;;
|
||||||
|
*.js )
|
||||||
|
${BABEL} "${file}" --out-file "${partialTarget}.js" --presets env
|
||||||
|
;;
|
||||||
|
*.scss )
|
||||||
|
${SASS} --no-cache --output-style compressed "$file" > "${partialTarget}.css"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
cp "$file" "${partialTarget}.${extension}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo -en "\033[0;92m"
|
||||||
|
echo " Done"
|
||||||
|
echo -en "\033[0;00m"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -n "Copying Assets... "
|
||||||
|
cp -R assets/ "${TARGET_DIR}/"
|
||||||
|
echo -en "\033[0;92m"
|
||||||
|
echo " Done"
|
||||||
|
echo -en "\033[0;00m"
|
||||||
76
data.json
Normal file
76
data.json
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"XID": "TEST:uuid:5F861BFF-C205-4F6C-94F0-2FEEF662404D",
|
||||||
|
"movieID": 982749837,
|
||||||
|
"extrasID": 530706165,
|
||||||
|
"extrasVersion": "1.0",
|
||||||
|
"extrasBuildNumber": 42,
|
||||||
|
"meta": {
|
||||||
|
"title": "König Ödipus",
|
||||||
|
"artist": "Sven Schütze",
|
||||||
|
"description": "Mit nur neun Requisiten und rasanten Rollenwechseln erzählt Bodo Wartke die Geschichte des Ödipus, Sohn des Laios, König von Theben, der unwissend seinen eigenen Vater tötet. Und später, als Belohnung dafür, dass er Theben von der Sphinx befreit, Iokaste, die Witwe des Königs und damit seine eigene Mutter, zur Ehefrau erhält. Ein Solo-Theater mit dem Klavierkabarettisten in allen 14 Rollen! Bodo Wartkes exzellente Darbietung seiner Bühnenfassung der klassischen Tragödie „König Ödipus“ bietet einen barrierefreien Einstieg in einen zu Recht berühmten Sagenstoff und vereint Komödie und Tragödie zu einem fantastischen und unvergesslichen Theaterabend – so macht Bildung Spaß! (aus dem Pressetext).",
|
||||||
|
"longDescription": "Mit nur neun Requisiten und rasanten Rollenwechseln erzählt Bodo Wartke die Geschichte des Ödipus, Sohn des Laios, König von Theben, der unwissend seinen eigenen Vater tötet. Und später, als Belohnung dafür, dass er Theben von der Sphinx befreit, Iokaste, die Witwe des Königs und damit seine eigene Mutter, zur Ehefrau erhält. Ein Solo-Theater mit dem Klavierkabarettisten in allen 14 Rollen! Bodo Wartkes exzellente Darbietung seiner Bühnenfassung der klassischen Tragödie „König Ödipus“ bietet einen barrierefreien Einstieg in einen zu Recht berühmten Sagenstoff und vereint Komödie und Tragödie zu einem fantastischen und unvergesslichen Theaterabend – so macht Bildung Spaß! (aus dem Pressetext).",
|
||||||
|
"genre": "Comedy",
|
||||||
|
"releaseDate": "2010-04-11T00:00:00Z",
|
||||||
|
"year": "2010",
|
||||||
|
"studio": "ReimKultur",
|
||||||
|
"sort-name": "König Ödipus"
|
||||||
|
},
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"title": "Gespräch I",
|
||||||
|
"description": "Katrin Jäger spricht mit Bodo Wartke, Sven Schütze und Carmen Kalisch über die Entsehung von „König Ödipus“, die Adaptionsarbeit, die Proben, über dramaturgische und schauspielerische Herausforderungen.",
|
||||||
|
"src": "Gespraech_I.m4v",
|
||||||
|
"imageName": "Gespraech_I.png",
|
||||||
|
"duration": "43:03"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Interview mit Polybos",
|
||||||
|
"description": "Katrin Jäger spricht mit Bodo Wartke über die Figur des Polybos.",
|
||||||
|
"src": "Interview_mit_Polybos.m4v",
|
||||||
|
"imageName": "Interview_mit_Polybos.png",
|
||||||
|
"duration": "0:50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Gespräch II",
|
||||||
|
"description": "Katrin Jäger spricht mit Bodo Wartke, Sven Schütze und Carmen Kalisch tiefergehend über die Problematik des Schicksalsbegriffs und den Umgang damit in Bodo Wartkes „König Ödipus“.",
|
||||||
|
"src": "Gespraech_II.m4v",
|
||||||
|
"imageName": "Gespraech_II.png",
|
||||||
|
"duration": "28:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Gespräche III",
|
||||||
|
"description": "Carl der Löwe plaudert mit Katrin Jäger über seine langjährige Karriere im Showgeschäft und seine Rolle als Sphinx im „König Ödipus“.",
|
||||||
|
"src": "Gespraech_III.m4v",
|
||||||
|
"imageName": "Gespraech_III.png",
|
||||||
|
"duration": "07:02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Das Making-of",
|
||||||
|
"description": "Wie „König Ödipus“ auf die DVD kam.",
|
||||||
|
"src": "Making-of.m4v",
|
||||||
|
"imageName": "Making-of.png",
|
||||||
|
"duration": "43:10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Episode IV: Ödipus und Teiresias",
|
||||||
|
"description": "Die erste von Bodo verfasste Szene des Dramas, hier in der Fassung der DVD zu „Ich denke, also sing’ ich“, aufgezeichnet 2004 im Werk9 in Berlin.",
|
||||||
|
"src": "Episode_IV.m4v",
|
||||||
|
"imageName": "Episode_IV.png",
|
||||||
|
"duration": "9:41"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Finale Mortale",
|
||||||
|
"description": "Anlässlich der gemeinsamen „United Slapstick Show“ erweiterte Bodo im Jahr 2000 das bis dahin als alleinstehende Zugabe existierende Ende des Stückes um etliche Rollen und Verse.",
|
||||||
|
"src": "Finale_Mortale.m4v",
|
||||||
|
"imageName": "Finale_Mortale.png",
|
||||||
|
"duration": "10:12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Antigone",
|
||||||
|
"description": "Das Sequel zu „König Ödipus“.",
|
||||||
|
"src": "Antigone.m4v",
|
||||||
|
"imageName": "Antigone.png",
|
||||||
|
"duration": "01:32"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
3246
package-lock.json
generated
Normal file
3246
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
10
package.json
Normal file
10
package.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "iTunes Extras Template",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-cli": "^6.26.0",
|
||||||
|
"babel-preset-env": "^1.6.0",
|
||||||
|
"mustache": "^2.3.0",
|
||||||
|
"node-sass": "^4.5.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/controllers/chapters.js
Normal file
74
src/controllers/chapters.js
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
const chaptersController = new TKPageSliderController({
|
||||||
|
id: 'chapters',
|
||||||
|
previousPageButton: '.carousel-previous',
|
||||||
|
nextPageButton: '.carousel-next',
|
||||||
|
outlets: [{name: 'label', selector: '.carousel-label'}],
|
||||||
|
title: _('Chapters')
|
||||||
|
});
|
||||||
|
|
||||||
|
chaptersController.viewDidLoad = function () {
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'emptyDiv',
|
||||||
|
className: 'carousel-previous button'
|
||||||
|
}));
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'emptyDiv',
|
||||||
|
className: 'carousel-next button'
|
||||||
|
}));
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'emptyDiv',
|
||||||
|
className: 'carousel-label'
|
||||||
|
}));
|
||||||
|
this.slidingViewData = {
|
||||||
|
sideElementsVisible: 4,
|
||||||
|
distanceBetweenElements: 800,
|
||||||
|
sideOffsetBefore: 0,
|
||||||
|
sideOffsetAfter: 0,
|
||||||
|
elements: this.createThumbnails(),
|
||||||
|
incrementalLoading: true
|
||||||
|
};
|
||||||
|
|
||||||
|
bookletController.registerForDisplayUpdates(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
chaptersController.viewDidAppear = function () {
|
||||||
|
this.updateDisplay();
|
||||||
|
};
|
||||||
|
|
||||||
|
chaptersController.updateDisplay = function () {
|
||||||
|
if (this.highlightedPageIndex !== (bookletController.getChapter() - 1)) {
|
||||||
|
this.highlightedPageIndex = bookletController.getChapter() - 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ==================== Creating Pages ==================== */
|
||||||
|
|
||||||
|
chaptersController.createThumbnails = function () {
|
||||||
|
let elements = [];
|
||||||
|
for (let i = 1; i <= appData.chapters.length; i++) {
|
||||||
|
let padded_index = (i < 10) ? '0' + i : i;
|
||||||
|
let url = 'images/chapters/chapter' + padded_index + '.jpg';
|
||||||
|
elements.push({
|
||||||
|
type: 'container',
|
||||||
|
children: [{
|
||||||
|
type: 'container', children: [
|
||||||
|
{type: 'image', src: url},
|
||||||
|
{type: 'image', src: 'images/interface/buttonPlayCircle.png'}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ==================== Pages Navigation ==================== */
|
||||||
|
|
||||||
|
// called when the user focuses another page
|
||||||
|
chaptersController.pageWasHighlighted = function (index) {
|
||||||
|
this.label.textContent = appData.chapters[index];
|
||||||
|
};
|
||||||
|
|
||||||
|
// called when the user activates the focused pages
|
||||||
|
chaptersController.pageWasSelected = function (index) {
|
||||||
|
bookletController.playChapter(index + 1);
|
||||||
|
};
|
||||||
25
src/controllers/data.js.mustache
Normal file
25
src/controllers/data.js.mustache
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
let appData = {
|
||||||
|
feature: {
|
||||||
|
XID: "{{{ XID }}}",
|
||||||
|
title: "{{{ meta.title }}}",
|
||||||
|
artist: "{{{ meta.artist }}}"
|
||||||
|
},
|
||||||
|
audioLoop: {
|
||||||
|
src: "audio/background.m4a",
|
||||||
|
loop: true
|
||||||
|
},
|
||||||
|
chapters: [
|
||||||
|
{{#chapters}}"{{{.}}}",{{/chapters}}
|
||||||
|
],
|
||||||
|
features: [
|
||||||
|
{{#features}}
|
||||||
|
{
|
||||||
|
title: "{{{title}}}",
|
||||||
|
description: "{{{description}}}",
|
||||||
|
src: "{{{src}}}",
|
||||||
|
imageName: "{{{imageName}}}",
|
||||||
|
duration: "{{{duration}}}"
|
||||||
|
},
|
||||||
|
{{/features}}
|
||||||
|
]
|
||||||
|
};
|
||||||
87
src/controllers/features.js
Normal file
87
src/controllers/features.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
let featuresHelper = {};
|
||||||
|
|
||||||
|
featuresHelper.createFeatureController = function (feature, index) {
|
||||||
|
let controller = new TKController({
|
||||||
|
id: 'selection-' + index
|
||||||
|
});
|
||||||
|
controller.viewDidLoad = function () {
|
||||||
|
this.view.classList.add('selection');
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'container',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'image',
|
||||||
|
src: 'images/' + feature.imageName
|
||||||
|
}, {
|
||||||
|
type: 'image',
|
||||||
|
src: 'images/interface/buttonPlayCircle.png',
|
||||||
|
className: 'play-overlay'
|
||||||
|
}]
|
||||||
|
}));
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'div',
|
||||||
|
className: 'title',
|
||||||
|
content: feature.title
|
||||||
|
}));
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'div',
|
||||||
|
className: 'description',
|
||||||
|
content: feature.description
|
||||||
|
}));
|
||||||
|
this.view.querySelector('.play-overlay').addEventListener('click', () => {
|
||||||
|
console.log(feature);
|
||||||
|
bookletController.playNonLibraryContent({src: feature.src, string: feature.title});
|
||||||
|
})
|
||||||
|
};
|
||||||
|
return controller;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
let featuresController = new TKTabController({
|
||||||
|
id: 'features',
|
||||||
|
tabsSelector: '.list .list-item',
|
||||||
|
controllers: appData.features.map(featuresHelper.createFeatureController),
|
||||||
|
title: _('Features')
|
||||||
|
});
|
||||||
|
|
||||||
|
featuresController.viewDidLoad = function () {
|
||||||
|
const vignetteElement = TKUtils.buildElement({
|
||||||
|
type: 'emptyDiv',
|
||||||
|
className: 'vignette'
|
||||||
|
});
|
||||||
|
this.view.appendChild(vignetteElement);
|
||||||
|
this.view.addClassName('list-on-right');
|
||||||
|
this.buildFeaturesList(appData.features);
|
||||||
|
};
|
||||||
|
|
||||||
|
featuresController.buildFeaturesList = function (features) {
|
||||||
|
let featureElements = features.map(feature => {
|
||||||
|
return {
|
||||||
|
type: 'container',
|
||||||
|
className: 'list-item',
|
||||||
|
children: [
|
||||||
|
{type: 'image', src: 'images/' + feature.imageName},
|
||||||
|
{
|
||||||
|
type: 'container',
|
||||||
|
className: 'list-item-body',
|
||||||
|
children: [
|
||||||
|
{type: 'div', className: 'title', content: feature.title},
|
||||||
|
{type: 'div', className: 'duration', content: formatTime(feature.duration)}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'container',
|
||||||
|
className: 'list',
|
||||||
|
children: [
|
||||||
|
{type: 'div', className: 'list-title', content: _('Features')},
|
||||||
|
{
|
||||||
|
type: 'container',
|
||||||
|
className: 'list-content',
|
||||||
|
children: featureElements
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
};
|
||||||
32
src/controllers/home.js
Normal file
32
src/controllers/home.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
const homeController = new TKController({
|
||||||
|
id: 'home',
|
||||||
|
actions: [
|
||||||
|
{selector: '.play', action: bookletController.playFeature}
|
||||||
|
],
|
||||||
|
navigatesTo: [
|
||||||
|
{selector: '.features', controller: 'features'}
|
||||||
|
],
|
||||||
|
highlightedElement: '.play'
|
||||||
|
});
|
||||||
|
|
||||||
|
homeController.viewDidLoad = function () {
|
||||||
|
let mainMenuItems = [];
|
||||||
|
mainMenuItems.push({
|
||||||
|
type: 'div',
|
||||||
|
className: 'play button',
|
||||||
|
content: _('Play')
|
||||||
|
});
|
||||||
|
if (typeof appData.features !== 'undefined' && appData.features.length > 0) {
|
||||||
|
mainMenuItems.push({
|
||||||
|
type: 'div',
|
||||||
|
className: 'features button',
|
||||||
|
content: _('Features')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.view.appendChild(TKUtils.buildElement({
|
||||||
|
type: 'container',
|
||||||
|
className: 'main-menu',
|
||||||
|
children: mainMenuItems
|
||||||
|
}));
|
||||||
|
};
|
||||||
31
src/controllers/navigation.js
Normal file
31
src/controllers/navigation.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
window.addEventListener('load', () => {
|
||||||
|
let backButtonElement = document.querySelector('#header .back');
|
||||||
|
backButtonElement.innerHTML = _('Back');
|
||||||
|
TKNavigationController.sharedNavigation.backButton = '.back';
|
||||||
|
});
|
||||||
|
|
||||||
|
bookletController.navigationControllerWillShowController = function (navigationController, controller) {
|
||||||
|
function showBackgroundForController() {
|
||||||
|
let imagePath = 'images/';
|
||||||
|
if (navigationController.rootController !== controller) {
|
||||||
|
imagePath += controller.id + '/'
|
||||||
|
}
|
||||||
|
imagePath += 'background.png';
|
||||||
|
controller.view.style.backgroundImage = "url('" + imagePath + "')";
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleHeader() {
|
||||||
|
let headerElement = document.getElementById('header');
|
||||||
|
let titleElement = headerElement.querySelector('.title');
|
||||||
|
if (controller === navigationController.rootController) {
|
||||||
|
headerElement.addClassName('hidden');
|
||||||
|
} else {
|
||||||
|
titleElement.innerHTML = controller.title;
|
||||||
|
headerElement.removeClassName('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleHeader();
|
||||||
|
showBackgroundForController();
|
||||||
|
};
|
||||||
|
|
||||||
37
src/controllers/strings.js
Normal file
37
src/controllers/strings.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
let STRINGS_DE = {
|
||||||
|
"Back": "Zurück",
|
||||||
|
"Play": "Wiedergabe",
|
||||||
|
"Chapters": "Kapitel",
|
||||||
|
"Features": "Bonusmaterial",
|
||||||
|
"Hr.": "Std.",
|
||||||
|
"Min.": "Min.",
|
||||||
|
"Sec.": "Sek."
|
||||||
|
};
|
||||||
|
|
||||||
|
function _(key) {
|
||||||
|
if (key in STRINGS_DE) {
|
||||||
|
return STRINGS_DE[key]
|
||||||
|
} else {
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTime(timeString) {
|
||||||
|
const components = timeString.split(':').map(Number);
|
||||||
|
let formattedComponents = [];
|
||||||
|
if (components[0] > 0) {
|
||||||
|
formattedComponents.push(components[0]);
|
||||||
|
const name = components.length === 3 ? _('Hr.') : _('Min.');
|
||||||
|
formattedComponents.push(name);
|
||||||
|
}
|
||||||
|
if (components[1] > 0) {
|
||||||
|
formattedComponents.push(components[1]);
|
||||||
|
const name = components.length === 3 ? _('Min.') : _('Sec.');
|
||||||
|
formattedComponents.push(name);
|
||||||
|
}
|
||||||
|
if (formattedComponents.length < 4 && components.length >= 3 && components[2] > 0) {
|
||||||
|
formattedComponents.push(components[2]);
|
||||||
|
formattedComponents.push(_('Sec.'));
|
||||||
|
}
|
||||||
|
return formattedComponents.join(' ');
|
||||||
|
}
|
||||||
23
src/css/_functions.scss
Normal file
23
src/css/_functions.scss
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
$directions: (
|
||||||
|
left: 135deg,
|
||||||
|
right: -45deg,
|
||||||
|
);
|
||||||
|
|
||||||
|
@mixin arrow($direction, $size, $thickness) {
|
||||||
|
$angle: 0;
|
||||||
|
@if map-has_key($directions, $direction) {
|
||||||
|
$angle: #{map_get($directions, $direction)}
|
||||||
|
} @else {
|
||||||
|
$angle: $direction
|
||||||
|
}
|
||||||
|
|
||||||
|
content: ' ';
|
||||||
|
border: 0 solid;
|
||||||
|
border-right-width: $thickness;
|
||||||
|
border-bottom-width: $thickness;
|
||||||
|
display: inline-block;
|
||||||
|
padding: $size;
|
||||||
|
transform: rotate($angle);
|
||||||
|
-webkit-transform: rotate($angle);
|
||||||
|
margin-bottom: $size / 2;
|
||||||
|
}
|
||||||
124
src/css/_variables.scss
Normal file
124
src/css/_variables.scss
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// Global (default) Values
|
||||||
|
$page-min-width: 1280px;
|
||||||
|
$page-min-height: 720px;
|
||||||
|
|
||||||
|
$content-margin-left: 75px;
|
||||||
|
$content-margin-right: 75px;
|
||||||
|
$content-margin-top: 140px; // Distance from top of page to top of content (ignoring the header)
|
||||||
|
$content-margin-bottom: 60px;
|
||||||
|
|
||||||
|
$default-text-color: rgba(235, 235, 235, 1);
|
||||||
|
$default-border-color: rgba(255, 255, 255, 0.3);
|
||||||
|
$default-transition-duration: 500ms;
|
||||||
|
|
||||||
|
$controller-change-transition-duration: $default-transition-duration;
|
||||||
|
|
||||||
|
$default-font-family: "Helvetica Neue", "Helvetica", sans-serif;
|
||||||
|
$default-font-size: 1rem;
|
||||||
|
$default-font-weight: 300;
|
||||||
|
|
||||||
|
$play-overlay-size: 100px;
|
||||||
|
|
||||||
|
// Z-Indexes
|
||||||
|
$header-z-index: 10;
|
||||||
|
$carousel-controls-z-index: 2;
|
||||||
|
|
||||||
|
// Header
|
||||||
|
|
||||||
|
$header-left: $content-margin-left;
|
||||||
|
$header-right: $content-margin-right;
|
||||||
|
$header-top: 0;
|
||||||
|
|
||||||
|
$header-vertical-padding: 0.8rem;
|
||||||
|
$header-horizontal-padding: 0;
|
||||||
|
$header-border-width: 1px;
|
||||||
|
$header-border-color: $default-border-color;
|
||||||
|
|
||||||
|
$header-font-size: 1.7rem;
|
||||||
|
|
||||||
|
$header-transition-duration: $controller-change-transition-duration;
|
||||||
|
|
||||||
|
// Back Button
|
||||||
|
|
||||||
|
$back-button-arrow-thickness: 1px;
|
||||||
|
$back-button-arrow-size: 4px; // TODO: Use rem instead
|
||||||
|
$back-button-arrow-text-spacer: 5px;
|
||||||
|
|
||||||
|
$back-button-font-size: 1.1rem;
|
||||||
|
$back-button-corner-radius: 5px;
|
||||||
|
$back-button-background-color: $header-border-color;
|
||||||
|
$back-button-horizontal-padding: 10px;
|
||||||
|
$back-button-vertical-padding: 7px;
|
||||||
|
|
||||||
|
// Main Menu
|
||||||
|
$main-menu-bottom-distance: 62px;
|
||||||
|
$main-menu-padding: 25px;
|
||||||
|
$main-menu-item-distance: 100px;
|
||||||
|
|
||||||
|
$main-menu-font-size: 1.7rem;
|
||||||
|
|
||||||
|
$main-menu-blur-radius: 10px;
|
||||||
|
$main-menu-background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
$main-menu-border-width: 1px;
|
||||||
|
$main-menu-border-color: $default-border-color;
|
||||||
|
|
||||||
|
// Carousel
|
||||||
|
|
||||||
|
$carousel-top-space: $content-margin-top;
|
||||||
|
$carousel-left-margin: 0;
|
||||||
|
$carousel-right-margin: 0;
|
||||||
|
|
||||||
|
$carousel-item-width: 800px;
|
||||||
|
$carousel-item-height: 450px;
|
||||||
|
$carousel-secondary-scale-factor: 0.75;
|
||||||
|
|
||||||
|
$carousel-transition-duration: $default-transition-duration;
|
||||||
|
|
||||||
|
$carousel-label-top-margin: 20px;
|
||||||
|
$carousel-label-font-size: 2.25rem;
|
||||||
|
|
||||||
|
$carousel-control-buttons-top-margin: $carousel-top-space + 0.5 * $carousel-item-height;
|
||||||
|
$carousel-previous-left: $content-margin-left;
|
||||||
|
$carousel-next-right: $content-margin-right;
|
||||||
|
$carousel-control-buttons-size: 15px;
|
||||||
|
$carousel-control-buttons-thickness: 5px;
|
||||||
|
|
||||||
|
// List on Right
|
||||||
|
|
||||||
|
$lor-margin-left: $content-margin-left;
|
||||||
|
$lor-margin-right: $content-margin-right;
|
||||||
|
$lor-margin-top: $content-margin-top;
|
||||||
|
$lor-margin-bottom: $content-margin-bottom;
|
||||||
|
|
||||||
|
$lor-list-margin-top: $lor-margin-top;
|
||||||
|
$lor-list-margin-right: $lor-margin-right;
|
||||||
|
$lor-list-margin-bottom: $lor-margin-bottom;
|
||||||
|
$lor-list-width: 320px;
|
||||||
|
$lor-list-background-color: rgba(0, 0, 0, 0.75);
|
||||||
|
|
||||||
|
$lor-list-title-color: white;
|
||||||
|
$lor-list-title-padding: 10px;
|
||||||
|
|
||||||
|
$lor-item-border: 1px solid $default-border-color;
|
||||||
|
$lor-item-background-color: transparent;
|
||||||
|
$lor-item-selected-background: linear-gradient(to bottom, rgba(41, 137, 216, 0.75) 0%, rgba(30, 87, 153, 0.75) 100%);
|
||||||
|
$lor-item-padding: 12px;
|
||||||
|
|
||||||
|
$lor-item-image-width: 64px;
|
||||||
|
$lor-item-image-height: 36px;
|
||||||
|
$lor-item-title-color: white;
|
||||||
|
$lor-item-duration-sep: 5px;
|
||||||
|
$lor-item-duration-color: rgb(140, 140, 140);
|
||||||
|
|
||||||
|
$lor-selection-width: 800px;
|
||||||
|
$lor-selection-image-max-height: 450px;
|
||||||
|
$lor-selection-title-sep: 10px;
|
||||||
|
$lor-selection-title-font-size: 1.6rem;
|
||||||
|
$lor-selection-title-color: white;
|
||||||
|
$lor-selection-description-sep: 10px;
|
||||||
|
$lor-selection-description-font-size: 1.6rem;
|
||||||
|
$lor-selection-description-font-weight: 200;
|
||||||
|
$lor-selection-description-color: rgba(255, 255, 255, 0.75);
|
||||||
|
|
||||||
|
$lor-vignette-color: black;
|
||||||
|
$lor-vignette-size: 750px;
|
||||||
92
src/css/carousel.scss
Normal file
92
src/css/carousel.scss
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
@import "variables";
|
||||||
|
@import "functions";
|
||||||
|
|
||||||
|
/* Sliding View */
|
||||||
|
|
||||||
|
.tk-page-slider-controller-view {
|
||||||
|
.sliding-view {
|
||||||
|
position: absolute;
|
||||||
|
top: $carousel-top-space;
|
||||||
|
left: $carousel-left-margin;
|
||||||
|
right: $carousel-right-margin;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
height: $carousel-item-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliding-view-element {
|
||||||
|
position: absolute;
|
||||||
|
left: calc(50% - #{$carousel-item-width / 2});
|
||||||
|
-webkit-transition: -webkit-transform $carousel-transition-duration;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
div {
|
||||||
|
-webkit-transition: -webkit-transform $carousel-transition-duration;
|
||||||
|
-webkit-transform: scale($carousel-secondary-scale-factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sliding-view-element-focused {
|
||||||
|
div {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The actual image of the item
|
||||||
|
div img:nth-child(1) {
|
||||||
|
width: $carousel-item-width;
|
||||||
|
height: $carousel-item-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The play button
|
||||||
|
div img:nth-child(2) {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: opacity $carousel-transition-duration;
|
||||||
|
}
|
||||||
|
.sliding-view-element-focused div img:nth-child(2) {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sliding-view-element-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Label */
|
||||||
|
|
||||||
|
.carousel-label {
|
||||||
|
position: absolute;
|
||||||
|
left: calc(50% - #{0.5 * $carousel-item-width});
|
||||||
|
right: calc(50% - #{0.5 * $carousel-item-width});
|
||||||
|
top: $carousel-top-space + $carousel-item-height + $carousel-label-top-margin;
|
||||||
|
|
||||||
|
font-size: $carousel-label-font-size;
|
||||||
|
text-align: center;
|
||||||
|
overflow: visible;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
hyphens: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Arrows */
|
||||||
|
|
||||||
|
.carousel-previous {
|
||||||
|
@include arrow(left, $carousel-control-buttons-size, $carousel-control-buttons-thickness);
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: $carousel-control-buttons-top-margin;
|
||||||
|
left: $carousel-previous-left;
|
||||||
|
z-index: $carousel-controls-z-index;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-next {
|
||||||
|
@include arrow(right, $carousel-control-buttons-size, $carousel-control-buttons-thickness);
|
||||||
|
position: absolute;
|
||||||
|
margin-top: $carousel-control-buttons-top-margin;
|
||||||
|
right: $carousel-next-right;
|
||||||
|
z-index: $carousel-controls-z-index;
|
||||||
|
}
|
||||||
26
src/css/home.scss
Normal file
26
src/css/home.scss
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@import "variables";
|
||||||
|
|
||||||
|
.main-menu {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: $main-menu-bottom-distance;
|
||||||
|
padding: $main-menu-padding;
|
||||||
|
|
||||||
|
-webkit-backdrop-filter: blur($main-menu-blur-radius);
|
||||||
|
background-color: $main-menu-background-color;
|
||||||
|
border-top: $main-menu-border-width solid $main-menu-border-color;
|
||||||
|
border-bottom: $main-menu-border-width solid $main-menu-border-color;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
div {
|
||||||
|
text-align: center;
|
||||||
|
font-size: $main-menu-font-size;
|
||||||
|
}
|
||||||
|
|
||||||
|
div + div {
|
||||||
|
margin-left: $main-menu-item-distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
95
src/css/list-on-right.scss
Normal file
95
src/css/list-on-right.scss
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
@import "variables";
|
||||||
|
|
||||||
|
.list-on-right .list {
|
||||||
|
position: absolute;
|
||||||
|
top: $lor-list-margin-top;
|
||||||
|
right: $lor-list-margin-right;
|
||||||
|
bottom: $lor-list-margin-bottom;
|
||||||
|
width: $lor-list-width;
|
||||||
|
background-color: $lor-list-background-color;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.list-title {
|
||||||
|
color: $lor-list-title-color;
|
||||||
|
padding: $lor-list-title-padding;
|
||||||
|
border-bottom: $lor-item-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-content {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
background-color: $lor-item-background-color;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
& + .list-item {
|
||||||
|
border-top: $lor-item-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.tk-tab-selected {
|
||||||
|
background: $lor-item-selected-background;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: $lor-item-image-width;
|
||||||
|
height: $lor-item-image-height;
|
||||||
|
margin: $lor-item-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item-body {
|
||||||
|
flex: 1;
|
||||||
|
margin: $lor-item-padding $lor-item-padding $lor-item-padding 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: $lor-item-title-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration {
|
||||||
|
margin-top: $lor-item-duration-sep;
|
||||||
|
color: $lor-item-duration-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-on-right .selection {
|
||||||
|
position: absolute;
|
||||||
|
left: $lor-margin-left;
|
||||||
|
top: $lor-margin-top;
|
||||||
|
width: $lor-selection-width;
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
img:not(.play-overlay) {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: $lor-selection-image-max-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-top: $lor-selection-title-sep;
|
||||||
|
font-size: $lor-selection-title-font-size;
|
||||||
|
color: $lor-selection-title-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-top: $lor-selection-description-sep;
|
||||||
|
font-size: $lor-selection-description-font-size;
|
||||||
|
font-weight: $lor-selection-description-font-weight;
|
||||||
|
color: $lor-selection-description-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vignette {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-shadow: 0 0 $lor-vignette-size $lor-vignette-color inset;
|
||||||
|
}
|
||||||
103
src/css/shared.scss
Normal file
103
src/css/shared.scss
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
@import "variables";
|
||||||
|
@import "functions";
|
||||||
|
|
||||||
|
* {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
min-width: $page-min-width;
|
||||||
|
min-height: $page-min-height;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
font-family: $default-font-family;
|
||||||
|
font-weight: $default-font-weight;
|
||||||
|
font-size: $default-font-size;
|
||||||
|
color: $default-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
position: absolute;
|
||||||
|
left: $header-left;
|
||||||
|
right: $header-right;
|
||||||
|
top: $header-top;
|
||||||
|
padding: $header-vertical-padding $header-horizontal-padding;
|
||||||
|
z-index: $header-z-index;
|
||||||
|
border-bottom: $header-border-width solid $header-border-color;
|
||||||
|
|
||||||
|
-webkit-transition: opacity $header-transition-duration;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
font-size: $header-font-size;
|
||||||
|
|
||||||
|
.back {
|
||||||
|
position: absolute;
|
||||||
|
font-size: $back-button-font-size;
|
||||||
|
border-radius: $back-button-corner-radius;
|
||||||
|
background-color: $back-button-background-color;
|
||||||
|
padding: $back-button-vertical-padding $back-button-horizontal-padding;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
@include arrow(left, $back-button-arrow-size, $back-button-arrow-thickness);
|
||||||
|
margin-right: $back-button-arrow-text-spacer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#navigation {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
background-image: url("/images/background.png");
|
||||||
|
background-size: cover;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elements
|
||||||
|
.button {
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inactive {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-overlay {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
width: $play-overlay-size;
|
||||||
|
height: $play-overlay-size;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
58
src/iTunesMetadata.plist.mustache
Normal file
58
src/iTunesMetadata.plist.mustache
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Metadata</key>
|
||||||
|
<dict>
|
||||||
|
<key>artistName</key>
|
||||||
|
<string>{{{ meta.artist }}}</string>
|
||||||
|
<key>description</key>
|
||||||
|
<string>{{{ meta.description }}}</string>
|
||||||
|
<key>longDescription</key>
|
||||||
|
<string>{{{ meta.longDescription }}}</string>
|
||||||
|
<key>genre</key>
|
||||||
|
<string>{{{ meta.genre }}}</string>
|
||||||
|
<key>itemId</key>
|
||||||
|
<integer>{{{ extrasID }}}</integer>
|
||||||
|
<key>itemName</key>
|
||||||
|
<string>{{{ meta.title }}} - iTunes Extras</string>
|
||||||
|
<key>kind</key>
|
||||||
|
<string>feature-movie</string>
|
||||||
|
<key>releaseDate</key>
|
||||||
|
<string>{{{ meta.releaseDate }}}</string>
|
||||||
|
<key>sort-artist-status</key>
|
||||||
|
<integer>128</integer>
|
||||||
|
<key>sort-name</key>
|
||||||
|
<string>{{{ meta.sort-name}}}</string>
|
||||||
|
<key>sort-name-status</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
<key>year</key>
|
||||||
|
<integer>{{{ meta.year }}}</integer>
|
||||||
|
<key>studio</key>
|
||||||
|
<string>{{{ meta.studio }}}</string>
|
||||||
|
<key>playlistId</key>
|
||||||
|
<integer>{{{ movieID }}}</integer>
|
||||||
|
<key>playlistName</key>
|
||||||
|
<string>{{{ meta.title }}}</string>
|
||||||
|
<key>xid</key>
|
||||||
|
<string>{{{ XID }}}_ITUNES_EXTRAS</string>
|
||||||
|
</dict>
|
||||||
|
<key>Name File</key>
|
||||||
|
<string>{{{ meta.title }}} - iTunes Extras.ite</string>
|
||||||
|
<key>associated-adam-ids</key>
|
||||||
|
<array>
|
||||||
|
<integer>{{{ movieID }}}</integer>
|
||||||
|
</array>
|
||||||
|
<key>xid-asset-mapping</key>
|
||||||
|
<dict>
|
||||||
|
<key>{{{ XID }}}</key>
|
||||||
|
<array>
|
||||||
|
<integer>{{{ movieID }}}</integer>
|
||||||
|
</array>
|
||||||
|
<key>{{{ XID }}}_ITUNES_EXTRAS</key>
|
||||||
|
<array>
|
||||||
|
<integer>{{{ extrasID }}}</integer>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
BIN
src/images/interface/buttonPlayCircle.png
Normal file
BIN
src/images/interface/buttonPlayCircle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
33
src/index.html
Normal file
33
src/index.html
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="hdtv-fullscreen" content="true"/>
|
||||||
|
<meta name="hdtv-cursor-off" content="true"/>
|
||||||
|
<title>iTunes Extra for Movie</title>
|
||||||
|
<!-- Styles -->
|
||||||
|
<link rel="stylesheet" href="css/shared.css" type="text/css" media="screen" charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="css/home.css" type="text/css" media="screen" charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="css/carousel.css" type="text/css" media="screen" charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="css/list-on-right.css" type="text/css" media="screen" charset="utf-8">
|
||||||
|
<!-- TuneKit -->
|
||||||
|
<script type="text/javascript" src="../TuneKit/src/TuneKit.js" charset="utf-8"></script>
|
||||||
|
<!-- Controllers -->
|
||||||
|
<script type="text/javascript" src="controllers/data.js" charset="utf-8"></script>
|
||||||
|
<script type="text/javascript" src="controllers/strings.js" charset="utf-8"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="controllers/navigation.js" charset="utf-8"></script>
|
||||||
|
<script type="text/javascript" src="controllers/home.js" charset="utf-8"></script>
|
||||||
|
<script type="text/javascript" src="controllers/chapters.js" charset="utf-8"></script>
|
||||||
|
<script type="text/javascript" src="controllers/features.js" charset="utf-8"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="navigation">
|
||||||
|
<header id="header" class="hidden">
|
||||||
|
<div class="back button"></div>
|
||||||
|
<div class="title"></div>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
14
src/manifest.xml.mustache
Normal file
14
src/manifest.xml.mustache
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<manifest xmlns="http://apple.com/itunes/media_archive/manifest" version="1.0" media_archive_version="{{{ extrasVersion }}}"
|
||||||
|
media_archive_build_number="{{{ extrasBuildNumber }}}">
|
||||||
|
<requirements>
|
||||||
|
<supported_platforms>
|
||||||
|
<platform name="iTunes" minimum_version="9.0"/>
|
||||||
|
<platform name="AppleTV" minimum_version="3.0"/>
|
||||||
|
</supported_platforms>
|
||||||
|
</requirements>
|
||||||
|
<library_items>
|
||||||
|
<library_item type="video" xid="{{{ XID }}}" name="{{{ meta.title }}}"/>
|
||||||
|
</library_items>
|
||||||
|
</manifest>
|
||||||
|
|
||||||
Reference in New Issue
Block a user