Added mod panel, nested fpanel menus, fpanel playlist

This commit is contained in:
rainbownapkin 2022-07-19 06:32:22 +00:00
parent 3f653c4893
commit 1da7cab9cd
15 changed files with 556 additions and 146 deletions

113
README.md
View file

@ -55,8 +55,6 @@ dev goals for 1.1 pineapple express:
- videojs.coffee(hls,videojs,raw-file,gdrive,rtmp) ✓ - videojs.coffee(hls,videojs,raw-file,gdrive,rtmp) ✓
- dailymotion ~(this is kinda broken, likely not possible client-side without breaking CORS policy. This can wait until next version when an installation script including nginx and cors-proxy config gets added to support the catbox.moe image upload button which faces the same issue. - dailymotion ~(this is kinda broken, likely not possible client-side without breaking CORS policy. This can wait until next version when an installation script including nginx and cors-proxy config gets added to support the catbox.moe image upload button which faces the same issue.
- vimeo ✓ - vimeo ✓
- add player.js updates to twitch
- save temporary vids to channel library
- slide out panel (not an end user feature in and of itself, however a common UI element used for most menus, made to be quick and ezpz ✓ - slide out panel (not an end user feature in and of itself, however a common UI element used for most menus, made to be quick and ezpz ✓
- function for opening, closing ✓ - function for opening, closing ✓
@ -124,10 +122,6 @@ dev goals for 1.1 pineapple express:
- server-whisper target parameter for user specific whispers ✓ - server-whisper target parameter for user specific whispers ✓
- server-whisper name ✓ - server-whisper name ✓
- getplaylistlinks outputs in fpanel
- I mean its pretty fucking simple I dont know how you can screw this one up bud.
- ezpzlmnsqze
- flex layout/legacy layout ripout ✓ - flex layout/legacy layout ripout ✓
- rip out legacy layout system ✓ - rip out legacy layout system ✓
- chat/player sized to fit canvas with navbar (remove -+ buttons on player) ✓ - chat/player sized to fit canvas with navbar (remove -+ buttons on player) ✓
@ -157,29 +151,52 @@ dev goals for 1.1 pineapple express:
- fix portrait/mobile mode ✓ - fix portrait/mobile mode ✓
- fix user tooltip menu position ✓ - fix user tooltip menu position ✓
- decaffeinate player.js - decaffeinate player.js
- Coffee script was a bad idea then, and it makes even less sense now. - Coffee script was a bad idea then, and it makes even less sense now.
- fuck me its just javascript with worse syntax, no real debugging tools, and build times - fuck me its just javascript with worse syntax, no real debugging tools, and build times
- literally fucking why though?(I guess it made sense before ES6 but still fuck me) - literally fucking why though?(I guess it made sense before ES6 but still fuck me)
- degoogling - degoogling ✓
- yt-dlp backend for serverside metadata acquisition of youtube videos w/o registered API key or google account - invidious api or yt-dlp backend for serverside metadata acquisition of youtube videos w/o registered API key or google account
- potentially leverage yt-dlp backend for other media sources - pull metadata for single video ✓
- pull metadata for playlist ✓
- search function ✓
- potentially leverage yt-dlp backend for other media sources X went with invidious. YT-DLP may make more sense for a total re-write in the future
- implement player.js updates into youtube.coffee - implement player.js updates into youtube.coffee
- latching - latching ✓
- getres - getres X Probably not possible without breaking cors policy. (same as DM)
- update minicont dur - handleVideoSize on load ✓
- update minicont buttons - update minicont dur ~ updates with server tick, doesnt look as good as other sources, but YT embeds suck.
- invidious embed support for youtube video playback - update minicont buttons ✓
- youtube source in user prefrences (three or four invidious instances from different countries/continents, official youtube embed, or custom invidious instance) - invidious embed support for youtube video playback X not possible with current setup. Reqs either update to invidious allowing embed control, or a cors proxy(will look into this next update, or whenever installation script is created)
- invidious embed alternative: pull raw video link on vid start server side, serve to client ✓
- youtube source in user prefrences (raw link or official yt embed for now) ✓
- autobump - mod/admin panel
- sepearate bump lists, based on js/txt files at first, will be stored in db next update (may use multiple at once) - button on chatbar ✓
- skip next bump/disable bumping - auto switch to admin panel ✓
- bump frequency (default: 1) - main panel
- queue method: random from last-half, round-robin, full random - poll creation ✓
- override next bump - tools
- require video be at least 4 minutes to add bump (mods can override from bump menu) - !announce button/field ✓
- !clear button w/ username dropdown ✓
- mod message (sends message to all active mods) ✓
- preferences ✓
- modflair ✓
- show modflair on chat header ✓
- show shadowmuted messages ✓
- show ips in tooltips ✓
- open playlist below video by default ✓
- nested menu
- new nested menu protoype object ✓
- playlist menu (just the playlist but in fpanel, currently one or the other) ✓
- move playlist between legacy area and fpanel on open/close ✓
- bugfixes ✓
- lock/unlock panel dissapears playlist (suicide by two shots to the back of the head) ✓
- fix scroll to item ✓
- fix scrolling while dragging pl item ✓
- autobump control menu
- tokebot control menu
- merge tokebot into ourfore.st codebase, one server instead of two. - merge tokebot into ourfore.st codebase, one server instead of two.
- profile and userlist entry - profile and userlist entry
@ -189,29 +206,43 @@ dev goals for 1.1 pineapple express:
- tokefile, list of usernames with toke count. This will be switched to mariadb in the next update - tokefile, list of usernames with toke count. This will be switched to mariadb in the next update
- total tokes listed on profile tooltip - total tokes listed on profile tooltip
- autobump
- sepearate bump lists, based on js/txt files at first, will be stored in db next update (may use multiple at once)
- skip next bump/disable bumping
- bump frequency (default: 1)
- queue method: random from last-half, round-robin, full random
- override next bump
- require video be at least 4 minutes to add bump (mods can override from bump menu)
- mod panel - finishing touches
- button on chatbar - CRITICAL BUG FIX: video sometimes unlatches if sync delayed on video start.(Fix pre-latch, if not duration check until sync is past 2s?)
- mod message (sends message to all active mods) - CRITICAL BUG FIX: userlist profile tooltips are currently broken
- new poll button - CRITICAL BUG FIX: chat does not fill screen in portrait mode (video height being subtracted while video collapsed)
- autobump control tab - save temporary vids to channel library
- tokebot control tab - getplaylistlinks outputs in fpanel
- playlist tab - display links
- modflair - pop mod nmenu
- open playlist below video (if closed, otherwise this does not appear) - css variables in theme for ez customizablity
- open playlist below video by default
- merge fore.st theme changes to fore.st dusk, consider moving some of them over to cytube.css for easier management - merge fore.st theme changes to fore.st dusk, consider moving some of them over to cytube.css for easier management
- extra shit(probs wait til next update, or hotfix) - extra shit(probs wait til next update, or hotfix)
- short chats (acronyms, emoji, single letters/numbers/symbols) pop in over video from left starting at top left, overflow pops in below, instead of in chat box. Chats slide back up into top of vid after 2s. (optional, default on) - short chats (acronyms, emoji, single letters/numbers/symbols) pop in over video from left starting at top left, overflow pops in below, instead of in chat box. Chats slide back up into top of vid after 2s. (optional, default on)
- basic mod chat (save to mod channel + pm all online mods) - pop out btn
- basic profile page (in side panel) - basic profile page (in side panel)
- css variables in theme for ez customizablity - improved mod chat (dedicated pop out to access mod channel chat from any channel)
- user themes - user themes
- movie night theme
- tree house theme
- the network theme
- change background to other themes background or img from url(theme background by default) - change background to other themes background or img from url(theme background by default)
- native odysee support (no raw embed) - click and drag to resize fpanel
- native odysee support (no raw embed) (might save for 1.2)
- fix touch & drag to resize chat/video split on mobile/touch devices
- add player.js updates to twitch/embed/soundcloud
- latching
- getres
- update minicont dur
- update minicont buttons
## License ## License
Original fore.st code is provided under the Affero General Public License v3 in order to prevent fore.st being used in proprietary software. Original fore.st code is provided under the Affero General Public License v3 in order to prevent fore.st being used in proprietary software.

View file

@ -1238,7 +1238,7 @@ PlaylistModule.prototype.startPlayback = function (time) {
} }
/* Lead-in time of 3 seconds to allow clients to buffer */ /* Lead-in time of 3 seconds to allow clients to buffer */
time = time || (media.seconds > 0 ? (media.type == "yt" ? -6 : -3) : 0); //if its a yt vid make it 6 for the link pull time = time || (media.seconds > 0 ? -3 : 0);
media.paused = time < 0; media.paused = time < 0;
media.currentTime = time; media.currentTime = time;

View file

@ -66,7 +66,7 @@ var defaults = {
} }
}, },
"invidious-backend": true, "invidious-backend": true,
"invidious-source": 'vid.puffyan.us', "invidious-source": 'inv.riverside.rocks',
"youtube-v3-key": "", "youtube-v3-key": "",
"channel-blacklist": [], "channel-blacklist": [],
"channel-path": "r", "channel-path": "r",

View file

@ -39,12 +39,11 @@ block content
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
.col-md-8.col-md-offset-2
.aboutText .aboutText
h1 Welcome to ourfore.st! h1 Welcome to ourfore.st!
h3 about fore.st/ourfore.st h3 about fore.st/ourfore.st
p. p.
fore.st is a fork of cytube built for the TTN community post-shutdown. TTN was a community based streaming service for cannabis enthusiasts. After eight years, the man behind the site went on to greener pastures. In it's place stands this, and many other community efforts such as <a href="https://treez.one/">Treezone</a>, and the community discord. While it may not be the same, we aim to provide a similiar service for the same people. The refrence instance for fore.st is hosted at <a href="https://ourfore.st/">ourfore.st</a>. fore.st is a fork of cytube built for the TTN community post-shutdown. TTN was a community based video & stream embedding/chat site for cannabis enthusiasts. After eight years, the man behind the site went on to greener pastures. In it's place stands this, and many other community efforts such as <a href="https://treez.one/">Treezone</a>, and the community discord. While it may not be the same, we aim to provide a similiar service for the same people. The refrence instance for fore.st is hosted at <a href="https://ourfore.st/">ourfore.st</a>.
h3 ourfore.st instance rules h3 ourfore.st instance rules
ul ul
li li

View file

@ -60,14 +60,14 @@ html(lang="en")
section#mainpage section#mainpage
.container .container
#motdrow.row #motdrow.row
#motdwrap.well #motdwrap.well.panelback
button#togglemotd.close.pull-right(type="button") button#togglemotd.close.pull-right(type="button")
span.glyphicon.glyphicon-minus span.glyphicon.glyphicon-minus
#motd #motd
.clear .clear
#announcements.row #announcements.row
#titles.row #titles.row
p#videowrap-header p#videowrap-header.panelback
i#blindvideo.glyphicon.glyphicon-chevron-down.pointer(title="Hide Player") i#blindvideo.glyphicon.glyphicon-chevron-down.pointer(title="Hide Player")
span#currenttitle Nothing Playing span#currenttitle Nothing Playing
span#minicontrol span#minicontrol
@ -81,9 +81,9 @@ html(lang="en")
span#cinemode.playercont.glyphicon.glyphicon-film.pointer(title="Toggle Cinema Mode") span#cinemode.playercont.glyphicon.glyphicon-film.pointer(title="Toggle Cinema Mode")
span#lockaspect.playercont.glyphicon.glyphicon-picture.pointer(style="display: none;", title="Lock to Aspect Ratio") span#lockaspect.playercont.glyphicon.glyphicon-picture.pointer(style="display: none;", title="Lock to Aspect Ratio")
span#latchvid.label.label-default.pull-right.pointer(style="display: none;") Sync span#latchvid.label.label-default.pull-right.pointer(style="display: none;") Sync
#chatheader #chatheader.panelback
i#blindchat.glyphicon.glyphicon-chevron-down.pointer(title="Hide Chat") i#blindchat.glyphicon.glyphicon-chevron-down.pointer(title="Hide Chat")
span#modflair.label.label-default.pull-right.pointer Name Color span#modflair.label.label-default.pointer Modflair
span(style="flex-grow: 2;") span(style="flex-grow: 2;")
span#usercount.pointer Not Connected span#usercount.pointer Not Connected
i#userlisttoggle.glyphicon.glyphicon-chevron-down.pull-left.pointer(title="Show/Hide Userlist") i#userlisttoggle.glyphicon.glyphicon-chevron-down.pull-left.pointer(title="Show/Hide Userlist")
@ -96,23 +96,24 @@ html(lang="en")
h3 Take a <a onclick="chatsmack('!toke')">Toke!</a> h3 Take a <a onclick="chatsmack('!toke')">Toke!</a>
#chatwrap #chatwrap
#chatmain #chatmain
#userlist #userlist.panelback
#fpaneldiv.fpanel(style="display: none;") #fpaneldiv.fpanel(style="display: none;")
#fptitlediv.fptitlebar.fpanel #fptitlediv.fptitlebar.fpanel
p#fptitle.fptitlebar.fpanel null p#fptitle.fptitlebar.fpanel null
p#closefpanel.fptitlebar.fpanel.glyphicon.glyphicon-remove.pointer(onclick="javascript:closeFPanel()", title="Close null panel.") p#closefpanel.fptitlebar.fpanel.glyphicon.glyphicon-remove.pointer(onclick="javascript:closeFPanel()", title="Close null panel.")
#fpcontdiv.fpcont.fpanel #fpcontdiv.fpcont.fpanel
#messagebuffer.linewrap #messagebuffer.linewrap.panelback
#chatbar(style="display: flex;") #chatbar(style="display: flex;")
button#pollopenbtn.btn.btn-sm.btn-default.glyphicon.glyphicon-ok.chatbtn(onclick="javascript:panelbtn(fpoll)",style="display: none;", title="Poll") button#pollopenbtn.btn.btn-sm.btn-default.glyphicon.glyphicon-ok.chatbtn.panelback(onclick="javascript:panelbtn(fpoll)",style="display: none;", title="Poll")
button#prefopenbtn.btn.btn-sm.btn-default.glyphicon.glyphicon-cog.chatbtn(onclick="javascript:panelbtn(fpset)",title="Quick Settings") button#prefopenbtn.btn.btn-sm.btn-default.glyphicon.glyphicon-cog.chatbtn.panelback(onclick="javascript:panelbtn(fpset)",title="Quick Settings")
button#emoteopenbtn.btn.btn-sm.btn-default.chatbtn(onclick="javascript:panelbtn(fpemote)",title="Emotes") ;) button#modopenbtn.btn.btn-sm.btn-default.chatbtn.panelback(onclick="javascript:panelbtn(fpmod)",title="Mod Panel", style="display: none;") MOD
button#emoteopenbtn.btn.btn-sm.btn-default.chatbtn.panelback(onclick="javascript:panelbtn(fpemote)",title="Emotes") ;)
form(action="javascript:void(0)" style="display: flex; flex-grow: 1;") form(action="javascript:void(0)" style="display: flex; flex-grow: 1;")
input#chatline.form-control(type="text", maxlength="320", style="display: none") input#chatline.form-control.panelback(type="text", maxlength="320", style="display: none")
#guestlogin.input-group #guestlogin.input-group
span.input-group-addon Registration Required! span.input-group-addon Registration Required!
//input#guestname.form-control(type="text", placeholder="Name") //input#guestname.form-control(type="text", placeholder="Name")
button#chatsend.btn.btn-sm.btn-default Send button#chatsend.btn.btn-sm.btn-default.panelback Send
//#videocontrols.btn-group.pull-right //#videocontrols.btn-group.pull-right
//button#fullscreenbtn.btn.btn-sm.btn-default(title="Make the video player fullscreen")This makes no sense, all supported players already have a full screen button. Not a fan of the placement of this anywho //button#fullscreenbtn.btn.btn-sm.btn-default(title="Make the video player fullscreen")This makes no sense, all supported players already have a full screen button. Not a fan of the placement of this anywho
@ -123,9 +124,9 @@ html(lang="en")
//#leftcontrols.col-lg-5.col-md-5 //#leftcontrols.col-lg-5.col-md-5
//button#newpollbtn.btn.btn-sm.btn-default New Poll //button#newpollbtn.btn.btn-sm.btn-default New Poll
#playlistrow.row #playlistrow.row
#rightpane #rightpane.panelback
#rightpane-inner.row #rightpane-inner.row
#rightcontrols #rightcontrols.panelback
#plcontrol.btn-group #plcontrol.btn-group
button#showmediaurl.btn.btn-sm.btn-default(title="Add video from URL", data-toggle="collapse", data-target="#addfromurl") button#showmediaurl.btn.btn-sm.btn-default(title="Add video from URL", data-toggle="collapse", data-target="#addfromurl")
span.glyphicon.glyphicon-plus span.glyphicon.glyphicon-plus

View file

@ -39,7 +39,7 @@ block content
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
.col-lg-9.col-md-9 .channel-list
h3 Public Channels h3 Public Channels
table.table.table-bordered.table-striped table.table.table-bordered.table-striped
thead thead

View file

@ -122,3 +122,4 @@ mixin us-mod
+rcheckbox("us-modflair", "Show name color") +rcheckbox("us-modflair", "Show name color")
+rcheckbox("us-shadowchat", "Show shadowmuted messages") +rcheckbox("us-shadowchat", "Show shadowmuted messages")
+rcheckbox("us-show-ip-in-tooltip", "Show IP addresses in profile tooltip") +rcheckbox("us-show-ip-in-tooltip", "Show IP addresses in profile tooltip")
+rcheckbox("us-show-playlist", "Legacy Playlist")

View file

@ -40,21 +40,49 @@ body{
max-width: 100%; max-width: 100%;
overflow-x: hidden; overflow-x: hidden;
} }
#mp-show-ip-in-tooltip{
margin-top: 0.5em;
}
#main, #titles{ #main, #titles{
display: flex; display: flex;
} }
.static-cont{
position: absolute;
width: auto !important;
height: auto !important;
min-width: 100%;
min-height: 100%;
}
.qt{
margin: 0.5em 0;
}
#qt-clearuser{
margin: 0 0.5em;
}
.container-fluid { .container-fluid {
padding-left: 15px; padding-left: 15px;
padding-right: 15px; padding-right: 15px;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
.nmenu{
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
z-index: 1;
}
.nmenu-btn{
flex-grow: 1;
}
#minicontrol{ #minicontrol{
display: none; display: none;
margin: 0 0.5em 0 0.5em; margin: 0 0.5em 0 0.5em;
} }
#vidplay{ #vidplay{
} }
#viddur{ #viddur{
@ -63,7 +91,14 @@ body{
#loginform > .form-group { #loginform > .form-group {
margin-right: 5px; margin-right: 5px;
} }
#npoll-timeout{
width: 4em;
}
#npopt{
display: flex;
height: 1.6em;
margin: 0.5em 0;
}
.center { .center {
text-align: center; text-align: center;
} }
@ -98,7 +133,7 @@ body{
#messagebuffer, #userlist { #messagebuffer, #userlist {
height: 329px; height: 329px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: scroll; overflow-y: auto;
margin-bottom: 0; margin-bottom: 0;
} }
@ -107,7 +142,12 @@ body{
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
} }
.floatcont{
position: absolute;
right: 0;
left: 0;
z-index: 1;
}
.linewrap, .linewrap code { .linewrap, .linewrap code {
white-space: pre-wrap; /* css-3 */ white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
@ -420,7 +460,8 @@ label[for="emotealphabox"]{
font-family: Monospace; font-family: Monospace;
} }
.fpcont{ .fpcont{
overflow: scroll; overflow-y: auto;
overflow-x: hidden;
} }
#optedit, #permedit, #filteredit, #motdedit, #cssedit, #jsedit, #optedit, #permedit, #filteredit, #motdedit, #cssedit, #jsedit,
#banlist, #loginhistory, #channelranks, #chanlog { #banlist, #loginhistory, #channelranks, #chanlog {

View file

@ -88,7 +88,13 @@ sub,sup{
font-size:75%; font-size:75%;
line-height:0; line-height:0;
position:relative; position:relative;
vertical-align:baseline vertical-align:baseline;
}
.btn.btn-sm.btn-default.nmenu-btn.nmenu-border{
border-left: 1px #949494 solid;
}
.nmenu{
border-top: 1px #949494 solid;
} }
.label-admin, .label.label-admin{ .label-admin, .label.label-admin{
background-color: #cc0000; background-color: #cc0000;
@ -5492,11 +5498,17 @@ a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{
text-decoration: none; text-decoration: none;
} }
#pollopenbtn, #prefopenbtn, #emoteopenbtn, #chatsend, #motdwrap, #chatline, #rightcontrols, #chatheader, #userlist, #messagebuffer, #videowrap-header, .embed-responsive, #rightpane, #mainrow{ .panelback, .embed-responsive{
background-color: #111111C0; background-color: #111111C0;
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
} }
.nmenu-btn{
background-color: #00000000;
backdrop-filter: blur(12px);
}
#fpaneldiv{ #fpaneldiv{
border: 1px #949494 solid; border: 1px #949494 solid;
background-color: #1119; background-color: #1119;
@ -5513,6 +5525,15 @@ a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover{
background-color: #111111C0; background-color: #111111C0;
padding: 10px; padding: 10px;
border: 1px solid #949494; border: 1px solid #949494;
position:absolute;
left: 50%;
right 50%;
transform: translate(-50%);
top: 10%;
width: 40%;
}
.npoll-opt{
width: 50%;
} }
#chatwrap, #videowrap{ #chatwrap, #videowrap{
padding-right: 0px; padding-right: 0px;

View file

@ -222,7 +222,9 @@ Callbacks = {
$("<p/>").appendTo(div) $("<p/>").appendTo(div)
.html("Go watch one of the channels that actually exists <a href='/'>here</a>."); .html("Go watch one of the channels that actually exists <a href='/'>here</a>.");
$("#ytapiplayer").append('<embed type="text/html" src="https://vid.puffyan.us/embed/HS-xJLNROqE?Autoplay=1&loop=1">')//KSSSSSSSSSSSSSSSSSSSSSSSH $("#ytapiplayer").removeClass("embed-responsive-item").addClass("static-cont");
$("#ytapiplayer").append('<video src="' + location.origin +'/vid/static.webm" autoplay loop class="static-cont">');//KSSSSSSSSSSSSSSSSSSSSSSSH
handleWindowResize();
}, },
setMotd: function(motd) { setMotd: function(motd) {

View file

@ -181,6 +181,7 @@ var USEROPTS = {
chat_tab_method : getOrDefault("chat_tab_method", "Cycle options"), chat_tab_method : getOrDefault("chat_tab_method", "Cycle options"),
notifications : getOrDefault("notifications", "never"), notifications : getOrDefault("notifications", "never"),
show_ip_in_tooltip : getOrDefault("show_ip_in_tooltip", true), show_ip_in_tooltip : getOrDefault("show_ip_in_tooltip", true),
show_playlist : getOrDefault("show_playlist", false),
show_orientation : getOrDefault("show_orientation", "true") show_orientation : getOrDefault("show_orientation", "true")
}; };

View file

@ -20,6 +20,9 @@ CURRENTFPANEL = null;
//---Global Functions--- //---Global Functions---
function closeFPanel(cb){//close and null out fpanel, cb function to call when panel is closed function closeFPanel(cb){//close and null out fpanel, cb function to call when panel is closed
$("#fpaneldiv").hide("slide", 250,function(){ $("#fpaneldiv").hide("slide", 250,function(){
if(typeof CURRENTFPANEL.ccall === 'function'){
CURRENTFPANEL.ccall();
}
$("#fpcontdiv").empty(); $("#fpcontdiv").empty();
$("#fptitle").html("null Panel"); $("#fptitle").html("null Panel");
$("#closefpanel").prop("title", "Close null panel."); $("#closefpanel").prop("title", "Close null panel.");
@ -49,14 +52,19 @@ function panelbtn(panel){
} }
//---base panel--- //---base panel---
function fpmenu(title, elm, data, ocall){//fpmenu constructor function fpmenu(title, elm, data, ocall, ccall){//fpmenu constructor
this.title = title;//title of menu this.title = title;//title of menu
this.elm = elm;//elements to insert (good for simple menus) this.elm = elm;//elements to insert (good for simple menus)
this.data = data;//menu data (not used for all 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) this.ocall = ocall;//function to call upon menu opening (used for more advanced menus)
this.ccall = ccall;//function to call upon menu closing
} }
fpmenu.prototype.popMenu = function(idata){//POP goes the weasal! fpmenu.prototype.popMenu = function(idata){//POP goes the weasal!
if(CURRENTFPANEL != null)
if(typeof CURRENTFPANEL.ccall === 'function'){
CURRENTFPANEL.ccall();
}
this.data = idata//set data this.data = idata//set data
$("#fpcontdiv").empty();//empty content div $("#fpcontdiv").empty();//empty content div
$("#fptitle").html(this.title + " Panel");//set panel tittle $("#fptitle").html(this.title + " Panel");//set panel tittle
@ -66,6 +74,34 @@ fpmenu.prototype.popMenu = function(idata){//POP goes the weasal!
CURRENTFPANEL = this; CURRENTFPANEL = this;
$("#fpaneldiv").show("slide", 250, function() {sizeFPDiv()});//show panel and correct size once open $("#fpaneldiv").show("slide", 250, function() {sizeFPDiv()});//show panel and correct size once open
} }
//---base nested menu bar---
function nmenu(title,p,menus,elm){//nested menu constructor(title(defaults to formatted parent title), parent, menu object array,append element(defaults to #fpcontdiv)
this.title = (title == null ? p.title.toLowerCase().replace(' ','-') + "-nested" : title);
this.parent = p;
this.menus = menus;
this.elm = (elm == null ? $("#fpcontdiv") : elm);
}
nmenu.prototype.popMenu = function(){//instantiate nested menu, to be thrown at end of ocall
melm = $("<div>").attr("id",this.title).addClass("nmenu");//create nmenu div
par = this.parent;
this.elm.append(melm.append(
$("<button>").addClass("btn btn-sm btn-default nmenu-btn panelback").attr("id",this.parent.title.toLowerCase().replace(' ','-')+"-nested-btn").html(this.parent.title).click(function(ev){
if(CURRENTFPANEL !== par){
par.popMenu();
}
})
));
this.menus.map(function(menu){//for every menu in menus array
melm.append(
$("<button>").addClass("btn btn-sm btn-default nmenu-btn nmenu-border panelback").attr("id",menu.title.toLowerCase().replace(' ','-')+"-nested-btn").html(menu.title).click(function(){
if(CURRENTFPANEL !== menu){
menu.popMenu();
}
})
);
});
}
//---fpanel poll--- //---fpanel poll---
var fpoll = new fpmenu("Poll");//create new panel fpoll var fpoll = new fpmenu("Poll");//create new panel fpoll
@ -330,3 +366,243 @@ fpset.loadSettings = function(){
$("#qs-timestamp-second").prop("checked", USEROPTS.show_seconds); $("#qs-timestamp-second").prop("checked", USEROPTS.show_seconds);
} }
//---admin/mod panel---
var fpmod = new fpmenu("Mod");//create new panel fpmod
fpmod.elm = [//fpmod element array
]
fpmod.ocall = function(){
//---Local Functions---
//---Poll Creation---
function addOpt(){
i = $("#opts").children().length;
$("#opts").append(
$("<input>").addClass("npoll-opt qs-form").prop("type","text").attr("placeholder","Option " + i)
);
}
function rmOpt(){
if($("#opts").children().length > 2){
$("#opts").children()[$("#opts").children().length - 1].remove();
}
}
//Mod Message
function modMsg(){
var names = [];
var msg = $("#qt-modmsg").val().toString();
$("#userlist").children().map(function(i, usr){
cn = usr.children[1].className;
if((cn === "userlist_siteadmin" || cn === "userlist_owner" || cn === "userlist_op") && usr.children[1].innerHTML !== CLIENT.name){//for all mods
var meta = {};//sendem msg
if (msg.trim() === "") {
return;
}
if (USEROPTS.modhat && CLIENT.rank >= Rank.Moderator) {
meta.modflair = CLIENT.rank;
}
if (CLIENT.rank >= 2 && msg.indexOf("/m ") === 0) {
meta.modflair = CLIENT.rank;
msg = msg.substring(3);
}
socket.emit("pm", {
to: usr.children[1].innerHTML,
msg: msg,
meta: meta
});
}
});
$("#qt-modmsg").val("");
}
//---Main Append---
$("#fpcontdiv").append(//main append
$("<h4>").html("Poll Creation"),
$("<form>").append(
$("<input>").prop("id","npoll-title").prop("type","text").addClass("qs-form").attr("placeholder","Poll Title"),
$("<input>").prop("id","npoll-timeout").prop("type","text").addClass("qs-form").attr("placeholder","Timer"),
$("<button/>").addClass("btn btn-primary btn-ln").text("Create Poll").prop("type","button").click(function(){
var menu = $("#fpcontdiv");
var title = $("#npoll-title");
var timeout = $("#npoll-timeout");
var hidden = $("#npoll-hide-result");
var retainVotes = $("#npoll-keep-vote");
var t = timeout.val().trim();
if (t) {
try {
t = parseTimeout(t);
} catch (e) {
if (timeoutError) {
timeoutError.remove();
}
timeoutError = $("<p/>").addClass("text-danger").text(e.message);
timeoutError.insertAfter(timeout);
timeout.focus();
return;
}
} else {
t = undefined;
}
var opts = [];
menu.find(".npoll-opt").each(function() {
if($(this).val() != "")
opts.push($(this).val());
});
socket.emit("newPoll", {
title: title.val(),
opts: opts,
obscured: hidden.prop("checked"),
retainVotes: retainVotes.prop("checked"),
timeout: t
}, function ack(result) {
if (result.error) {
modalAlert({
title: 'Error creating poll',
textContent: result.error.message
});
}
});
}),
),
$("<form>").append(
$("<label>").prop("for","npoll-hide-result").html("Hide result until poll closes: "),
$("<input>").prop("id","npoll-hide-result").prop("type","checkbox").addClass("qs-form")
),
$("<form>").append(
$("<label>").prop("for","npoll-keep-vote").html("Keep user's vote after disconnect: "),
$("<input>").prop("id","npoll-keep-vote").prop("type","checkbox").addClass("qs-form")
),
$("<span>").append(
$("<button/>").addClass("btn btn-primary btn-ln").text("-").prop("type","button").click(rmOpt),
$("<p>").html(" Poll Opts "),
$("<button/>").addClass("btn btn-primary btn-ln").text("+").prop("type","button").click(addOpt)
).attr("id","npopt"),
$("<form>").attr("id", "opts"),
//---Quick Tools---
$("<h4>").html("Quick Tools"),
$("<form>").addClass("qt").append(
$("<button/>").addClass("btn btn-primary btn-ln").attr("id","qt-announcebtn").text("!announce").prop("type","button").click(function(){
chatsmack("!announce " + $("#qt-announce").val());
}),
$("<input>").prop("id","qt-announce").prop("type","text").addClass("qs-form").attr("placeholder","Announce text.").keydown(function(ev){
if(ev.keyCode==13){
chatsmack("!announce " + $("#qt-announce").val());
return false;
}
})
),
$("<form>").addClass("qt").append(
$("<button/>").addClass("btn btn-primary btn-ln").attr("id","qt-clearbtn").text("!clear").prop("type","button").click(function(){
chatsmack("!clear " + $("#qt-clearuser").val());
}),
$("<select>").prop("id","qt-clearuser").addClass("qs-form").append($('<option value=""></option>'))
),
$("<form>").addClass("qt").append(
$("<input>").prop("id","qt-modmsg").prop("type","text").addClass("qs-form").attr("placeholder","Mod Message").keydown(function(ev){
if(ev.keyCode==13){
modMsg();
return false;
}
}),
$("<button/>").addClass("btn btn-primary btn-ln").text("Send Mod Msg").prop("type","button").click(modMsg)
),
//---Preferences---
$("<h4>").html("Quick Settings"),
$("<span>").addClass("qt").attr("id","qt-modflair").addClass($("#modflair").attr("class")).html("Modflair").click(modflair),
$("<form>").append(
$("<label>").prop("for","mp-show-ip-in-tooltip").html("Show IP in profile tooltips: "),
$("<input>").prop("id","mp-show-ip-in-tooltip").prop("type","checkbox").addClass("qs-form").prop("checked",USEROPTS.show_ip_in_tooltip).change(function() {
USEROPTS.show_ip_in_tooltip = $("#mp-show-ip-in-tooltip").prop("checked");
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","mp-shadowchat").html("Show Shadowmuted Messages: "),
$("<input>").prop("id","mp-shadowchat").prop("type","checkbox").addClass("qs-form").prop("checked",USEROPTS.show_shadowchat).change(function() {
USEROPTS.show_shadowchat = $("#mp-shadowchat").prop("checked");
processOpts();
}),
),
$("<form>").append(
$("<label>").prop("for","mp-show-playlist").html("Legacy Playlist: "),
$("<input>").prop("id","mp-show-playlist").prop("type","checkbox").addClass("qs-form").prop("checked",USEROPTS.show_playlist).change(function() {
USEROPTS.show_playlist = $("#mp-show-playlist").prop("checked");
processOpts();
}),
),
);
//after-append
//---Poll Creation---
addOpt();
addOpt();
//---Quick Tools---
usrColors[0].map(function(u){
$("#qt-clearuser").append($('<option value="' + u + '">' + u + "</option>"));
});
modNested.popMenu();
}
//---Mod Panel Nested Panels---
//---Playlist---
var fpplaylist = new fpmenu("Playlist");//create new panel fpmod
fpplaylist.elm = [//fpmod element array
]
fpplaylist.ocall = function(){
modNested.popMenu();
if(!USEROPTS.show_playlist){
nesth = $("#mod-nested").outerHeight();
panlh = $("#fpcontdiv").outerHeight();
prow = $("#playlistrow").show().appendTo("#fpcontdiv");
prow.find("#rightcontrols").show().addClass("floatcont").prependTo("#fpcontdiv");
conth = $("#rightcontrols").outerHeight();
$("#rightpane").css("background-color","rgba(0,0,0,0)");
prow.find("#queue").css("max-height", panlh - conth - nesth + "px").css("margin-top",conth + "px").css("margin-bottom", nesth + "px");
}else{
$("<h4>").html("Please disable the Legacy Playlist setting to use this tab.").appendTo("#fpcontdiv");
}
}
fpplaylist.ccall = function(){
if(!USEROPTS.show_playlist){
$("#rightcontrols").hide().removeClass("floatcont").prependTo("#rightpane-inner");
$("#playlistrow").hide().appendTo($(".container")[0]);
$("#queue").css("max-height","500px").css("margin-top","0px").css("margin-bottom","0px");
$("#rightpane").css("background-color","");
}
}
//---Autobump---
var fpbump = new fpmenu("Auto Bump");//create new panel fpmod
fpbump.elm = [//fpmod element array
]
fpbump.ocall = function(){
modNested.popMenu();
}
//---Tokebot---
var fptoke = new fpmenu("Tokebot");//create new panel fpmod
fptoke.elm = [//fpmod element array
]
fptoke.ocall = function(){
modNested.popMenu();
}
//---Mod Panel Nested Menu---
modNested = new nmenu(null,fpmod,[fpplaylist,fpbump,fptoke]);

View file

@ -151,29 +151,38 @@ $("#blindchat").click(function() {
blindChat(); blindChat();
}); });
$("#modflair").click(function () { $("#modflair").click(modflair);
function modflair(){
var m = $("#modflair"); var m = $("#modflair");
var q = $("#qt-modflair");
if (m.hasClass("label-success")) { if (m.hasClass("label-success")) {
USEROPTS.modhat = false; USEROPTS.modhat = false;
m.removeClass("label-success"); m.removeClass("label-success");
q.removeClass("label-success");
if (SUPERADMIN) { if (SUPERADMIN) {
USEROPTS.adminhat = true; USEROPTS.adminhat = true;
m.addClass("label-admin"); m.addClass("label-admin");
q.addClass("label-admin");
} else { } else {
m.addClass("label-default"); m.addClass("label-default");
q.addClass("label-default");
} }
} else if (m.hasClass("label-admin")) { } else if (m.hasClass("label-admin")) {
USEROPTS.adminhat = false; USEROPTS.adminhat = false;
m.removeClass("label-admin") m.removeClass("label-admin")
.addClass("label-default"); .addClass("label-default");
q.removeClass("label-admin")
.addClass("label-default");
} else { } else {
USEROPTS.modhat = true; USEROPTS.modhat = true;
m.removeClass("label-default") m.removeClass("label-default")
.addClass("label-success"); .addClass("label-success");
q.removeClass("label-default")
.addClass("label-success");
} }
$("#us-modflair").prop("checked", USEROPTS.modhat); $("#us-modflair").prop("checked", USEROPTS.modhat);
setOpt('modhat', USEROPTS.modhat); setOpt('modhat', USEROPTS.modhat);
}); }
$("#usercount").mouseenter(function (ev) { $("#usercount").mouseenter(function (ev) {
var breakdown = calcUserBreakdown(); var breakdown = calcUserBreakdown();
@ -527,6 +536,8 @@ function setDur(){
/* playlist controls */ /* playlist controls */
$("#queue").sortable({ $("#queue").sortable({
scroll: true,
containment: "parent",
start: function(ev, ui) { start: function(ev, ui) {
PL_FROM = ui.item.data("uid"); PL_FROM = ui.item.data("uid");
}, },

View file

@ -520,7 +520,7 @@ function scrollQueue() {
li = $(li); li = $(li);
$("#queue").scrollTop(0); $("#queue").scrollTop(0);
var scroll = li.position().top - $("#queue").position().top; var scroll = li.position().top - $("#queue").position().top;
$("#queue").scrollTop(scroll); $("#queue").scrollTop(scroll - (!USEROPTS.show_playlist ? $("#rightcontrols").outerHeight() + 1 : 0));
} }
function makeQueueEntry(item, addbtns) { function makeQueueEntry(item, addbtns) {
@ -731,6 +731,7 @@ function showUserOptions() {
$("#us-modflair").prop("checked", USEROPTS.modhat); $("#us-modflair").prop("checked", USEROPTS.modhat);
$("#us-shadowchat").prop("checked", USEROPTS.show_shadowchat); $("#us-shadowchat").prop("checked", USEROPTS.show_shadowchat);
$("#us-show-ip-in-tooltip").prop("checked", USEROPTS.show_ip_in_tooltip); $("#us-show-ip-in-tooltip").prop("checked", USEROPTS.show_ip_in_tooltip);
$("#us-show-playlist").prop("checked", USEROPTS.show_playlist);
formatScriptAccessPrefs(); formatScriptAccessPrefs();
@ -744,6 +745,7 @@ function saveUserOptions() {
USEROPTS.ignore_channelcss = $("#us-no-channelcss").prop("checked"); USEROPTS.ignore_channelcss = $("#us-no-channelcss").prop("checked");
USEROPTS.ignore_channeljs = $("#us-no-channeljs").prop("checked"); USEROPTS.ignore_channeljs = $("#us-no-channeljs").prop("checked");
USEROPTS.show_ip_in_tooltip = $("#us-show-ip-in-tooltip").prop("checked"); USEROPTS.show_ip_in_tooltip = $("#us-show-ip-in-tooltip").prop("checked");
USEROPTS.show_playlist = $("#us-show-playlist").prop("checked");
USEROPTS.synch = $("#us-synch").prop("checked"); USEROPTS.synch = $("#us-synch").prop("checked");
USEROPTS.sync_accuracy = parseFloat($("#us-synch-accuracy").val()) || 2; USEROPTS.sync_accuracy = parseFloat($("#us-synch-accuracy").val()) || 2;
@ -815,6 +817,16 @@ function applyOpts() {
removeVideo(); removeVideo();
} }
if(hasPermission("playlistadd")){
if(USEROPTS.show_playlist){
$("#showplaylist").click();
}else{
$("#rightcontrols").hide();
$("#playlistrow").hide();
$("#showplaylist").hide();
}
}
$("#chatbtn").remove(); $("#chatbtn").remove();
if(false) { if(false) {
var btn = $("<button/>").addClass("btn btn-default btn-block") var btn = $("<button/>").addClass("btn btn-default btn-block")
@ -1085,6 +1097,7 @@ function handlePermissionChange() {
setVisible("#showchansettings", CLIENT.rank >= 2); setVisible("#showchansettings", CLIENT.rank >= 2);
setVisible("#playlistmanagerwrap", CLIENT.rank >= 1); setVisible("#playlistmanagerwrap", CLIENT.rank >= 1);
setVisible("#modflair", CLIENT.rank >= 2); setVisible("#modflair", CLIENT.rank >= 2);
setVisible("#modopenbtn", CLIENT.rank >= 2);
setVisible("#guestlogin", CLIENT.rank < 0); setVisible("#guestlogin", CLIENT.rank < 0);
setVisible("#chatline", CLIENT.rank >= 0); setVisible("#chatline", CLIENT.rank >= 0);
setVisible("#queue", hasPermission("seeplaylist")); setVisible("#queue", hasPermission("seeplaylist"));
@ -1128,6 +1141,11 @@ function handlePermissionChange() {
} }
} }
if(CLIENT.rank > 2){
$("#modopenbtn").html("ADMN").attr("title","Admin Panel");
fpmod.title = "Admin";
}
if(hasPermission("playlistmove")) { if(hasPermission("playlistmove")) {
$("#queue").sortable("enable"); $("#queue").sortable("enable");
$("#queue").addClass("queue_sortable"); $("#queue").addClass("queue_sortable");
@ -1180,6 +1198,13 @@ function handlePermissionChange() {
$("#chatline").attr("placeholder", ""); $("#chatline").attr("placeholder", "");
} }
rebuildPlaylist(); rebuildPlaylist();
if(!USEROPTS.show_playlist && $("#playlistrow").parent()[0].className == "container"){
$("#hideplaylist").click();
$("#rightcontrols").hide();
$("#playlistrow").hide();
$("#showplaylist").hide();
}
} }
function fixWeirdButtonAlignmentIssue() { function fixWeirdButtonAlignmentIssue() {
@ -1831,6 +1856,7 @@ function handleWindowResize() {
($("#motdwrap").is(":visible") ? $("#motdwrap").outerHeight() : 0) - ($("#motdwrap").is(":visible") ? $("#motdwrap").outerHeight() : 0) -
($("#footer").is(":visible") ? $("#footer").outerHeight() : 0) - ($("#footer").is(":visible") ? $("#footer").outerHeight() : 0) -
($(".navbar").is(":visible") ? $(".navbar").outerHeight() : 0) - ($(".navbar").is(":visible") ? $(".navbar").outerHeight() : 0) -
($("#announcements").is(":visible") ? $("#announcements").outerHeight() : 0) -
$("#chatheader").outerHeight() - 1; $("#chatheader").outerHeight() - 1;
var h = rawh - $("#chatline").outerHeight(); var h = rawh - $("#chatline").outerHeight();

BIN
www/vid/static.webm Normal file

Binary file not shown.