Commit c43b37d8 authored by yPhil's avatar yPhil

Sys: Huge refactoring, everything is now in the PLT Module namespace

parent 5172c8f1
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
var PTL = (function() {
return {
// language: Prefs.readConfig('lang'),
language: 'en',
start : function() {
var self = this;
},
tr : function( string ) {
var _trAux,
stringVarRegExp = /(%.)/,
matchData,
translatedString,
translations,
currentReplacement,
i = 1; // pour pointer sur le premier argument optionnel, arguments[1]
// Retourne la traduction de la chaine de caractère passée en argument.
_trAux = function( string ) {
if( !string ) {
return "";
}
if ( PTL.language === "en" ) {
// Le discriminant sert à distinguer masculin/féminin ou singulier pluriel, ex <plural>Open
// En "en" la clé sert aussi à la traduction, donc on retire simplement le discriminant
var discriminantRegExp = /(<.*>)(.*)/;
var match = string.match( discriminantRegExp );
var stringWithoutDiscriminant = match ? match[ 2 ] : null;
return stringWithoutDiscriminant || string;
} else {
translations = PTL.i18n.translations[ string ];
translatedString = translations ? translations[ PTL.language ] : string;
return translatedString || string;
}
};
translatedString = _trAux( string );
while ( ( matchData = stringVarRegExp.exec( translatedString ) ) !== null ) {
currentReplacement = translatedString.replace( matchData[0], arguments[ i ] );
translatedString = currentReplacement;
i++;
}
return translatedString;
}
};
})();
$('<div id="menu">').appendTo($('body')).load('/static/templates/menu.html', function() {
var $menu = $(this),
$overlay = $('#overlay'),
$menuButton = $('#menuButton'),
$helpButton = $('.helpButton'),
$newSourceButton = $('#newSourceButton'),
$sourceCodeButton = $('button#sourceCode'),
$importButton = $("button#fileImport"),
$fileImportInput = $("input#fileImport"),
$saveButton = $('#saveTabs'),
$langMenu = $('select#language'),
$donateButton = $('button#donate'),
$slider = $('div#gallerySpeedSlider'),
$spinner = $('#gallerySpeedSpinner');
$('button').button();
PTL.sync.attachWidget();
$menuButton.click(function() {
$overlay.toggleClass('visible');
$menu.toggleClass('expanded');
});
$sourceCodeButton.click(function(event) {
event.preventDefault();
window.open('https://framagit.org/yphil/petrolette');
});
$overlay.click(function() {
$(this).removeClass('visible');
$menu.removeClass('expanded');
});
$newSourceButton.click(function() {
var $openGroupPanel = $($('.ui-tabs-active').find('a').attr('href')).find('.tabSort');
$overlay.removeClass('visible');
$menu.removeClass('expanded');
PTL.feed.make($openGroupPanel, 'New Feed', 'mixed', 8, true);
});
$(document).keydown(function(event) {
if (event.keyCode === $.ui.keyCode.ESCAPE) {
$('.tabSort' ).sortable('cancel');
}
});
var $widget = $('#remotestorage-widget');
var $readMore = $('<a>')
.attr('class', 'rs-help')
.attr('href', 'https:remotestorage.io/')
.text(PTL.tr('Read more.'));
$widget.find('.rs-short-desc').text(PTL.tr('Pétrolette allows you to sync data with a storage of your choice ; '))
.append($readMore);
var $fuckingButton = $widget.find('.rs-choose-rs');
$fuckingButton.css('border-color', '#f00');
$fuckingButton.click(function (event) {
event.preventDefault();
});
PTL.utilities.translate();
$langMenu.val(PTL.prefs.readConfig('lang')).prop('selected', true);
$langMenu.change(function() {
var selectedLang = $(this).val();
PTL.language = selectedLang;
PTL.prefs.writeConfig('lang', selectedLang);
PTL.utilities.translate();
});
$helpButton.click(function (event) {
event.preventDefault();
$('#tabs').tabs('option', 'active', 0);
// PTL.utilities.help('ui');
PTL.dialog.help();
});
$donateButton.click(function (event) {
event.preventDefault();
window.open('https://liberapay.com/yPhil/donate', '_blank');
});
$importButton.click(function () {
$("input#fileImport").click();
return false;
});
$saveButton.click(function () {
PTL.prefs.exportConfig(PTL.tab.list(), 'petrolette.conf');
return false;
});
$(".checkboxradio").checkboxradio({
icon: false
});
$(this).find('input#' + PTL.prefs.readConfig('theme')).prop("checked", true)
.checkboxradio('refresh');
$('.themeSwitcher').change(function() {
console.log('Theme: ' + '/static/css/themes/' + $(this).attr('value') + '.css');
$("#mobStyle").attr({href : '/static/css/themes/' + $(this).attr('value') + '.css'});
PTL.prefs.writeConfig('theme', $(this).attr('value'));
});
var gallerySlideshowSpeed = PTL.prefs.readConfig('gallerySlideshowSpeed');
var gallerySlideTransition = PTL.prefs.readConfig('gallerySlideTransition');
// $.fancybox.defaults.thumbs.autoStart = true;
$.fancybox.defaults.transitionEffect = gallerySlideTransition;
$.fancybox.defaults.slideShow.speed = gallerySlideshowSpeed;
$menu.find('select#gallerySlideTransition').change(function() {
console.log('New FX: %s', $(this).val());
$.fancybox.defaults.transitionEffect = $(this).val();
PTL.prefs.writeConfig('gallerySlideTransition', $(this).val());
});
$menu.find('select#gallerySlideTransition').val(gallerySlideTransition);
if (PTL.prefs.readConfig('tabDropActivate') === 'true')
$('input#tabDropActivate').prop('checked', true).checkboxradio('refresh');
else
$('input#tabDropActivate').prop('checked', false).checkboxradio('refresh');
$('input#tabDropActivate').change(function() {
PTL.prefs.writeConfig('tabDropActivate', $(this).prop('checked'));
});
$spinner.spinner({
min: 0.5,
max: 10000,
step: 0.5,
classes: {
"ui-spinner": "shrink ui-corner-all",
"ui-spinner-down": "ui-corner-br",
"ui-spinner-up": "ui-corner-tr"
}
});
$spinner.spinner('value', PTL.utilities.milliToSecs(gallerySlideshowSpeed));
$spinner.on( 'spinstop', function() {
$slider.slider( 'option', 'value', $(this).val() * 1000);
$('.ui-slider-handle').text(PTL.utilities.milliToSecs($(this).val() * 1000) + 's');
});
$slider.slider({
classes: {
"ui-slider": "grow ui-corner-all",
"ui-slider-handle": "ui-corner-all",
"ui-slider-range": "ui-corner-all ui-widget-header"
},
value: gallerySlideshowSpeed,
min: 500,
max: 10000,
step: 500,
create: function() {
$(this).find('.ui-slider-handle').text(PTL.utilities.milliToSecs(gallerySlideshowSpeed) + 's');
},
slide: function(event, ui) {
// $('#gallerySlideshowSpeedValue').text(ui.value + 'ms');
$spinner.val(PTL.utilities.milliToSecs(ui.value));
$(this).find('.ui-slider-handle').text(PTL.utilities.milliToSecs(ui.value) + 's');
},
change: function(event, ui) {
PTL.prefs.writeConfig('gallerySlideshowSpeed', ui.value);
$('#tabs').find("[data-fancybox]").fancybox({
slideShow: {
speed: ui.value
}
});
}
});
// File reader
$fileImportInput.change(function(evt){
var f = evt.target.files[0],
reader = new FileReader();
reader.onload = (function() {
return function(e) {
function isOk(o) {
var isValid = false;
if (Object.prototype.toString.call(o) === '[object Array]') {
isValid = o.some(obj => Array.isArray(obj.feeds) && obj.feeds.some(feed => Object.prototype.hasOwnProperty.call(feed, 'url')));
} else {
isValid = false;
}
return isValid;
}
var y = e.target.result;
function isJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
var p = false;
if (isJsonString(y)) {
p = JSON.parse(y);
} else {
console.error('Pétrolette | ' + PTL.tr('This file is bad'));
}
if (p && isOk(p) === true){
console.info('Pétrolette | ' + PTL.tr('Loading of [%s] OK', f.name));
PTL.tab.populate(p, true);
} else {
console.error('Pétrolette | ' + PTL.tr('This file is bad'));
}
};
})(f);
reader.readAsText(f);
});
});
PTL.prefs = (function() {
var emptyTabList = [
{"name":"Group 1",
"feeds": [
{"url":"http://www.androidpolice.com/feed","type":"mixed","limit": 8},
{"url":"http://feeds.nature.com/nature/rss/current","type":"text","limit": 16},
{"url":"https://www.nasa.gov/rss/dyn/lg_image_of_the_day.rss","type":"photo","limit": 4}
]
}
];
var newsTabList = [
{"name":"World",
"feeds": [
{"url":"http://feeds.bbci.co.uk/news/world/rss.xml","type":"mixed","limit":8},
{"url":"http://www.nytimes.com/services/xml/rss/nyt/World.xml","type":"mixed","limit": 4},
{"url":"http://feeds.reuters.com/Reuters/worldNews","type":"text","limit": 16},
{"url":"http://feeds.reuters.com/reuters/USVideoWorldNews","type":"photo","limit": 16},
{"url":"http://www.economist.com/sections/international/rss.xml","type":"text","limit": 8},
{"url":"https://www.reddit.com/.rss","type":"text","limit": 8}
]
},
{"name":"Europe",
"feeds": [
{"url":"http://www.economist.com/sections/europe/rss.xml", "type":"text", "limit": 12},
{"url":"https://feeds.feedburner.com/TechCrunch/","type":"mixed","limit": 8},
{"url":"http://xkcd.com/rss.xml","type":"photo","limit": 4},
{"url":"https://www.reddit.com/.rss","type":"text","limit": 8}
]
}
];
var miscTabList = [
{"name":"Tech",
"feeds": [
{"url":"https://feeds.feedburner.com/TechCrunch/","type":"mixed","limit": 8},
{"url":"http://feeds.reuters.com/reuters/technologyNews", "type":"text", "limit": 16},
{"url":"https://www.sciencedaily.com/rss/matter_energy/engineering.xml", "type":"mixed", "limit": 12},
{"url":"https://www.theengineer.co.uk/feed", "type":"mixed", "limit": 14},
{"url":"http://feed.cnet.com/feed/topics/tech-industry", "type":"mixed", "limit": 14},
{"url":"https://spectrum.ieee.org/rss/videos", "type":"mixed", "limit": 16}
]
},
{"name":"Computing",
"feeds": [
{"url":"http://feeds.reuters.com/reuters/technologyNews", "type":"text", "limit": 16},
{"url":"https://spectrum.ieee.org/rss/computing/fulltext", "type":"mixed", "limit": 12},
{"url":"https://www.technologyreview.com/c/computing/rss/", "type":"photo", "limit": 4},
{"url":"http://www.economist.com/blogs/gametheory/index.xml","type":"mixed","limit": 8},
{"url":"http://rss.slashdot.org/Slashdot/slashdot", "type":"mixed", "limit": 4},
{"url":"http://rss.slashdot.org/Slashdot/slashdot", "type":"mixed", "limit": 4},
{"url":"http://rss.slashdot.org/Slashdot/slashdot", "type":"mixed", "limit": 4},
{"url":"http://www.economist.com/topics/computer-technology/index.xml", "type":"text", "limit": 16}
]
},
{"name":"Science",
"feeds": [
{"url":"http://feeds.bbci.co.uk/news/science_and_environment/rss.xml", "type":"mixed", "limit": 6},
{"url":"https://feeds.feedburner.com/TechCrunch/","type":"mixed","limit": 8},
{"url":"https://spectrum.ieee.org/rss/biomedical/fulltext","type":"mixed","limit": 4},
{"url":"https://www.technologyreview.com/topnews.rss","type":"mixed","limit": 4},
{"url":"https://www.technologyreview.com/c/biomedicine/rss/","type":"mixed","limit": 4},
{"url":"https://www.technologyreview.com/c/energy/rss/","type":"mixed","limit": 4},
{"url":"https://spectrum.ieee.org/rss/blog/energywise/fulltext","type":"mixed","limit": 4},
{"url":"https://spectrum.ieee.org/rss/blog/automaton/fulltext","type":"mixed","limit": 4},
{"url":"https://www.reddit.com/.rss","type":"text","limit": 8}
]
},
{"name":"Comics",
"feeds": [
{"url":"http://xkcd.com/rss.xml","type":"photo","limit": 8},
{"url":"http://thisisindexed.com/feed","type":"photo","limit": 8},
{"url":"http://what-if.xkcd.com/feed.atom","type":"photo","limit": 8},
{"url":"http://phdcomics.com/gradfeed.php","type":"photo","limit": 8},
{"url":"http://comicfeeds.chrisbenard.net/view/pennyarcade/default","type":"photo","limit": 8},
{"url":"http://comicfeeds.chrisbenard.net/view/dilbert/default","type":"photo","limit": 8}
]
}
];
var defaults = {
'gallerySlideTransition': 'fade',
'gallerySlideshowSpeed': 3000,
'tabDropActivate': true,
'theme': 'day',
'columns': 3,
'lang': 'en',
'explicitLang': false,
'tabs': JSON.stringify(emptyTabList)
};
var collections = {
'news': JSON.stringify(newsTabList),
'misc': JSON.stringify(miscTabList)
};
return {
collection:function(key) {
return collections[key];
},
isValidSourcesFile:function(sources) {
var isValid = false;
if (Object.prototype.toString.call(sources) === '[object Array]') {
isValid = sources.some(obj => Array.isArray(obj.feeds) && obj.feeds.some(feed => Object.prototype.hasOwnProperty.call(feed, 'url')));
} else {
isValid = false;
}
return isValid;
},
readConfig:function(key) {
if(typeof localStorage.getItem(key) === 'undefined' || !localStorage.getItem(key)) {
return defaults[key];
} else {
return localStorage.getItem(key);
}
},
writeConfig:function(key, val) {
var $loader = $('#indicatorContainer');
$loader.fadeToggle(50);
localStorage.setItem(key, val);
$loader.fadeToggle('fast');
},
exportConfig:function(data, fileName) {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var json = JSON.stringify(data, null, 2),
blob = new Blob([json], {type: "application/json"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
};
}());
PTL.sync = (function() {
var synchronized = false;
var syncDirectory = 'petrolette';
var Sources = {
name: syncDirectory, builder: function(privateClient, publicClient) {
return {
exports: {
read: function () {
return privateClient.getFile('petrolette.conf', 9999999999)
.then(function (file) {
return file.data;
});
},
write: function (sources) {
return privateClient.storeFile('text/plain', 'petrolette.conf', sources);
}
}
};
}
};
const remoteStorage = new RemoteStorage({
// logging: true,
// cordovaRedirectUri: 'http://petrolette.space',
modules: [ Sources ]
});
// remoteStorage.setApiKeys({
// dropbox: 'jyss37l88l4ural',
// googledrive: '228755392285-87kkpdod9op50nmnrvnvo6eofr5d3ehl.apps.googleusercontent.com'
// });
remoteStorage.on('connected', function() {
synchronized = true;
console.info('Pétrolette | Connected to remote storage');
});
remoteStorage.on('disconnected', function() {
synchronized = false;
console.info('Pétrolette | Disconnected from remote storage');
});
return {
attachWidget:function() {
const widget = new Widget(remoteStorage, {
leaveOpen: true
// logging: true
});
remoteStorage.access.claim('petrolette', 'rw');
return widget.attach('syncBox');
},
readSync:function() {
remoteStorage.petrolette.read()
.then((data) => {
if (PTL.prefs.isValidSourcesFile(JSON.parse(data))) {
console.info('Pétrolette | Remote file validation OK');
return PTL.tab.populate(JSON.parse(data));
} else {
console.error('Pétrolette | Remote file validation NOT OK(%s) Tryin browser cache', data);
if (PTL.prefs.isValidSourcesFile(JSON.parse(PTL.prefs.readConfig('tabs')))) {
console.log('plop');
PTL.tab.populate(JSON.parse(PTL.prefs.readConfig('tabs')));
} else {
localStorage.setItem("tabs", "");
}
}
})
.catch((err) => {
if (PTL.prefs.isValidSourcesFile(JSON.parse(PTL.prefs.readConfig('tabs')))) {
PTL.tab.populate(JSON.parse(PTL.prefs.readConfig('tabs')));
} else {
localStorage.setItem("tabs", "");
}
});
},
writeSync:function(sources) {
var $loader = $('#indicatorContainer');
$loader.fadeToggle(50);
remoteStorage.petrolette.write(sources)
.then(() => {
console.info('Pétrolette | Writing to remote storage OK');
})
.catch((err) => {
console.error('Pétrolette | Remote file validation error:', err);
});
// localStorage.setItem(key, val);
$loader.fadeToggle('fast');
}
};
}());
PTL.utilities = {
isImage:function(string) {
// return string.split('.').pop() === 'jpg';
return (['jpg', 'png'].indexOf(string.split('.').pop()) >= 0);
},
noSourcesButton:function() {
var $loadingSpinner = $('<i>')
.attr('class', 'icon-arrows-cw spin');
var $noSourcesText = $('<div>').text('Loading sources');
var $noSourcesButton = $('<div>')
// .append('<span data-content="Whoops, no sources!" data-title="Whoops, no sources!" class="translate"> Whoops, no sources! </span> <br/> <span data-content="Click here to add some." data-title="Click here to add some." class="translate"> Click here to add some.</span>')
.append($loadingSpinner)
.append('<br>')
.append($noSourcesText);
var $noSourcesButtonContainer = $('<div>')
.attr('id', 'noSourcesButton')
.attr('class', 'deadCenter')
.append($noSourcesButton);
$('main').append($noSourcesButtonContainer);
},
vWidth:function() {
var vWidth = $(window).width(),
vW;
if(PTL.utilities.isMobile() || vWidth < 720 ) {
vW = vWidth - 8;
} else {
vW = vWidth - vWidth / 4;
}
return vW;
},
moveEltLeft:function($elt) {
$elt.insertBefore($elt.prev());
},
moveEltRight:function($elt) {
if (!$elt.next().hasClass('newContentButton')) {
$elt.insertAfter($elt.next());
}
},
isMobile:function() {
var isMobile = false;
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
isMobile = true;
} else {
isMobile = false;
}
return isMobile;
},
help:function(type) {
var dialog = introJs(),
menu = introJs(),
ui = introJs();
ui.setOptions({
steps: [
{
element: 'li[aria-controls=tab-1]',
intro: PTL.tr('This is a group. It contains sources.')
},
{
element: 'li[aria-controls=tab-2]',
intro: PTL.tr('Click on a group tab to display it.')
},
{
element: 'li[aria-controls=tab-1]',
intro: PTL.tr('Click on the current/selected group tab to change its name and position.')
},
{
element: 'li.feed',
intro: PTL.tr('This is a source.')
},
{
element: 'div#newSourceButton',
intro: PTL.tr('Click to add a source.')
},
{
element: '.mobFeedRefresh',
intro: PTL.tr('Refresh / reload this source.')
},
{
element: 'li#feed-0 i.feedControl.mobFeedPrefs',
intro: PTL.tr('Configure this source.')
},
{
element: '.feedDelete',
intro: PTL.tr('Delete this source.')
},
{
element: '.feedSelect',
intro: PTL.tr('Select this source (for drag & drop).')
},
{
element: '.feedHandle',
intro: PTL.tr('Drag here to move this source (and all other selected sources) within this group, or into another.')
},
{
element: 'div.feedToggle',
intro: PTL.tr('Expand / collapse this source.')
}
]
});
dialog.setOptions({
steps: [
{
element: 'input#feedGuess',
intro: '<span class="translate" data-content="Enter a website address/URL and click search, then OK, or simply enter the URL of the">' + PTL.tr('Enter a website address/URL and click search, then OK, or simply enter the URL of the') + '</span> <a class="rssDocLink" href="https://' + PTL.language + '.wikipedia.org/wiki/RSS">' + PTL.tr('source') + '</a>. <span class="translate" data-content="Heck, enter anything, and Pétrolette will build a source from your search query.">' + PTL.tr('Heck, enter anything, and Pétrolette will build a source from your search query.') + '</span>',
position: 'bottom'
},
{
element: 'button#feedGuess',
intro: PTL.tr('Find the website\'s source, or build a new one from the seach query.'),
position: 'left'
},
{
element: 'fieldset#feedGroup',
intro: PTL.tr('Move this source to another group.'),
position: 'bottom'
},
{
element: 'fieldset#feedType',
intro: PTL.tr('The type of source: It can be all text, all image, or mixed.'),
position: 'top'
},
{
element: 'fieldset#feedLimit',
intro: PTL.tr('How many new items should this source display at a time?'),
position: 'top'