Skip to content

Commit

Permalink
Merge pull request #2 from rafaismyname/feature/options
Browse files Browse the repository at this point in the history
0.2.1
  • Loading branch information
rafaismyname authored Oct 8, 2018
2 parents fc41c81 + d7fa873 commit efd1677
Show file tree
Hide file tree
Showing 11 changed files with 337 additions and 194 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## 0.2.1 - More controls (2018-10-08)
* New option: Enable/Disable Chat tools (macros/wysi**n**wyg)!
* New option: Enable/Disable Hide chat from list!

## 0.2.0 - Hide Chat Feature! (2018-10-05)
* New feature: Hide List - hide annoying contacts!
* Performance Improvs
* Bugfixes

## 0.1.0 - First Release! (2018-10-02)
* Messages Macros
* WYSI**N**WYG
* Styled options screen
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# WhatsBuddy
> WebExtension that gives your WhatsApp Web SUPER POWERS! 🖥💬⚡️🔥
[![npm version](https://badge.fury.io/js/whatsbuddy.svg)](https://badge.fury.io/js/whatsbuddy)

🤘🏼Hide List: Hide annoying contacts! Keep your chatlist enjoyable again!

⚡️Message Macros: Add quick message macros for a faster response!
Expand Down Expand Up @@ -31,10 +33,7 @@ Just make sure to follow [Airbnb's JS Style Guidelines](https://github.com/airbn

## Release History

* 0.1.0 - First Release!
* Messages Macros
* WYSI**N**WYG
* Styled options screen
Check [CHANGELOG.md](https://github.com/rafaismyname/whatsbuddy/blob/master/CHANGELOG.md) for updated Release/Changes history.

## Authors

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "whatsbuddy",
"version": "0.2.0",
"version": "0.2.1",
"description": "WebExtension that adds extra functionalities to WhatsApp Web",
"license": "MIT",
"bugs": {
Expand Down
16 changes: 10 additions & 6 deletions src/chat/chat.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as storage from '../helpers/storage';
import { onDocumentReady, onChatOpen } from '../helpers/events';
import { onChatOpen } from '../helpers/events';

const MESSAGE_INPUT_SELECTOR = '#main footer div[contenteditable]';
const SEND_BUTTON_CHILD_SELECTOR = '#main footer button span[data-icon=send]';
Expand Down Expand Up @@ -64,7 +64,7 @@ const formatSelectedText = (wrapper) => {
return insertMessageText(replacementText);
};

onChatOpen(() => {
const chatOpenCallback = () => {
const toolsContainer = document.createElement('div');
toolsContainer.id = TOOLS_CONTAINER_ID;

Expand Down Expand Up @@ -125,9 +125,13 @@ onChatOpen(() => {

const footerContainer = document.querySelector(CHAT_FOOTER_SELECTOR);
footerContainer.insertBefore(toolsContainer, footerContainer.firstChild);
});
};

const storageParams = { macrosEnabled: true, macros: [] };
storage.get(storageParams).then(({ macrosEnabled, macros }) => {
if (!macrosEnabled) return;

chatMacros.push(...macros);

onDocumentReady(() => {
const storageParams = { macros: [] };
storage.get(storageParams).then(({ macros }) => chatMacros.push(...macros));
onChatOpen(() => chatOpenCallback());
});
12 changes: 12 additions & 0 deletions src/helpers/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ export const onClick = (selector, callback) => {

element.addEventListener('click', ({ target }) => callback(target), false);
};

export const onChange = (selector, callback) => {
const element = (() => {
if (typeof selector === 'string') {
return document.querySelector(selector);
}

return selector;
})();

element.addEventListener('change', ({ target }) => callback(target), false);
};
10 changes: 9 additions & 1 deletion src/list/list.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import * as storage from '../helpers/storage';
import { onSidePaneLoaded } from './events';
import { BaseList, OverlayList } from './models';

const baseList = new BaseList();
const overlayList = new OverlayList();

onSidePaneLoaded((sidePane) => {
const sidePaneLoadCallback = (sidePane) => {
baseList.build(sidePane, overlayList);

overlayList.build(sidePane, baseList);
overlayList.init();

window.addEventListener('error', () => document.location.reload());
};

const storageParams = { enableHideChats: true, hiddenChats: [] };
storage.get(storageParams).then(({ enableHideChats, hiddenChats }) => {
if (!enableHideChats || hiddenChats.length === 0) return;

onSidePaneLoaded(sidePane => sidePaneLoadCallback(sidePane));
});
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

"name": "WhatsBuddy",
"description": "WebExtension that adds extra functionalities to WhatsApp Web",
"version": "0.2.0",
"version": "0.2.1",

"icons": {
"512": "./icons/icon.png",
Expand Down
122 changes: 122 additions & 0 deletions src/options/chat/macros.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import * as storage from '../../helpers/storage';
import { onDocumentReady, onClick, onChange } from '../../helpers/events';

const SWITCH_INPUT_SELECTOR = 'input#whatsbuddy-macros-enabled';
const SWITCH_STATUS_SELECTOR = 'span#whatsbuddy-macros-status';
const MACROS_CONTAINER_SELECTOR = '#whatsbuddy-options-macros';
const ADD_MACRO_BUTTON_SELECTOR = '#whatsbuddy-options-add-macro';
const MACRO_CONTAINER_CLASSNAME = 'whatsbuddy-options-macro';
const MACRO_NAME_INPUT_CLASSNAME = 'whatsbuddy-options-macro-name form-input input-lg';
const MACRO_NAME_INPUT_SELECTOR = 'input.whatsbuddy-options-macro-name';
const MACRO_MESSAGE_INPUT_CLASSNAME = 'whatsbuddy-options-macro-message form-input input-lg';
const MACRO_MESSAGE_INPUT_SELECTOR = 'input.whatsbuddy-options-macro-message';
const MACRO_DELETE_BUTTON_CLASSNAME = 'whatsbuddy-options-macro-delete btn btn-error';

let state = {
macrosEnabled: true,
macros: [],
};

const renderEnableSwitch = () => {
const enableSwitch = document.querySelector(SWITCH_INPUT_SELECTOR);
enableSwitch.checked = state.macrosEnabled;

const enableStatus = document.querySelector(SWITCH_STATUS_SELECTOR);
enableStatus.innerHTML = state.macrosEnabled ? 'Enabled' : 'Disabled';
};

const toggleEnableSwitch = () => {
const enabled = state.macrosEnabled;
state = Object.assign({}, state, { macrosEnabled: !enabled });

renderEnableSwitch();
};

onChange(SWITCH_INPUT_SELECTOR, () => toggleEnableSwitch());

const insertMacro = (name = null, message = null) => {
const macrosContainer = document.querySelector(MACROS_CONTAINER_SELECTOR);

const macroContainer = document.createElement('tr');
macroContainer.className = MACRO_CONTAINER_CLASSNAME;

const macroNameContainer = document.createElement('td');
const macroNameInput = document.createElement('input');
macroNameInput.className = MACRO_NAME_INPUT_CLASSNAME;
if (name !== null) {
macroNameInput.value = name;
}
macroNameContainer.appendChild(macroNameInput);

macroContainer.appendChild(macroNameContainer);

const macroMessageContainer = document.createElement('td');
const macroMessageInput = document.createElement('input');
macroMessageInput.className = MACRO_MESSAGE_INPUT_CLASSNAME;
if (message !== null) {
macroMessageInput.value = message;
}
macroMessageContainer.appendChild(macroMessageInput);

macroContainer.appendChild(macroMessageContainer);

const macroDeleteContainer = document.createElement('td');
const macroDeleteButton = document.createElement('button');
macroDeleteButton.className = MACRO_DELETE_BUTTON_CLASSNAME;
macroDeleteButton.innerHTML = '<i class="icon icon-cross"></i>';
onClick(macroDeleteButton, () => {
macrosContainer.removeChild(macroContainer);
});
macroDeleteContainer.appendChild(macroDeleteButton);

macroContainer.appendChild(macroDeleteContainer);

macrosContainer.appendChild(macroContainer);
};

const renderMacros = () => {
state.macros.forEach(({ name, message }) => insertMacro(name, message));
};

const serializeMacros = () => {
const macrosContainers = document.querySelectorAll(`${MACROS_CONTAINER_SELECTOR} .${MACRO_CONTAINER_CLASSNAME}`);

const rawMacros = ([...macrosContainers]).map((macroContainer) => {
const macroNameInput = macroContainer.querySelector(MACRO_NAME_INPUT_SELECTOR);
const name = macroNameInput.value;

const macroMessageInput = macroContainer.querySelector(MACRO_MESSAGE_INPUT_SELECTOR);
const message = macroMessageInput.value;

return { name, message };
});

const macros = rawMacros.filter((macro) => {
const { name, message } = macro;

return (name.trim() !== '' && message.trim() !== '');
});

return macros;
};

onClick(ADD_MACRO_BUTTON_SELECTOR, () => insertMacro());

export const save = () => {
const macros = serializeMacros();

state = Object.assign({}, state, { macros });

return storage.save(state);
};

onDocumentReady(() => {
storage.get(state)
.then((response) => {
state = Object.assign({}, state, response);
})
.then(() => renderEnableSwitch())
.then(() => renderMacros());
});

export default {};
124 changes: 124 additions & 0 deletions src/options/list/chats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import * as storage from '../../helpers/storage';
import { onDocumentReady, onClick, onChange } from '../../helpers/events';

const HIDE_CHAT_SWITCH_SELECTOR = 'input#whatsbuddy-hide-chat-enabled';
const HIDE_CHAT_STATUS_SELECTOR = 'span#whatsbuddy-hide-chat-status';
const CHATS_CONTAINER_SELECTOR = '#whatsbuddy-chats';
const HIDDEN_CHATS_CONTAINER_SELECTOR = '#whatsbuddy-hidden-chats';

let state = {
chats: [],
enableHideChats: true,
hiddenChats: [],
};

const renderHideChatEnableSwitch = () => {
const enableSwitch = document.querySelector(HIDE_CHAT_SWITCH_SELECTOR);
enableSwitch.checked = state.enableHideChats;

const enableStatus = document.querySelector(HIDE_CHAT_STATUS_SELECTOR);
enableStatus.innerHTML = state.enableHideChats ? 'Enabled' : 'Disabled';
};

const toggleHideChatEnableSwitch = () => {
const enabled = state.enableHideChats;
state = Object.assign({}, state, { enableHideChats: !enabled });

renderHideChatEnableSwitch();
};

onChange(HIDE_CHAT_SWITCH_SELECTOR, () => toggleHideChatEnableSwitch());

const insertChat = (chat, chats) => {
const chatsContainer = document.querySelector(CHATS_CONTAINER_SELECTOR);

const chatContainer = document.createElement('tr');

const nameContainer = document.createElement('td');
nameContainer.innerHTML = chat.name;
nameContainer.dataset.chatId = chat.id;

chatContainer.appendChild(nameContainer);

const hideContainer = document.createElement('td');
const hideButton = document.createElement('button');
hideButton.innerHTML = '<i class="icon icon-arrow-right"></i>';
hideButton.className = 'btn btn-error';
onClick(hideButton, () => {
chatsContainer.removeChild(chatContainer);
insertHiddenChat(chat, chats); // eslint-disable-line
});
hideContainer.appendChild(hideButton);

chatContainer.appendChild(hideContainer);

chatsContainer.appendChild(chatContainer);
};

const renderChatList = () => {
const { chats, hiddenChats } = state;
const filteredChats = chats.filter(chat => !hiddenChats.includes(chat.id));
filteredChats.forEach(chat => insertChat(chat, chats));
};

const insertHiddenChat = (chat, chats) => {
const chatsContainer = document.querySelector(HIDDEN_CHATS_CONTAINER_SELECTOR);

const chatContainer = document.createElement('tr');

const showContainer = document.createElement('td');
const showButton = document.createElement('button');
showButton.innerHTML = '<i class="icon icon-arrow-left"></i>';
showButton.className = 'btn btn-success';
onClick(showButton, () => {
chatsContainer.removeChild(chatContainer);
insertChat(chat, chats);
});
showContainer.appendChild(showButton);

chatContainer.appendChild(showContainer);

const nameContainer = document.createElement('td');
nameContainer.className = 'text-right';
nameContainer.innerHTML = chat.name || chat.id;
nameContainer.dataset.chatId = chat.id;

chatContainer.appendChild(nameContainer);

chatsContainer.appendChild(chatContainer);
};

const renderHiddenChatList = () => {
const { chats, hiddenChats } = state;
hiddenChats.forEach((chatId) => {
const chat = chats.find(c => c.id === chatId) || { id: chatId };
insertHiddenChat(chat, chats);
});
};

const serializeHiddenChatList = () => {
const chatsContainer = document.querySelector(HIDDEN_CHATS_CONTAINER_SELECTOR);
const hiddenList = chatsContainer.querySelectorAll('tr td:last-child');

return ([...hiddenList]).map(node => node.dataset.chatId);
};

export const save = () => {
const hiddenChats = serializeHiddenChatList();

state = Object.assign({}, state, { hiddenChats });

return storage.save(state);
};

onDocumentReady(() => {
storage.get(state)
.then((response) => {
state = Object.assign({}, state, response);
})
.then(() => renderHideChatEnableSwitch())
.then(() => renderChatList())
.then(() => renderHiddenChatList());
});

export default {};
Loading

0 comments on commit efd1677

Please sign in to comment.