mirror of
https://github.com/SEPPDROID/JellyCAT.git
synced 2025-10-22 16:04:20 +00:00
user input > atv.storage working :) + some minor changes
This commit is contained in:
BIN
app/assets/img/jfserver.png
Normal file
BIN
app/assets/img/jfserver.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
81
app/js/about.js
Normal file
81
app/js/about.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// /\_/|
|
||||||
|
// { ' ' } JellyCAT
|
||||||
|
// \____\
|
||||||
|
|
||||||
|
//----------------------------DOMView--------------------------------------------
|
||||||
|
|
||||||
|
var JCATAboutXML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
|
||||||
|
'<atv>\n' +
|
||||||
|
' <head>\n' +
|
||||||
|
' </head>\n' +
|
||||||
|
' <body>\n' +
|
||||||
|
' <scrollingText id="com.jellycat.jcatabout" initialSelection="1">\n' +
|
||||||
|
' <title>JellyCAT About</title>\n' +
|
||||||
|
' <text><![CDATA[\n' +
|
||||||
|
'// /\\_/ |\n' +
|
||||||
|
'// { \' \' } JellyCAT\n' +
|
||||||
|
'// \\____\\\n' +
|
||||||
|
'\n' +
|
||||||
|
'ENGLISH | ABOUT\n' +
|
||||||
|
' \n' +
|
||||||
|
'JellyCAT $atvcsettings.version\n' +
|
||||||
|
' \n' +
|
||||||
|
'Thank you for using JellyCAT! A (hacky) Jellyfin client for Apple TV 2 & 3.\n' +
|
||||||
|
' \n' +
|
||||||
|
'== soon more ==\n' +
|
||||||
|
' \n' +
|
||||||
|
'\n\n\n' +
|
||||||
|
'-=JellyCAT Server (JCHOST) Information=-\n' +
|
||||||
|
'\n\n' +
|
||||||
|
'JellyCAT Server Host (fallback):\n' +
|
||||||
|
'http://jcathost.dns\n' +
|
||||||
|
'\n' +
|
||||||
|
'ATVCSETTINGS pick-up location:\n' +
|
||||||
|
'http://jcathost.dns/atvcsettings\n' +
|
||||||
|
'\n' +
|
||||||
|
'ATVCSETTINGS Hello:\n' +
|
||||||
|
'$atvcsettings.hello\n' +
|
||||||
|
'\n' +
|
||||||
|
'ATVCSETTINGS System Information:\n' +
|
||||||
|
'$atvcsettings.system\n' +
|
||||||
|
'\n' +
|
||||||
|
'JellyCat Version:\n' +
|
||||||
|
'$atvcsettings.version\n' +
|
||||||
|
'\n' +
|
||||||
|
'Hijacked Host App domain\n' +
|
||||||
|
'$atvcsettings.sighost\n' +
|
||||||
|
'\n' +
|
||||||
|
'JellyCAT Server Host IP\n' +
|
||||||
|
'$atvcsettings.hostip\n' +
|
||||||
|
'\n' +
|
||||||
|
'-=Jellyfin Client settings=-\n' +
|
||||||
|
' ]]></text>\n' +
|
||||||
|
' <buttons>\n' +
|
||||||
|
' <actionButton onSelect="DomViewManager.unloadView(\'JcatAboutView\');" id="close">\n' +
|
||||||
|
' <title>Close</title>\n' +
|
||||||
|
' </actionButton>\n' +
|
||||||
|
' </buttons>\n' +
|
||||||
|
' </scrollingText>\n' +
|
||||||
|
' </body>\n' +
|
||||||
|
'</atv>';
|
||||||
|
|
||||||
|
|
||||||
|
JCATAboutXML = JCATAboutXML
|
||||||
|
.replace(/\$atvcsettings\.hello/g, atv.jcathost.HelloMessage)
|
||||||
|
.replace(/\$atvcsettings\.system/g, atv.jcathost.System)
|
||||||
|
.replace(/\$atvcsettings\.version/g, atv.jcathost.Version)
|
||||||
|
.replace(/\$atvcsettings\.sighost/g, atv.jcathost.SigHost)
|
||||||
|
.replace(/\$atvcsettings\.hostip/g, atv.jcathost.HostIP);
|
||||||
|
|
||||||
|
|
||||||
|
function generateJCATAboutXML() {
|
||||||
|
var doc = atv.parseXML( JCATAboutXML );
|
||||||
|
|
||||||
|
console.log( "Creating the view --> " );
|
||||||
|
DomViewManager.createView( "JcatAboutView" );
|
||||||
|
|
||||||
|
console.log( "Loading the view --> " );
|
||||||
|
DomViewManager.loadView( "JcatAboutView", doc );
|
||||||
|
|
||||||
|
console.log( "View is loaded" );
|
||||||
|
}
|
@@ -42,7 +42,7 @@ var JCATHOSTInfoXML = '<?xml version="1.0" encoding="UTF-8"?>\n' +
|
|||||||
'$atvcsettings.hostip\n' +
|
'$atvcsettings.hostip\n' +
|
||||||
']]></text>\n' +
|
']]></text>\n' +
|
||||||
' <buttons>\n' +
|
' <buttons>\n' +
|
||||||
' <actionButton onSelect="atvutils.loadURL(\'https://\'+ atv.jcathost.SigHost +\'/xml/about.xml\');" id="help">\n' +
|
' <actionButton onSelect="generateJCATAboutXML();" id="about">\n' +
|
||||||
' <title>About</title>\n' +
|
' <title>About</title>\n' +
|
||||||
' </actionButton>\n' +
|
' </actionButton>\n' +
|
||||||
' <actionButton onSelect="DomViewManager.unloadView(\'JcathostInfoView\');" id="close">\n' +
|
' <actionButton onSelect="DomViewManager.unloadView(\'JcathostInfoView\');" id="close">\n' +
|
||||||
@@ -71,232 +71,4 @@ function generateJCATHOSTInfoXML() {
|
|||||||
DomViewManager.loadView( "JcathostInfoView", doc );
|
DomViewManager.loadView( "JcathostInfoView", doc );
|
||||||
|
|
||||||
console.log( "View is loaded" );
|
console.log( "View is loaded" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************************************************
|
|
||||||
// DOMView | Wrapper
|
|
||||||
// https://github.com/wahlmanj/sample-aTV/blob/dba73806c21183fb35d6edca94b960691d8e5d66/js/views/DOMView/DOMView.js
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This wrapper makes it easier to handle the DOM View JS calls.
|
|
||||||
* The actual calls for DOMView are:
|
|
||||||
* view = new atv.DOMView()
|
|
||||||
* view.onUnload - similar to onPageUnload
|
|
||||||
* view.load ( XMLDOC, function(sucess) { ... } ) - pushes the view onto the stack the callback function is called back and gives you a success or fail call.
|
|
||||||
* view.unload - removes the view from the stack.
|
|
||||||
*/
|
|
||||||
var DomViewManager = ( function() {
|
|
||||||
var views = {},
|
|
||||||
ViewNames = [],
|
|
||||||
config = {},
|
|
||||||
callbackEvents = {},
|
|
||||||
optionDialogXML = {};
|
|
||||||
|
|
||||||
|
|
||||||
function _saveView( name, view ) {
|
|
||||||
if( name && view ) {
|
|
||||||
views[ name ] = view;
|
|
||||||
_addViewToList( name );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.error( "When saving a view, both name and view are required" );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function _deleteView( name ) {
|
|
||||||
if( views[ name ] ) {
|
|
||||||
delete views[ name ];
|
|
||||||
_removeViewFromList( name );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function _retrieveView( name ) {
|
|
||||||
if( name ) {
|
|
||||||
return views[ name ] || null;
|
|
||||||
} else {
|
|
||||||
console.error( "When attempting to retrieve a view name is required.");
|
|
||||||
};
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
function _addViewToList( name ) {
|
|
||||||
var index = ViewNames.indexOf( name );
|
|
||||||
if( index == -1 ) {
|
|
||||||
ViewNames.push( name );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function _removeViewFromList( name ) {
|
|
||||||
var index = ViewNames.indexOf( name );
|
|
||||||
if( index > -1 ) {
|
|
||||||
ViewNames.splice( index, 1 );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function _createDialogXML( dialogOptions ) {
|
|
||||||
var doc = atv.parseXML( optionDialogXML ),
|
|
||||||
title = dialogOptions.title,
|
|
||||||
description = dialogOptions.description,
|
|
||||||
initialSelection = dialogOptions.initialSelection || 0,
|
|
||||||
options = dialogOptions.options || [];
|
|
||||||
|
|
||||||
|
|
||||||
// fill in the title, accessibility label
|
|
||||||
doc.rootElement.getElementByTagName( 'title' ).textContent = title;
|
|
||||||
doc.rootElement.getElementByTagName( 'simpleHeader' ).setAttribute( 'accessibilityLabel', title +". "+ description );
|
|
||||||
|
|
||||||
// fill in the description
|
|
||||||
doc.rootElement.getElementByTagName( 'description' ).textContent = description;
|
|
||||||
|
|
||||||
// fill in the initial selection
|
|
||||||
doc.rootElement.getElementByTagName( 'row' ).textContent = initialSelection;
|
|
||||||
|
|
||||||
// fill in the options
|
|
||||||
var items = doc.rootElement.getElementByTagName( 'items' );
|
|
||||||
options.forEach( function ( option, index ) {
|
|
||||||
// save option callbacks
|
|
||||||
RegisterCallbackEvent( "DialogOption_"+index, option.callback );
|
|
||||||
|
|
||||||
// create the option
|
|
||||||
var newOptionButton = ATVUtils.createNode({
|
|
||||||
"name": "oneLineMenuItem",
|
|
||||||
"attrs": [{
|
|
||||||
"name": "id",
|
|
||||||
"value": "DialogOption_"+ index
|
|
||||||
}, {
|
|
||||||
"name": "accessibilityLabel",
|
|
||||||
"value": option.label
|
|
||||||
}, {
|
|
||||||
"name": "onSelect",
|
|
||||||
"value": "DomViewManager.fireCallback( 'DialogOption_"+ index +"' );"
|
|
||||||
}],
|
|
||||||
"children": [{
|
|
||||||
"name": "label",
|
|
||||||
"text": option.label
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
doc );
|
|
||||||
|
|
||||||
// append it to the items.
|
|
||||||
items.appendChild( newOptionButton );
|
|
||||||
});
|
|
||||||
|
|
||||||
return doc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function ListSavedViews() {
|
|
||||||
return ViewNames;
|
|
||||||
};
|
|
||||||
|
|
||||||
function setConfig(property, value) {
|
|
||||||
console.log( " ===> Setting: "+ property +" = "+ value +" <=== " );
|
|
||||||
config[ property ] = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
function getConfig(property) {
|
|
||||||
var value = config[property];
|
|
||||||
return (value) ? value: null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create a new DomView
|
|
||||||
function CreateView( name, dialogOptions ) {
|
|
||||||
if( name ) {
|
|
||||||
var view = new atv.DOMView();
|
|
||||||
|
|
||||||
_saveView( name, view );
|
|
||||||
|
|
||||||
if( typeof( dialogOptions ) === "object" ) {
|
|
||||||
var doc = _createDialogXML( dialogOptions );
|
|
||||||
};
|
|
||||||
|
|
||||||
setConfig( name+"_doc", doc )
|
|
||||||
|
|
||||||
view.onUnload = function() {
|
|
||||||
console.log(" == DOMView onUnload called == " );
|
|
||||||
FireCallbackEvent("ONUNLOADVIEW", {
|
|
||||||
"name": name,
|
|
||||||
"view": this
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
} else {
|
|
||||||
console.error("When attempting to create a DOM view, name is required.");
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function RemoveView( name ) {
|
|
||||||
// unload the view, remove the view from the view list, remove the view name
|
|
||||||
UnloadView( name );
|
|
||||||
_deleteView( name );
|
|
||||||
};
|
|
||||||
|
|
||||||
function LoadView( name, doc ) {
|
|
||||||
try {
|
|
||||||
var view = _retrieveView( name ),
|
|
||||||
doc = doc || getConfig( name+"_doc" );
|
|
||||||
|
|
||||||
if( !view )
|
|
||||||
{
|
|
||||||
CreateView( name );
|
|
||||||
view = _retrieveView( name );
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log( "We load the view: "+ name +" : "+ view );
|
|
||||||
view.load(doc, function(success) {
|
|
||||||
console.log("DOMView succeeded " + success);
|
|
||||||
if( success )
|
|
||||||
{
|
|
||||||
console.log("=== Saving Document: "+ name +"_doc ===");
|
|
||||||
view.doc = doc.serializeToString();
|
|
||||||
FireCallbackEvent( "ONLOADSUCCESS", { "view": name } )
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var msg = "Unable to load view."
|
|
||||||
FireCallbackEvent( "ONLOADERROR", { "id": "LOADERROR", "view":name, "msg": msg } );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch ( error ) {
|
|
||||||
console.error( "LOAD ERROR: "+ error );
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function UnloadView( name ) {
|
|
||||||
var view = _retrieveView( name );
|
|
||||||
view.unload();
|
|
||||||
};
|
|
||||||
|
|
||||||
function RegisterCallbackEvent( name, callback ) {
|
|
||||||
console.log(" ---- Registering Callback: " + name + " with callback type: " + typeof(callback));
|
|
||||||
if (typeof callback === "function") {
|
|
||||||
callbackEvents[name] = callback;
|
|
||||||
} else {
|
|
||||||
console.error("When attempting to register a callback event, a callback function is required.");
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function FireCallbackEvent( name, parameters, scope ) {
|
|
||||||
var scope = scope || this,
|
|
||||||
parameters = parameters || {};
|
|
||||||
|
|
||||||
if (callbackEvents[name] && typeof callbackEvents[name] === "function") {
|
|
||||||
callbackEvents[name].call(scope, parameters)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
"createView": CreateView,
|
|
||||||
"removeView": RemoveView,
|
|
||||||
"loadView": LoadView,
|
|
||||||
"unloadView": UnloadView,
|
|
||||||
"listViews": ListSavedViews,
|
|
||||||
"registerCallback": RegisterCallbackEvent,
|
|
||||||
"fireCallback": FireCallbackEvent
|
|
||||||
};
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
|
|
||||||
// ------ End DOM View Manager --------
|
|
||||||
|
|
229
app/js/jcm.js
229
app/js/jcm.js
@@ -717,5 +717,234 @@ function handleNavbarNavigate( event ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***************************************************
|
||||||
|
// DOMView | Wrapper
|
||||||
|
// https://github.com/wahlmanj/sample-aTV/blob/dba73806c21183fb35d6edca94b960691d8e5d66/js/views/DOMView/DOMView.js
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This wrapper makes it easier to handle the DOM View JS calls.
|
||||||
|
* The actual calls for DOMView are:
|
||||||
|
* view = new atv.DOMView()
|
||||||
|
* view.onUnload - similar to onPageUnload
|
||||||
|
* view.load ( XMLDOC, function(sucess) { ... } ) - pushes the view onto the stack the callback function is called back and gives you a success or fail call.
|
||||||
|
* view.unload - removes the view from the stack.
|
||||||
|
*/
|
||||||
|
var DomViewManager = ( function() {
|
||||||
|
var views = {},
|
||||||
|
ViewNames = [],
|
||||||
|
config = {},
|
||||||
|
callbackEvents = {},
|
||||||
|
optionDialogXML = {};
|
||||||
|
|
||||||
|
|
||||||
|
function _saveView( name, view ) {
|
||||||
|
if( name && view ) {
|
||||||
|
views[ name ] = view;
|
||||||
|
_addViewToList( name );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.error( "When saving a view, both name and view are required" );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function _deleteView( name ) {
|
||||||
|
if( views[ name ] ) {
|
||||||
|
delete views[ name ];
|
||||||
|
_removeViewFromList( name );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function _retrieveView( name ) {
|
||||||
|
if( name ) {
|
||||||
|
return views[ name ] || null;
|
||||||
|
} else {
|
||||||
|
console.error( "When attempting to retrieve a view name is required.");
|
||||||
|
};
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
function _addViewToList( name ) {
|
||||||
|
var index = ViewNames.indexOf( name );
|
||||||
|
if( index == -1 ) {
|
||||||
|
ViewNames.push( name );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function _removeViewFromList( name ) {
|
||||||
|
var index = ViewNames.indexOf( name );
|
||||||
|
if( index > -1 ) {
|
||||||
|
ViewNames.splice( index, 1 );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function _createDialogXML( dialogOptions ) {
|
||||||
|
var doc = atv.parseXML( optionDialogXML ),
|
||||||
|
title = dialogOptions.title,
|
||||||
|
description = dialogOptions.description,
|
||||||
|
initialSelection = dialogOptions.initialSelection || 0,
|
||||||
|
options = dialogOptions.options || [];
|
||||||
|
|
||||||
|
|
||||||
|
// fill in the title, accessibility label
|
||||||
|
doc.rootElement.getElementByTagName( 'title' ).textContent = title;
|
||||||
|
doc.rootElement.getElementByTagName( 'simpleHeader' ).setAttribute( 'accessibilityLabel', title +". "+ description );
|
||||||
|
|
||||||
|
// fill in the description
|
||||||
|
doc.rootElement.getElementByTagName( 'description' ).textContent = description;
|
||||||
|
|
||||||
|
// fill in the initial selection
|
||||||
|
doc.rootElement.getElementByTagName( 'row' ).textContent = initialSelection;
|
||||||
|
|
||||||
|
// fill in the options
|
||||||
|
var items = doc.rootElement.getElementByTagName( 'items' );
|
||||||
|
options.forEach( function ( option, index ) {
|
||||||
|
// save option callbacks
|
||||||
|
RegisterCallbackEvent( "DialogOption_"+index, option.callback );
|
||||||
|
|
||||||
|
// create the option
|
||||||
|
var newOptionButton = ATVUtils.createNode({
|
||||||
|
"name": "oneLineMenuItem",
|
||||||
|
"attrs": [{
|
||||||
|
"name": "id",
|
||||||
|
"value": "DialogOption_"+ index
|
||||||
|
}, {
|
||||||
|
"name": "accessibilityLabel",
|
||||||
|
"value": option.label
|
||||||
|
}, {
|
||||||
|
"name": "onSelect",
|
||||||
|
"value": "DomViewManager.fireCallback( 'DialogOption_"+ index +"' );"
|
||||||
|
}],
|
||||||
|
"children": [{
|
||||||
|
"name": "label",
|
||||||
|
"text": option.label
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
doc );
|
||||||
|
|
||||||
|
// append it to the items.
|
||||||
|
items.appendChild( newOptionButton );
|
||||||
|
});
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function ListSavedViews() {
|
||||||
|
return ViewNames;
|
||||||
|
};
|
||||||
|
|
||||||
|
function setConfig(property, value) {
|
||||||
|
console.log( " ===> Setting: "+ property +" = "+ value +" <=== " );
|
||||||
|
config[ property ] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getConfig(property) {
|
||||||
|
var value = config[property];
|
||||||
|
return (value) ? value: null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a new DomView
|
||||||
|
function CreateView( name, dialogOptions ) {
|
||||||
|
if( name ) {
|
||||||
|
|
||||||
|
var view = new atv.DOMView();
|
||||||
|
// console.log("This log prevents occasional hanging for some reason...")
|
||||||
|
|
||||||
|
_saveView( name, view );
|
||||||
|
|
||||||
|
if( typeof( dialogOptions ) === "object" ) {
|
||||||
|
var doc = _createDialogXML( dialogOptions );
|
||||||
|
};
|
||||||
|
|
||||||
|
setConfig( name+"_doc", doc )
|
||||||
|
|
||||||
|
view.onUnload = function() {
|
||||||
|
console.log(" == DOMView onUnload called == " );
|
||||||
|
FireCallbackEvent("ONUNLOADVIEW", {
|
||||||
|
"name": name,
|
||||||
|
"view": this
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
console.error("When attempting to create a DOM view, name is required.");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function RemoveView( name ) {
|
||||||
|
// unload the view, remove the view from the view list, remove the view name
|
||||||
|
UnloadView( name );
|
||||||
|
_deleteView( name );
|
||||||
|
};
|
||||||
|
|
||||||
|
function LoadView( name, doc ) {
|
||||||
|
try {
|
||||||
|
var view = _retrieveView( name ),
|
||||||
|
doc = doc || getConfig( name+"_doc" );
|
||||||
|
|
||||||
|
if( !view )
|
||||||
|
{
|
||||||
|
CreateView( name );
|
||||||
|
view = _retrieveView( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log( "We load the view: "+ name +" : "+ view );
|
||||||
|
view.load(doc, function(success) {
|
||||||
|
console.log("DOMView succeeded " + success);
|
||||||
|
if( success )
|
||||||
|
{
|
||||||
|
console.log("=== Saving Document: "+ name +"_doc ===");
|
||||||
|
view.doc = doc.serializeToString();
|
||||||
|
FireCallbackEvent( "ONLOADSUCCESS", { "view": name } )
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var msg = "Unable to load view."
|
||||||
|
FireCallbackEvent( "ONLOADERROR", { "id": "LOADERROR", "view":name, "msg": msg } );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch ( error ) {
|
||||||
|
console.error( "LOAD ERROR: "+ error );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function UnloadView( name ) {
|
||||||
|
var view = _retrieveView( name );
|
||||||
|
view.unload();
|
||||||
|
};
|
||||||
|
|
||||||
|
function RegisterCallbackEvent( name, callback ) {
|
||||||
|
console.log(" ---- Registering Callback: " + name + " with callback type: " + typeof(callback));
|
||||||
|
if (typeof callback === "function") {
|
||||||
|
callbackEvents[name] = callback;
|
||||||
|
} else {
|
||||||
|
console.error("When attempting to register a callback event, a callback function is required.");
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
function FireCallbackEvent( name, parameters, scope ) {
|
||||||
|
var scope = scope || this,
|
||||||
|
parameters = parameters || {};
|
||||||
|
|
||||||
|
if (callbackEvents[name] && typeof callbackEvents[name] === "function") {
|
||||||
|
callbackEvents[name].call(scope, parameters)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
"createView": CreateView,
|
||||||
|
"removeView": RemoveView,
|
||||||
|
"loadView": LoadView,
|
||||||
|
"unloadView": UnloadView,
|
||||||
|
"listViews": ListSavedViews,
|
||||||
|
"registerCallback": RegisterCallbackEvent,
|
||||||
|
"fireCallback": FireCallbackEvent
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
// ------ End DOM View Manager --------
|
||||||
|
|
||||||
console.log('Reached EOF!');
|
console.log('Reached EOF!');
|
||||||
|
|
||||||
|
70
app/js/jellyfin-setup.js
Normal file
70
app/js/jellyfin-setup.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
// /\_/|
|
||||||
|
// { ' ' } JellyCAT
|
||||||
|
// \____\
|
||||||
|
|
||||||
|
// Function to show text entry page
|
||||||
|
showTextEntryPage = function(input_type, input_title, input_instructions, callback_submit, callback_cancel, defaultvalue) {
|
||||||
|
var textEntry = new atv.TextEntry();
|
||||||
|
|
||||||
|
textEntry.type = input_type;
|
||||||
|
textEntry.title = input_title;
|
||||||
|
textEntry.instructions = input_instructions;
|
||||||
|
textEntry.defaultValue = defaultvalue;
|
||||||
|
textEntry.defaultToAppleID = false;
|
||||||
|
// textEntry.image =
|
||||||
|
textEntry.onSubmit = callback_submit;
|
||||||
|
textEntry.onCancel = callback_cancel;
|
||||||
|
|
||||||
|
textEntry.show();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to set server address
|
||||||
|
function setServerAddress() {
|
||||||
|
showTextEntryPage(
|
||||||
|
"emailAddress",
|
||||||
|
"Set Jellyfin Server Address",
|
||||||
|
"Enter the address of the Jellyfin server:",
|
||||||
|
function(value) {
|
||||||
|
// Save server address to localStorage
|
||||||
|
atv.localStorage['jellyfin_server_address'] = value;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
atv.localStorage['jellyfin_server_address'] || ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set username
|
||||||
|
function setUsername() {
|
||||||
|
showTextEntryPage(
|
||||||
|
"emailAddress",
|
||||||
|
"Set Username",
|
||||||
|
"Enter your username:",
|
||||||
|
function(value) {
|
||||||
|
// Save username to localStorage
|
||||||
|
atv.localStorage['jellyfin_username'] = value;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
atv.localStorage['jellyfin_username'] || ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to set password
|
||||||
|
function setPassword() {
|
||||||
|
showTextEntryPage(
|
||||||
|
"password",
|
||||||
|
"Set Password",
|
||||||
|
"Enter your password:",
|
||||||
|
function(value) {
|
||||||
|
// Save password to localStorage
|
||||||
|
atv.localStorage['jellyfin_password'] = value;
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
atv.localStorage['jellyfin_password'] || ""
|
||||||
|
);
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
function printSessionStorage() {
|
function printSessionStorage() {
|
||||||
|
|
||||||
var keys = ['test', 'exampleKey2', 'exampleKey3'];
|
var keys = ['test', 'exampleKey'];
|
||||||
|
|
||||||
keys.forEach(function(key) {
|
keys.forEach(function(key) {
|
||||||
var value = atv.sessionStorage.getItem(key);
|
var value = atv.sessionStorage.getItem(key);
|
||||||
@@ -18,7 +18,7 @@ function printSessionStorage() {
|
|||||||
|
|
||||||
function printLocalStorage() {
|
function printLocalStorage() {
|
||||||
|
|
||||||
var keys = ['test', 'exampleKey2', 'exampleKey3'];
|
var keys = ['test', 'jellyfin_server_address', 'jellyfin_username', 'jellyfin_password', 'jellyfin_auth'];
|
||||||
|
|
||||||
keys.forEach(function(key) {
|
keys.forEach(function(key) {
|
||||||
var value = atv.localStorage.getItem(key);
|
var value = atv.localStorage.getItem(key);
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<script src="http://jcathost.dns/js/jcm.js"/>
|
<script src="http://jcathost.dns/js/jcm.js"/>
|
||||||
<script src="http://jcathost.dns/js/jcathostinfo.js"/>
|
<script src="http://jcathost.dns/js/jcathostinfo.js"/>
|
||||||
|
<script src="http://jcathost.dns/js/about.js"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<optionDialog id="com.jellycat.devtools">
|
<optionDialog id="com.jellycat.devtools">
|
||||||
|
50
app/xml/server-settings.xml
Normal file
50
app/xml/server-settings.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<atv>
|
||||||
|
<head>
|
||||||
|
<script src="http://jcathost.dns/js/jcm.js"/>
|
||||||
|
<script src="http://jcathost.dns/js/jellyfin-setup.js"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<listWithPreview id="com.jellycat.jellyfin-server-settings">
|
||||||
|
<header>
|
||||||
|
<simpleHeader accessibilityLabel="Menu items">
|
||||||
|
<title>Jellyfin Server Settings</title>
|
||||||
|
</simpleHeader>
|
||||||
|
</header>
|
||||||
|
<preview>
|
||||||
|
<crossFadePreview>
|
||||||
|
<image>http://jcathost.dns/assets/img/jfserver.png</image>
|
||||||
|
</crossFadePreview>
|
||||||
|
</preview>
|
||||||
|
<menu>
|
||||||
|
<initialSelection>
|
||||||
|
<row>3</row>
|
||||||
|
</initialSelection>
|
||||||
|
<sections>
|
||||||
|
<menuSection>
|
||||||
|
<items>
|
||||||
|
<oneLineMenuItem accessibilityLabel="List item 0" id="list_0" onSelect="setServerAddress();">
|
||||||
|
<label>Server Address</label>
|
||||||
|
<rightLabel>(not set)</rightLabel>
|
||||||
|
</oneLineMenuItem>
|
||||||
|
<oneLineMenuItem accessibilityLabel="List item 1" id="list_1" onSelect="setUsername();">
|
||||||
|
<label>Server Username</label>
|
||||||
|
<rightLabel>(not set)</rightLabel>
|
||||||
|
</oneLineMenuItem>
|
||||||
|
<oneLineMenuItem accessibilityLabel="List item 2" id="list_2" onSelect="setPassword();">
|
||||||
|
<label>Server Password</label>
|
||||||
|
<rightLabel>(always hidden)</rightLabel>
|
||||||
|
</oneLineMenuItem>
|
||||||
|
<oneLineMenuItem accessibilityLabel="List item 3" id="list_3" onSelect="">
|
||||||
|
<label>Test connection</label>
|
||||||
|
</oneLineMenuItem>
|
||||||
|
<oneLineMenuItem accessibilityLabel="List item 4" id="list_4" onSelect="console.log('Logging out and clearing storage'); atv.localStorage.clear(); atv.sessionStorage.clear(); atv.exitApp();">
|
||||||
|
<label>Remove saved data</label>
|
||||||
|
</oneLineMenuItem>
|
||||||
|
</items>
|
||||||
|
</menuSection>
|
||||||
|
</sections>
|
||||||
|
</menu>
|
||||||
|
</listWithPreview>
|
||||||
|
</body>
|
||||||
|
</atv>
|
@@ -2,6 +2,7 @@
|
|||||||
<atv>
|
<atv>
|
||||||
<head>
|
<head>
|
||||||
<script src="http://jcathost.dns/js/jcm.js"/>
|
<script src="http://jcathost.dns/js/jcm.js"/>
|
||||||
|
<script src="http://jcathost.dns/js/about.js"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<listWithPreview id="com.jellycat.settings">
|
<listWithPreview id="com.jellycat.settings">
|
||||||
@@ -24,14 +25,16 @@
|
|||||||
</horizontalDivider>
|
</horizontalDivider>
|
||||||
</header>
|
</header>
|
||||||
<items>
|
<items>
|
||||||
<oneLineMenuItem id="list_center_1" accessibilityLabel="Menu Item 1">
|
<twoLineMenuItem id="list_center_1" accessibilityLabel="Menu Item 1" onSelect="atvutils.loadURL('https://' + atv.jcathost.SigHost + '/xml/server-settings.xml');">
|
||||||
<label>Menu item title</label>
|
<label>Jellyfin Server Settings</label>
|
||||||
</oneLineMenuItem>
|
<label2>Set Jellyfin Server and User</label2>
|
||||||
|
<image>http://jcathost.dns/assets/img/jfserver.png</image>
|
||||||
|
</twoLineMenuItem>
|
||||||
<oneLineMenuItem id="list_center_2" accessibilityLabel="Menu Item 2">
|
<oneLineMenuItem id="list_center_2" accessibilityLabel="Menu Item 2">
|
||||||
<label>Menu item title</label>
|
<label>Audio and Video settings</label>
|
||||||
</oneLineMenuItem>
|
</oneLineMenuItem>
|
||||||
<oneLineMenuItem id="list_center_3" accessibilityLabel="Menu Item 3">
|
<oneLineMenuItem id="list_center_3" accessibilityLabel="Menu Item 3">
|
||||||
<label>Menu item title</label>
|
<label>Advanced settings</label>
|
||||||
</oneLineMenuItem>
|
</oneLineMenuItem>
|
||||||
</items>
|
</items>
|
||||||
</menuSection>
|
</menuSection>
|
||||||
@@ -45,7 +48,7 @@
|
|||||||
<oneLineMenuItem id="list_center_1" accessibilityLabel="tools" onSelect="atvutils.loadURL('https://' + atv.jcathost.SigHost + '/xml/dvt/devtools.xml');">
|
<oneLineMenuItem id="list_center_1" accessibilityLabel="tools" onSelect="atvutils.loadURL('https://' + atv.jcathost.SigHost + '/xml/dvt/devtools.xml');">
|
||||||
<label>Tools</label>
|
<label>Tools</label>
|
||||||
</oneLineMenuItem>
|
</oneLineMenuItem>
|
||||||
<oneLineMenuItem id="list_center_1" accessibilityLabel="about" onSelect="atvutils.loadURL('https://' + atv.jcathost.SigHost + '/xml/about.xml');">
|
<oneLineMenuItem id="list_center_1" accessibilityLabel="about" onSelect="generateJCATAboutXML();">
|
||||||
<label>About</label>
|
<label>About</label>
|
||||||
</oneLineMenuItem>
|
</oneLineMenuItem>
|
||||||
<oneLineMenuItem id="list_center_1" accessibilityLabel="about" onSelect="atvutils.loadURL('https://' + atv.jcathost.SigHost + '/xml/help.xml');">
|
<oneLineMenuItem id="list_center_1" accessibilityLabel="about" onSelect="atvutils.loadURL('https://' + atv.jcathost.SigHost + '/xml/help.xml');">
|
||||||
|
2
main.go
2
main.go
@@ -26,7 +26,7 @@ func main() {
|
|||||||
|
|
||||||
// Default information store
|
// Default information store
|
||||||
JellyCAT = JcatDefaults{
|
JellyCAT = JcatDefaults{
|
||||||
Version: "0.1.2revA",
|
Version: "0.1.2revB",
|
||||||
Name: "JellyCAT Serving stHack",
|
Name: "JellyCAT Serving stHack",
|
||||||
HostName: config.CertName,
|
HostName: config.CertName,
|
||||||
HostIP: config.HijackIP,
|
HostIP: config.HijackIP,
|
||||||
|
Reference in New Issue
Block a user