diff --git a/src/renderer/index.html b/src/renderer/index.html
index 6dd5e42..f3b7210 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -31,12 +31,6 @@
-
-
-
-
@@ -46,6 +40,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/renderer/scr.exec.js b/src/renderer/scr.exec.js
index a8f3738..a2eb858 100644
--- a/src/renderer/scr.exec.js
+++ b/src/renderer/scr.exec.js
@@ -26,14 +26,18 @@ document.addEventListener("DOMContentLoaded", () => {
STATE.setMessagesPerPage(GUI.getOptionMessagesPerPage());
- GUI.onOptionMessagesByUserChanged(() => {
- STATE.setMessagesByUser(GUI.getOptionMessagesByUser());
+ GUI.onOptMessageFilterChanged(filter => {
+ STATE.setActiveFilter(filter);
});
-
+
GUI.onNavigationButtonClicked(action => {
STATE.updateCurrentPage(action);
});
+ STATE.onUsersRefreshed(users => {
+ GUI.updateUserList(users);
+ });
+
STATE.onChannelsRefreshed(channels => {
GUI.updateChannelList(channels, STATE.selectChannel);
});
@@ -43,8 +47,4 @@ document.addEventListener("DOMContentLoaded", () => {
GUI.updateMessageList(messages);
GUI.scrollMessagesToTop();
});
-
- STATE.onUsersRefreshed(users => {
- GUI.updateUserFilter(users);
- });
});
diff --git a/src/renderer/scr.gui.js b/src/renderer/scr.gui.js
index fa4548e..5674c18 100644
--- a/src/renderer/scr.gui.js
+++ b/src/renderer/scr.gui.js
@@ -1,9 +1,22 @@
var GUI = (function(){
var eventOnFileUploaded;
var eventOnOptMessagesPerPageChanged;
- var eventOnOptMessagesByUserChanged;
+ var eventOnOptMessageFilterChanged;
var eventOnNavButtonClicked;
+ var getActiveFilter = function(){
+ var active = DOM.fcls("active", DOM.id("opt-filter-list"));
+
+ return active && active.value !== "" ? {
+ "type": active.getAttribute("data-filter-type"),
+ "value": active.value
+ } : null;
+ };
+
+ var triggerFilterChanged = function(){
+ eventOnOptMessageFilterChanged && eventOnOptMessageFilterChanged(getActiveFilter());
+ };
+
var showModal = function(width, html){
var dialog = DOM.id("dialog");
dialog.innerHTML = html;
@@ -59,6 +72,8 @@ var GUI = (function(){
*/
setup: function(){
var inputUploadedFile = DOM.id("uploaded-file");
+ var inputMessageFilter = DOM.id("opt-messages-filter");
+ var containerFilterList = DOM.id("opt-filter-list");
DOM.id("btn-upload-file").addEventListener("click", () => {
inputUploadedFile.click();
@@ -67,16 +82,31 @@ var GUI = (function(){
inputUploadedFile.addEventListener("change", () => {
if (eventOnFileUploaded && eventOnFileUploaded(inputUploadedFile.files)){
inputUploadedFile.value = null;
+
+ inputMessageFilter.value = "";
+ inputMessageFilter.dispatchEvent(new Event("change"));
}
});
+ inputMessageFilter.value = ""; // required to prevent browsers from remembering old value
+
+ inputMessageFilter.addEventListener("change", () => {
+ DOM.cls("active", containerFilterList).forEach(ele => ele.classList.remove("active"));
+
+ if (inputMessageFilter.value){
+ containerFilterList.querySelector("[data-filter-type='"+inputMessageFilter.value+"']").classList.add("active");
+ }
+
+ triggerFilterChanged();
+ });
+
+ Array.prototype.forEach.call(containerFilterList.children, ele => {
+ ele.addEventListener("change", e => triggerFilterChanged());
+ });
+
DOM.id("opt-messages-per-page").addEventListener("change", () => {
eventOnOptMessagesPerPageChanged && eventOnOptMessagesPerPageChanged();
});
-
- DOM.id("opt-messages-by-user").addEventListener("change", () => {
- eventOnOptMessagesByUserChanged && eventOnOptMessagesByUserChanged();
- });
DOM.tag("button", DOM.fcls("nav")).forEach(button => {
button.disabled = true;
@@ -119,10 +149,10 @@ var GUI = (function(){
},
/*
- * Sets a callback for when the user changes the messages by user option. The callback is not passed any arguments.
+ * Sets a callback for when the user changes the active filter. The callback is passed either null or an object such as { type: , value: }.
*/
- onOptionMessagesByUserChanged: function(callback){
- eventOnOptMessagesByUserChanged = callback;
+ onOptMessageFilterChanged: function(callback){
+ eventOnOptMessageFilterChanged = callback;
},
/*
@@ -142,13 +172,6 @@ var GUI = (function(){
getOptionMessagesPerPage: function(){
return parseInt(DOM.id("opt-messages-per-page").value, 10);
},
-
- /*
- * Returns the user which to filter messages by.
- */
- getOptionMessagesByUser: function(){
- return DOM.id("opt-messages-by-user").value;
- },
/*
* Updates the navigation text and buttons.
@@ -163,9 +186,9 @@ var GUI = (function(){
DOM.id("nav-last").disabled = currentPage === (totalPages || 1);
},
- // ------------
- // Channel list
- // ------------
+ // --------------
+ // Updating lists
+ // --------------
/*
* Updates the channel list and sets up their click events. The callback is triggered whenever a channel is selected, and takes the channel ID as its argument.
@@ -177,7 +200,11 @@ var GUI = (function(){
eleChannels.innerHTML = "";
}
else{
- eleChannels.innerHTML = channels.filter(channel => channel.msgcount > 0).map(channel => DISCORD.getChannelHTML(channel)).join("");
+ if (getActiveFilter() != null){
+ channels = channels.filter(channel => channel.msgcount > 0);
+ }
+
+ eleChannels.innerHTML = channels.map(channel => DISCORD.getChannelHTML(channel)).join("");
Array.prototype.forEach.call(eleChannels.children, ele => {
ele.addEventListener("click", e => {
@@ -206,31 +233,26 @@ var GUI = (function(){
},
/*
- * Updates the select box with all possibly user names.
+ * Updates the user filter list.
*/
- updateUserFilter: function(users){
- var select = DOM.id("opt-messages-by-user");
-
- // Remove all but first option
- for (var i = select.length; i > 0; i--) {
- select.remove(i);
+ updateUserList: function(users){
+ var eleSelect = DOM.id("opt-filter-user");
+
+ while(eleSelect.length > 1){
+ eleSelect.remove(1);
}
-
+
var options = [];
- for (var key in users) {
- // Skip loop if the property is from prototype
- if (!users.hasOwnProperty(key)) continue;
-
+
+ for(var key of Object.keys(users)){
var option = document.createElement("option");
option.value = key;
option.text = users[key].name;
options.push(option);
}
- options.sort((a, b) => {
- return a.text.toLowerCase().localeCompare(b.text.toLowerCase());
- }).forEach(option => {
- select.add(option);
- });
+
+ options.sort((a, b) => a.text.toLocaleLowerCase().localeCompare(b.text.toLocaleLowerCase()));
+ options.forEach(option => eleSelect.add(option));
},
/*
diff --git a/src/renderer/scr.savefile.js b/src/renderer/scr.savefile.js
index e4e85da..9165d0b 100644
--- a/src/renderer/scr.savefile.js
+++ b/src/renderer/scr.savefile.js
@@ -26,6 +26,10 @@ SAVEFILE.prototype.getChannelById = function(channel){
return this.meta.channels[channel] || { "id": channel, "name": channel };
};
+SAVEFILE.prototype.getUsers = function(){
+ return this.meta.users;
+};
+
SAVEFILE.prototype.getUser = function(index){
return this.meta.users[this.meta.userindex[index]] || { "name": "<unknown>" };
};
@@ -34,20 +38,6 @@ SAVEFILE.prototype.getUserById = function(user){
return this.meta.users[user] || { "name": user };
};
-SAVEFILE.prototype.getMessageCount = function(channel){
- return Object.keys(this.getMessages(channel)).length;
-};
-
-SAVEFILE.prototype.getFilteredMessageCount = function(channel, userindex){
- if (userindex === -1) return this.getMessageCount(channel);
-
- var count = 0;
- UTILS.forEachValue(this.getMessages(channel), messageObject => {
- if (messageObject.u === userindex) count++;
- });
- return count;
-};
-
SAVEFILE.prototype.getAllMessages = function(){
var messages = {};
@@ -56,6 +46,8 @@ SAVEFILE.prototype.getAllMessages = function(){
});
return messages;
+SAVEFILE.prototype.getUserIndex = function(user){
+ return this.meta.userindex.indexOf(user);
};
SAVEFILE.prototype.getMessages = function(channel){
diff --git a/src/renderer/scr.state.js b/src/renderer/scr.state.js
index a118135..523fbe3 100644
--- a/src/renderer/scr.state.js
+++ b/src/renderer/scr.state.js
@@ -11,7 +11,7 @@ var STATE = (function(){
var selectedChannel;
var currentPage;
var messagesPerPage;
- var messagesByUser;
+ var filterFunction;
// ----------------------------------
// Channel and message refresh events
@@ -53,10 +53,10 @@ var STATE = (function(){
FILE = file;
MSGS = null;
currentPage = 1;
-
+
+ triggerUsersRefreshed();
triggerChannelsRefreshed();
triggerMessagesRefreshed();
- triggerUsersRefreshed();
};
ROOT.getChannelName = function(channel){
@@ -74,24 +74,34 @@ var STATE = (function(){
// --------------------------
// Channel list and selection
// --------------------------
+
+ var getFilteredMessageKeys = function(channel){
+ var messages = FILE.getMessages(channel);
+ var keys = Object.keys(messages);
+
+ if (filterFunction){
+ keys = keys.filter(key => filterFunction(messages[key]));
+ }
+
+ return keys;
+ };
ROOT.getChannelList = function(){
var channels = FILE.getChannels();
- var userindex = messagesByUser ? FILE.meta.userindex.indexOf(messagesByUser) : -1;
return Object.keys(channels).map(key => ({
"id": key,
"name": channels[key].name,
"server": FILE.getServer(channels[key].server),
- "msgcount": FILE.getFilteredMessageCount(key, userindex)
+ "msgcount": getFilteredMessageKeys(key).length
}));
};
ROOT.selectChannel = function(channel){
currentPage = 1;
selectedChannel = channel;
- MSGS = Object.keys(FILE.getMessages(channel)).sort(PROCESSOR.SORTER.oldestToNewest);
-
+
+ MSGS = getFilteredMessageKeys(channel).sort(PROCESSOR.SORTER.oldestToNewest);
triggerMessagesRefreshed();
};
@@ -102,19 +112,6 @@ var STATE = (function(){
// ------------
// Message list
// ------------
- ROOT.getFilteredMessageList = function(){
- if (!messagesByUser) {
- return MSGS;
- }
-
- var pos = FILE.meta.userindex.indexOf(messagesByUser);
- var messages = FILE.getMessages(selectedChannel);
- return MSGS.filter(key => {
- var message = messages[key];
- return message.u == pos;
- });
- };
-
ROOT.getMessageList = function(){
if (!MSGS){
@@ -124,7 +121,7 @@ var STATE = (function(){
var messages = FILE.getMessages(selectedChannel);
var startIndex = messagesPerPage*(ROOT.getCurrentPage()-1);
- return ROOT.getFilteredMessageList().slice(startIndex, !messagesPerPage ? undefined : startIndex+messagesPerPage).map(key => {
+ return MSGS.slice(startIndex, !messagesPerPage ? undefined : startIndex+messagesPerPage).map(key => {
var message = messages[key];
return {
@@ -137,24 +134,32 @@ var STATE = (function(){
};
});
};
-
- ROOT.getUserList = function(){
- if (!FILE){
- return [];
- }
-
- return FILE.meta.users;
- };
// ----------
// Filtering
// ----------
+
+ ROOT.setActiveFilter = function(filter){
+ switch(filter ? filter.type : ""){
+ case "user":
+ filterFunction = PROCESSOR.FILTER.byUser(FILE.getUserIndex(filter.value));
+ break;
- ROOT.setMessagesByUser = function(key){
- currentPage = 1;
- messagesByUser = key;
+ default:
+ filterFunction = null;
+ break;
+ }
+
triggerChannelsRefreshed();
- triggerMessagesRefreshed();
+ ROOT.selectChannel(selectedChannel); // resets current page and updates messages
+ };
+
+ // -----
+ // Users
+ // -----
+
+ ROOT.getUserList = function(){
+ return FILE ? FILE.getUsers() : [];
};
// ----------
@@ -188,7 +193,7 @@ var STATE = (function(){
};
ROOT.getPageCount = function(){
- return !MSGS ? 0 : (!messagesPerPage ? 1 : Math.ceil(ROOT.getFilteredMessageList().length/messagesPerPage));
+ return !MSGS ? 0 : (!messagesPerPage ? 1 : Math.ceil(MSGS.length/messagesPerPage));
};
// --------
diff --git a/src/renderer/stl.menu.css b/src/renderer/stl.menu.css
index 7904667..09816c8 100644
--- a/src/renderer/stl.menu.css
+++ b/src/renderer/stl.menu.css
@@ -60,3 +60,11 @@
#menu .nav > button, #menu .nav > p {
margin: 8px 1px;
}
+
+#opt-filter-list > select, #opt-filter-list > input {
+ display: none;
+}
+
+#opt-filter-list > .active {
+ display: block;
+}