fore.st - Panama Red (v1)

changelist:
-pseudo-random name colors
-layout fixes(moved chat after the video on the .pug. also disabled said
feature in fcyp.js)
-theme updates(tokebot flair, changed modflair, more compact layout,
unfucked cytube provided css (srsly, WTF calzoneman? Why?)
link decorations, made things moar unified)
-added image embedding, disabling fcyp image embed (nothing new from a
user standpoint, simply slowly stripping fcyp.js out)
-moved emote button to chatbar, added send button as well
-chatpaste & chatsmack functions allowing clickable usernames/
-fixed raw video controls
-ripped out chat processing logic from fcyp.js, it was breaking a lot of
shit and everything it did has been implemented by this update and moar

devnotes:
Biggest update yet, also made some good steps towards fully ripping
fcyp.js out completely. Played around with an image upload button. I
might have to setup a cors relay to get that working, I'll have to play
around more :p
This commit is contained in:
rainbownapkin 2022-02-03 02:27:31 +00:00
parent 1148f63959
commit 9455fd8964
16 changed files with 5744 additions and 198 deletions

View file

@ -30,12 +30,11 @@
#usercount {
white-space: nowrap;
flex-grow: 2;
}
#userlist {
width: 120px;
float: left;
float: right;
border-right: 0;
font-size: 9pt;
list-style: none outside none;

View file

@ -26,5 +26,5 @@ body {
}
#mainpage {
padding-top: 60px;
padding-top: 0px;
}

File diff suppressed because one or more lines are too long

View file

@ -68,7 +68,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// If you need more explanations, go to https://github.com/zimny-lech/CyTube-Plus/wiki/FAQ
UI_DefaultSynchtube = 1; // default old Synchtube layout (player and playlist on the left)
UI_DefaultSynchtube = 0; // default old Synchtube layout (player and playlist on the left)
UI_Favicon = 0; // [&] channel favicon
UI_MiniLogo = 0; // [&] small channel logo/avatar in the top navbar
UI_ChannelName =0; // [&] channel custom brand name
@ -92,7 +92,7 @@ UI_UserCommands = 1; // [&] additional commands in the chat window
UI_UserMarks = 0; // [&] special signs/avatars before every message for defined users
UI_Squavatars = 0; // automatic squavatars (2-colored square avatars) before every message
// [ REQUIRE: UI_UserMarks enabled ]
UI_UsernameMark = 1; // [&] custom mark after username (default ":")
UI_UsernameMark = 0; // [&] custom mark after username (default ":")
UI_MessagesSuffix = 0; // [&] text added to random chat messages
UI_CustomPingSound = 1; // [&] custom sound for chat notifications
UI_SoundFilters = 0; // [&] chat sounds played after sending certain words
@ -115,7 +115,7 @@ UI_ChannelDatabase = 1; // [&] box with embed additional media database
UI_ChannelGalleries = 0; // [&] box with embed galleries
UI_DisplayModeSel = 1; // selector with player display modes
UI_ChannelTheme = 1; // [&] additional default channel theme
UI_EmbeddingMedia = 1; // [&] possibility to embedding (displaying) images and .webm videos on the chat
UI_EmbeddingMedia = 0; // [&] possibility to embedding (displaying) images and .webm videos on the chat
UI_MediaControls = 1; // embedded video preloaded controls
// [ REQUIRE: UI_EmbeddingMedia enabled ]
UI_QuickCommandsBtns = 1; // buttons with '/clear' and '/afk' functions
@ -651,16 +651,16 @@ function customCSS(a) {
// set global layout according to user preferences
function setLayout() {
playerLocation(USERCONFIG.player);
userlistLocation(USERCONFIG.userlist);
queueLocation(USERCONFIG.queue);
queueSize(USERCONFIG.qsize);
mainLocation(USERCONFIG.main);
motdLocation(USERCONFIG.motd);
logoInsert(USERCONFIG.logo);
headerMode(USERCONFIG.header);
customCSS(USERCONFIG.css);
refreshPlayer();
// playerLocation(USERCONFIG.player);
// userlistLocation(USERCONFIG.userlist);
// queueLocation(USERCONFIG.queue);
// queueSize(USERCONFIG.qsize);
// mainLocation(USERCONFIG.main);
// motdLocation(USERCONFIG.motd);
// logoInsert(USERCONFIG.logo);
// headerMode(USERCONFIG.header);
// customCSS(USERCONFIG.css);
// refreshPlayer();
}
//-----STOP BREAKIN SHIT!
@ -929,7 +929,7 @@ function createSquavatar(str) {
// format chat messages before sending and execute commands
function prepareMessage(msg) {
if (UI_MessagesSuffix=="1") {
/*if (UI_MessagesSuffix=="1") {
if ((typeof MessagesSuffix_Percentage!=="number") || MessagesSuffix_Percentage<0) {
MessagesSuffix_Percentage='10';
}
@ -1085,7 +1085,7 @@ function prepareMessage(msg) {
} else {
COMMAND=false;
}
}
}*/
return msg;
}
@ -2292,7 +2292,7 @@ zerorow = $('<div id="zerorow" class="row" />').insertBefore("#motdrow");
// adding top logo row
azukirow = $('<div id="azukirow" class="row" />').insertBefore(zerorow);
//azukirow = $('<div id="azukirow" class="row" />').insertBefore(zerorow);
// adding video wrap if user has enabled "Hide Player" option
@ -2347,7 +2347,7 @@ $("#rightpane").prepend($("#videocontrols").detach());
$("#rightpane").prepend($("#plcontrol").detach());
$("#leftpane").prepend($("#newpollbtn").detach());
$("#plcontrol").prepend($("#showmediaurl").detach());
$("#leftpane").prepend($("#emotelistbtn").detach());
//$("#leftpane").prepend($("#emotelistbtn").detach());
// header and footer links open in a new tab
@ -3342,16 +3342,16 @@ if (UI_UserStatistics=="1") {
// alter chat messages formatting
// DEV NOTE: this is extended function from CyTube "util.js" file
if (ALTERCHATFORMAT) {
/*if (ALTERCHATFORMAT) {
function formatChatMessage(data, last) {
if (!data.meta || data.msgclass) {
data.meta = {addClass:data.msgclass, addClassToNameAndTimestamp:data.msgclass};
}
skip=data.username===last.name;
data.meta.addClass==="server-whisper" ? skip=true : '';
data.msg.match(/^\s*<strong>\w+\s*:\s*<\/strong>\s*/) ? skip=false : '';
data.meta.forceShowName ? skip=false : '';
data.meta.addClass==="server-whisper" ? skip=true : '';*/
//*data.msg.match(/^\s*<strong>\w+\s*:\s*<\/strong>\s*/) ? skip=false : '';/*
/*data.meta.forceShowName ? skip=false : '';
data.msg=execEmotes(data.msg);
last.name = data.username;
@ -3473,7 +3473,7 @@ if (ALTERCHATFORMAT) {
return div;
}
}
}*/
// client-side chat buffer for playing sounds
@ -3507,7 +3507,7 @@ addChatMessage=function(data) {
// fix formatting and sending chat messages
// DEV NOTE: this are extended events from CyTube "util.js" file
/*
$("#chatline, #chatbtn").unbind();
$("#chatline").on("keydown", function(ev) {
@ -3580,7 +3580,7 @@ $("#chatbtn").on("click", function() {
$("#chatline").val('');
}
});
*/
// fix layout behaviour after resizing
// DEV NOTE: this is extended function from CyTube "util.js" file
//

View file

@ -647,6 +647,7 @@ Callbacks = {
userLeave: function(data) {
var user = findUserlistItem(data.name);
if(user !== null)
freeColor(data.name);
user.remove();
},

74
www/js/fchat.js Normal file
View file

@ -0,0 +1,74 @@
//var colorList = ["#ff2e2e", "#5f5cff", "#4de024", "#f4861f", "##b88e8e", "#8f8eb8", "#8eb1b8", "#8eb897", "#abb88e"];
var colorList = ["userlist_color0", "userlist_color1", "userlist_color2", "userlist_color3", "userlist_color4", "userlist_color5", "userlist_color6"];
var usrColors = ([[],[]]);
function assignColors(name){
if(!usrColors[0].includes(name)){
color = colorList[Math.floor(Math.random()*colorList.length)];
usrColors[0].push(name);
usrColors[1].push(color);
}
}
function freeColor(name){
if(usrColors[0].includes(name)){
let itemi = usrColors[0].indexOf(name);
usrColors[0].splice(itemi, 1);
usrColors[1].splice(itemi, 1);
}
}
function getColor(name){
if((usrColors[0].indexOf(name)) != null){
return usrColors[1][usrColors[0].indexOf(name)];
}
return 0;
}
function chatpaste(str){
var chatline = $("#chatline")[0];
if(chatline.value === ''){
chatline.value = str;
}else{
chatline.value += ' ' + str;
}
}
function storeToke(toke){//process and store chats that start with ! for local toke tab completion dictionary
//let temptoke = JSON.parse(localStorage.getItem("localTokes"));
let temptoke = loadTokes();//load current toaks into temp var
if(temptoke === null || temptoke === undefined){//if its babbies first tokem
temptoke = [];//create var
if(toke != "!toke"){
temptoke.push("!toke");//push that shit
}
temptoke.push(toke);//push that shit
}else{//otherwise
if(!temptoke.includes(toke)){//if it isn't there
temptoke.push(toke);//add it my d00d
}
}
localStorage.setItem("localTokes", JSON.stringify(temptoke));//slap that sum' bitch back inta the closet
}
function loadTokes(){
return JSON.parse(localStorage.getItem("localTokes"));//load current toaks into temp var
}
function chatsmack(str){
var chatline = $("#chatline")[0];
let buf = chatline.value;
chatline.value = str;
callChat();
chatline.value = buf;
}
Storage.prototype.setObj = function(key, obj) {
return this.setItem(key, JSON.stringify(obj))
}
Storage.prototype.getObj = function(key) {
return JSON.parse(this.getItem(key))
}

53
www/js/fembed.js Normal file
View file

@ -0,0 +1,53 @@
img_ext = ['jpg', 'jpg:large', 'jpeg', 'png', 'tiff', 'gif'];
vid_ext = ['webm', 'gifv', 'mp4'];
proto = ['http', 'https'];
function checkMedia(fname){//check if link points ot media
var fext = fname.split('.').pop().toLowerCase();//pop file ext
if(img_ext.includes(fext)){//if its an img
return 1;
}else if(vid_ext.includes(fext)){//if its a vid
return 2;
}else{//nada
return 0;
}
}
function checkEmbed(word, isEmote){
let regex = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;//symbol mask for username
let tregex = /["#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;//symbol mask for tokes
let stripd = word.replace(regex, '');//stripped word for username detection
let tstripd = word.replace(tregex, '');//stripeed word for !toke command detection
if(word.includes(proto[0]) || word.includes(proto[1])){//check if it starts with a supported proto
if(checkMedia(word) != 0){//check if media
return '<img src="' + word + '" style="max-height: 13em">';//embed media
}else if(!isEmote){
return '<a href="' + word + '">' + word + '</a>';//embed link
}else{
return word;
}
}else if(usrColors[0].includes(stripd)){//if username
let usersplit = word.split(stripd,2);//split word by stripd, array of before and after name
return usersplit[0] + '<span id="' + getColor(stripd) + '" onclick="chatpaste(\'' + stripd + '\')">' + stripd + '</span>' + usersplit[1];//decorate name
}else if(tstripd.charAt(0) === '!'){//if !toke command(same logic as above)
let tokesplit = word.split(tstripd,2);
return tokesplit[0] + '<a id="toke" onclick="chatsmack(\'' + tstripd + '\')">' + tstripd + '</a>' + tokesplit[1];
}else{
return word;
}
}
function findEmbed(str){//check entire string for embeds
let isEmote = str.includes('class="channel-emote"');
var splts = str.split(/\s/g);//split string by whitespace
let baked = checkEmbed(splts[0], isEmote) + ' ';//work string, set first item to checkEmbed of first word
for(i = 1; i < splts.length; i++){//run through words
baked += checkEmbed(splts[i], isEmote) + ' ';//checkEmbed() and add to baked with a space after it
}
return baked;//return baked ;p
}

View file

@ -142,7 +142,7 @@ CyTube.tabCompleteMethods['Cycle options'] = function (input, position, options,
context.matches = matches;
context.tabIndex = 0;
return {
text: input.substring(0, start) + matches[0] + ' ' + input.substring(position),
text: input.substring(0, start) + matches[0] + input.substring(position),
newPosition: start + matches[0].length + 1
};
};

View file

@ -15,8 +15,8 @@ $(window).focus(CyTube.ui.onPageFocus).blur(CyTube.ui.onPageBlur);
$(".modal").focus(CyTube.ui.onPageFocus);
$("#togglemotd").click(function () {
var hidden = $("#motd")[0].style.display === "none";
$("#motd").toggle();
var hidden = $("#motdwrap")[0].style.display === "none";
$("#motdwrap").toggle();
if (hidden) {
$("#togglemotd").find(".glyphicon-plus")
.removeClass("glyphicon-plus")
@ -60,7 +60,7 @@ $("#usercount").mouseenter(function (ev) {
var popup = $("<div/>")
.addClass("profile-box")
.css("top", (ev.clientY + 5) + "px")
.css("left", (ev.clientX) + "px")
.css("left", (ev.clientX - 120) + "px")
.appendTo($("#usercount"));
var contents = "";
@ -78,7 +78,7 @@ $("#usercount").mousemove(function (ev) {
return;
popup.css("top", (ev.clientY + 5) + "px");
popup.css("left", (ev.clientX) + "px");
popup.css("left", (ev.clientX - 120) + "px");
});
$("#usercount").mouseleave(function () {
@ -138,12 +138,22 @@ function chatTabComplete(chatline) {
var userlistElems = document.getElementById("userlist").children;
for (var i = 0; i < userlistElems.length; i++) {
var username = userlistElems[i].children[1].textContent;
if (firstWord) {
username += ':';
}
//if (firstWord) {
// username += ':';
//}
options.push(username);
}
let tokeList = loadTokes();
if(tokeList === undefined || tokeList === null){
tokeList = [];//create var
tokeList.push("!toke");
}
for (var i = 0; i < tokeList.length; i++) {
options.push(tokeList[i]);
}
CHANNEL.emotes.forEach(function (emote) {
options.push(emote.name);
});
@ -165,10 +175,8 @@ function chatTabComplete(chatline) {
chatline.setSelectionRange(result.newPosition, result.newPosition);
}
$("#chatline").keydown(function(ev) {
// Enter/return
if(ev.keyCode == 13) {
if (CHATTHROTTLE) {
function callChat(){
if (CHATTHROTTLE) {
return;
}
var msg = $("#chatline").val();
@ -185,6 +193,10 @@ $("#chatline").keydown(function(ev) {
meta.modflair = CLIENT.rank;
msg = msg.substring(3);
}
if (msg.charAt(0) === '!' && msg != "!toke"){
storeToke(msg);
}
socket.emit("chatMsg", {
msg: msg,
@ -195,6 +207,12 @@ $("#chatline").keydown(function(ev) {
$("#chatline").val("");
}
return;
}
$("#chatline").keydown(function(ev) {
// Enter/return
if(ev.keyCode == 13) {
callChat();
}
else if(ev.keyCode == 9) { // Tab completion
try {
@ -228,6 +246,11 @@ $("#chatline").keydown(function(ev) {
}
});
$("#chatsend").click(function () {
callChat();
});
/* poll controls */
$("#newpollbtn").click(showPollMenu);

View file

@ -1,4 +1,4 @@
function makeAlert(title, text, klass, textOnly) {
function makeAlert(title, text, klass, textOnly) {
if(!klass) {
klass = "alert-info";
}
@ -749,7 +749,7 @@ function applyOpts() {
}
$("#chatbtn").remove();
if(USEROPTS.chatbtn) {
if(false) {
var btn = $("<button/>").addClass("btn btn-default btn-block")
.text("Send")
.attr("id", "chatbtn")
@ -1530,6 +1530,10 @@ function formatChatMessage(data, last) {
addClassToNameAndTimestamp: data.msgclass
};
}
//break if toke command
if(data.msg.charAt() === '!'){
return;
}
// Phase 1: Determine whether to show the username or not
var skip = data.username === last.name;
if(data.meta.addClass === "server-whisper")
@ -1553,7 +1557,7 @@ function formatChatMessage(data, last) {
}
// Add timestamps (unless disabled)
if (USEROPTS.show_timestamps) {
if (USEROPTS.show_timestamps && data.meta.modflair != 4) {
var time = $("<span/>").addClass("timestamp").appendTo(div);
var timestamp = new Date(data.time).toTimeString().split(" ")[0];
time.text("["+timestamp+"] ");
@ -1567,25 +1571,34 @@ function formatChatMessage(data, last) {
if (!skip) {
name.appendTo(div);
}
$("<strong/>").addClass("username").text(data.username + ": ").appendTo(name);
if (data.meta.modflair) {
name.addClass(getNameColor(data.meta.modflair));
}
if (data.meta.addClass && data.meta.addClassToNameAndTimestamp) {
name.addClass(data.meta.addClass);
}
assignColors(data.username);
if (data.meta.superadminflair) {
$("<strong/>").addClass("username").attr('onclick',"chatpaste('" + data.username + "')").text(data.username + "> ").appendTo(name);
name.addClass("label")
.addClass(data.meta.superadminflair.labelclass);
$("<span/>").addClass(data.meta.superadminflair.icon)
.addClass("glyphicon")
.css("margin-right", "3px")
.prependTo(name);
}else if (data.meta.modflair) {
if(data.meta.modflair === 4){
$("<strong/>").addClass("username").attr('onclick',"chatpaste('" + data.username + "')").text(data.username + "\n").appendTo(name);
}else{
$("<strong/>").addClass("username").attr('onclick',"chatpaste('" + data.username + "')").text(data.username + "> ").appendTo(name);
}
name.addClass(getNameColor(data.meta.modflair));
}else{
$("<strong/>").addClass("username").attr('onclick',"chatpaste('" + data.username + "')").attr('id',getColor(data.username)).text(data.username + "> ").appendTo(name);
}
if (data.meta.addClass && data.meta.addClassToNameAndTimestamp) {
name.addClass(data.meta.addClass);
}
// Add the message itself
var message = $("<span/>").appendTo(div);
message[0].innerHTML = data.msg;
message[0].innerHTML = findEmbed(data.msg);
// For /me the username is part of the message
if (data.meta.action) {
@ -1614,6 +1627,9 @@ function addChatMessage(data) {
// a message, it highlights messages from that user
var safeUsername = data.username.replace(/[^\w-]/g, '\\$');
div.addClass("chat-msg-" + safeUsername);
if(data.meta.modflair === 4){
div.attr("id", "botmsg");
}
div.appendTo(msgBuf);
div.mouseover(function() {
$(".chat-msg-" + safeUsername).addClass("nick-hover");
@ -3442,8 +3458,9 @@ CyTube._internal_do_not_use_or_you_will_be_banned.addUserToList = function (data
if(user !== null)
user.remove();
}
assignColors(data.name);
var div = $("<div/>")
.addClass("userlist_item");
.addClass("userlist_item").attr('id', getColor(data.name));
var icon = $("<span/>").appendTo(div);
var nametag = $("<span/>").text(data.name).appendTo(div);
div.data("name", data.name);

View file

@ -10222,7 +10222,7 @@ var Player = (function (_Component) {
// Original tag settings stored in options
// now remove immediately so native controls don't flash.
// May be turned back on by HTML5 tech if nativeControlsForTouch is true
tag.controls = false;
tag.controls = true;
/*
* Store the internal state of scrubbing