diff --git a/lib/channel.js b/lib/channel.js
index 7b164121..7c1e4f01 100644
--- a/lib/channel.js
+++ b/lib/channel.js
@@ -1610,7 +1610,7 @@ Channel.prototype.addMedia = function(data, user) {
if (self.dead)
return;
- if (err) {
+ if (err && err !== "Item not in library") {
user.socket.emit("queueFail", {
msg: "Internal error: " + err,
link: $util.formatLink(data.id, data.type)
diff --git a/lib/io/ioserver.js b/lib/io/ioserver.js
index acd71e72..953d1714 100644
--- a/lib/io/ioserver.js
+++ b/lib/io/ioserver.js
@@ -103,6 +103,11 @@ function handleConnection(sock) {
user.name = sock.handshake.user.name;
user.global_rank = sock.handshake.user.global_rank;
user.loggedIn = true;
+ user.socket.emit("login", {
+ success: true,
+ name: user.name
+ });
+ user.socket.emit("rank", user.global_rank);
}
}
diff --git a/lib/web/jade.js b/lib/web/jade.js
index b7098201..391eb108 100644
--- a/lib/web/jade.js
+++ b/lib/web/jade.js
@@ -43,7 +43,8 @@ function sendJade(res, view, locals) {
if (!(view in cache) || process.env['DEBUG']) {
var file = path.join(templates, view + '.jade');
var fn = jade.compile(fs.readFileSync(file), {
- filename: file
+ filename: file,
+ pretty: true
});
cache[view] = fn;
}
diff --git a/templates/channel.jade b/templates/channel.jade
index ffe9c9bb..e553d3a3 100644
--- a/templates/channel.jade
+++ b/templates/channel.jade
@@ -13,8 +13,8 @@ html(lang="en")
- var cname = "/r/" + channelName
ul.nav.navbar-nav
+navdefaultlinks(cname)
- li: a(href="javascript:showUserOptions()") Options
- li: a(href="javascript:$('#channeloptions').modal()") Channel Settings
+ li: a(href="#", onclick="javascript:showUserOptions()") Options
+ li: a(href="#", onclick="javascript:$('#channeloptions').modal()") Channel Settings
+navloginlogout(cname)
section#mainpage
.container
@@ -123,14 +123,6 @@ html(lang="en")
i.glyphicon.glyphicon-lock
.col-lg-12.col-md-12
#queue.videolist
- li.queue_entry
- a.qe_title(href="#") Derp
- span.qe_time 00:00
- div.qe_clear
- li.queue_entry.queue_active.queue_temp
- a.qe_title(href="#") Derp
- span.qe_time 00:00
- div.qe_clear
#plmeta
span#plcount 0 items
span#pllength 00:00:00
@@ -138,6 +130,27 @@ html(lang="en")
.col-lg-5.col-md-5
#videowidth.col-lg-7.col-md-7
#sitefooter
+ #useroptions.modal.fade(tabindex="-1", role="dialog", aria-hidden="true")
+ .modal-dialog
+ .modal-content
+ .modal-header
+ button.close(data-dismiss="modal", aria-hidden="true")×
+ h4 User Preferences
+ ul.nav.nav-tabs
+ li: a(href="#us-general", data-toggle="tab") General
+ li: a(href="#us-playback", data-toggle="tab") Playback
+ li: a(href="#us-chat", data-toggle="tab") Chat
+ li: a(href="#us-mod", data-toggle="tab", style="") Moderator
+ .modal-body
+ .tab-content
+ include useroptions
+ +us-general()
+ +us-playback()
+ +us-chat()
+ +us-mod()
+ .modal-footer
+ button.btn.btn-primary(type="button", data-dismiss="modal", onclick="javascript:saveUserOptions()") Save
+ button.btn.btn-default(type="button", data-dismiss="modal") Close
#channeloptions.modal.fade(tabindex="-1", role="dialog", aria-hidden="true")
.modal-dialog
.modal-content
diff --git a/templates/useroptions.jade b/templates/useroptions.jade
new file mode 100644
index 00000000..6d5c8e58
--- /dev/null
+++ b/templates/useroptions.jade
@@ -0,0 +1,82 @@
+mixin lcheckbox(id, label)
+ .form-group
+ label.control-label.col-sm-4(for=id)= label
+ .col-sm-8
+ .checkbox
+ input(type="checkbox", id=id)
+
+mixin rcheckbox(id, label)
+ .form-group
+ .col-sm-8.col-sm-offset-4
+ .checkbox
+ label.control-label(for=id)= label
+ input(type="checkbox", id=id)
+
+mixin textbox(id, label, placeholder)
+ .form-group
+ label.control-label.col-sm-4(for=id)= label
+ .col-sm-8
+ if placeholder
+ input.form-control(id=id, type="text", placeholder=placeholder)
+ else
+ input.form-control(id=id, type="text")
+
+mixin us-general
+ #us-general.tab-pane
+ h4 General Preferences
+ form.form-horizontal(action="javascript:void(0)")
+ .form-group
+ label.control-label.col-sm-4(for="#us-theme") Theme
+ .col-sm-8
+ select#us-theme.form-control
+ option(value="default") Default
+ option(value="/css/bootstrap-theme.min.css") Bootstrap
+ option(value="/css/dark.css") Dark
+ .form-group
+ label.control-label.col-sm-4(for="#us-layout") Layout
+ .col-sm-8
+ select#us-layout.form-control
+ option(value="default") Compact
+ option(value="synchtube") Synchtube (flipped)
+ option(value="fluid") Fluid
+ .col-sm-4
+ .col-sm-8
+ p.text-danger Changing layouts may require refreshing to take effect.
+ +rcheckbox("us-no-channelcss", "Ignore Channel CSS")
+ +rcheckbox("us-no-channeljs", "Ignore Channel Javascript")
+ +rcheckbox("us-ssl", "Encrypt connection with SSL")
+
+mixin us-playback
+ #us-playback.tab-pane
+ h4 Playback Preferences
+ form.form-horizontal(action="javascript:void(0)")
+ +rcheckbox("us-synch", "Synchronize video playback")
+ +textbox("us-synch-accuracy", "Synch threshold (seconds)", "2")
+ +rcheckbox("us-wmode-transparent", "Set wmode=transparent")
+ .col-sm-4
+ .col-sm-8
+ p.text-info Setting wmode=transparent
allows objects to be displayed above the video player, but may cause performance issues on some systems.
+ +rcheckbox("us-hidevideo", "Remove the video player")
+ +rcheckbox("us-playlistbuttons", "Hide playlist buttons by default")
+ +rcheckbox("us-oldbtns", "Old style playlist buttons")
+
+mixin us-chat
+ #us-chat.tab-pane
+ h4 Chat Preferences
+ form.form-horizontal(action="javascript:void(0)")
+ +rcheckbox("us-chat-timestamp", "Show timestamps in chat")
+ +rcheckbox("us-sort-rank", "Sort userlist by rank")
+ +rcheckbox("us-sort-afk", "Sort AFKers to bottom")
+ +rcheckbox("us-chat-notice", "Ping on all new messages")
+ .col-sm-4
+ .col-sm-8
+ p.text-info When unchecked, you will only be pinged if your name is mentioned
+ +rcheckbox("us-boop", "Play a sound when pinged")
+ +rcheckbox("us-sendbtn", "Add a send button to chat")
+
+mixin us-mod
+ #us-mod.tab-pane
+ h4 Moderator Preferences
+ form.form-horizontal(action="javascript:void(0)")
+ +rcheckbox("us-modflair", "Show name color")
+ +rcheckbox("us-joinmessage", "Show join messages")
diff --git a/www/assets/js/ui.js b/www/assets/js/ui.js
index 60d043a3..26ac9ca8 100644
--- a/www/assets/js/ui.js
+++ b/www/assets/js/ui.js
@@ -238,7 +238,7 @@ $("#userpl_save").click(function() {
$(select).click(function() {
VIDEOQUALITY = preset;
USEROPTS.default_quality = select;
- saveOpts();
+ storeOpts();
var btn = $("#qdrop");
var caret = btn.find(".caret").detach();
btn.text($(select).text());
@@ -435,9 +435,12 @@ $(window).resize(function() {
/* load channel */
var loc = document.location+"";
-var m = loc.match(/\/r\/([a-zA-Z0-9-_]+)$/);
+var m = loc.match(/\/r\/([a-zA-Z0-9-_#]+)$/);
if(m) {
CHANNEL.name = m[1];
+ if (CHANNEL.name.indexOf("#") !== -1) {
+ CHANNEL.name = CHANNEL.name.substring(0, CHANNEL.name.indexOf("#"));
+ }
}
/*
else {
diff --git a/www/assets/js/util.js b/www/assets/js/util.js
index 165c9d21..613f55f7 100644
--- a/www/assets/js/util.js
+++ b/www/assets/js/util.js
@@ -476,7 +476,7 @@ function addQueueButtons(li) {
menu.detach().prependTo(li);
menu.find(".btn").each(function() {
// Clear icon
- var icon = $(this).find("i");
+ var icon = $(this).find(".glyphicon");
$(this).html("");
icon.appendTo(this);
});
@@ -524,242 +524,75 @@ function rebuildPlaylist() {
/* menus */
/* user settings menu */
-// TODO fix this
-function showOptionsMenu() {
+function showUserOptions() {
hidePlayer();
- var modal = $("
").addClass("modal hide fade")
- .appendTo($("body"));
-
- modal.load("useroptions.html", function () {
- if (CLIENT.rank < 2) {
- $("#uopt-btn-mod").remove();
- }
-
- var tabHandler = function (btnid, panelid) {
- $(btnid).click(function () {
- modal.find(".btn.btn-small").attr("disabled", false);
- modal.find(".uopt-panel").hide();
- $(btnid).attr("disabled", true);
- $(panelid).show();
- });
- };
-
- tabHandler("#uopt-btn-general", "#uopt-panel-general");
- tabHandler("#uopt-btn-playback", "#uopt-panel-playback");
- tabHandler("#uopt-btn-chat", "#uopt-panel-chat");
- tabHandler("#uopt-btn-mod", "#uopt-panel-mod");
-
- var initForm = function (id) {
- var f = $("").appendTo($(id))
- .addClass("form-horizontal")
- .attr("action", "javascript:void(0)");
- return $("").appendTo(f);
- };
-
- var addOption = function (form, lbl, thing) {
- var g = $("").addClass("control-group").appendTo(form);
- $("").addClass("control-label").text(lbl).appendTo(g);
- var c = $("").addClass("controls").appendTo(g);
- thing.appendTo(c);
- };
-
- var addCheckbox = function (form, opt, lbl) {
- var c = $("").addClass("checkbox")
- .text(lbl);
- var box = $("").attr("type", "checkbox")
- .appendTo(c);
- addOption(form, opt, c);
- return box;
- };
-
- // general options
- var general = initForm("#uopt-panel-general");
-
- var gen_theme = $("");
- $("").attr("value", "default")
- .text("Default")
- .appendTo(gen_theme);
- $("").attr("value", "assets/css/darkstrap.css")
- .text("Dark")
- .appendTo(gen_theme);
- $("").attr("value", "assets/css/altdark.css")
- .text("Alternate Dark")
- .appendTo(gen_theme);
- gen_theme.val(USEROPTS.theme);
- addOption(general, "Theme", gen_theme);
-
- var gen_layout = $("");
- $("").attr("value", "default")
- .text("Compact")
- .appendTo(gen_layout);
- $("").attr("value", "synchtube")
- .text("Synchtube")
- .appendTo(gen_layout);
- $("").attr("value", "fluid")
- .text("Fluid")
- .appendTo(gen_layout);
- gen_layout.val(USEROPTS.layout);
- addOption(general, "Layout", gen_layout);
-
- var gen_layoutwarn = $("").addClass("text-error")
- .text("Changing layouts may require a refresh");
- addOption(general, "", gen_layoutwarn);
-
- var gen_css = $("").attr("type", "text")
- .attr("placeholder", "Stylesheet URL");
- gen_css.val(USEROPTS.css);
- addOption(general, "User CSS", gen_css);
-
- var gen_nocss = addCheckbox(general, "Channel CSS",
- "Ignore channel CSS");
- gen_nocss.prop("checked", USEROPTS.ignore_channelcss);
-
- var gen_nojs = addCheckbox(general, "Channel JS",
- "Ignore channel JS");
- gen_nojs.prop("checked", USEROPTS.ignore_channeljs);
-
- var gen_altsocket = addCheckbox(general, "Alternate Socket",
- "Use alternate socket connection");
- gen_altsocket.prop("checked", USEROPTS.altsocket);
-
- var gen_altsocketinfo = $("")
- .addClass("text-error")
- .text("Alternate socket requires a refresh after changing. "+
- "It should only be used if the default (unchecked) "+
- "does not work.");
- addOption(general, "", gen_altsocketinfo);
-
- var gen_secure = addCheckbox(general, "SSL",
- "Encrypt connections with SSL");
- gen_secure.prop("checked", USEROPTS.secure_connection);
- gen_secure.attr("disabled", !ALLOW_SSL);
-
- var gen_secureinfo = $("")
- .addClass("text-error")
- .text("If enabled, websocket traffic and API calls (logins, "+
- "account management) will be sent over a secure "+
- "connection. Changes take effect after a refresh.");
- addOption(general, "", gen_secureinfo);
- if (!ALLOW_SSL) {
- gen_secureinfo.text("This server does not support SSL.");
- }
-
- // playback options
- var playback = initForm("#uopt-panel-playback");
-
- var pl_synch = addCheckbox(playback, "Synchronize",
- "Synchronize media playback");
- pl_synch.prop("checked", USEROPTS.synch);
-
- var pl_synchacc = $("").attr("type", "text")
- .attr("placeholder", "Accuracy in seconds");
- pl_synchacc.val(USEROPTS.sync_accuracy);
- addOption(playback, "Synch Accuracy (seconds)", pl_synchacc);
-
- var pl_wmode = addCheckbox(playback, "Transparent wmode",
- "Allow transparency over video player");
- pl_wmode.prop("checked", USEROPTS.wmode_transparent);
-
- var pl_wmodewarn = $("").addClass("text-error")
- .text("Enabling transparent wmode may cause performance "+
- "issues on some systems");
- addOption(playback, "", pl_wmodewarn);
-
- var pl_hide = addCheckbox(playback, "Hide Video",
- "Remove the video player");
- pl_hide.prop("checked", USEROPTS.hidevid);
-
- var pl_hidebtn = addCheckbox(playback, "Playlist Buttons",
- "Hide playlist buttons by default");
- pl_hidebtn.prop("checked", USEROPTS.qbtn_hide);
-
- var pl_oldbtn = addCheckbox(playback, "Playlist Buttons (old)",
- "Old style playlist buttons");
- pl_oldbtn.prop("checked", USEROPTS.qbtn_idontlikechange);
-
- // chat options
- var chat = initForm("#uopt-panel-chat");
-
- var chat_time = addCheckbox(chat, "Timestamps",
- "Show timestamps in chat");
- chat_time.prop("checked", USEROPTS.show_timestamps);
-
- var chat_sort_rank = addCheckbox(chat, "Userlist sort",
- "Sort userlist by rank");
- chat_sort_rank.prop("checked", USEROPTS.sort_rank);
-
- var chat_sort_afk = addCheckbox(chat, "Userlist sort",
- "Sort AFKers to bottom");
- chat_sort_afk.prop("checked", USEROPTS.sort_afk);
-
- var chat_all = addCheckbox(chat, "Chat Notice",
- "Notify on all messages");
- chat_all.prop("checked", USEROPTS.blink_title);
-
- var chat_allinfo = $("")
- .text("When disabled, you will only be notified if your "+
- "name is mentioned");
- addOption(chat, "", chat_allinfo);
-
- var chat_boop = addCheckbox(chat, "Chat Sound",
- "Play a sound for notifications");
- chat_boop.prop("checked", USEROPTS.boop);
-
- var chat_sendbtn = addCheckbox(chat, "Send Button",
- "Add a send button to chat");
- chat_sendbtn.prop("checked", USEROPTS.chatbtn);
-
- // mod options
- var mod = initForm("#uopt-panel-mod");
-
- var mod_flair = addCheckbox(mod, "Modflair", "Show name color");
- mod_flair.prop("checked", USEROPTS.modhat);
-
- var mod_joinmsg = addCheckbox(mod, "Join Messages",
- "Show join messages");
- mod_joinmsg.prop("checked", USEROPTS.joinmessage);
-
-
- $("#uopt-btn-general").click();
- $("#uopt-btn-save").click(function () {
- USEROPTS.theme = gen_theme.val();
- USEROPTS.layout = gen_layout.val();
- USEROPTS.css = gen_css.val();
- USEROPTS.ignore_channelcss = gen_nocss.prop("checked");
- USEROPTS.ignore_channeljs = gen_nojs.prop("checked");
- USEROPTS.altsocket = gen_altsocket.prop("checked");
- USEROPTS.synch = pl_synch.prop("checked");
- USEROPTS.sync_accuracy = parseFloat(pl_synchacc.val())||2;
- USEROPTS.wmode_transparent = pl_wmode.prop("checked");
- USEROPTS.hidevid = pl_hide.prop("checked");
- USEROPTS.qbtn_hide = pl_hidebtn.prop("checked");
- USEROPTS.qbtn_idontlikechange = pl_oldbtn.prop("checked");
- USEROPTS.show_timestamps = chat_time.prop("checked");
- USEROPTS.sort_rank = chat_sort_rank.prop("checked");
- USEROPTS.sort_afk = chat_sort_afk.prop("checked");
- USEROPTS.blink_title = chat_all.prop("checked");
- USEROPTS.boop = chat_boop.prop("checked");
- USEROPTS.chatbtn = chat_sendbtn.prop("checked");
- USEROPTS.secure_connection = gen_secure.prop("checked");
- if (CLIENT.rank >= 2) {
- USEROPTS.modhat = mod_flair.prop("checked");
- USEROPTS.joinmessage = mod_joinmsg.prop("checked");
- }
- saveOpts();
- modal.modal("hide");
- });
- });
-
- modal.on("hidden", function () {
+ $("#useroptions").on("hidden", function () {
unhidePlayer();
- applyOpts();
- modal.remove();
});
- modal.modal();
+ if (CLIENT.rank < 2) {
+ $("a[href='#us-mod']").parent().hide();
+ } else {
+ $("a[href='#us-mod']").parent().show();
+ }
+
+ $("#us-theme").val(USEROPTS.theme);
+ $("#us-layout").val(USEROPTS.layout);
+ $("#us-no-channelcss").prop("checked", USEROPTS.ignore_channelcss);
+ $("#us-no-channeljs").prop("checked", USEROPTS.ignore_channeljs);
+ $("#us-ssl").prop("checked", USEROPTS.secure_connection);
+
+ $("#us-synch").prop("checked", USEROPTS.synch);
+ $("#us-synch-accuracy").val(USEROPTS.synch_accuracy);
+ $("#us-wmode-transparent").prop("checked", USEROPTS.wmode_transparent);
+ $("#us-hidevideo").prop("checked", USEROPTS.hidevid);
+ $("#us-playlistbuttons").prop("checked", USEROPTS.qbtn_hide);
+ $("#us-oldbtns").prop("checked", USEROPTS.qbtn_idontlikechange);
+
+ $("#us-chat-timestamp").prop("checked", USEROPTS.show_timestamps);
+ $("#us-sort-rank").prop("checked", USEROPTS.sort_rank);
+ $("#us-sort-afk").prop("checked", USEROPTS.sort_afk);
+ $("#us-chat-notice").prop("checked", USEROPTS.blink_title);
+ $("#us-boop").prop("checked", USEROPTS.boop);
+ $("#us-sendbtn").prop("checked", USEROPTS.chatbtn);
+
+ $("#us-modflair").prop("checked", USEROPTS.modhat);
+ $("#us-joinmessage").prop("checked", USEROPTS.joinmessage);
+
+ $("a[href='#us-general']").click();
+ $("#useroptions").modal();
}
-function saveOpts() {
+function saveUserOptions() {
+ USEROPTS.theme = $("#us-theme").val();
+ USEROPTS.layout = $("#us-layout").val();
+ USEROPTS.ignore_channelcss = $("#us-no-channelcss").prop("checked");
+ USEROPTS.ignore_channeljs = $("#us-no-channeljs").prop("checked");
+ USEROPTS.secure_connection = $("#us-ssl").prop("checked");
+
+ USEROPTS.synch = $("#us-synch").prop("checked");
+ USEROPTS.synch_accuracy = parseFloat($("#us-synch-accuracy").val()) || 2;
+ USEROPTS.wmode_transparent = $("#us-wmode-transparent").prop("checked");
+ USEROPTS.hidevid = $("#us-hidevideo").prop("checked");
+ USEROPTS.qbtn_hide = $("#us-playlistbuttons").prop("checked");
+ USEROPTS.qbtn_idontlikechange = $("#us-oldbtns").prop("checked");
+
+ USEROPTS.show_timestamps = $("#us-chat-timestamp").prop("checked");
+ USEROPTS.sort_rank = $("#us-sort-rank").prop("checked");
+ USEROPTS.sort_afk = $("#us-sort-afk").prop("checked");
+ USEROPTS.blink_title = $("#us-chat-notice").prop("checked");
+ USEROPTS.boop = $("#us-boop").prop("checked");
+ USEROPTS.chatbtn = $("#us-sendbtn").prop("checked");
+
+ if (CLIENT.rank >= 2) {
+ USEROPTS.modhat = $("#us-modflair").prop("checked");
+ USEROPTS.joinmessage = $("#us-joinmessage").prop("checked");
+ }
+
+ storeOpts();
+}
+
+function storeOpts() {
for(var key in USEROPTS) {
setOpt(key, USEROPTS[key]);
}
@@ -775,15 +608,6 @@ function applyOpts() {
.appendTo($("head"));
}
- $("#usercss").remove();
- if(USEROPTS.css) {
- $("").attr("rel", "stylesheet")
- .attr("type", "text/css")
- .attr("id", "usercss")
- .attr("href", USEROPTS.css)
- .appendTo($("head"));
- }
-
switch(USEROPTS.layout) {
case "synchtube":
synchtubeLayout();
@@ -798,13 +622,13 @@ function applyOpts() {
if(USEROPTS.hidevid) {
$("#qualitywrap").html("");
$("#videowrap").remove();
- $("#chatwrap").removeClass("span5").addClass("span12");
- $("#chatline").removeClass().addClass("span12");
+ $("#chatwrap").removeClass("col-lg-5 col-md-5").addClass("col-lg-12 col-md-12");
+ $("#chatline").removeClass().addClass("col-lg-12 col-md-12");
}
$("#chatbtn").remove();
if(USEROPTS.chatbtn) {
- var btn = $("").addClass("btn btn-block")
+ var btn = $("").addClass("btn btn-default btn-block")
.text("Send")
.attr("id", "chatbtn")
.appendTo($("#chatwrap"));
@@ -1009,7 +833,7 @@ function handlePermissionChange() {
.appendTo(al)
.click(function() {
USEROPTS.first_visit = false;
- saveOpts();
+ storeOpts();
al.hide("blind", function() {
al.remove();
});
diff --git a/www/css/cytube.css b/www/css/cytube.css
index 162cd37d..4f6c3dcb 100644
--- a/www/css/cytube.css
+++ b/www/css/cytube.css
@@ -477,3 +477,14 @@
border-width: 3px !important;
margin-right: 10px;
}
+
+#useroptions .modal-header {
+ border-bottom: 0;
+ padding-bottom: 0;
+ margin-bottom: 0;
+}
+
+#useroptions .modal-body {
+ padding-top: 0;
+ margin-top: 0;
+}