merged master fixed conflicts

v1.18.x
Baris Usakli 11 years ago
commit c096656eff

@ -2,84 +2,96 @@
{
"name": "Announcements",
"description": "Announcements regarding our community",
"blockclass": "category-blue",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-bullhorn",
"order": 1
},
{
"name": "General Discussion",
"description": "A place to talk about whateeeever you want",
"blockclass": "category-blue",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-comment",
"order": 2
},
{
"name": "NodeBB Development",
"description": "NodeBB development news and announcements",
"blockclass": "category-blue",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-github",
"order": 3
},
{
"name": "Blogs",
"description": "Blog posts from individual members",
"blockclass": "category-blue",
"bgColor": "#0059B2",
"color": "#fff",
"icon" : "fa-pencil",
"order": 4
},
{
"name": "Feature Requests",
"description": "Got a feature request you'd like to see? Give us a shout here.",
"blockclass": "category-purple",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-lightbulb-o",
"order": 5
},
{
"name": "Bug Reports",
"description": "Having trouble with NodeBB? Let us know...",
"blockclass": "category-purple",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-cogs",
"order": 6
},
{
"name": "NodeBB Plugins",
"description": "Enhance your NodeBB with plugins!",
"blockclass": "category-purple",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-plus-square",
"order": 7
},
{
"name": "NodeBB Link Exchange",
"description": "Link exchange",
"blockclass": "category-purple",
"bgColor": "#ab1290",
"color": "#fff",
"icon" : "fa-exchange",
"order": 8
},
{
"name": "News",
"description": "News from around the world",
"blockclass": "category-darkblue",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-globe",
"order": 9
},
{
"name": "Movies",
"description": "Discuss the latest movies here",
"blockclass": "category-darkblue",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-film",
"order": 10
},
{
"name": "Games",
"description": "Discuss the latest games here",
"blockclass": "category-darkblue",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-crosshairs",
"order": 11
},
{
"name": "Random",
"description": "Anything and (almost) everything welcome!",
"blockclass": "category-darkblue",
"bgColor": "#004C66",
"color": "#fff",
"icon" : "fa-beer",
"order": 12
}

@ -39,7 +39,7 @@ define(['forum/accountheader'], function(header) {
uid: theirid
}, function(success) {
if (success) {
followBtn.addClasss('hide');
followBtn.addClass('hide');
unfollowBtn.removeClass('hide');
app.alertSuccess('You are now following ' + username + '!');
} else {
@ -98,4 +98,4 @@ define(['forum/accountheader'], function(header) {
};
return Account;
});
});

@ -66,7 +66,7 @@
var notifContainer = document.getElementsByClassName('notifications')[0],
notifTrigger = notifContainer.querySelector('a'),
notifList = document.getElementById('notif-list'),
notifIcon = document.querySelector('.notifications a i');
notifIcon = $('.notifications a');
notifTrigger.addEventListener('click', function(e) {
e.preventDefault();
if (notifContainer.className.indexOf('open') === -1) {
@ -77,7 +77,6 @@
numUnread = data.unread.length,
x;
notifList.innerHTML = '';
console.log(data);
if ((data.read.length + data.unread.length) > 0) {
for (x = 0; x < numUnread; x++) {
notifEl.setAttribute('data-nid', data.unread[x].nid);
@ -106,14 +105,18 @@
notifList.appendChild(notifFrag);
if (data.unread.length > 0) {
notifIcon.className = 'fa fa-circle active';
notifIcon.toggleClass('active', true);
} else {
notifIcon.className = 'fa fa-circle-o';
notifIcon.toggleClass('active', false);
}
socket.emit('api:notifications.mark_all_read', null, function() {
notifIcon.className = 'fa fa-circle-o';
notifIcon.toggleClass('active', false);
utils.refreshTitle();
// Update favicon + local count
Tinycon.setBubble(0);
localStorage.setItem('notifications:count', 0);
});
});
}
@ -138,8 +141,25 @@
}
});
socket.emit('api:notifications.getCount', function(err, count) {
// Update notification icon, if necessary
if (count > 0) {
notifIcon.toggleClass('active', true);
} else {
notifIcon.toggleClass('active', false);
}
// Update the favicon + saved local count
Tinycon.setBubble(count);
localStorage.setItem('notifications:count', count);
});
if (localStorage.getItem('notifications:count') !== null) {
Tinycon.setBubble(parseInt(localStorage.getItem('notifications:count'), 10));
}
socket.on('event:new_notification', function() {
document.querySelector('.notifications a i').className = 'fa fa-circle active';
notifIcon.toggleClass('active', true);
app.alert({
alert_id: 'new_notif',
title: 'New notification',
@ -148,6 +168,11 @@
timeout: 2000
});
utils.refreshTitle();
// Update the favicon + local storage
var savedCount = parseInt(localStorage.getItem('notifications:count'),10) || 0;
localStorage.setItem('notifications:count', savedCount+1);
Tinycon.setBubble(savedCount+1);
});
@ -158,15 +183,20 @@
if (chat.modalExists(data.fromuid)) {
modal = chat.getModal(data.fromuid);
chat.appendChatMessage(modal, data.message, data.timestamp);
if (modal.is(":visible")) {
chat.load(modal.attr('UUID'));
} else {
chat.toggleNew(modal.attr('UUID'), true);
}
} else {
modal = chat.createModal(data.username, data.fromuid);
chat.toggleNew(modal.attr('UUID'), true);
}
chat.load(modal.attr('UUID'));
});
});
require(['mobileMenu'], function(mobileMenu) {
mobileMenu.init();
});
}());
}());

@ -67,7 +67,8 @@ define(['taskbar'], function(taskbar) {
chatModal.find('.close').on('click', function(e) {
clearInterval(chatModal.intervalId);
chatModal.intervalId = 0;
chatModal.hide();
chatModal.remove();
chatModal.data('modal', null);
taskbar.discard('chat', uuid);
});
@ -81,7 +82,11 @@ define(['taskbar'], function(taskbar) {
checkOnlineStatus(chatModal);
});
taskbar.push('chat', chatModal.attr('UUID'), {title:'chat with ' + username});
taskbar.push('chat', chatModal.attr('UUID'), {
title:'<i class="fa fa-comment"></i> ' + username,
state: ''
});
return chatModal;
}
@ -149,7 +154,11 @@ define(['taskbar'], function(taskbar) {
chatContent.scrollTop(
chatContent[0].scrollHeight - chatContent.height()
);
}
};
module.toggleNew = function(uuid, state) {
taskbar.toggleNew(uuid, state);
};
return module;
});

@ -25,6 +25,7 @@ define(function() {
if (_btn.className.indexOf('active') === -1) {
taskbar.minimizeAll();
module.load(uuid);
taskbar.toggleNew(uuid, false);
// Highlight the button
$(taskbar.tasklist).removeClass('active');
@ -69,7 +70,7 @@ define(function() {
'</a>';
btnEl.setAttribute('data-module', module);
btnEl.setAttribute('data-uuid', uuid);
btnEl.className = options.state || 'active';
btnEl.className = options.state !== undefined ? options.state : 'active';
if (!options.state || options.state === 'active') taskbar.minimizeAll();
taskbar.tasklist.appendChild(btnEl);
@ -82,14 +83,21 @@ define(function() {
},
minimizeAll: function() {
$(taskbar.tasklist.querySelectorAll('.active')).removeClass('active');
},
toggleNew: function(uuid, state) {
var btnEl = $(taskbar.tasklist.querySelector('[data-uuid="' + uuid + '"]'));
btnEl.toggleClass('new', state);
}
}
if (!taskbar.initialized) taskbar.init();
if (!taskbar.initialized) {
taskbar.init();
}
return {
push: taskbar.push,
discard: taskbar.discard,
minimize: taskbar.minimize
minimize: taskbar.minimize,
toggleNew: taskbar.toggleNew
}
});

@ -90,7 +90,7 @@
</li>
<li id="notifications-list" class="notifications dropdown text-center hidden-xs">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"><i class="fa fa-circle-o"></i></a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#" id="notif_dropdown"></a>
<ul id="notif-list" class="dropdown-menu" aria-labelledby="notif_dropdown">
<li>
<a href="#"><i class="fa fa-refresh fa-spin"></i> [[global:notifications.loading]]</a>
@ -152,4 +152,4 @@
<input id="csrf_token" type="hidden" template-variable="csrf" value="{csrf}" />
<div class="container" id="content">
<div class="container" id="content">

@ -0,0 +1,267 @@
/*!
* Tinycon - A small library for manipulating the Favicon
* Tom Moor, http://tommoor.com
* Copyright (c) 2012 Tom Moor
* MIT Licensed
* @version 0.6.1
*/
(function(){
var Tinycon = {};
var currentFavicon = null;
var originalFavicon = null;
var originalTitle = document.title;
var faviconImage = null;
var canvas = null;
var options = {};
var r = window.devicePixelRatio || 1;
var size = 16 * r;
var defaults = {
width: 7,
height: 9,
font: 10 * r + 'px arial',
colour: '#ffffff',
background: '#F03D25',
fallback: true,
crossOrigin: true,
abbreviate: true
};
var ua = (function () {
var agent = navigator.userAgent.toLowerCase();
// New function has access to 'agent' via closure
return function (browser) {
return agent.indexOf(browser) !== -1;
};
}());
var browser = {
ie: ua('msie'),
chrome: ua('chrome'),
webkit: ua('chrome') || ua('safari'),
safari: ua('safari') && !ua('chrome'),
mozilla: ua('mozilla') && !ua('chrome') && !ua('safari')
};
// private methods
var getFaviconTag = function(){
var links = document.getElementsByTagName('link');
for(var i=0, len=links.length; i < len; i++) {
if ((links[i].getAttribute('rel') || '').match(/\bicon\b/)) {
return links[i];
}
}
return false;
};
var removeFaviconTag = function(){
var links = document.getElementsByTagName('link');
var head = document.getElementsByTagName('head')[0];
for(var i=0, len=links.length; i < len; i++) {
var exists = (typeof(links[i]) !== 'undefined');
if (exists && (links[i].getAttribute('rel') || '').match(/\bicon\b/)) {
head.removeChild(links[i]);
}
}
};
var getCurrentFavicon = function(){
if (!originalFavicon || !currentFavicon) {
var tag = getFaviconTag();
originalFavicon = currentFavicon = tag ? tag.getAttribute('href') : '/favicon.ico';
}
return currentFavicon;
};
var getCanvas = function (){
if (!canvas) {
canvas = document.createElement("canvas");
canvas.width = size;
canvas.height = size;
}
return canvas;
};
var setFaviconTag = function(url){
removeFaviconTag();
var link = document.createElement('link');
link.type = 'image/x-icon';
link.rel = 'icon';
link.href = url;
document.getElementsByTagName('head')[0].appendChild(link);
};
var log = function(message){
if (window.console) window.console.log(message);
};
var drawFavicon = function(label, colour) {
// fallback to updating the browser title if unsupported
if (!getCanvas().getContext || browser.ie || browser.safari || options.fallback === 'force') {
return updateTitle(label);
}
var context = getCanvas().getContext("2d");
var colour = colour || '#000000';
var src = getCurrentFavicon();
faviconImage = document.createElement('img');
faviconImage.onload = function() {
// clear canvas
context.clearRect(0, 0, size, size);
// draw the favicon
context.drawImage(faviconImage, 0, 0, faviconImage.width, faviconImage.height, 0, 0, size, size);
// draw bubble over the top
if ((label + '').length > 0) drawBubble(context, label, colour);
// refresh tag in page
refreshFavicon();
};
// allow cross origin resource requests if the image is not a data:uri
// as detailed here: https://github.com/mrdoob/three.js/issues/1305
if (!src.match(/^data/) && options.crossOrigin) {
faviconImage.crossOrigin = 'anonymous';
}
faviconImage.src = src;
};
var updateTitle = function(label) {
if (options.fallback) {
if ((label + '').length > 0) {
document.title = '(' + label + ') ' + originalTitle;
} else {
document.title = originalTitle;
}
}
};
var drawBubble = function(context, label, colour) {
// automatic abbreviation for long (>2 digits) numbers
if (typeof label == 'number' && label > 99 && options.abbreviate) {
label = abbreviateNumber(label);
}
// bubble needs to be larger for double digits
var len = (label + '').length-1;
var width = options.width * r + (6 * r * len),
height = options.height * r;
var top = size - height,
left = size - width - r,
bottom = 16 * r,
right = 16 * r,
radius = 2 * r;
// webkit seems to render fonts lighter than firefox
context.font = (browser.webkit ? 'bold ' : '') + options.font;
context.fillStyle = options.background;
context.strokeStyle = options.background;
context.lineWidth = r;
// bubble
context.beginPath();
context.moveTo(left + radius, top);
context.quadraticCurveTo(left, top, left, top + radius);
context.lineTo(left, bottom - radius);
context.quadraticCurveTo(left, bottom, left + radius, bottom);
context.lineTo(right - radius, bottom);
context.quadraticCurveTo(right, bottom, right, bottom - radius);
context.lineTo(right, top + radius);
context.quadraticCurveTo(right, top, right - radius, top);
context.closePath();
context.fill();
// bottom shadow
context.beginPath();
context.strokeStyle = "rgba(0,0,0,0.3)";
context.moveTo(left + radius / 2.0, bottom);
context.lineTo(right - radius / 2.0, bottom);
context.stroke();
// label
context.fillStyle = options.colour;
context.textAlign = "right";
context.textBaseline = "top";
// unfortunately webkit/mozilla are a pixel different in text positioning
context.fillText(label, r === 2 ? 29 : 15, browser.mozilla ? 7*r : 6*r);
};
var refreshFavicon = function(){
// check support
if (!getCanvas().getContext) return;
setFaviconTag(getCanvas().toDataURL());
};
var abbreviateNumber = function(label) {
var metricPrefixes = [
['G', 1000000000],
['M', 1000000],
['k', 1000]
];
for(var i = 0; i < metricPrefixes.length; ++i) {
if (label >= metricPrefixes[i][1]) {
label = round(label / metricPrefixes[i][1]) + metricPrefixes[i][0];
break;
}
}
return label;
};
var round = function (value, precision) {
var number = new Number(value);
return number.toFixed(precision);
};
// public methods
Tinycon.setOptions = function(custom){
options = {};
for(var key in defaults){
options[key] = custom.hasOwnProperty(key) ? custom[key] : defaults[key];
}
return this;
};
Tinycon.setImage = function(url){
currentFavicon = url;
refreshFavicon();
return this;
};
Tinycon.setBubble = function(label, colour) {
label = label || '';
drawFavicon(label, colour);
return this;
};
Tinycon.reset = function(){
setFaviconTag(originalFavicon);
};
Tinycon.setOptions(defaults);
window.Tinycon = Tinycon;
})();

@ -201,9 +201,10 @@ var fs = require('fs'),
'vendor/jquery/js/jquery.timeago.js',
'vendor/jquery/js/jquery.form.js',
'vendor/bootstrap/js/bootstrap.min.js',
'src/app.js',
'vendor/requirejs/require.js',
'vendor/bootbox/bootbox.min.js',
'vendor/tinycon/tinycon.js',
'src/app.js',
'src/templates.js',
'src/ajaxify.js',
'src/translator.js',

@ -9,6 +9,7 @@ var async = require('async'),
(function(Notifications) {
"use strict";
Notifications.init = function() {
if (process.env.NODE_ENV === 'development') {
@ -144,16 +145,16 @@ var async = require('async'),
}
Notifications.mark_read = function(nid, uid, callback) {
if (parseInt(uid) > 0) {
Notifications.get(nid, uid, function(notif_data) {
db.sortedSetRemove('uid:' + uid + ':notifications:unread', nid);
db.sortedSetAdd('uid:' + uid + ':notifications:read', notif_data.datetime, nid);
if (callback) {
callback();
}
});
}
if (parseInt(uid, 10) > 0) {
Notifications.get(nid, uid, function(notif_data) {
db.sortedSetRemove('uid:' + uid + ':notifications:unread', nid);
db.sortedSetAdd('uid:' + uid + ':notifications:read', notif_data.datetime, nid);
if (callback) {
callback();
}
});
}
};
Notifications.mark_read_multiple = function(nids, uid, callback) {
if (!Array.isArray(nids) && parseInt(nids, 10) > 0) {

@ -223,7 +223,7 @@ var db = require('./database'),
}
}
plugins.fireHook('filter:posts.custom_profile_info', {profile: "", uid: post.uid}, function(err, profile_info) {
plugins.fireHook('filter:posts.custom_profile_info', {profile: "", uid: post.uid, pid: post.pid}, function(err, profile_info) {
post.additional_profile_info = profile_info.profile;
if (post.editor !== '') {

@ -48,9 +48,9 @@ var nconf = require('nconf'),
}
Admin.createRoutes = function (app) {
app.all('/api/admin/*', Admin.isAdmin);
app.all('/admin/*', Admin.isAdmin);
app.get('/admin', Admin.isAdmin);
(function () {
var routes = [

@ -36,7 +36,7 @@
passport.use(new passportTwitter({
consumerKey: meta.config['social:twitter:key'],
consumerSecret: meta.config['social:twitter:secret'],
callbackURL: 'auth/twitter/callback'
callbackURL: nconf.get('url') + 'auth/twitter/callback'
}, function(token, tokenSecret, profile, done) {
login_module.loginViaTwitter(profile.id, profile.username, profile.photos, function(err, user) {
if (err) {
@ -59,7 +59,7 @@
passport.use(new passportGoogle({
clientID: meta.config['social:google:id'],
clientSecret: meta.config['social:google:secret'],
callbackURL: 'auth/google/callback'
callbackURL: nconf.get('url') + 'auth/google/callback'
}, function(accessToken, refreshToken, profile, done) {
login_module.loginViaGoogle(profile.id, profile.displayName, profile.emails[0].value, function(err, user) {
if (err) {

@ -190,6 +190,13 @@ var DebugRoute = function(app) {
});*/
}
function sortedSetCount(callback) {
db.sortedSetCount('sortedSet3', -Infinity, Infinity, function(err, data) {
console.log('sortedSetCount return', data);
callback(err, {'sortedSetCount': data});
});
}
function listAppend(callback) {
db.listAppend('myList5', 5, function(err, data) {
console.log('listAppend return', data);
@ -327,6 +334,7 @@ var DebugRoute = function(app) {
getSortedSetRange,
//sortedSetRemove,
getSortedSetRange,
sortedSetCount
];
var listTasks = [

@ -1035,7 +1035,7 @@ var bcrypt = require('bcrypt'),
},
getUnreadCount: function(uid, callback) {
db.sortedSetCount('uid:' + uid + ':notifications:unread', 0, 10, callback);
db.sortedSetCount('uid:' + uid + ':notifications:unread', -Infinity, Infinity, callback);
},
getUnreadByUniqueId: function(uid, uniqueId, callback) {
db.getSortedSetRange('uid:' + uid + ':notifications:unread', 0, -1, function(err, nids) {

@ -120,6 +120,7 @@ var path = require('path'),
// Cache static files on production
if (global.env !== 'development') {
app.enable('cache');
app.enable('minification');
}
// Middlewares
@ -135,7 +136,7 @@ var path = require('path'),
app.use(require('less-middleware')({
src: path.join(__dirname, '../', 'public'),
prefix: nconf.get('relative_path'),
yuicompress: true
yuicompress: app.enabled('minification') ? true : false
}));
app.use(express.bodyParser()); // Puts POST vars in request.body
app.use(express.cookieParser()); // If you want to parse cookies (res.cookies)
@ -204,7 +205,7 @@ var path = require('path'),
src: path.join(__dirname, '../node_modules/' + themeId),
dest: path.join(__dirname, '../public/css'),
prefix: nconf.get('relative_path') + '/css',
yuicompress: true
yuicompress: app.enabled('minification') ? true : false
}));
next();
@ -218,7 +219,7 @@ var path = require('path'),
src: path.join(__dirname, '../node_modules/nodebb-theme-vanilla'),
dest: path.join(__dirname, '../public/css'),
prefix: nconf.get('relative_path') + '/css',
yuicompress: true
yuicompress: app.enabled('minification') ? true : false
}));
next();
@ -743,7 +744,7 @@ var path = require('path'),
var custom_routes = {
'routes': [],
'api_methods': []
'api': []
};
plugins.ready(function() {
@ -765,6 +766,20 @@ var path = require('path'),
}(route));
}
}
var apiRoutes = custom_routes.api;
for (var route in apiRoutes) {
if (apiRoutes.hasOwnProperty(route)) {
(function(route) {
app[apiRoutes[route].method || 'get']('/api' + apiRoutes[route].route, function(req, res) {
apiRoutes[route].callback(req, res, function(data) {
res.json(data);
});
});
}(route));
}
}
});
});

@ -668,6 +668,12 @@ websockets.init = function(io) {
});
});
socket.on('api:notifications.getCount', function(callback) {
user.notifications.getUnreadCount(uid, function(err, count) {
callback(err ? err.message : null, count);
});
});
socket.on('api:categories.getRecentReplies', function(tid) {
categories.getRecentReplies(tid, 4, function(replies) {
socket.emit('api:categories.getRecentReplies', replies);

Loading…
Cancel
Save