Commit c0407195 authored by yPhil's avatar yPhil

Merge branch 'columns' into dev

parents 8ea5f883 988fada0
......@@ -3,6 +3,12 @@ var express = require('express'),
index = require('./routes/index'),
app = express();
// fs.exists(cacheDir, (exists) => {
// if (!exists) fs.mkdirSync(cacheDir);
// });
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('html', require('ejs').renderFile);
......
......@@ -12,11 +12,11 @@
"url": "https://framagit.org/yphil/petrolette"
},
"scripts": {
"start": "pm2 start -f bin/www --log-date-format='YYYY-MM-DD HH:mm Z' --name PTL",
"start": "pm2 start -f bin/www --watch --log-date-format='YYYY-MM-DD HH:mm Z' --name PTL",
"stop": "pm2 stop PTL",
"build:pre": "uglifyjs public/js/PTL.main.js public/js/PTL.prefs.js public/js/PTL.i18n.js -m -o dist/js/PTL.pre.min.js",
"build:post": "uglifyjs public/js/PTL.utilities.js public/js/PTL.tab.js public/js/PTL.feed.js public/js/PTL.dialog.js public/js/PTL.sync.js public/js/PTL.menu.js -m -o dist/js/PTL.post.min.js",
"build:js": "mkdir -p dist/js && npm run build:pre && npm run build:post",
"build:js": "mkdir -p dist/js cache-favicons && npm run build:pre && npm run build:post",
"watch:js": "onchange 'public/js/*.js' -- npm run build:js",
"postinstall": "npm run build:js && bower install"
},
......@@ -32,5 +32,6 @@
"feedrat": "latest",
"favicon": "0.0.2",
"pm2": "2.8.0"
}
},
"cacheDirName": "favicon-cache"
}
......@@ -825,8 +825,8 @@ li.feed {
}
.tabSort .ui-sortable-placeholder {
visibility: visible;
outline: 3px dashed var(--color-sec) !important;
visibility: visible !important;
outline: .1em dashed var(--color-sec);
}
.mobHeader > .feedTitle {
......@@ -887,11 +887,6 @@ li.feed {
margin: 0 0 0 2px;
}
.feed * {
transition: all .1s linear;
}
.mobHeader > .feedToggle {
margin: 2px;
flex-basis: auto;
......@@ -1127,6 +1122,13 @@ div.introjs-helperLayer {
position: absolute;
top: 0;
z-index: 5;
}
div#logoTitle > .logoTitle > a:link,
div#logoTitle > .logoTitle > a:visited,
.topnav i,
#scrollToTop,
#scrollToTop i {
transition: all .3s linear;
}
......@@ -1154,7 +1156,6 @@ i.icon-petrolette {
font-size:24pt;
margin: 6px 12px 6px 6px;
color: var(--ui-color-pri);
transition: all .3s linear;
}
i.icon-petrolette:hover,
......@@ -1185,7 +1186,6 @@ div#logoTitle > .logoTitle {
div#logoTitle > .logoTitle > a:link,
div#logoTitle > .logoTitle > a:visited {
color: var(--ui-color-pri);
transition: all 0.3s linear;
}
div#logoTitle > .logoTitle > a:hover {
......@@ -1217,7 +1217,6 @@ div#logoTitle > .logoTitle > a:hover {
position: fixed;
right: 20px;
text-decoration: none;
transition: all 0.3s ease;
width: 50px;
}
......@@ -1228,7 +1227,6 @@ div#logoTitle > .logoTitle > a:hover {
margin: 0;
position: relative;
top: 13px;
transition: all 0.3s ease;
}
#scrollToTop:hover {
......
......@@ -39,9 +39,6 @@ PTL.menu = {
var $menu = $(this),
$overlay = $('#overlay'),
$menuButton = $('#menuButton'),
$helpButton = $('.helpButton'),
$newSourceButton = $('#newSourceButton'),
$sourceCodeButton = $('button#sourceCode'),
$importButton = $("button#fileImport"),
$fileImportInput = $("input#fileImport"),
......@@ -54,37 +51,42 @@ PTL.menu = {
PTL.sync.attachWidget();
$menuButton.click(function() {
$('body').on('click','#menuButton', 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');
$('body').on('click','#helpButton', function() {
$('#tabs').tabs('option', 'active', 0);
PTL.dialog.help();
});
$newSourceButton.click(function() {
$('body').on('click','#newSourceButton', 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');
}
$sourceCodeButton.click(function(event) {
event.preventDefault();
window.open('https://framagit.org/yphil/petrolette');
});
var $widget = $('#remotestorage-widget');
$overlay.click(function() {
$(this).removeClass('visible');
$menu.removeClass('expanded');
});
$(document).keydown(function(event) {
if (event.keyCode === $.ui.keyCode.ESCAPE) {
$('.tabSort' ).sortable('cancel');
}
});
var $widget = $('#remotestorage-widget');
var $readMore = $('<a>')
var $readMore = $('<a>')
.attr('class', 'rs-help')
.attr('href', 'https:remotestorage.io/')
.text(PTL.tr('Read more.'));
......@@ -111,13 +113,6 @@ PTL.menu = {
PTL.utilities.translate();
});
$helpButton.click(function (event) {
event.preventDefault();
$('#tabs').tabs('option', 'active', 0);
// PTL.utilities.help('ui');
PTL.dialog.help();
});
$importButton.click(function () {
$("input#fileImport").click();
return false;
......
......@@ -2,6 +2,21 @@
PTL.prefs = (function() {
var newList = [
{"name":"News",
"feeds": [
{"url":"http://xkcd.com/rss.xml","type":"mixed","limit": 8},
{"url":"http://xkcd.com/rss.xml","type":"photo","limit": 4}
]
},
{"name":"Comics",
"feeds": [
{"url":"http://xkcd.com/rss.xml","type":"photo","limit": 8},
{"url":"http://superphazed.tumblr.com/rss","type":"photo","limit": 8}
]
}
];
var emptyTabList = [
{"name":"News",
"feeds": [
......@@ -46,6 +61,8 @@ PTL.prefs = (function() {
'columns': 3,
'lang': 'en',
'explicitLang': false,
'writeTime': Date.now(),
'sources': JSON.stringify(newList),
'tabs': JSON.stringify(emptyTabList)
};
......@@ -62,6 +79,11 @@ PTL.prefs = (function() {
writeConfig:function(key, val) {
$('div#logoTitle i').addClass('writing');
if (key === 'tabs') {
localStorage.setItem('writeTime', Date.now());
}
localStorage.setItem(key, val);
setTimeout(function () {
$('div#logoTitle i').delay('slow').removeClass('writing');
......
......@@ -29,7 +29,7 @@
PTL.sync = (function() {
var synchronized = false;
PTL.synchronized = false;
var syncDirectory = 'petrolette';
......@@ -39,7 +39,7 @@ PTL.sync = (function() {
return {
exports: {
read: function () {
return privateClient.getFile('petrolette.conf', 9999999999)
return privateClient.getFile('petrolette.conf', (Date.now() - PTL.prefs.readConfig('writeTime')))
.then(function (file) {
return file.data;
});
......@@ -64,12 +64,17 @@ PTL.sync = (function() {
// });
remoteStorage.on('connected', function() {
synchronized = true;
PTL.synchronized = true;
console.info('Pétrolette | ' + PTL.tr('Connected to remote storage'));
});
remoteStorage.on('not-connected', function() {
PTL.synchronized = false;
console.info('Pétrolette | ' + PTL.tr('NOT connected to remote storage'));
});
remoteStorage.on('disconnected', function() {
synchronized = false;
PTL.synchronized = false;
console.warn('Pétrolette | ' + PTL.tr('Disconnected from remote storage'));
});
......@@ -98,24 +103,15 @@ PTL.sync = (function() {
} else {
console.warn('Pétrolette | ' + PTL.tr('Remote file validation NOT OK (error [%1]) now reading from browser cache', data));
if (PTL.utilities.isValidSourcesFile(JSON.parse(PTL.prefs.readConfig('tabs')))) {
console.log('plop');
PTL.tab.populate(JSON.parse(PTL.prefs.readConfig('tabs')));
} else {
localStorage.setItem("tabs", "");
}
PTL.tab.populate(JSON.parse(PTL.prefs.readConfig('tabs')));
}
})
.catch((err) => {
if (PTL.utilities.isValidSourcesFile(JSON.parse(PTL.prefs.readConfig('tabs')))) {
PTL.tab.populate(JSON.parse(PTL.prefs.readConfig('tabs')));
} else {
localStorage.setItem("tabs", "");
}
console.warn('Pétrolette | ' + PTL.tr('Remote file validation NOT OK (error [%1]) now reading from browser cache', err));
PTL.tab.populate(JSON.parse(PTL.prefs.readConfig('tabs')));
});
......
......@@ -85,11 +85,9 @@ PTL.tab = {
PTL.tab.saveTabs();
PTL.tab.makeNewTabButton($('div#tabs'));
},
populate:function(tabs, clickToRefresh, add) {
populate:function(sources, clickToRefresh, add) {
if (add) {
console.log('ADD!');
} else {
if (!add) {
$('div#tabs div').remove();
$('div#tabs ul li').remove();
PTL.tab.makeNewTabButton($('div#tabs'));
......@@ -98,13 +96,13 @@ PTL.tab = {
var totalFeeds = 0,
progress = PTL.utilities.buildProgress();
tabs.forEach(function(tab) {
sources.forEach(function(tab) {
totalFeeds += tab.feeds.length;
});
progress.init(totalFeeds);
tabs.forEach(function(tab) {
sources.forEach(function(tab) {
PTL.tab.make($('#tabs'), tab.name, tab.feeds, progress);
});
......@@ -150,43 +148,48 @@ PTL.tab = {
},
makeNewTabButton:function($tabs) {
var $newTabButton = $('<li id="newTabButton" class="translate newContentButton" data-title="Add a new group" title="Add a new group">'),
$dummyTabLink = $('<a href="#"><i class="plusButton icon-plus-1"></i></a>').bind('click', function(e) {
e.stopImmediatePropagation();
var $newTabButton = $('<li>')
.attr('id', 'newTabButton')
.attr('class', 'translate newContentButton')
.data('title', 'Add a new group')
.attr('title', PTL.tr('Add a new group'));
PTL.tab.make($($tabs));
var $newTabButtonLink = $('<a>')
.attr('href', '#');
return false;
var $newTabButtonIcon = $('<a>')
.attr('class', 'plusButton icon-plus-1');
$newTabButtonLink.bind('click', function(event) {
event.stopImmediatePropagation();
PTL.tab.make($($tabs));
return false;
});
$dummyTabLink.appendTo($newTabButton);
$newTabButtonIcon.appendTo($newTabButtonLink);
$newTabButtonLink.appendTo($newTabButton);
$newTabButton.appendTo($tabs.find('ul#tabUl'));
PTL.utilities.translate();
},
make:function($tabs, name, feeds, progress) {
// $tabs.tabs();
$('#noSourcesButton').fadeOut('fast');
var tabIndex = $('ul#tabUl li.mobTab').length + 1;
if (!name) name = 'Group ' + tabIndex;
name = name || 'Group ' + tabIndex;
var $sortable = $('<ul>')
.attr('class', 'tabSort')
// .css('columns', 'auto ' + PTL.prefs.readConfig('columns'))
.attr('id', 'sortable' + tabIndex);
.attr('class', 'tabSort');
var $tabCloser = $('<i>')
.attr('class', 'icon-cancel tabCloser translate dangerous')
.data('title', PTL.tr('Delete the [%1] tab', name))
.attr('title', PTL.tr('Delete the [%1] tab', name));
var $tabPanel = $('<div class="tab" id="tab-' + tabIndex + '"></div>')
var $tabPanel = $('<div>')
.attr('id', 'tab-' + tabIndex)
.attr('class', 'tab');
......@@ -241,7 +244,9 @@ PTL.tab = {
PTL.qstring = null;
}
var $thisTabLink = $('<a href="#tab-' + tabIndex + '">' + name + '</a>');
var $thisTabLink = $('<a>')
.attr('href', '#tab-' + tabIndex)
.append(name);
var $thisTab = $('<li>')
.attr('class', 'modal mobTab translate')
......@@ -284,7 +289,7 @@ PTL.tab = {
if(typeof feeds != 'undefined') {
feeds.forEach(function(feed) {
PTL.feed.make($('#tab-' + tabIndex + ' ul.tabSort'), feed.url, feed.type, feed.limit, false, progress);
PTL.feed.make($sortable, feed.url, feed.type, feed.limit, false, progress);
});
}
......
......@@ -4,18 +4,15 @@ PTL.utilities = {
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;
}
sources.forEach(function(element) {
if (element.feeds) isValid = true;
});
return isValid;
},
isImage:function(string) {
// return string.split('.').pop() === 'jpg';
return (['jpg', 'png'].indexOf(string.split('.').pop()) >= 0);
},
noSourcesButton:function() {
......@@ -26,15 +23,14 @@ PTL.utilities = {
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);
.append($loadingSpinner)
.append('<br>')
.append($noSourcesText);
var $noSourcesButtonContainer = $('<div>')
.attr('id', 'noSourcesButton')
.attr('class', 'deadCenter')
.append($noSourcesButton);
var $noSourcesButtonContainer = $('<div>')
.attr('id', 'noSourcesButton')
.attr('class', 'deadCenter')
.append($noSourcesButton);
$('main').append($noSourcesButtonContainer);
......@@ -44,7 +40,7 @@ PTL.utilities = {
var vWidth = $(window).width(),
vW;
if(PTL.utilities.isMobile() || vWidth < 720 ) {
if (PTL.utilities.isMobile() || vWidth < 720 ) {
vW = vWidth - 8;
} else {
vW = vWidth - vWidth / 4;
......
var express = require('express');
var router = express.Router();
var favicon = require('favicon');
var FeedParser = require('feedparser');
var request = require('request');
var feedrat = require('feedrat');
var express = require('express'),
router = express.Router(),
favicon = require('favicon'),
FeedParser = require('feedparser'),
request = require('request'),
feedrat = require('feedrat'),
Url = require('url'),
fs = require('fs'),
path = require('path'),
packageJson = require('../package.json'),
cacheDir = path.join(__dirname, packageJson.cacheDirName);
// require('request').debug = true;
......@@ -16,14 +21,14 @@ router.get('/about/javascript', function(req, res) {
});
router.use(function(req,res,next){
var _send = res.send;
var sent = false;
res.send = function(data){
if(sent) return;
_send.bind(res)(data);
sent = true;
};
next();
var _send = res.send;
var sent = false;
res.send = function(data){
if(sent) return;
_send.bind(res)(data);
sent = true;
};
next();
});
function getFeed (urlfeed, callback) {
......@@ -47,14 +52,14 @@ function getFeed (urlfeed, callback) {
stream.pipe (feedparser);
} else {
console.log ('getFeed: Content-type Error read %s (%s) .', urlfeed, res.headers['content-type']);
// console.log ('getFeed: Content-type Error read %s (%s) .', urlfeed, res.headers['content-type']);
callback (res.headers['content-type']);
return;
}
});
req.on ('error', function (res) {
console.log ('getFeed: Error read %s (%s) .', urlfeed, res);
// console.log ('getFeed: Error read %s (%s) .', urlfeed, res);
});
feedparser.on ('readable', function () {
......@@ -65,7 +70,7 @@ function getFeed (urlfeed, callback) {
}
}
catch (err) {
console.log ('getFeed: err.message == ' + err.message);
// console.log ('getFeed: err.message == ' + err.message);
}
}).on ('end', function () {
var meta = this.meta;
......@@ -94,15 +99,47 @@ router.get('/feed', function(req, res) {
router.get('/feedicon', function(req, res) {
favicon(req.query.url, function(err, u) {
// var p = Url.parse(req.query.url),
// fileName = p.host + "-" + p.path;
if (u) {
res.send(u);
} else {
res.status(500).send('No icon found');
}
// fs.exists(path.join(cacheDir, fileName), (exists) => {
// if (!exists) {
// console.log('path.join(cacheDir, fileName) does not exist');
// // fs.mkdirSync(cacheDir);
// }
// });
});
favicon(req.query.url, function(err, iconUrl) {
if (iconUrl) {
res.send(iconUrl);
var u = Url.parse(iconUrl);
var fileName = u.host + '.' + u.pathname.replace(/(^\/|\/$)/g,'');
console.log('(%s) is not in (%s)', fileName, cacheDir);
// console.log('icon! (%s) Name: %s', iconUrl, root);
// var s = fs.ReadStream(u);
// s.on('data', function(d) {
// shasum.update(d);
// });
// s.on('end', function() {
// var d = shasum.digest('hex');
// console.log('plop! ' + d + ' ' + u);
// });
} else {
res.status(500).send('No icon found');
}
});
});
router.get('/discover', function(req, res) {
......
......@@ -136,15 +136,11 @@
-->
<script>
PTL.menu.top();
PTL.menu.side();
var qstring = "<%= qstring %>";
setTimeout(
function() {
PTL.tab.init(qstring);
}, 500);
PTL.menu.top();
PTL.menu.side();
PTL.tab.init(qstring);
</script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment