Rewrite most of the handling and fresh msg detection

Closes #15
Closes #16
This commit is contained in:
chylex 2017-10-27 00:07:57 +02:00
parent e3c6e703ed
commit 8b80bce56b
4 changed files with 111 additions and 56 deletions

View File

@ -1,39 +1,60 @@
var DISCORD = (function(){
var regexMessageRequest = /\/channels\/(\d+)\/messages[^a-z]/;
var lastLoadedMessage = null;
var getFirstMessage = function(){
var props = DISCORD.getReactProps(DOM.fcls("messages"));
var array = props && props.children.find(ele => ele && ele.length);
if (array){
for(let obj of array){
if (obj.props.messages && obj.props.messages.length > 0){
return obj.props.messages[0];
}
}
}
return null;
var getTopMessageViewElement = function(){
let view = DOM.fcls("messages");
return view && view.children.length && view.children[0];
};
var observerTimer = 0, waitingForCleanup = 0;
return {
/*
* Sets up a callback hook to trigger whenever the list of messages is updated.
* Sets up a callback hook to trigger whenever the list of messages is updated. The callback is given a boolean value that is true if there are more messages to load.
*/
setupMessageUpdateCallback: function(callback){
var observerInterval = window.setInterval(function(){
var firstMsg = getFirstMessage();
if (firstMsg === null){
lastLoadedMessage = null;
var onTimerFinished = function(){
let topEle = getTopMessageViewElement();
if (!topEle){
restartTimer(500);
}
else if (lastLoadedMessage === null || (lastLoadedMessage !== null && lastLoadedMessage !== firstMsg.id)){
callback();
else if (!topEle.classList.contains("loading-more")){
let messages = DOM.fcls("messages").children.length;
if (messages < 100){
waitingForCleanup = 0;
}
if (waitingForCleanup > 0){
--waitingForCleanup;
restartTimer(750);
}
else{
if (messages > 300){
waitingForCleanup = 6;
DOM.setTimer(() => {
let view = DOM.fcls("messages");
view.scrollTop = view.scrollHeight/2;
}, 1);
}
callback(topEle.classList.contains("has-more"));
restartTimer(200);
}
}
}, 100);
else{
restartTimer(25);
}
};
window.DHT_ON_UNLOAD.push(() => window.clearInterval(observerInterval));
var restartTimer = function(delay){
observerTimer = DOM.setTimer(onTimerFinished, delay);
};
onTimerFinished();
window.DHT_ON_UNLOAD.push(() => window.clearInterval(observerTimer));
},
/*
@ -115,27 +136,32 @@ var DISCORD = (function(){
Array.prototype.push.apply(messages, obj.props.messages);
}
}
lastLoadedMessage = messages.length === 0 ? null : messages[0].id;
}
return messages;
},
/*
* Returns true if the message column is visible.
* Returns true if the message view is visible.
*/
isInMessageView: (_) => DOM.cls("messages").length > 0,
isInMessageView: () => DOM.cls("messages").length > 0,
/*
* Returns true if there are more messages available.
* Returns true if there are more messages available or if they're still loading.
*/
hasMoreMessages: (_) => DOM.fcls("messages").children[0].classList.contains("has-more"),
hasMoreMessages: function(){
let classes = getTopMessageViewElement().classList;
return classes.contains("has-more") || classes.contains("loading-more");
},
/*
* Forces the message column to scroll all the way up to load older messages.
* Forces the message view to load older messages by scrolling all the way up.
*/
loadOlderMessages: (_) => DOM.fcls("messages").scrollTop = 0,
loadOlderMessages: function(){
let view = DOM.fcls("messages");
view.scrollTop = view.scrollHeight/2;
view.scrollTop = 0;
},
/*
* Selects the next text channel and returns true, otherwise returns false if there are no more channels.

View File

@ -91,6 +91,7 @@ var SAVEFILE = function(parsedObj){
me.tmp.userlookup = {};
me.tmp.channelkeys = new Set();
me.tmp.messagekeys = new Set();
me.tmp.freshmsgs = new Set();
};
SAVEFILE.isValid = function(parsedObj){
@ -184,11 +185,18 @@ SAVEFILE.prototype.convertToMessageObject = function(discordMessage){
return obj;
};
SAVEFILE.prototype.isMessageFresh = function(id){
return this.tmp.freshmsgs.has(id);
};
SAVEFILE.prototype.addMessagesFromDiscord = function(channelId, discordMessageArray){
var hasNewMessages = false;
for(var discordMessage of discordMessageArray){
hasNewMessages |= this.addMessage(channelId, discordMessage.id, this.convertToMessageObject(discordMessage));
if (this.addMessage(channelId, discordMessage.id, this.convertToMessageObject(discordMessage))){
this.tmp.freshmsgs.add(discordMessage.id);
hasNewMessages = true;
}
}
return hasNewMessages;

View File

@ -57,6 +57,14 @@ var STATE = (function(){
triggerStateChanged("tracking", this._isTracking);
};
/*
* Toggles the tracking state.
*/
CLS.prototype.toggleTracking = function(){
this._isTracking = !this._isTracking;
triggerStateChanged("tracking", this._isTracking);
};
/*
* Combines current savefile with the provided one.
*/
@ -99,6 +107,13 @@ var STATE = (function(){
}
};
/*
* Returns true if the message was added during this session.
*/
CLS.prototype.isMessageFresh = function(id){
return this.getSavefile().isMessageFresh(id);
};
/*
* Adds a listener that is called whenever the state changes. The callback is a function that takes subject (generic type) and detail (specific type or data).
*/

View File

@ -14,38 +14,39 @@ window.DHT_ON_UNLOAD = [];
// Execution
DISCORD.setupMessageUpdateCallback(channel => {
if (STATE.isTracking()){
var info = DISCORD.getSelectedChannel();
let ignoreMessageCallback = false;
DISCORD.setupMessageUpdateCallback(hasMoreMessages => {
if (STATE.isTracking() && !ignoreMessageCallback){
let info = DISCORD.getSelectedChannel();
STATE.addDiscordChannel(info.server, info.type, info.id, info.channel);
var hasUpdatedFile = STATE.addDiscordMessages(info.id, DISCORD.getMessages());
let messages = DISCORD.getMessages();
let hasUpdatedFile = STATE.addDiscordMessages(info.id, messages);
if (SETTINGS.autoscroll){
DOM.setTimer(() => {
var action = CONSTANTS.AUTOSCROLL_ACTION_NOTHING;
let action = CONSTANTS.AUTOSCROLL_ACTION_NOTHING;
if (!hasUpdatedFile && !(messages.length && STATE.isMessageFresh(messages[0].id))){
action = SETTINGS.afterSavedMsg;
}
else if (!hasMoreMessages){
action = SETTINGS.afterFirstMsg;
}
if (!hasUpdatedFile){
action = SETTINGS.afterSavedMsg;
}
else if (!DISCORD.hasMoreMessages()){
action = SETTINGS.afterFirstMsg;
}
if ((action === CONSTANTS.AUTOSCROLL_ACTION_SWITCH && !DISCORD.selectNextTextChannel()) || action === CONSTANTS.AUTOSCROLL_ACTION_PAUSE){
STATE.toggleTracking();
}
else{
DISCORD.loadOlderMessages();
}
}, 25);
if ((action === CONSTANTS.AUTOSCROLL_ACTION_SWITCH && !DISCORD.selectNextTextChannel()) || action === CONSTANTS.AUTOSCROLL_ACTION_PAUSE){
STATE.toggleTracking();
}
else{
DISCORD.loadOlderMessages();
}
}
}
});
STATE.onStateChanged((type, enabled) => {
if (type === "tracking" && enabled){
var info = DISCORD.getSelectedChannel();
let info = DISCORD.getSelectedChannel();
if (info){
STATE.addDiscordChannel(info.server, info.type, info.id, info.channel);
@ -57,10 +58,15 @@ STATE.onStateChanged((type, enabled) => {
DISCORD.loadOlderMessages();
}
else{
var action = SETTINGS.afterFirstMsg;
let action = SETTINGS.afterFirstMsg;
if ((action === CONSTANTS.AUTOSCROLL_ACTION_SWITCH && !DISCORD.selectNextTextChannel()) || action === CONSTANTS.AUTOSCROLL_ACTION_PAUSE){
DOM.setTimer(() => STATE.toggleTracking(), 200); // give the user visual feedback after clicking the button before switching off
ignoreMessageCallback = true;
DOM.setTimer(() => {
STATE.toggleTracking();
ignoreMessageCallback = false;
}, 200); // give the user visual feedback after clicking the button before switching off
}
}
}