mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-21 15:56:10 +08:00
fix(tracking): fix link tracking and read receipt plugins
Fix broken links in link tracking and read receipts Fix bug in email frame where it wouldn't adjust the height even when content changed MessageItem bodies automatically clear the MessageBodyProcessor cache when the message contents (including metadata) change. Remove unused Account stuff from nylas-observables Plugins appIds properly read if there's an environment set
This commit is contained in:
parent
90b9570f91
commit
9dd7a9600a
|
@ -29,6 +29,7 @@ export default class LinkTrackingComposerExtension extends ComposerExtension {
|
|||
// loop through all <a href> elements, replace with redirect links and save mappings
|
||||
draftBody.unquoted = draftBody.unquoted.replace(RegExpUtils.linkTagRegex(), (match, prefix, url, suffix, content, closingTag) => {
|
||||
const encoded = encodeURIComponent(url);
|
||||
// the links param is an index of the link array.
|
||||
const redirectUrl = `${PLUGIN_URL}/link/${draft.accountId}/${messageUid}/${links.length}?redirect=${encoded}`;
|
||||
links.push({url: url, click_count: 0, click_data: [], redirect_url: redirectUrl});
|
||||
return prefix + redirectUrl + suffix + content + closingTag;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {MessageViewExtension, RegExpUtils} from 'nylas-exports'
|
||||
import plugin from '../package.json'
|
||||
import {PLUGIN_ID} from './link-tracking-constants'
|
||||
|
||||
export default class LinkTrackingMessageExtension extends MessageViewExtension {
|
||||
static formatMessageBody({message}) {
|
||||
const metadata = message.metadataForPluginId(plugin.appId) || {};
|
||||
const metadata = message.metadataForPluginId(PLUGIN_ID) || {};
|
||||
if ((metadata.links || []).length === 0) { return }
|
||||
const links = {}
|
||||
for (const link of metadata.links) {
|
||||
|
|
|
@ -31,7 +31,7 @@ function afterDraftSend({draftClientId}) {
|
|||
body: JSON.stringify(data),
|
||||
}).then( ([response, responseBody]) => {
|
||||
if (response.statusCode !== 200) {
|
||||
throw new Error();
|
||||
throw new Error(`Link Tracking server error ${response.statusCode} at ${serverUrl}: ${responseBody}`);
|
||||
}
|
||||
return responseBody;
|
||||
}).catch(error => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
React = require 'react'
|
||||
_ = require "underscore"
|
||||
{EventedIFrame} = require 'nylas-component-kit'
|
||||
{QuotedHTMLTransformer} = require 'nylas-exports'
|
||||
{Utils, QuotedHTMLTransformer} = require 'nylas-exports'
|
||||
|
||||
EmailFrameStylesStore = require './email-frame-styles-store'
|
||||
|
||||
|
@ -11,9 +11,6 @@ class EmailFrame extends React.Component
|
|||
@propTypes:
|
||||
content: React.PropTypes.string.isRequired
|
||||
|
||||
constructor: (@props) ->
|
||||
@_lastComputedHeight = 0
|
||||
|
||||
render: =>
|
||||
<EventedIFrame ref="iframe" seamless="seamless" onResize={@_setFrameHeight}/>
|
||||
|
||||
|
@ -29,14 +26,12 @@ class EmailFrame extends React.Component
|
|||
componentDidUpdate: =>
|
||||
@_writeContent()
|
||||
|
||||
shouldComponentUpdate: (newProps, newState) =>
|
||||
# Turns out, React is not able to tell if props.children has changed,
|
||||
# so whenever the message list updates each email-frame is repopulated,
|
||||
# often with the exact same content. To avoid unnecessary calls to
|
||||
# _writeContent, we do a quick check for deep equality.
|
||||
!_.isEqual(newProps, @props)
|
||||
shouldComponentUpdate: (nextProps, nextState) =>
|
||||
not Utils.isEqualReact(nextProps, @props) or
|
||||
not Utils.isEqualReact(nextState, @state)
|
||||
|
||||
_writeContent: =>
|
||||
@_lastComputedHeight = 0
|
||||
domNode = React.findDOMNode(@)
|
||||
doc = domNode.contentDocument
|
||||
return unless doc
|
||||
|
|
|
@ -22,11 +22,20 @@ class MessageItemBody extends React.Component
|
|||
processedBody: undefined
|
||||
|
||||
componentWillMount: =>
|
||||
@_unsub = MessageBodyProcessor.processAndSubscribe(@props.message, @_onBodyChanged)
|
||||
@_prepareBody(@props)
|
||||
|
||||
componentWillReceiveProps: (newProps) =>
|
||||
shouldComponentUpdate: (nextProps, nextState) ->
|
||||
not Utils.isEqualReact(nextProps, @props) or
|
||||
not Utils.isEqualReact(nextState, @state)
|
||||
|
||||
componentWillUpdate: (nextProps, nextState) =>
|
||||
if not Utils.isEqualReact(nextProps.message, @props.message)
|
||||
@_prepareBody(nextProps)
|
||||
|
||||
_prepareBody: (props) ->
|
||||
MessageBodyProcessor.resetCache(props.message)
|
||||
@_unsub?()
|
||||
@_unsub = MessageBodyProcessor.processAndSubscribe(newProps.message, @_onBodyChanged)
|
||||
@_unsub = MessageBodyProcessor.processAndSubscribe(props.message, @_onBodyChanged)
|
||||
|
||||
componentWillUnmount: =>
|
||||
@_unsub?()
|
||||
|
|
|
@ -106,7 +106,7 @@ describe "MessageItem", ->
|
|||
snippet: "snippet one..."
|
||||
subject: "Subject One"
|
||||
threadId: "thread_12345"
|
||||
accountId: TEST_ACCOUNT_ID
|
||||
accountId: window.TEST_ACCOUNT_ID
|
||||
|
||||
# Generate the test component. Should be called after @message is configured
|
||||
# for the test, since MessageItem assumes attributes of the message will not
|
||||
|
|
|
@ -2,7 +2,6 @@ import {DraftStore, React, Actions, NylasAPI, DatabaseStore, Message, Rx} from '
|
|||
import {RetinaImg} from 'nylas-component-kit'
|
||||
import {PLUGIN_ID, PLUGIN_NAME} from './open-tracking-constants'
|
||||
|
||||
|
||||
export default class OpenTrackingButton extends React.Component {
|
||||
|
||||
static displayName = 'OpenTrackingButton';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {React} from 'nylas-exports'
|
||||
import {RetinaImg} from 'nylas-component-kit'
|
||||
import plugin from '../package.json'
|
||||
import {PLUGIN_ID} from './open-tracking-constants'
|
||||
|
||||
export default class OpenTrackingMessageStatus extends React.Component {
|
||||
static displayName = "OpenTrackingMessageStatus";
|
||||
|
@ -15,7 +15,7 @@ export default class OpenTrackingMessageStatus extends React.Component {
|
|||
}
|
||||
|
||||
_getStateFromMessage(message) {
|
||||
const metadata = message.metadataForPluginId(plugin.appId);
|
||||
const metadata = message.metadataForPluginId(PLUGIN_ID);
|
||||
if (!metadata) {
|
||||
return {hasMetadata: false, opened: false}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
.open-tracking-icon {
|
||||
height: 10px;
|
||||
margin: -9px 0 0 4px;
|
||||
}
|
||||
|
||||
.read-receipt-message-status {
|
||||
|
|
|
@ -109,6 +109,7 @@ window.TEST_ACCOUNT_CLIENT_ID = "local-test-account-client-id"
|
|||
window.TEST_ACCOUNT_ID = "test-account-server-id"
|
||||
window.TEST_ACCOUNT_EMAIL = "tester@nylas.com"
|
||||
window.TEST_ACCOUNT_NAME = "Nylas Test"
|
||||
window.TEST_PLUGIN_ID = "test-plugin-id-123"
|
||||
|
||||
beforeEach ->
|
||||
NylasEnv.testOrganizationUnit = null
|
||||
|
|
|
@ -11,13 +11,17 @@ class MessageBodyProcessor
|
|||
@_subscriptions = []
|
||||
@resetCache()
|
||||
|
||||
resetCache: ->
|
||||
# Store an object for recently processed items. Put the item reference into
|
||||
# both data structures so we can access it in O(1) and also delete in O(1)
|
||||
@_recentlyProcessedA = []
|
||||
@_recentlyProcessedD = {}
|
||||
for {message, callback} in @_subscriptions
|
||||
callback(@process(message))
|
||||
resetCache: (msg) ->
|
||||
if msg
|
||||
key = @_key(msg)
|
||||
delete @_recentlyProcessedD[key]
|
||||
else
|
||||
# Store an object for recently processed items. Put the item reference into
|
||||
# both data structures so we can access it in O(1) and also delete in O(1)
|
||||
@_recentlyProcessedA = []
|
||||
@_recentlyProcessedD = {}
|
||||
for {message, callback} in @_subscriptions
|
||||
callback(@process(message))
|
||||
|
||||
# It's far safer to key off the hash of the body then the [id, version]
|
||||
# pair. This is because it's theoretically possible for the body to
|
||||
|
|
|
@ -2,13 +2,8 @@ Rx = require 'rx-lite'
|
|||
_ = require 'underscore'
|
||||
Category = require '../flux/models/category'
|
||||
QuerySubscriptionPool = require '../flux/models/query-subscription-pool'
|
||||
AccountStore = require '../flux/stores/account-store'
|
||||
DatabaseStore = require '../flux/stores/database-store'
|
||||
|
||||
AccountOperators = {}
|
||||
|
||||
AccountObservables = {}
|
||||
|
||||
CategoryOperators =
|
||||
sort: ->
|
||||
obs = @.map (categories) ->
|
||||
|
@ -60,10 +55,8 @@ CategoryObservables =
|
|||
CategoryObservables.forAccount(account).sort()
|
||||
.categoryFilter (cat) -> cat.isHiddenCategory()
|
||||
|
||||
|
||||
module.exports =
|
||||
Categories: CategoryObservables
|
||||
Accounts: AccountObservables
|
||||
|
||||
# Attach a few global helpers
|
||||
|
||||
|
|
|
@ -75,7 +75,17 @@ class Package
|
|||
@metadata ?= Package.loadMetadata(@path)
|
||||
@bundledPackage = Package.isBundledPackagePath(@path)
|
||||
@name = @metadata?.name ? path.basename(@path)
|
||||
@pluginAppId = @metadata.appId ? null
|
||||
|
||||
if @metadata.appId
|
||||
if _.isString @metadata.appId
|
||||
@pluginAppId = @metadata.appId ? null
|
||||
else if _.isObject @metadata.appId
|
||||
@pluginAppId = @metadata.appId[NylasEnv.config.get('env')] ? null
|
||||
else
|
||||
@pluginAppId = null
|
||||
else
|
||||
@pluginAppId = null
|
||||
|
||||
@displayName = @metadata?.displayName || @name
|
||||
ModuleCache.add(@path, @metadata)
|
||||
@reset()
|
||||
|
|
Loading…
Reference in a new issue