mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-21 15:56:10 +08:00
feat(snooze): Add snooze date label to snooze threads
- Adds a new InjectedComponentSet for the role 'ThreadList:Label'. - Adds a new label to the thread list indicating the snooze date if the thread has been snoozed - Coerces MailLabel to achieve this. This is a temporary hack, we should design a better view to display snooze date information
This commit is contained in:
parent
f75eddb518
commit
f22fdbae49
|
@ -80,7 +80,13 @@ c3 = new ListTabular.Column
|
|||
labels.push c3LabelComponentCache[label.id]
|
||||
|
||||
<span className="details">
|
||||
{labels}
|
||||
<InjectedComponentSet
|
||||
inline
|
||||
containerRequired={false}
|
||||
children={labels}
|
||||
matching={role: "ThreadList:Label"}
|
||||
className="thread-injected-mail-labels"
|
||||
exposedProps={thread: thread}/>
|
||||
<span className="subject">{subject(thread.subject)}</span>
|
||||
<span className="snippet">{thread.snippet}</span>
|
||||
{attachment}
|
||||
|
@ -148,7 +154,13 @@ cNarrow = new ListTabular.Column
|
|||
<div className="snippet-and-labels">
|
||||
<div className="snippet">{thread.snippet} </div>
|
||||
<div style={flex: 1, flexShrink: 1}></div>
|
||||
{labels}
|
||||
<InjectedComponentSet
|
||||
inline
|
||||
containerRequired={false}
|
||||
children={labels}
|
||||
matching={role: "ThreadList:Label"}
|
||||
className="thread-injected-mail-labels-narrow"
|
||||
exposedProps={thread: thread}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -239,6 +239,9 @@
|
|||
.thread-injected-icons {
|
||||
vertical-align: top;
|
||||
}
|
||||
.thread-injected-mail-labels {
|
||||
margin-right: 6px;
|
||||
}
|
||||
.thread-icon {
|
||||
width:25px;
|
||||
height:24px;
|
||||
|
|
|
@ -1,21 +1,24 @@
|
|||
/** @babel */
|
||||
import {ComponentRegistry} from 'nylas-exports';
|
||||
import {ToolbarSnooze, BulkThreadSnooze} from './toolbar-components';
|
||||
import QuickActionSnoozeButton from './quick-action-snooze-button'
|
||||
import {ToolbarSnooze, BulkThreadSnooze} from './snooze-toolbar-components';
|
||||
import SnoozeQuickActionButton from './snooze-quick-action-button'
|
||||
import SnoozeMailLabel from './snooze-mail-label'
|
||||
import SnoozeStore from './snooze-store'
|
||||
|
||||
|
||||
export function activate() {
|
||||
this.snoozeStore = new SnoozeStore()
|
||||
ComponentRegistry.register(ToolbarSnooze, {role: 'message:Toolbar'});
|
||||
ComponentRegistry.register(QuickActionSnoozeButton, {role: 'ThreadListQuickAction'});
|
||||
ComponentRegistry.register(SnoozeQuickActionButton, {role: 'ThreadListQuickAction'});
|
||||
ComponentRegistry.register(BulkThreadSnooze, {role: 'thread:BulkAction'});
|
||||
ComponentRegistry.register(SnoozeMailLabel, {role: 'ThreadList:Label'});
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
ComponentRegistry.unregister(ToolbarSnooze);
|
||||
ComponentRegistry.unregister(QuickActionSnoozeButton);
|
||||
ComponentRegistry.unregister(SnoozeQuickActionButton);
|
||||
ComponentRegistry.unregister(BulkThreadSnooze);
|
||||
ComponentRegistry.unregister(SnoozeMailLabel);
|
||||
this.snoozeStore.deactivate()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,4 +5,4 @@ export const PLUGIN_ID = plugin.appId[NylasEnv.config.get("env")];
|
|||
export const PLUGIN_NAME = "Snooze Plugin"
|
||||
export const SNOOZE_CATEGORY_NAME = "N1-Snoozed"
|
||||
export const DATE_FORMAT_LONG = 'ddd, MMM D, YYYY h:mmA'
|
||||
export const DATE_FORMAT_SHORT = 'MMM D h:mmA'
|
||||
export const DATE_FORMAT_SHORT = 'MMM D, h:mmA'
|
||||
|
|
44
internal_packages/thread-snooze/lib/snooze-mail-label.jsx
Normal file
44
internal_packages/thread-snooze/lib/snooze-mail-label.jsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import _ from 'underscore';
|
||||
import React, {Component, PropTypes} from 'react';
|
||||
import {RetinaImg, MailLabel} from 'nylas-component-kit';
|
||||
import {SNOOZE_CATEGORY_NAME, PLUGIN_ID} from './snooze-constants';
|
||||
import {snoozeMessage} from './snooze-utils';
|
||||
|
||||
|
||||
class SnoozeMailLabel extends Component {
|
||||
static displayName = 'SnoozeMailLabel';
|
||||
|
||||
static propTypes = {
|
||||
thread: PropTypes.object,
|
||||
};
|
||||
|
||||
render() {
|
||||
const {thread} = this.props;
|
||||
if (_.findWhere(thread.categories, {displayName: SNOOZE_CATEGORY_NAME})) {
|
||||
const metadata = thread.metadataForPluginId(PLUGIN_ID);
|
||||
if (metadata) {
|
||||
// TODO this is such a hack
|
||||
const {snoozeDate} = metadata;
|
||||
const message = snoozeMessage(snoozeDate).replace('Snoozed', '')
|
||||
const content = (
|
||||
<span className="snooze-mail-label">
|
||||
<RetinaImg
|
||||
name="icon-snoozed.png"
|
||||
mode={RetinaImg.Mode.ContentIsMask} />
|
||||
<span className="date-message">{message}</span>
|
||||
</span>
|
||||
)
|
||||
const label = {
|
||||
displayName: content,
|
||||
isLockedCategory: ()=> true,
|
||||
hue: ()=> 259,
|
||||
}
|
||||
return <MailLabel label={label} key={'snooze-message-' + thread.id} />;
|
||||
}
|
||||
return <span />
|
||||
}
|
||||
return <span />
|
||||
}
|
||||
}
|
||||
|
||||
export default SnoozeMailLabel;
|
|
@ -1,7 +1,7 @@
|
|||
/** @babel */
|
||||
import _ from 'underscore';
|
||||
import {Actions, NylasAPI, AccountStore} from 'nylas-exports';
|
||||
import {moveThreadsToSnooze} from './snooze-category-helpers';
|
||||
import {moveThreadsToSnooze, moveThreadsFromSnooze} from './snooze-utils';
|
||||
import {PLUGIN_ID, PLUGIN_NAME} from './snooze-constants';
|
||||
import SnoozeActions from './snooze-actions';
|
||||
|
||||
|
@ -40,6 +40,7 @@ class SnoozeStore {
|
|||
})
|
||||
})
|
||||
.catch((error)=> {
|
||||
moveThreadsFromSnooze(threads)
|
||||
Actions.closePopover();
|
||||
NylasEnv.reportError(error);
|
||||
NylasEnv.showErrorDialog(`Sorry, we were unable to save your snooze settings. ${error.message}`);
|
||||
|
|
|
@ -15,6 +15,25 @@ import {
|
|||
} from 'nylas-exports';
|
||||
import {SNOOZE_CATEGORY_NAME, DATE_FORMAT_SHORT} from './snooze-constants'
|
||||
|
||||
export function snoozeMessage(snoozeDate) {
|
||||
let message = 'Snoozed'
|
||||
if (snoozeDate) {
|
||||
let dateFormat = DATE_FORMAT_SHORT
|
||||
const date = moment(snoozeDate)
|
||||
const now = moment()
|
||||
const hourDifference = moment.duration(date.diff(now)).asHours()
|
||||
|
||||
if (hourDifference < 24) {
|
||||
dateFormat = dateFormat.replace('MMM D, ', '');
|
||||
}
|
||||
if (date.minutes() === 0) {
|
||||
dateFormat = dateFormat.replace(':mm', '');
|
||||
}
|
||||
|
||||
message += ` until ${DateUtils.format(date, dateFormat)}`;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
export function createSnoozeCategory(accountId, name = SNOOZE_CATEGORY_NAME) {
|
||||
const category = new Category({
|
||||
|
@ -76,7 +95,7 @@ export function getSnoozeCategoriesByAccount(accounts = AccountStore.accounts())
|
|||
|
||||
|
||||
export function groupProcessedThreadsByAccountId(categoriesByAccountId, threads) {
|
||||
return DatabaseStore.modelify(Thread, _.pluck(threads, 'id')).then((updatedThreads)=> {
|
||||
return DatabaseStore.modelify(Thread, _.pluck(threads, 'clientId')).then((updatedThreads)=> {
|
||||
const threadsByAccountId = {}
|
||||
updatedThreads.forEach((thread)=> {
|
||||
const accId = thread.accountId
|
||||
|
@ -95,15 +114,9 @@ export function groupProcessedThreadsByAccountId(categoriesByAccountId, threads)
|
|||
}
|
||||
|
||||
|
||||
export function moveThreads(threads, categoriesByAccountId, {snooze, snoozeDate} = {}) {
|
||||
export function moveThreads(threads, categoriesByAccountId, {snooze, description} = {}) {
|
||||
const inbox = CategoryStore.getInboxCategory
|
||||
const snoozeCat = (accId)=> categoriesByAccountId[accId]
|
||||
let description = 'Snoozed'
|
||||
if (snoozeDate) {
|
||||
const date = moment(snoozeDate)
|
||||
description += ` until ${DateUtils.format(date, DATE_FORMAT_SHORT)}`
|
||||
}
|
||||
|
||||
const tasks = TaskFactory.tasksForApplyingCategories({
|
||||
threads,
|
||||
categoriesToRemove: snooze ? inbox : snoozeCat,
|
||||
|
@ -125,7 +138,8 @@ export function moveThreads(threads, categoriesByAccountId, {snooze, snoozeDate}
|
|||
export function moveThreadsToSnooze(threads, snoozeDate) {
|
||||
return getSnoozeCategoriesByAccount()
|
||||
.then((categoriesByAccountId)=> {
|
||||
return moveThreads(threads, categoriesByAccountId, {snooze: true, snoozeDate})
|
||||
const description = snoozeMessage(snoozeDate)
|
||||
return moveThreads(threads, categoriesByAccountId, {snooze: true, description})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -133,6 +147,7 @@ export function moveThreadsToSnooze(threads, snoozeDate) {
|
|||
export function moveThreadsFromSnooze(threads) {
|
||||
return getSnoozeCategoriesByAccount()
|
||||
.then((categoriesByAccountId)=> {
|
||||
return moveThreads(threads, categoriesByAccountId, {snooze: false})
|
||||
const description = 'Unsnoozed';
|
||||
return moveThreads(threads, categoriesByAccountId, {snooze: false, description})
|
||||
})
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
@snooze-color: #472B82;
|
||||
|
||||
.snooze-mail-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
background-color: @snooze-color;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
BIN
static/images/thread-list/icon-snoozed@1x.png
Normal file
BIN
static/images/thread-list/icon-snoozed@1x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
static/images/thread-list/icon-snoozed@2x.png
Normal file
BIN
static/images/thread-list/icon-snoozed@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in a new issue