179 lines
5.3 KiB
JavaScript
179 lines
5.3 KiB
JavaScript
import { Subject, Observable } from 'rx';
|
|
import Chat from 'gitter-sidecar';
|
|
import types from '../../common/app/redux/types';
|
|
import {
|
|
openHelpChat,
|
|
closeHelpChat,
|
|
toggleMainChat
|
|
} from '../../common/app/redux/actions';
|
|
|
|
export function createHeader(room, title, document) {
|
|
const type = room === 'freecodecamp' ? 'main' : 'help';
|
|
const div = document.createElement('div');
|
|
const span = document.createElement('span');
|
|
const actionBar = document.querySelector(
|
|
`#chat-embed-${type}> .gitter-chat-embed-action-bar`
|
|
);
|
|
span.appendChild(document.createTextNode(title));
|
|
div.className = `chat-embed-${type}-title`;
|
|
div.appendChild(span);
|
|
actionBar.insertBefore(div, actionBar.firstChild);
|
|
}
|
|
|
|
export function createHelpContainer(document) {
|
|
const container = document.createElement('aside');
|
|
container.id = 'chat-embed-help';
|
|
container.className = 'gitter-chat-embed is-collapsed';
|
|
document.body.appendChild(container);
|
|
return container;
|
|
}
|
|
|
|
export function createMainChat(getState, document) {
|
|
let mainChatTitleAdded = false;
|
|
const mainChatContainer = document.createElement('aside');
|
|
mainChatContainer.id = 'chat-embed-main';
|
|
mainChatContainer.className = 'gitter-chat-embed is-collapsed';
|
|
document.body.appendChild(mainChatContainer);
|
|
const mainChat = new Chat({
|
|
room: 'freecodecamp/freecodecamp',
|
|
activationElement: false,
|
|
targetElement: mainChatContainer
|
|
});
|
|
|
|
const toggle$ = Observable.fromEventPattern(
|
|
h => mainChatContainer.addEventListener('gitter-chat-toggle', h),
|
|
h => mainChatContainer.removeEventListener('gitter-chat-toggle', h)
|
|
)
|
|
.map(e => {
|
|
const { isMainChatOpen } = getState().app;
|
|
if (!mainChatTitleAdded) {
|
|
mainChatTitleAdded = true;
|
|
createHeader('freecodecamp', 'Free Code Camp\'s Main Chat', document);
|
|
}
|
|
if (isMainChatOpen === e.detail.state) {
|
|
return null;
|
|
}
|
|
return toggleMainChat();
|
|
});
|
|
return {
|
|
mainChat,
|
|
toggle$
|
|
};
|
|
}
|
|
|
|
// only one help room may be alive at once
|
|
export function createHelpChat(room, container, proxy, document) {
|
|
const title = room.replace(/([A-Z])/g, ' $1');
|
|
let isTitleAdded = false;
|
|
const chat = new Chat({
|
|
room: `freecodecamp/${room}`,
|
|
activationElement: false,
|
|
targetElement: container
|
|
});
|
|
// return subscription to toggle stream
|
|
// dispose when rooms switch
|
|
const subscription = Observable.fromEventPattern(
|
|
h => container.addEventListener('gitter-chat-toggle', h),
|
|
h => container.removeEventListener('gitter-chat-toggle', h)
|
|
)
|
|
.map(e => {
|
|
if (!isTitleAdded) {
|
|
isTitleAdded = true;
|
|
createHeader(room, title, document);
|
|
}
|
|
const gitterState = e.detail.state;
|
|
return gitterState ? openHelpChat() : closeHelpChat();
|
|
})
|
|
// use subject proxy to dispatch actions
|
|
.subscribe(proxy);
|
|
return { chat, subscription };
|
|
}
|
|
|
|
export const cache = {};
|
|
export function toggleHelpChat(isOpen, room, proxy, document) {
|
|
// check is container is already created
|
|
if (!cache['container']) {
|
|
cache['container'] = createHelpContainer(document);
|
|
}
|
|
const { container } = cache;
|
|
if (!cache['chat']) {
|
|
const {
|
|
chat,
|
|
subscription
|
|
} = createHelpChat(room, container, proxy, document);
|
|
cache.chat = chat;
|
|
// make sure we clear out old subscription
|
|
if (cache.subscription && cache.subscription.dispose) {
|
|
cache.subscription.dispose();
|
|
}
|
|
cache.subscription = subscription;
|
|
cache.currentRoom = room;
|
|
}
|
|
// have we switched rooms?
|
|
if (!cache.currentRoom === room) {
|
|
// room has changed, if chat object exist, destroy it
|
|
// and end subscription to toggle
|
|
try {
|
|
cache.chat.destroy();
|
|
cache.subscription.dispose();
|
|
// chat and subscription may not exist at first so we catch errors here
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
// create new chat room and cache
|
|
const {
|
|
chat,
|
|
subscription
|
|
} = createHelpChat(room, container, proxy, document);
|
|
cache.chat = chat;
|
|
cache.subscription = subscription;
|
|
cache.currentRoom = room;
|
|
}
|
|
// all goes well pull chat object from cache
|
|
const { chat } = cache;
|
|
chat.toggleChat(isOpen);
|
|
}
|
|
|
|
export default function gitterSaga(actions$, getState, { document }) {
|
|
const helpToggleProxy = new Subject();
|
|
const {
|
|
mainChat,
|
|
toggle$: mainChatToggle$
|
|
} = createMainChat(getState, document);
|
|
return Observable.merge(
|
|
mainChatToggle$,
|
|
helpToggleProxy,
|
|
actions$
|
|
.filter(({ type }) => (
|
|
type === types.openMainChat ||
|
|
type === types.closeMainChat ||
|
|
type === types.toggleMainChat ||
|
|
type === types.toggleHelpChat
|
|
))
|
|
.map(({ type }) => {
|
|
const state = getState();
|
|
let shouldBlur = false;
|
|
if (type === types.toggleHelpChat) {
|
|
const {
|
|
app: { isHelpChatOpen },
|
|
challengesApp: { helpChatRoom }
|
|
} = state;
|
|
shouldBlur = !isHelpChatOpen;
|
|
toggleHelpChat(
|
|
isHelpChatOpen,
|
|
helpChatRoom,
|
|
helpToggleProxy,
|
|
document
|
|
);
|
|
}
|
|
const { isMainChatOpen } = state.app;
|
|
mainChat.toggleChat(isMainChatOpen);
|
|
shouldBlur = !isMainChatOpen;
|
|
if (!shouldBlur) {
|
|
document.activeElement.blur();
|
|
}
|
|
return null;
|
|
})
|
|
);
|
|
}
|