Skip to content

Commit

Permalink
Added unread indicator support for calendar #6 #152 and make alerts a…
Browse files Browse the repository at this point in the history
…ctivate account automatically
  • Loading branch information
Thomas101 committed Sep 27, 2017
1 parent 78330ea commit bfb7c45
Show file tree
Hide file tree
Showing 20 changed files with 294 additions and 44 deletions.
48 changes: 48 additions & 0 deletions src/guest/src/Google/GoogleCalendar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const GoogleService = require('./GoogleService')
const { ipcRenderer } = require('electron')
const req = require('../req')
const extensionLoader = require('../Extensions/extensionLoader')
const { WAVEBOX_CONTENT_IMPL_ENDPOINTS } = req.shared('extensionApis')
const { WB_BROWSER_GOOGLE_CALENDAR_ALERT_PRESENTED } = req.shared('ipcEvents')
const uuid = require('uuid')

class GoogleCalendar extends GoogleService {
/* **************************************************************************/
// Lifecycle
/* **************************************************************************/

constructor () {
super()
this.apiKey = uuid.v4()
window.addEventListener('message', this.handleWindowMessage.bind(this))
extensionLoader.loadWaveboxGuestApi(WAVEBOX_CONTENT_IMPL_ENDPOINTS.GOOGLE_CALENDAR_ALERT, this.apiKey)
}

/* **************************************************************************/
// Message handling
/* **************************************************************************/

/**
* Handles a new window message
* @param evt: the event that fired
*/
handleWindowMessage (evt) {
if (evt.origin === window.location.origin && evt.isTrusted) {
let data
try {
data = JSON.parse(evt.data)
} catch (ex) { return }
if (!data.wavebox) { return }
if (data.apiKey !== this.apiKey) { return }

if (data.type === 'wavebox-alert-present') {
ipcRenderer.sendToHost({
type: WB_BROWSER_GOOGLE_CALENDAR_ALERT_PRESENTED,
data: { message: data.message }
})
}
}
}
}

module.exports = GoogleCalendar
15 changes: 3 additions & 12 deletions src/guest/src/Google/GoogleCommunication.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
const injector = require('../injector')
const Browser = require('../Browser/Browser')
const Wavebox = require('../Wavebox/Wavebox')
const GoogleService = require('./GoogleService')
const {ipcRenderer} = require('electron')
const req = require('../req')
const { WB_BROWSER_GOOGLE_COMMUNICATION_UNREAD_COUNT_CHANGED } = req.shared('ipcEvents')
const NOTIFICATION_CHANGE_CHECK_INTERVAL = 1500

class GoogleCommunication {
class GoogleCommunication extends GoogleService {
/* **************************************************************************/
// Lifecycle
/* **************************************************************************/

constructor () {
this.browser = new Browser()
this.wavebox = new Wavebox()
super()

this.state = {
count: undefined
}
this.notificationInterval = setInterval(this.checkNewNotifications.bind(this), NOTIFICATION_CHANGE_CHECK_INTERVAL)

injector.injectStyle(`
a[href*="/SignOutOptions"] {
visibility: hidden !important;
}
`)
}

/* **************************************************************************/
Expand Down
9 changes: 9 additions & 0 deletions src/guest/src/preload/googleCalendar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const elconsole = require('../elconsole')
try {
const GoogleCalendar = require('../Google/GoogleCalendar')
/*eslint-disable */
const googleCalendar = new GoogleCalendar()
/*eslint-enable */
} catch (ex) {
elconsole.error('Error', ex)
}
18 changes: 18 additions & 0 deletions src/guestApi/src/GoogleCalendarAlert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* global WB_API_KEY */

(function () {
const polyfillAlert = function (window) {
const original = window.alert
window.alert = function () {
window.top.postMessage(JSON.stringify({
apiKey: WB_API_KEY,
wavebox: true,
type: 'wavebox-alert-present',
message: arguments[0]
}), '*')
return original.apply(this, Array.from(arguments))
}
}

polyfillAlert(window)
})()
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export default class DefaultServiceBadge extends React.Component {
mailboxUnreadCount,
mailboxHasUnreadActivity
} = this.state
if (!mailbox || !service) { return false }

if (displayMailboxOverview && mailbox.hasAdditionalServices) {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import GoogleMailboxMailWebView from './MailboxWebView/Google/GoogleMailboxMailW
import GoogleMailboxServiceWebView from './MailboxWebView/Google/GoogleMailboxServiceWebView'
import GoogleMailboxStorageWebView from './MailboxWebView/Google/GoogleMailboxStorageWebView'
import GoogleMailboxCommunicationWebView from './MailboxWebView/Google/GoogleMailboxCommunicationWebView'
import GoogleMailboxCalendarWebView from './MailboxWebView/Google/GoogleMailboxCalendarWebView'
import TrelloMailboxWebView from './MailboxWebView/Trello/TrelloMailboxWebView'
import SlackMailboxWebView from './MailboxWebView/Slack/SlackMailboxWebView'
import GenericMailboxDefaultServiceWebView from './MailboxWebView/Generic/GenericMailboxDefaultServiceWebView'
Expand Down Expand Up @@ -139,6 +140,8 @@ export default class MailboxTab extends React.Component {
return (<GoogleMailboxStorageWebView mailboxId={mailboxId} key={key} />)
case CoreService.SERVICE_TYPES.COMMUNICATION:
return (<GoogleMailboxCommunicationWebView mailboxId={mailboxId} key={key} />)
case CoreService.SERVICE_TYPES.CALENDAR:
return (<GoogleMailboxCalendarWebView mailboxId={mailboxId} key={key} />)
default:
return (<GoogleMailboxServiceWebView mailboxId={mailboxId} serviceType={serviceType} key={key} />)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,6 @@ export default class GenericMailboxDefaultServiceWebView extends React.Component

componentDidMount () {
mailboxStore.listen(this.mailboxChanged)
if (this.state.isActive) {
mailboxActions.reduceService.defer(
this.props.mailboxId,
CoreService.SERVICE_TYPES.DEFAULT,
GenericDefaultServiceReducer.clearUnseenNotifications
)
}
}

componentWillUnmount () {
Expand Down Expand Up @@ -64,8 +57,7 @@ export default class GenericMailboxDefaultServiceWebView extends React.Component
const service = mailbox ? mailbox.serviceForType(CoreService.SERVICE_TYPES.DEFAULT) : null
return {
defaultWindowOpenMode: mailbox ? mailbox.defaultWindowOpenMode : CoreMailbox.DEFAULT_WINDOW_OPEN_MODES.WAVEBOX,
url: service ? service.url : undefined,
isActive: mailboxState.isActive(props.mailboxId, CoreService.SERVICE_TYPES.DEFAULT)
url: service ? service.url : undefined
}
}

Expand All @@ -74,8 +66,7 @@ export default class GenericMailboxDefaultServiceWebView extends React.Component
const service = mailbox ? mailbox.serviceForType(CoreService.SERVICE_TYPES.DEFAULT) : null
this.setState({
defaultWindowOpenMode: mailbox ? mailbox.defaultWindowOpenMode : CoreMailbox.DEFAULT_WINDOW_OPEN_MODES.WAVEBOX,
url: service ? service.url : undefined,
isActive: mailboxState.isActive(this.props.mailboxId, CoreService.SERVICE_TYPES.DEFAULT)
url: service ? service.url : undefined
})
}

Expand Down Expand Up @@ -127,13 +118,11 @@ export default class GenericMailboxDefaultServiceWebView extends React.Component
* Handles the browser presenting a notification
*/
handleBrowserNotificationPresented = () => {
if (!this.state.isActive) {
mailboxActions.reduceService(
this.props.mailboxId,
CoreService.SERVICE_TYPES.DEFAULT,
GenericDefaultServiceReducer.notificationPresented
)
}
mailboxActions.reduceServiceIfInactive(
this.props.mailboxId,
CoreService.SERVICE_TYPES.DEFAULT,
GenericDefaultServiceReducer.notificationPresented
)
}

/* **************************************************************************/
Expand All @@ -144,17 +133,6 @@ export default class GenericMailboxDefaultServiceWebView extends React.Component
return shallowCompare(this, nextProps, nextState)
}

componentDidUpdate (prevProps, prevState) {
if (this.state.isActive && !prevState.isActive) {
// Not great that we've put this here, but component lifecycle is kinda handled here :-/
mailboxActions.reduceService.defer(
this.props.mailboxId,
CoreService.SERVICE_TYPES.DEFAULT,
GenericDefaultServiceReducer.clearUnseenNotifications
)
}
}

render () {
const { mailboxId } = this.props
const { url } = this.state
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import PropTypes from 'prop-types'
import React from 'react'
import MailboxWebViewHibernator from '../MailboxWebViewHibernator'
import CoreService from 'shared/Models/Accounts/CoreService'
import Resolver from 'Runtime/Resolver'
import { mailboxActions, GoogleCalendarServiceReducer } from 'stores/mailbox'
import shallowCompare from 'react-addons-shallow-compare'
import {
WB_BROWSER_NOTIFICATION_PRESENT,
WB_BROWSER_GOOGLE_CALENDAR_ALERT_PRESENTED
} from 'shared/ipcEvents'

const REF = 'mailbox_tab'

export default class GoogleMailboxCalendarWebView extends React.Component {
/* **************************************************************************/
// Class
/* **************************************************************************/

static propTypes = {
mailboxId: PropTypes.string.isRequired
}

/* **************************************************************************/
// Browser Events
/* **************************************************************************/

/**
* Dispatches browser IPC messages to the correct call
* @param evt: the event that fired
*/
dispatchBrowserIPCMessage = (evt) => {
switch (evt.channel.type) {
case WB_BROWSER_NOTIFICATION_PRESENT: this.handleBrowserNotificationPresented(); break
case WB_BROWSER_GOOGLE_CALENDAR_ALERT_PRESENTED: this.handleBrowserAlertPresented(); break
default: break
}
}

/**
* Handles the browser presenting a notification or alert
*/
handleBrowserNotificationPresented = () => {
mailboxActions.reduceServiceIfInactive(
this.props.mailboxId,
CoreService.SERVICE_TYPES.CALENDAR,
GoogleCalendarServiceReducer.notificationPresented
)
}

/**
* Auto changes the browser active mailbox to this service on presentation
*/
handleBrowserAlertPresented = () => {
mailboxActions.changeActive(this.props.mailboxId, CoreService.SERVICE_TYPES.CALENDAR)
}

/* **************************************************************************/
// Rendering
/* **************************************************************************/

shouldComponentUpdate (nextProps, nextState) {
return shallowCompare(this, nextProps, nextState)
}

render () {
const { mailboxId } = this.props
return (
<MailboxWebViewHibernator
ref={REF}
preload={Resolver.guestPreload('googleCalendar')}
mailboxId={mailboxId}
serviceType={CoreService.SERVICE_TYPES.CALENDAR}
ipcMessage={this.dispatchBrowserIPCMessage} />
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default class Toolbar extends React.Component {
const mailbox = mailboxState.activeMailbox()
if (!mailbox) { return false }
if (mailbox.serviceDisplayMode !== CoreMailbox.SERVICE_DISPLAY_MODES.TOOLBAR) { return false }
if (!mailbox.hasAdditionalServices) { return false }
if (!userState.user.hasServices) { return false }
if (mailbox.enabledServiceTypes <= 1) { return false }
return true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import ServiceReducer from './ServiceReducer'

class GoogleCalendarServiceReducer extends ServiceReducer {
/* **************************************************************************/
// Notifications
/* **************************************************************************/

/**
* Sets that a notification was presented
* @param mailbox: the mailbox that contains the service
* @param service: the service to update
*/
static notificationPresented (mailbox, service) {
return service.changeData({ lastUnseenNotificationTime: new Date().getTime() })
}

/**
* Clears the unseen notifications
* @param mailbox: the mailbox that contains the service
* @param service: the service to update
*/
static clearUnseenNotifications (mailbox, service) {
return service.changeData({ lastUnseenNotificationTime: null })
}
}

export default GoogleCalendarServiceReducer
17 changes: 17 additions & 0 deletions src/scenes/mailboxes/src/stores/mailbox/ServiceReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ class ServiceReducer {
static setCustomJS (mailbox, service, js) {
return service.changeData({ customJS: js })
}

/* **************************************************************************/
// Utils
/* **************************************************************************/

/**
* Runs the mergeChangesetOnActive merge on the service
* @param mailbox: the mailbox that contains the service
* @param service: the service to update
*/
static mergeChangesetOnActive (mailbox, service) {
if (service.mergeChangesetOnActive) {
return service.changeData(service.mergeChangesetOnActive)
} else {
return undefined
}
}
}

export default ServiceReducer
2 changes: 2 additions & 0 deletions src/scenes/mailboxes/src/stores/mailbox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import GenericDefaultServiceReducer from './GenericDefaultServiceReducer'
import GoogleMailboxReducer from './GoogleMailboxReducer'
import GoogleDefaultServiceReducer from './GoogleDefaultServiceReducer'
import GoogleCommunicationServiceReducer from './GoogleCommunicationServiceReducer'
import GoogleCalendarServiceReducer from './GoogleCalendarServiceReducer'
import SlackMailboxReducer from './SlackMailboxReducer'
import SlackDefaultServiceReducer from './SlackDefaultServiceReducer'
import TrelloMailboxReducer from './TrelloMailboxReducer'
Expand All @@ -29,6 +30,7 @@ export {
GoogleMailboxReducer,
GoogleDefaultServiceReducer,
GoogleCommunicationServiceReducer,
GoogleCalendarServiceReducer,
SlackMailboxReducer,
SlackDefaultServiceReducer,
TrelloMailboxReducer,
Expand Down
22 changes: 22 additions & 0 deletions src/scenes/mailboxes/src/stores/mailbox/mailboxActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,28 @@ class MailboxActions {
return { id: id, serviceType: serviceType, reducer: reducer, reducerArgs: reducerArgs }
}

/**
* Updates and modifies a mailbox service only if it's active
* @param id: the id of the mailbox to change
* @param serviceType: the type of service to work on
* @param reducer: the reducer to run on the mailbox
* @param ...reducerArgs: the arguments to supply to the reducer
*/
reduceServiceIfActive (id, serviceType, reducer, ...reducerArgs) {
return { id: id, serviceType: serviceType, reducer: reducer, reducerArgs: reducerArgs }
}

/**
* Updates and modifies a mailbox service only if it's inactive
* @param id: the id of the mailbox to change
* @param serviceType: the type of service to work on
* @param reducer: the reducer to run on the mailbox
* @param ...reducerArgs: the arguments to supply to the reducer
*/
reduceServiceIfInactive (id, serviceType, reducer, ...reducerArgs) {
return { id: id, serviceType: serviceType, reducer: reducer, reducerArgs: reducerArgs }
}

/* **************************************************************************/
// Avatar
/* **************************************************************************/
Expand Down
Loading

0 comments on commit bfb7c45

Please sign in to comment.