mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
VChat Improvements
Hopefully, anyway. - Arbitrary font size setting - Line height setting - Multiple crush settings - Rewrote how tabs work hopefully for performance - Hidden messages are actually put elsewhere - Attempts to correct chat backlog restore on rejoin
This commit is contained in:
@@ -31,6 +31,11 @@ body.inverted {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inputbox {
|
||||
width: 5em !important;
|
||||
padding: 0.1em !important;
|
||||
}
|
||||
|
||||
.icon-left-open-outline:hover, .icon-right-open-outline:hover, .icon-cancel-circled-outline:hover {
|
||||
color: red;
|
||||
}
|
||||
@@ -46,25 +51,6 @@ body.inverted {
|
||||
}
|
||||
}
|
||||
|
||||
/* The chat message display classes */
|
||||
#messagebox div { display: none; } /* Hide messages by default */
|
||||
#messagebox.vc_showall div { display: block; } /* Unless we have vc_showall */
|
||||
|
||||
#messagebox.vc_localchat .vc_localchat { display: block; }
|
||||
#messagebox.vc_radio .vc_radio { display: block; }
|
||||
#messagebox.vc_warnings .vc_warnings { display: block; }
|
||||
#messagebox.vc_info .vc_info { display: block; }
|
||||
#messagebox.vc_deadchat .vc_deadchat { display: block; }
|
||||
#messagebox.vc_globalooc .vc_globalooc { display: block; }
|
||||
#messagebox.vc_looc .vc_looc { display: block; }
|
||||
#messagebox.vc_adminpm .vc_adminpm { display: block; }
|
||||
#messagebox.vc_adminchat .vc_adminchat { display: block; }
|
||||
#messagebox.vc_modchat .vc_modchat { display: block; }
|
||||
#messagebox.vc_eventchat .vc_eventchat { display: block; }
|
||||
#messagebox.vc_system .vc_system { display: block; }
|
||||
#messagebox.vc_nif .vc_nif { display: block; } /* VOREStation Add */
|
||||
|
||||
|
||||
/* SS13 Styles */
|
||||
#messagebox {font-family: Verdana, sans-serif;}
|
||||
|
||||
@@ -188,7 +174,7 @@ h1.alert, h2.alert {color: #000000;}
|
||||
img.icon {vertical-align: middle; max-height: 1em;}
|
||||
img.icon.bigicon {max-height: 32px;}
|
||||
|
||||
/* Zoom levels */
|
||||
/* Zoom levels - Replaced with arbitrary font sizes
|
||||
.zoom_normal {
|
||||
font-size: 0.9em;
|
||||
line-height: 1.35;
|
||||
@@ -201,6 +187,7 @@ img.icon.bigicon {max-height: 32px;}
|
||||
font-size: 0.8em;
|
||||
line-height: 1.2;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Debug Logs */
|
||||
.debug_error {color:#FF0000; font-weight:bold}
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
<p>VChat is still loading. If you see this for a very long time, try the OOC 'Reload VChat' verb, or reconnecting.</p>
|
||||
<p>Sometimes if you're still caching resources, it will take longer than usual.</p>
|
||||
</div>
|
||||
<div id="app" @mouseup="on_mouseup" style="display: none;">
|
||||
<div id="app" @mouseup="on_mouseup" style="display: none;" :class="{ inverted: inverted }">
|
||||
|
||||
<!-- Top menu -->
|
||||
<div id="topmenu" class="ui top fixed menu" :class="{ inverted: inverted }">
|
||||
<div v-for="(tab,index) in tabs" class="item" :class="{ active: tab.active, inverted: inverted }" @click="switchtab(tab)" @click.ctrl="editmode">
|
||||
<div v-for="(tab,index) in tabs" class="item" :class="{ active: tab.active }" @click="switchtab(tab)" @click.ctrl="editmode">
|
||||
<i v-show="editing && !tab.immutable && index >= 2" class="icon-left-open-outline" @click.stop.prevent="movetab(tab,-1)" title="Move tab left"></i>
|
||||
{{tab.name}}
|
||||
<i v-show="editing && !tab.immutable" class="icon-cancel-circled-outline" @click.stop.prevent="deltab(tab)" title="Delete tab"></i>
|
||||
@@ -34,11 +34,11 @@
|
||||
</div>
|
||||
|
||||
<div class="right menu">
|
||||
<div class="item" :class="{ inverted: inverted }" @click="newtab" title="New Tab"><i class="icon-folder-add"></i></div>
|
||||
<div class="item" :class="{ inverted: inverted }" @click="pause" title="Pause Autoscroll">
|
||||
<div class="item" @click="newtab" title="New Tab"><i class="icon-folder-add"></i></div>
|
||||
<div class="item" @click="pause" title="Pause Autoscroll">
|
||||
<i class="icon-pause-outline" :class="{ blinkwarn: paused }"></i>
|
||||
</div>
|
||||
<div class="item" :class="{ inverted: inverted }" @click="editmode" title="Edit Mode">
|
||||
<div class="item" @click="editmode" title="Edit Mode">
|
||||
<i class="icon-cog-outline" :class="{ blinkwarn: editing }"></i>
|
||||
</div>
|
||||
<div class="item"><span class="ui circular label" title="VChat Latency (Not exactly network latency)" :class="ping_classes">{{latency}}ms</span></div>
|
||||
@@ -49,7 +49,7 @@
|
||||
<!-- Editor box -->
|
||||
<div id="contentbox">
|
||||
<div v-show="editing" id="editbox" class="ui segment" :class="{ inverted: inverted }">
|
||||
<div class="ui internally celled grid">
|
||||
<div class="ui internally celled grid" :class="{ inverted: inverted }">
|
||||
<div class="row">
|
||||
<div class="sixteen wide column">
|
||||
<div class="ui center aligned header" :class="{ inverted: inverted }">
|
||||
@@ -67,9 +67,9 @@
|
||||
<h5>Messages to display:</h5>
|
||||
<div class="ui form">
|
||||
<div class="grouped fields">
|
||||
<div class="field" v-for="type in type_table">
|
||||
<div class="field" v-for="type in type_table" :title="type.tooltip">
|
||||
<div v-show="!type.admin || is_admin" class="ui slider checkbox" :class="{ inverted: inverted, disabled: type.required || active_tab.immutable, checked: type.required || active_tab.immutable }">
|
||||
<input type="checkbox" id="type.becomes" :value="type.becomes" v-model="active_tab.classes" :disabled="type.required || active_tab.immutable" :checked="type.required || active_tab.immutable"><label :for="type.becomes">{{type.pretty}}</label>
|
||||
<input type="checkbox" id="type.becomes" :value="type.becomes" v-model="active_tab.categories" :disabled="type.required || active_tab.immutable" :checked="type.required || active_tab.immutable"><label :for="type.becomes">{{type.pretty}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,6 +78,7 @@
|
||||
</div>
|
||||
<div class="eight wide column">
|
||||
<h3>Global Settings</h3>
|
||||
<p>Clicking anywhere in VChat saves your settings.</p>
|
||||
<div class="ui form" :class="{ inverted: inverted }">
|
||||
<div class="grouped fields">
|
||||
<div class="field">
|
||||
@@ -85,11 +86,6 @@
|
||||
<input type="checkbox" id="darkmode" v-model="inverted"><label for="darkmode">Dark Mode</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui slider checkbox" :class="{ inverted: inverted }">
|
||||
<input type="checkbox" id="combining" v-model="crushing"><label for="combining">Combine Messages</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui slider checkbox" :class="{ inverted: inverted }">
|
||||
<input type="checkbox" id="combining" v-model="animated"><label for="animated">Animate Messages</label>
|
||||
@@ -97,57 +93,82 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline fields">
|
||||
<label>Font Size</label>
|
||||
<div class="field">
|
||||
<label>Combine Messages</label>
|
||||
<div class="field" title="Combine no messages together.">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" id="fssmall" name="fontsize" v-model="fontsize" value="zoom_less">
|
||||
<label for="fssmall">Small</label>
|
||||
<input type="radio" id="cnone" name="crushing" v-model.number="crushing" value="0">
|
||||
<label for="cnone">None</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="field" title="Try to combine the newest and last message.">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" id="fsstd" name="fontsize" v-model="fontsize" value="zoom_normal">
|
||||
<label for="fsstd">Standard</label>
|
||||
<input type="radio" id="cone" name="crushing" v-model.number="crushing" value="1">
|
||||
<label for="cone">One</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="field" title="Try to combine the newest and last 3 messages.">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" id="fslarge" name="fontsize" v-model="fontsize" value="zoom_more">
|
||||
<label for="fslarge">Large</label>
|
||||
<input type="radio" id="cthree" name="crushing" v-model.number="crushing" value="3">
|
||||
<label for="cthree">Three</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline fields">
|
||||
<div class="field">
|
||||
<label># Shown Messages</label>
|
||||
<input :class="{ inverted: inverted }" type="number" name="showingnum" placeholder="200" title="Will affect performance!" v-model.lazy.number="showingnum" required style="width: 5em; padding: 0.1em;">
|
||||
<div class="field" title="Font size (Min 0.2, Max 5, Default 0.9)">
|
||||
<label>Font Scale</label>
|
||||
<input class="inputbox" type="number" name="fontsize" placeholder="0.9" v-model.lazy.number="fontsize" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline fields">
|
||||
<div class="field" title="Line height % (Min 100, Max 200, Default 130)">
|
||||
<label>Line Height %</label>
|
||||
<input class="inputbox" type="number" name="lineheight" placeholder="130" v-model.lazy.number="lineheight" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline fields">
|
||||
<div class="field" title="Hides messages for performance (Min 50, Max 2000, Default 200)">
|
||||
<label># Stored Messages</label>
|
||||
<input class="inputbox" type="number" name="showingnum" placeholder="200" v-model.lazy.number="showingnum" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui button" :class="{ inverted: inverted }" @click="save_chatlog">Export Chatlog</button>
|
||||
<button class="ui button" @click="save_chatlog">Export Chatlog</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Messages box -->
|
||||
<div v-show="!editing" id="messagebox" class="ui segment" :class="active_classes" @click="click_message">
|
||||
<div v-show="messages.length > showingnum" class="vc_system">
|
||||
<span class='notice'>[ {{messages.length - showingnum}} previous messages hidden due to display settings. ]</span>
|
||||
</div>
|
||||
<div v-show="!editing" id="messagebox" class="ui segment" @click="click_message" :class="{ inverted: inverted }" :style="{fontSize: fontsize+'em', lineHeight: lineheight+'%'}">
|
||||
<transition-group name="msgsanim" tag="span" :css="animated">
|
||||
<div v-for="message in shown_messages" :class="[message.category, fontsize]" :key="message.id">
|
||||
<span v-html="message.content"></span>
|
||||
<span v-show="message.repeats > 1" class="ui grey circular label">x{{message.repeats}}</span>
|
||||
</div>
|
||||
<!-- We're filtering -->
|
||||
<template v-if="current_categories.length">
|
||||
<div v-show="unshown_messages > 0" key="hidewarn1"><span class='notice'>[ {{unshown_messages}} previous messages archived for performance. ]</span></div>
|
||||
<div v-for="message in shown_messages" :key="message.id">
|
||||
<span v-html="message.content"></span>
|
||||
<span v-show="message.repeats > 1" class="ui grey circular label">x{{message.repeats}}</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- We're not filtering, messages go directly to dom -->
|
||||
<template v-else>
|
||||
<div v-show="archived_messages.length > 0" key="hidewarn2"><span class='notice'>[ {{archived_messages.length}} previous messages archived for performance. ]</span></div>
|
||||
<div v-for="message in messages" :key="message.id">
|
||||
<span v-html="message.content"></span>
|
||||
<span v-show="message.repeats > 1" class="ui grey circular label">x{{message.repeats}}</span>
|
||||
</div>
|
||||
</template>
|
||||
</transition-group>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--
|
||||
Tab: {{active_tab}}<br>
|
||||
Classes: {{active_classes}}<br>
|
||||
Fontsize: {{fontsize}}<br>
|
||||
<div class="ui segment">
|
||||
active_tab: {{active_tab}}<br>
|
||||
current_categories: {{current_categories}}<br>
|
||||
messages.length: {{messages.length}}<br>
|
||||
archived_messages.length: {{archived_messages.length}}<br>
|
||||
shown_messages.length: {{shown_messages.length}}<br>
|
||||
</div>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
//Options for vchat
|
||||
var vchat_opts = {
|
||||
crush_messages: 3, //How many messages back should we try to combine if crushing is on
|
||||
pingThisOften: 10000, //ms
|
||||
pingDropsAllowed: 2,
|
||||
cookiePrefix: "vst-" //If you're another server, you can change this if you want.
|
||||
cookiePrefix: "vst-", //If you're another server, you can change this if you want.
|
||||
alwaysShow: ["vc_looc", "vc_system"] //Categories to always display on every tab
|
||||
};
|
||||
|
||||
var DARKMODE_COLORS = {
|
||||
@@ -115,10 +115,12 @@ function start_vue() {
|
||||
el: '#app',
|
||||
data: {
|
||||
messages: [], //List o messages from byond
|
||||
shown_messages: [], //Used on filtered tabs, but not "Main" because it has 0len categories list, which bypasses filtering for speed
|
||||
unshown_messages: 0, //How many messages in archive would be shown but aren't
|
||||
archived_messages: [], //Too old to show
|
||||
tabs: [ //Our tabs
|
||||
{name: "Main", classes: ["vc_showall"], immutable: true, active: true}
|
||||
{name: "Main", categories: [], immutable: true, active: true}
|
||||
],
|
||||
always_show: ["vc_looc", "vc_system"], //Classes to always display on every tab
|
||||
unread_messages: {}, //Message categories that haven't been looked at since we got one of them
|
||||
editing: false, //If we're in settings edit mode
|
||||
paused: false, //Autoscrolling
|
||||
@@ -128,17 +130,19 @@ function start_vue() {
|
||||
|
||||
//Settings
|
||||
inverted: false, //Dark mode
|
||||
crushing: true, //Combine similar messages
|
||||
crushing: 3, //Combine similar messages
|
||||
animated: false, //Small CSS animations for new messages
|
||||
fontsize: 0.9, //Font size nudging
|
||||
lineheight: 130,
|
||||
showingnum: 200, //How many messages to show
|
||||
animated: true, //Small CSS animations for new messages
|
||||
fontsize: "zoom_normal", //Font size nudging
|
||||
|
||||
//The table to map game css classes to our vchat classes
|
||||
//The table to map game css classes to our vchat categories
|
||||
type_table: [
|
||||
{
|
||||
matches: ".say, .emote",
|
||||
becomes: "vc_localchat",
|
||||
pretty: "Local Chat",
|
||||
tooltip: "In-character local messages (say, emote, etc)",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -146,6 +150,7 @@ function start_vue() {
|
||||
matches: ".alert, .syndradio, .centradio, .airadio, .entradio, .comradio, .secradio, .engradio, .medradio, .sciradio, .supradio, .srvradio, .expradio, .radio, .deptradio, .newscaster",
|
||||
becomes: "vc_radio",
|
||||
pretty: "Radio Comms",
|
||||
tooltip: "All departments of radio messages",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -153,6 +158,7 @@ function start_vue() {
|
||||
matches: ".notice, .adminnotice, .info, .sinister, .cult",
|
||||
becomes: "vc_info",
|
||||
pretty: "Notices",
|
||||
tooltip: "Non-urgent messages from the game and items",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -160,6 +166,7 @@ function start_vue() {
|
||||
matches: ".critical, .danger, .userdanger, .warning, .italics",
|
||||
becomes: "vc_warnings",
|
||||
pretty: "Warnings",
|
||||
tooltip: "Urgent messages from the game and items",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -167,6 +174,7 @@ function start_vue() {
|
||||
matches: ".deadsay",
|
||||
becomes: "vc_deadchat",
|
||||
pretty: "Deadchat",
|
||||
tooltip: "All of deadchat",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -174,6 +182,7 @@ function start_vue() {
|
||||
matches: ".ooc:not(.looc)",
|
||||
becomes: "vc_globalooc",
|
||||
pretty: "Global OOC",
|
||||
tooltip: "The bluewall of global OOC messages",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -190,6 +199,7 @@ function start_vue() {
|
||||
matches: ".pm",
|
||||
becomes: "vc_adminpm",
|
||||
pretty: "Admin PMs",
|
||||
tooltip: "Messages to/from admins ('adminhelps')",
|
||||
required: false,
|
||||
admin: false
|
||||
},
|
||||
@@ -197,6 +207,7 @@ function start_vue() {
|
||||
matches: ".admin_channel",
|
||||
becomes: "vc_adminchat",
|
||||
pretty: "Admin Chat",
|
||||
tooltip: "ASAY messages",
|
||||
required: false,
|
||||
admin: true
|
||||
},
|
||||
@@ -204,6 +215,7 @@ function start_vue() {
|
||||
matches: ".mod_channel",
|
||||
becomes: "vc_modchat",
|
||||
pretty: "Mod Chat",
|
||||
tooltip: "MSAY messages",
|
||||
required: false,
|
||||
admin: true
|
||||
},
|
||||
@@ -211,6 +223,7 @@ function start_vue() {
|
||||
matches: ".event_channel",
|
||||
becomes: "vc_eventchat",
|
||||
pretty: "Event Chat",
|
||||
tooltip: "ESAY messages",
|
||||
required: false,
|
||||
admin: true
|
||||
},
|
||||
@@ -218,38 +231,18 @@ function start_vue() {
|
||||
matches: ".ooc.looc, .ooc .looc", //Dumb game
|
||||
becomes: "vc_looc",
|
||||
pretty: "Local OOC",
|
||||
tooltip: "Local OOC messages, always enabled",
|
||||
required: true
|
||||
},
|
||||
{
|
||||
matches: ".boldannounce",
|
||||
becomes: "vc_system",
|
||||
pretty: "System Messages",
|
||||
tooltip: "Messages from your client, always enabled",
|
||||
required: true
|
||||
}
|
||||
],
|
||||
},
|
||||
created: function() {
|
||||
/*Dog mode
|
||||
setTimeout(function(){
|
||||
document.body.className += " woof";
|
||||
},5000);
|
||||
*/
|
||||
/* Stress test
|
||||
var varthis = this;
|
||||
setInterval( function() {
|
||||
if(varthis.messages.length > 10000) {
|
||||
return;
|
||||
}
|
||||
var stringymessages = JSON.stringify(varthis.messages);
|
||||
var unstringy = JSON.parse(stringymessages);
|
||||
unstringy.forEach( function(message) {
|
||||
message.id = ++vchat_state.lastId;
|
||||
varthis.messages.push(message);
|
||||
});
|
||||
varthis.internal_message("Now have " + varthis.messages.length + " messages in array.");
|
||||
}, 10000);
|
||||
*/
|
||||
},
|
||||
mounted: function() {
|
||||
//Load our settings
|
||||
this.load_settings();
|
||||
@@ -284,22 +277,50 @@ function start_vue() {
|
||||
animated: function (newSetting) {
|
||||
set_storage("animated",newSetting);
|
||||
},
|
||||
fontsize: function (newSetting) {
|
||||
fontsize: function (newSetting, oldSetting) {
|
||||
if(isNaN(newSetting)) { //Numbers only
|
||||
this.fontsize = oldSetting;
|
||||
return;
|
||||
}
|
||||
if(newSetting < 0.2) {
|
||||
this.fontsize = 0.2;
|
||||
} else if(newSetting > 5) {
|
||||
this.fontsize = 5;
|
||||
}
|
||||
set_storage("fontsize",newSetting);
|
||||
},
|
||||
lineheight: function (newSetting, oldSetting) {
|
||||
if(!isFinite(newSetting)) { //Integers only
|
||||
this.lineheight = oldSetting;
|
||||
return;
|
||||
}
|
||||
if(newSetting < 100) {
|
||||
this.lineheight = 100;
|
||||
} else if(newSetting > 200) {
|
||||
this.lineheight = 200;
|
||||
}
|
||||
set_storage("lineheight",newSetting);
|
||||
},
|
||||
showingnum: function (newSetting, oldSetting) {
|
||||
if(!isFinite(newSetting)) {
|
||||
if(!isFinite(newSetting)) { //Integers only
|
||||
this.showingnum = oldSetting;
|
||||
return;
|
||||
}
|
||||
|
||||
newSetting = Math.floor(newSetting);
|
||||
if(newSetting <= 50) {
|
||||
if(newSetting < 50) {
|
||||
this.showingnum = 50;
|
||||
} else if(newSetting > 2000) {
|
||||
this.showingnum = 2000;
|
||||
}
|
||||
|
||||
set_storage("showingnum",this.showingnum);
|
||||
this.attempt_archive();
|
||||
},
|
||||
current_categories: function(newSetting, oldSetting) {
|
||||
if(newSetting.length) {
|
||||
this.apply_filter(newSetting);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -311,14 +332,6 @@ function start_vue() {
|
||||
});
|
||||
return tab;
|
||||
},
|
||||
//Which classes does the active tab need?
|
||||
active_classes: function() {
|
||||
let classarray = this.active_tab.classes;
|
||||
let classtext = classarray.toString(); //Convert to a string
|
||||
let classproper = classtext.replace(/,/g," ");
|
||||
if(this.inverted) classproper += " inverted";
|
||||
return classproper; //Swap commas for spaces
|
||||
},
|
||||
//What color does the latency pip get?
|
||||
ping_classes: function() {
|
||||
if(this.latency === 0) { return "grey"; }
|
||||
@@ -327,11 +340,11 @@ function start_vue() {
|
||||
else if(this.latency <= 400) { return "yellow"; }
|
||||
else { return "red"; }
|
||||
},
|
||||
shown_messages: function() {
|
||||
if(this.messages.length <= this.showingnum) {
|
||||
return this.messages;
|
||||
current_categories: function() {
|
||||
if(this.active_tab == this.tabs[0]) {
|
||||
return []; //Everything, no filtering, special case for speed.
|
||||
} else {
|
||||
return this.messages.slice(-1*this.showingnum);
|
||||
return this.active_tab.categories.concat(vchat_opts.alwaysShow);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -339,10 +352,14 @@ function start_vue() {
|
||||
//Load the chat settings
|
||||
load_settings: function() {
|
||||
this.inverted = get_storage("darkmode", false);
|
||||
this.crushing = get_storage("crushing", true);
|
||||
this.crushing = get_storage("crushing", 3);
|
||||
this.animated = get_storage("animated", false);
|
||||
this.fontsize = get_storage("fontsize", 0.9);
|
||||
this.lineheight = get_storage("lineheight", 130);
|
||||
this.showingnum = get_storage("showingnum", 200);
|
||||
this.animated = get_storage("animated", true);
|
||||
this.fontsize = get_storage("fontsize", 'zoom_normal');
|
||||
|
||||
if(isNaN(this.crushing)){this.crushing = 3;} //This used to be a bool (03-02-2020)
|
||||
if(isNaN(this.fontsize)){this.fontsize = 0.9;} //This used to be a string (03-02-2020)
|
||||
},
|
||||
//Change to another tab
|
||||
switchtab: function(tab) {
|
||||
@@ -350,9 +367,11 @@ function start_vue() {
|
||||
this.active_tab.active = false;
|
||||
tab.active = true;
|
||||
|
||||
tab.classes.forEach( function(cls) {
|
||||
tab.categories.forEach( function(cls) {
|
||||
this.unread_messages[cls] = 0;
|
||||
}, this);
|
||||
|
||||
this.apply_filter(this.current_categories);
|
||||
},
|
||||
//Toggle edit mode
|
||||
editmode: function() {
|
||||
@@ -366,7 +385,7 @@ function start_vue() {
|
||||
newtab: function() {
|
||||
this.tabs.push({
|
||||
name: "New Tab",
|
||||
classes: this.always_show.slice(),
|
||||
categories: [],
|
||||
immutable: false,
|
||||
active: false
|
||||
});
|
||||
@@ -406,17 +425,17 @@ function start_vue() {
|
||||
tab_unread_count: function(tab) {
|
||||
var unreads = 0;
|
||||
var thisum = this.unread_messages;
|
||||
tab.classes.find( function(cls){
|
||||
tab.categories.find( function(cls){
|
||||
if(thisum[cls]) {
|
||||
unreads += thisum[cls];
|
||||
}
|
||||
});
|
||||
return unreads;
|
||||
},
|
||||
tab_unread_classes: function(tab) {
|
||||
tab_unread_categories: function(tab) {
|
||||
var unreads = false;
|
||||
var thisum = this.unread_messages;
|
||||
tab.classes.find( function(cls){
|
||||
tab.categories.find( function(cls){
|
||||
if(thisum[cls]) {
|
||||
unreads = true;
|
||||
return true;
|
||||
@@ -425,6 +444,39 @@ function start_vue() {
|
||||
|
||||
return { red: unreads, grey: !unreads};
|
||||
},
|
||||
attempt_archive: function() {
|
||||
var wiggle = 20; //Wiggle room to prevent hysterisis effects. Slice off 20 at a time.
|
||||
//Pushing out old messages
|
||||
if(this.messages.length > this.showingnum) {//Time to slice off old messages
|
||||
var too_old = this.messages.splice(0,wiggle); //We do a few at a time to avoid doing it too often
|
||||
Array.prototype.push.apply(this.archived_messages, too_old); //ES6 adds spread operator. I'd use it if I could.
|
||||
}/*
|
||||
//Pulling back old messages
|
||||
} else if(this.messages.length < (this.showingnum - wiggle)) { //Sigh, repopulate old messages
|
||||
var too_new = this.archived_messages.splice(this.messages.length - (this.showingnum - wiggle));
|
||||
Array.prototype.shift.apply(this.messages, too_new);
|
||||
}
|
||||
*/
|
||||
},
|
||||
apply_filter: function(cat_array) {
|
||||
//Clean up the array
|
||||
this.shown_messages.splice(0);
|
||||
this.unshown_messages = 0;
|
||||
|
||||
//For each message, try to find it's category in the categories we're showing
|
||||
this.messages.forEach( function(msg){
|
||||
if(cat_array.indexOf(msg.category) > -1) { //Returns the position in the array, and -1 for not found
|
||||
this.shown_messages.push(msg);
|
||||
}
|
||||
}, this);
|
||||
|
||||
//For each message, try to find it's category in the categories we're showing
|
||||
this.archived_messages.forEach( function(msg){
|
||||
if(cat_array.indexOf(msg.category) > -1) { //Returns the position in the array, and -1 for not found
|
||||
this.unshown_messages++;
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
//Push a new message into our array
|
||||
add_message: function(message) {
|
||||
//IE doesn't support the 'class' syntactic sugar so we're left making our own object.
|
||||
@@ -434,18 +486,13 @@ function start_vue() {
|
||||
content: message.message,
|
||||
repeats: 1
|
||||
};
|
||||
|
||||
//Get a category
|
||||
newmessage.category = this.get_category(newmessage.content);
|
||||
if(!this.active_tab.classes.some(function(cls) { return (cls == newmessage.category || cls == "vc_showall"); })) {
|
||||
if (isNaN(this.unread_messages[newmessage.category])) {
|
||||
this.unread_messages[newmessage.category] = 0;
|
||||
}
|
||||
this.unread_messages[newmessage.category] += 1;
|
||||
}
|
||||
|
||||
//Try to crush it with one of the last few
|
||||
if(this.crushing) {
|
||||
let crushwith = this.messages.slice(-(vchat_opts.crush_messages));
|
||||
let crushwith = this.messages.slice(-(this.crushing));
|
||||
for (let i = crushwith.length - 1; i >= 0; i--) {
|
||||
let oldmessage = crushwith[i];
|
||||
if(oldmessage.content == newmessage.content) {
|
||||
@@ -455,8 +502,19 @@ function start_vue() {
|
||||
}
|
||||
}
|
||||
|
||||
//Unread indicator and insertion into current tab shown messages if sensible
|
||||
if(this.current_categories.length && (this.current_categories.indexOf(newmessage.category) < 0)) { //Not in the current categories
|
||||
if (isNaN(this.unread_messages[newmessage.category])) {
|
||||
this.unread_messages[newmessage.category] = 0;
|
||||
}
|
||||
this.unread_messages[newmessage.category] += 1;
|
||||
} else if(this.current_categories.length) { //Is in the current categories
|
||||
this.shown_messages.push(newmessage);
|
||||
}
|
||||
|
||||
//Append to vue's messages
|
||||
newmessage.id = ++vchat_state.lastId;
|
||||
this.attempt_archive();
|
||||
this.messages.push(newmessage);
|
||||
},
|
||||
//Push an internally generated message into our array
|
||||
@@ -518,7 +576,10 @@ function start_vue() {
|
||||
},
|
||||
save_chatlog: function() {
|
||||
var textToSave = "<html><head><style>"+this.ext_styles+"</style></head><body>";
|
||||
this.messages.forEach( function(message) {
|
||||
|
||||
var messagesToSave = this.archived_messages.concat(this.messages);
|
||||
|
||||
messagesToSave.forEach( function(message) {
|
||||
textToSave += message.content;
|
||||
if(message.repeats > 1) {
|
||||
textToSave += "(x"+message.repeats+")";
|
||||
@@ -676,10 +737,14 @@ function get_localstorage(key, deffo) {
|
||||
//localstorage only stores strings.
|
||||
if(value === "null" || value === null) {
|
||||
value = deffo;
|
||||
//Coerce bools back into their native forms
|
||||
} else if(value === "true") {
|
||||
value = true;
|
||||
} else if(value === "false") {
|
||||
value = false;
|
||||
//Coerce numbers back into numerical form
|
||||
} else if(!isNaN(value)) {
|
||||
value = +value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -708,6 +773,8 @@ function get_cookie(key, deffo) {
|
||||
right = true;
|
||||
} else if(right === "false") {
|
||||
right = false;
|
||||
} else if(!isNaN(right)) {
|
||||
right = +right;
|
||||
}
|
||||
cookie_object[left] = right; //Stick into object
|
||||
});
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define BACKLOG_LENGTH 20 MINUTES
|
||||
|
||||
//The 'V' is for 'VORE' but you can pretend it's for Vue.js if you really want.
|
||||
|
||||
//These are sent to the client via browse_rsc() in advance so the HTML can access them.
|
||||
@@ -124,10 +122,14 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
|
||||
//Perform DB shenanigans
|
||||
/datum/chatOutput/proc/load_database()
|
||||
set waitfor = FALSE
|
||||
var/list/results = vchat_get_messages(owner.ckey, world.time - BACKLOG_LENGTH)
|
||||
var/list/results = vchat_get_messages(owner.ckey) //If there's bad performance on reconnects, look no further
|
||||
for(var/list/message in results)
|
||||
var/count = 10
|
||||
to_chat_immediate(owner, message["time"], message["message"])
|
||||
CHECK_TICK
|
||||
count++
|
||||
if(count >= 10)
|
||||
count = 0
|
||||
CHECK_TICK
|
||||
|
||||
//It din work
|
||||
/datum/chatOutput/proc/become_broken()
|
||||
@@ -325,5 +327,3 @@ var/to_chat_src
|
||||
|
||||
var/list/tojson = list("time" = time, "message" = message);
|
||||
target << output(jsEncode(tojson), "htmloutput:putmessage")
|
||||
|
||||
#undef BACKLOG_LENGTH
|
||||
|
||||
@@ -83,8 +83,6 @@ GLOBAL_DATUM(vchatdb, /database)
|
||||
//Byond is so great half the time it doesn't delete the file
|
||||
var/cleanup = "DROP TABLE IF EXISTS messages"
|
||||
vchat_exec_update(cleanup)
|
||||
cleanup = "VACUUM"
|
||||
vchat_exec_update(cleanup)
|
||||
|
||||
//Messages table
|
||||
var/tabledef = "CREATE TABLE messages(\
|
||||
|
||||
Reference in New Issue
Block a user