fore.st/www/js/fpanel.js
rainbownapkin 3f653c4893 Added raw file youtube support as holdover until invidious embed is
viable. This does not help with region locking, but at least allows
age restricted videos with no sign in, doesnt run any google scripts,
and does not run ads.
2022-07-14 01:54:06 +00:00

333 lines
13 KiB
JavaScript

/*
fore.st is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
fore.st is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with fore.st. If not, see < http://www.gnu.org/licenses/ >.
(C) 2022- by rainbownapkin, <ourforest@420blaze.it>
*/
//---Global Variables---
CURRENTFPANEL = null;
//---Global Functions---
function closeFPanel(cb){//close and null out fpanel, cb function to call when panel is closed
$("#fpaneldiv").hide("slide", 250,function(){
$("#fpcontdiv").empty();
$("#fptitle").html("null Panel");
$("#closefpanel").prop("title", "Close null panel.");
CURRENTFPANEL = null;
if(typeof cb === 'function'){
cb();
}
});
}
function sizeFPDiv(){//set inner div height to fix overflow
$("#fpaneldiv").outerWidth($("#chatwrap").outerWidth() * 0.7);
$("#fpcontdiv").outerHeight($("#fpaneldiv").height() - $("#fptitlediv").outerHeight());
}
function panelbtn(panel){
if($("#fpaneldiv").is(":visible")){//if panel is visible
difClose = CURRENTFPANEL != panel;//set difclose to if CURRENTPANEL is the same one attatched to the button we're clicking
closeFPanel(function(){//closem panel
if(difClose){//if
panel.popMenu(panel.data);//pop da panel
}
});
}else{//else
panel.popMenu(panel.data);//pop that bitch son
}
}
//---base panel---
function fpmenu(title, elm, data, ocall){//fpmenu constructor
this.title = title;//title of menu
this.elm = elm;//elements to insert (good for simple menus)
this.data = data;//menu data (not used for all menus)
this.ocall = function ocall(){};//function to call upon menu opening (used for more advanced menus)
}
fpmenu.prototype.popMenu = function(idata){//POP goes the weasal!
this.data = idata//set data
$("#fpcontdiv").empty();//empty content div
$("#fptitle").html(this.title + " Panel");//set panel tittle
$("#closefpanel").prop("title", "Close " + this.title + " panel.");//set close button hover text
$("#fpcontdiv").append(this.elm);//append element array
this.ocall(this.data);//run open function
CURRENTFPANEL = this;
$("#fpaneldiv").show("slide", 250, function() {sizeFPDiv()});//show panel and correct size once open
}
//---fpanel poll---
var fpoll = new fpmenu("Poll");//create new panel fpoll
fpoll.elm = [//fpoll element array
$("<h3>").prop("id","polltitle").html("Null Poll Title")//poll title
]
fpoll.ocall = function(data){//fpoll open call function
$("#polltitle").html("Poll: " + data.title);//set poll title
if(hasPermission("pollctl")) {//if ur allowed to fuck wit da poll
$("<button/>").addClass("btn btn-danger btn-sm pull-right").text("End Poll")//add end poll button
.prop("id","endpollbtn")//set id
.appendTo("#fpcontdiv")//append
.click(function() {//click event
socket.emit("closePoll")//endem poll
});
}
for(var i = 0; i < data.options.length; i++) {//fer all the options in the poll
(function(i) {
var callback = function () {//create callback function
socket.emit("vote", {//send vote
option: i//use current option
});
$("#fpcontdiv").find(".option button").each(function() {//find currently selected button
$(this).removeClass("active");//unselect it
$(this).parent().removeClass("option-selected");
});
$(this).addClass("active");//set current option as actively selected
$(this).parent().addClass("option-selected");
}
$("<button/>").addClass("btn btn-default btn-sm").text(data.options[i])//add button
.prependTo($("<div/>").addClass("option").html('<p style="display: inline;">' + data.counts[i] + "</p>")//set cont labels
.appendTo("#fpcontdiv"))//append them to div
.click(callback);//add click event to callback function
})(i);
}
}
fpoll.updatePoll = function(data){//updatem poll
var poll = $("#pollwrap .active");
var i = 0;
$("#fpcontdiv").find(".option p").each(function() {//for every option
$(this).html(data.counts[i]);//correct count labels
i++;//increment counter
});
}
fpoll.closePoll = function(data){//close poll
tmpttl = $("#polltitle").html();//grab poll title
$("#polltitle").html(tmpttl + " (Poll Closed)");//add closed label
$("#pollopenbtn").hide("blinds");//hide poll button
$("#fpcontdiv").find(".option button").each(function() {//disable poll buttons
$(this).prop("disabled", true);
});
$("#fpcontdiv").find(".btn-danger").each(function() {//remove end poll button
$(this).remove()
});
}
//---emote panel---
var fpemote = new fpmenu("Emote");//create fpemote new fpanel obj
fpemote.isAlpha = true;//isAlpha to true because this emote panel is a fucking chad
fpemote.ocall = function(data){//fpemote open function
let symask = /["!#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g;//symbol mask
$("<form>").prop("action","javascript:void(0)").prop("id","emotecont").append([//top inputs
$("<input>").prop("placeholder","Search Emotes").prop("type","text").prop("id", "esearchbar").addClass("form-control").keyup(function(ev){//emote search bar
fpemote.searchEmote($("#esearchbar").val());//search for emotes when key as users finger lifts up
}),
$("<span>").prop("id","anumspan").append([//alphanumspan
$("<input>").prop("id","emotealphabox").prop("type", "checkbox").prop("checked", fpemote.isAlpha).click(function(){//alphanum sort checkbox
fpemote.alphaPop($("#emotealphabox").prop("checked"));//pop alphanum sort
}),
$("<label>").prop("for", "emotealphabox").addClass("glyphicon glyphicon-sort-by-alphabet")//alphanum sort label
])
]).appendTo("#fpcontdiv");//add search bar, adding this in elm causes strange behavior
$("<div>").addClass("emotecontdiv").appendTo("#fpcontdiv");//add emote container div, creating this in elm causes obnoxious behaviour
fpemote.alpha = window.CHANNEL.emotes.slice(0);//create second emote array
fpemote.alpha.sort((a, b) => a.name.replace(symask, '').toLowerCase().localeCompare(b.name.replace(symask, '').toLowerCase()));//sort it by alphabetical
earray = fpemote.isAlpha ? fpemote.alpha : window.CHANNEL.emotes//use the alphanum sorted array if alphanum sort is enabled
earray.forEach(function(value){//for every emote
fpemote.popEmote(value);//poulate emotes
});
}
fpemote.popEmote = function(emote){
$("<div>").addClass("emotediv").append([//add new div for every emote
$("<span>").prop("id","emspan").append($("<img>").prop("src", emote.image)),//insert emote thumbnails
$("<p>").html(emote.name),//insert emote name labels
]).click(function(){//find current emote and add onclick function
chatpaste(emote.name);//paste emote name
closeFPanel();//close fpanel
}).appendTo(".emotecontdiv");//append to emote container div
}
fpemote.searchEmote = function(sstring){
i = 0;
$(".emotecontdiv").empty();
earray = fpemote.isAlpha ? fpemote.alpha : window.CHANNEL.emotes
earray.forEach(function(value){
if(value.name.toLowerCase().includes(sstring.toLowerCase()) || (sstring == null || sstring == "")){
i++;
fpemote.popEmote(value);
}
});
if(i <= 2){
$(".emotecontdiv").prop("style", "grid-template-columns: auto");
}else{
$(".emotecontdiv").prop("style", "");
}
}
fpemote.alphaPop = function(setalpha){
$(".emotecontdiv").empty();
if(setalpha == null){
fpemote.isAlpha = !fpemote.isAlpha;
}else{
fpemote.isAlpha = setalpha
}
earray = fpemote.isAlpha ? fpemote.alpha : window.CHANNEL.emotes
if($("#esearchbar").val() != ""){
fpemote.searchEmote($("#esearchbar").val());
}else{
earray.forEach(function(value){//for every emote
fpemote.popEmote(value);//poulate emotes
});
}
}
//---Quick Settings Panel---
var fpset = new fpmenu("Quick Settings");
fpset.ocall = function(){
$("#fpcontdiv").append(spanel = $("<div>").prop("id","fpsetdiv"));
spanel.append([
$("<h4>").html("General Preferences"),
$("<form>").append(
$("<label>").prop("for","qs-theme").html("Theme: "),
$("<select>").prop("id","qs-theme").addClass("qs-form").change(function() {
USEROPTS.theme = $("#qs-theme").val();
processOpts();
}),
),
$("<h4>").html("Playback Preferences"),
$("<p>").html("Video Orientation: "),
$("<span>").prop("id","flipx-video").addClass("qsbtn glyphicon glyphicon-resize-horizontal pointer").prop("title", "Flip Player Horizontally").attr("onclick",'javascript:$("#ytapiplayer").toggleClass("mirx")'),
$("<span>").prop("id","flipy-video").addClass("qsbtn glyphicon glyphicon-resize-vertical pointer").prop("title", "Flip Player Vertically").attr("onclick",'javascript:$("#ytapiplayer").toggleClass("miry")'),
$("<form>").append(
$("<label>").prop("for","qs-orient-buttons").html("Video Orientation Buttons on Titlebar: "),
$("<input>").prop("id","qs-orient-buttons").prop("type","checkbox").addClass("qs-form").change(function() {
USEROPTS.show_orientation = $("#qs-orient-buttons").prop("checked");
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-sync-threshold").html("Sync Threshold(seconds): "),
$("<input>").prop("id","qs-sync-threshold").prop("type","text").addClass("qs-form"),
$("<button/>").addClass("btn btn-primary btn-ln").text("Save").prop("type","button").prop("id","qs-sync-threshold-save").click(function() {
USEROPTS.sync_accuracy = parseFloat($("#qs-sync-threshold").val()) || 2;
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-yt-source").html("Youtube Source: "),
$("<select>").prop("id","qs-yt-source").addClass("qs-form").change(function(){
USEROPTS.yt_source = $("#qs-yt-source").val();
processOpts();
}),
),
$("<h4>").html("Chat Preferences"),
$("<form>").append(
$("<label>").prop("for","qs-legacy-emote").html("Use legacy cytube emote menu: "),
$("<input>").prop("id","qs-legacy-emote").prop("type","checkbox").addClass("qs-form").change(function() {
USEROPTS.legacy_emote = $("#qs-legacy-emote").prop("checked");
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-blink-title").html("Blink page title on new messages: "),
$("<select>").prop("id","qs-blink-title").addClass("qs-form").change(function() {
USEROPTS.blink_title = $("#qs-blink-title").val();
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-boop").html("Beep on new message: "),
$("<select>").prop("id","qs-boop").addClass("qs-form").change(function() {
USEROPTS.boop = $("#qs-boop").val();
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-notifications").html("Browser Notification on new message: "),
$("<select>").prop("id","qs-notifications").addClass("qs-form").change(function() {
USEROPTS.notifications = $("#qs-notifications").val();
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-show-timestamp").html("Show Timestamps (reqs refresh on enable): "),
$("<input>").prop("id","qs-show-timestamp").prop("type","checkbox").addClass("qs-form").change(function() {
USEROPTS.show_timestamps = $("#qs-show-timestamps").prop("checked");
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","qs-timestamp-second").html("Show Seconds on Timestamps: "),
$("<input>").prop("id","qs-timestamp-second").prop("type","checkbox").addClass("qs-form").change(function() {
USEROPTS.show_seconds = $("#qs-timestamp-second").prop("checked");
processOpts();
}),
),
])
fpset.loadSettings();
}
fpset.loadSettings = function(){
$("#us-theme").children().clone().appendTo($("#qs-theme"));
$("#us-yt-source").children().clone().appendTo($("#qs-yt-source"));
$("#qs-theme").val(USEROPTS.theme);
$("#qs-orient-buttons").prop("checked", USEROPTS.show_orientation);
$("#qs-sync-threshold").val(USEROPTS.sync_accuracy);
$("#qs-yt-source").val(USEROPTS.yt_source);
$("#qs-legacy-emote").prop("checked", USEROPTS.legacy_emote);
$("#us-blink-title").children().clone().appendTo($("#qs-blink-title"));
$("#qs-blink-title").val(USEROPTS.blink_title);
$("#us-ping-sound").children().clone().appendTo($("#qs-boop"));
$("#qs-boop").val(USEROPTS.boop);
$("#us-notifications").children().clone().appendTo($("#qs-notifications"));
$("#qs-notifications").val(USEROPTS.notifications);
$("#qs-show-timestamp").prop("checked", USEROPTS.show_timestamps);
$("#qs-timestamp-second").parent().toggle(USEROPTS.show_timestamps);
$("#qs-timestamp-second").prop("checked", USEROPTS.show_seconds);
}