diff options
Diffstat (limited to 'src/components/services/tabs/TabItem.js')
-rw-r--r-- | src/components/services/tabs/TabItem.js | 193 |
1 files changed, 114 insertions, 79 deletions
diff --git a/src/components/services/tabs/TabItem.js b/src/components/services/tabs/TabItem.js index ccf3333f8..023e152c7 100644 --- a/src/components/services/tabs/TabItem.js +++ b/src/components/services/tabs/TabItem.js | |||
@@ -1,6 +1,4 @@ | |||
1 | import { | 1 | import { Menu, dialog, app, getCurrentWindow } from '@electron/remote'; |
2 | Menu, dialog, app, getCurrentWindow, | ||
3 | } from '@electron/remote'; | ||
4 | import React, { Component } from 'react'; | 2 | import React, { Component } from 'react'; |
5 | import { defineMessages, intlShape } from 'react-intl'; | 3 | import { defineMessages, intlShape } from 'react-intl'; |
6 | import PropTypes from 'prop-types'; | 4 | import PropTypes from 'prop-types'; |
@@ -14,7 +12,9 @@ import { observable, autorun } from 'mobx'; | |||
14 | import ServiceModel from '../../../models/Service'; | 12 | import ServiceModel from '../../../models/Service'; |
15 | import { ctrlKey, cmdKey } from '../../../environment'; | 13 | import { ctrlKey, cmdKey } from '../../../environment'; |
16 | 14 | ||
17 | const IS_SERVICE_DEBUGGING_ENABLED = (localStorage.getItem('debug') || '').includes('Ferdi:Service'); | 15 | const IS_SERVICE_DEBUGGING_ENABLED = ( |
16 | localStorage.getItem('debug') || '' | ||
17 | ).includes('Ferdi:Service'); | ||
18 | 18 | ||
19 | const messages = defineMessages({ | 19 | const messages = defineMessages({ |
20 | reload: { | 20 | reload: { |
@@ -63,10 +63,21 @@ const messages = defineMessages({ | |||
63 | }, | 63 | }, |
64 | confirmDeleteService: { | 64 | confirmDeleteService: { |
65 | id: 'tabs.item.confirmDeleteService', | 65 | id: 'tabs.item.confirmDeleteService', |
66 | defaultMessage: '!!!Do you really want to delete the {serviceName} service?', | 66 | defaultMessage: |
67 | '!!!Do you really want to delete the {serviceName} service?', | ||
67 | }, | 68 | }, |
68 | }); | 69 | }); |
69 | 70 | ||
71 | let pollIndicatorTransition = 'none'; | ||
72 | let polledTransition = 'none'; | ||
73 | let pollAnsweredTransition = 'none'; | ||
74 | |||
75 | if (window.matchMedia('(prefers-reduced-motion: no-preference)')) { | ||
76 | pollIndicatorTransition = 'background 0.5s'; | ||
77 | polledTransition = 'background 0.1s'; | ||
78 | pollAnsweredTransition = 'background 0.1s'; | ||
79 | } | ||
80 | |||
70 | const styles = { | 81 | const styles = { |
71 | pollIndicator: { | 82 | pollIndicator: { |
72 | position: 'absolute', | 83 | position: 'absolute', |
@@ -75,7 +86,7 @@ const styles = { | |||
75 | height: 10, | 86 | height: 10, |
76 | borderRadius: 5, | 87 | borderRadius: 5, |
77 | background: 'gray', | 88 | background: 'gray', |
78 | transition: 'background 0.5s', | 89 | transition: pollIndicatorTransition, |
79 | }, | 90 | }, |
80 | pollIndicatorPoll: { | 91 | pollIndicatorPoll: { |
81 | left: 2, | 92 | left: 2, |
@@ -85,18 +96,20 @@ const styles = { | |||
85 | }, | 96 | }, |
86 | polled: { | 97 | polled: { |
87 | background: 'yellow !important', | 98 | background: 'yellow !important', |
88 | transition: 'background 0.1s', | 99 | transition: polledTransition, |
89 | }, | 100 | }, |
90 | pollAnswered: { | 101 | pollAnswered: { |
91 | background: 'green !important', | 102 | background: 'green !important', |
92 | transition: 'background 0.1s', | 103 | transition: pollAnsweredTransition, |
93 | }, | 104 | }, |
94 | stale: { | 105 | stale: { |
95 | background: 'red !important', | 106 | background: 'red !important', |
96 | }, | 107 | }, |
97 | }; | 108 | }; |
98 | 109 | ||
99 | @injectSheet(styles) @observer class TabItem extends Component { | 110 | @injectSheet(styles) |
111 | @observer | ||
112 | class TabItem extends Component { | ||
100 | static propTypes = { | 113 | static propTypes = { |
101 | classes: PropTypes.object.isRequired, | 114 | classes: PropTypes.object.isRequired, |
102 | service: PropTypes.instanceOf(ServiceModel).isRequired, | 115 | service: PropTypes.instanceOf(ServiceModel).isRequired, |
@@ -131,13 +144,17 @@ const styles = { | |||
131 | if (Date.now() - service.lastPoll < ms('0.2s')) { | 144 | if (Date.now() - service.lastPoll < ms('0.2s')) { |
132 | this.isPolled = true; | 145 | this.isPolled = true; |
133 | 146 | ||
134 | setTimeout(() => { this.isPolled = false; }, ms('1s')); | 147 | setTimeout(() => { |
148 | this.isPolled = false; | ||
149 | }, ms('1s')); | ||
135 | } | 150 | } |
136 | 151 | ||
137 | if (Date.now() - service.lastPollAnswer < ms('0.2s')) { | 152 | if (Date.now() - service.lastPollAnswer < ms('0.2s')) { |
138 | this.isPollAnswered = true; | 153 | this.isPollAnswered = true; |
139 | 154 | ||
140 | setTimeout(() => { this.isPollAnswered = false; }, ms('1s')); | 155 | setTimeout(() => { |
156 | this.isPollAnswered = false; | ||
157 | }, ms('1s')); | ||
141 | } | 158 | } |
142 | }); | 159 | }); |
143 | } | 160 | } |
@@ -163,62 +180,85 @@ const styles = { | |||
163 | } = this.props; | 180 | } = this.props; |
164 | const { intl } = this.context; | 181 | const { intl } = this.context; |
165 | 182 | ||
166 | const menuTemplate = [{ | 183 | const menuTemplate = [ |
167 | label: service.name || service.recipe.name, | 184 | { |
168 | enabled: false, | 185 | label: service.name || service.recipe.name, |
169 | }, { | 186 | enabled: false, |
170 | type: 'separator', | 187 | }, |
171 | }, { | 188 | { |
172 | label: intl.formatMessage(messages.reload), | 189 | type: 'separator', |
173 | click: reload, | 190 | }, |
174 | accelerator: `${cmdKey}+R`, | 191 | { |
175 | }, { | 192 | label: intl.formatMessage(messages.reload), |
176 | label: intl.formatMessage(messages.edit), | 193 | click: reload, |
177 | click: () => openSettings({ | 194 | accelerator: `${cmdKey}+R`, |
178 | path: `services/edit/${service.id}`, | 195 | }, |
179 | }), | 196 | { |
180 | }, { | 197 | label: intl.formatMessage(messages.edit), |
181 | type: 'separator', | 198 | click: () => |
182 | }, { | 199 | openSettings({ |
183 | label: service.isNotificationEnabled | 200 | path: `services/edit/${service.id}`, |
184 | ? intl.formatMessage(messages.disableNotifications) | 201 | }), |
185 | : intl.formatMessage(messages.enableNotifications), | 202 | }, |
186 | click: () => toggleNotifications(), | 203 | { |
187 | }, { | 204 | type: 'separator', |
188 | label: service.isMuted | ||
189 | ? intl.formatMessage(messages.enableAudio) | ||
190 | : intl.formatMessage(messages.disableAudio), | ||
191 | click: () => toggleAudio(), | ||
192 | }, { | ||
193 | label: intl.formatMessage(service.isEnabled ? messages.disableService : messages.enableService), | ||
194 | click: () => (service.isEnabled ? disableService() : enableService()), | ||
195 | }, { | ||
196 | label: intl.formatMessage(service.isHibernating ? messages.wakeUpService : messages.hibernateService), | ||
197 | click: () => (service.isHibernating ? wakeUpService() : hibernateService()), | ||
198 | enabled: service.canHibernate, | ||
199 | }, { | ||
200 | type: 'separator', | ||
201 | }, { | ||
202 | label: intl.formatMessage(messages.deleteService), | ||
203 | click: () => { | ||
204 | const selection = dialog.showMessageBoxSync(app.mainWindow, { | ||
205 | type: 'question', | ||
206 | message: intl.formatMessage(messages.deleteService), | ||
207 | detail: intl.formatMessage(messages.confirmDeleteService, { serviceName: service.name || service.recipe.name }), | ||
208 | buttons: [ | ||
209 | 'Yes', | ||
210 | 'No', | ||
211 | ], | ||
212 | }); | ||
213 | if (selection === 0) { | ||
214 | deleteService(); | ||
215 | } | ||
216 | }, | 205 | }, |
217 | }]; | 206 | { |
207 | label: service.isNotificationEnabled | ||
208 | ? intl.formatMessage(messages.disableNotifications) | ||
209 | : intl.formatMessage(messages.enableNotifications), | ||
210 | click: () => toggleNotifications(), | ||
211 | }, | ||
212 | { | ||
213 | label: service.isMuted | ||
214 | ? intl.formatMessage(messages.enableAudio) | ||
215 | : intl.formatMessage(messages.disableAudio), | ||
216 | click: () => toggleAudio(), | ||
217 | }, | ||
218 | { | ||
219 | label: intl.formatMessage( | ||
220 | service.isEnabled ? messages.disableService : messages.enableService, | ||
221 | ), | ||
222 | click: () => (service.isEnabled ? disableService() : enableService()), | ||
223 | }, | ||
224 | { | ||
225 | label: intl.formatMessage( | ||
226 | service.isHibernating | ||
227 | ? messages.wakeUpService | ||
228 | : messages.hibernateService, | ||
229 | ), | ||
230 | click: () => | ||
231 | (service.isHibernating ? wakeUpService() : hibernateService()), | ||
232 | enabled: service.canHibernate, | ||
233 | }, | ||
234 | { | ||
235 | type: 'separator', | ||
236 | }, | ||
237 | { | ||
238 | label: intl.formatMessage(messages.deleteService), | ||
239 | click: () => { | ||
240 | const selection = dialog.showMessageBoxSync(app.mainWindow, { | ||
241 | type: 'question', | ||
242 | message: intl.formatMessage(messages.deleteService), | ||
243 | detail: intl.formatMessage(messages.confirmDeleteService, { | ||
244 | serviceName: service.name || service.recipe.name, | ||
245 | }), | ||
246 | buttons: ['Yes', 'No'], | ||
247 | }); | ||
248 | if (selection === 0) { | ||
249 | deleteService(); | ||
250 | } | ||
251 | }, | ||
252 | }, | ||
253 | ]; | ||
218 | const menu = Menu.buildFromTemplate(menuTemplate); | 254 | const menu = Menu.buildFromTemplate(menuTemplate); |
219 | 255 | ||
220 | let notificationBadge = null; | 256 | let notificationBadge = null; |
221 | if ((showMessageBadgeWhenMutedSetting || service.isNotificationEnabled) && showMessageBadgesEvenWhenMuted && service.isBadgeEnabled) { | 257 | if ( |
258 | (showMessageBadgeWhenMutedSetting || service.isNotificationEnabled) && | ||
259 | showMessageBadgesEvenWhenMuted && | ||
260 | service.isBadgeEnabled | ||
261 | ) { | ||
222 | notificationBadge = ( | 262 | notificationBadge = ( |
223 | <span> | 263 | <span> |
224 | {service.unreadDirectMessageCount > 0 && ( | 264 | {service.unreadDirectMessageCount > 0 && ( |
@@ -226,17 +266,13 @@ const styles = { | |||
226 | {service.unreadDirectMessageCount} | 266 | {service.unreadDirectMessageCount} |
227 | </span> | 267 | </span> |
228 | )} | 268 | )} |
229 | {service.unreadIndirectMessageCount > 0 | 269 | {service.unreadIndirectMessageCount > 0 && |
230 | && service.unreadDirectMessageCount === 0 | 270 | service.unreadDirectMessageCount === 0 && |
231 | && service.isIndirectMessageBadgeEnabled && ( | 271 | service.isIndirectMessageBadgeEnabled && ( |
232 | <span className="tab-item__message-count is-indirect"> | 272 | <span className="tab-item__message-count is-indirect">•</span> |
233 | • | ||
234 | </span> | ||
235 | )} | 273 | )} |
236 | {service.isHibernating && ( | 274 | {service.isHibernating && ( |
237 | <span className="tab-item__message-count hibernating"> | 275 | <span className="tab-item__message-count hibernating">•</span> |
238 | • | ||
239 | </span> | ||
240 | )} | 276 | )} |
241 | </span> | 277 | </span> |
242 | ); | 278 | ); |
@@ -245,7 +281,8 @@ const styles = { | |||
245 | return ( | 281 | return ( |
246 | <li | 282 | <li |
247 | className={classnames({ | 283 | className={classnames({ |
248 | [classes.stale]: IS_SERVICE_DEBUGGING_ENABLED && service.lostRecipeConnection, | 284 | [classes.stale]: |
285 | IS_SERVICE_DEBUGGING_ENABLED && service.lostRecipeConnection, | ||
249 | 'tab-item': true, | 286 | 'tab-item': true, |
250 | 'is-active': service.isActive, | 287 | 'is-active': service.isActive, |
251 | 'has-custom-icon': service.hasCustomIcon, | 288 | 'has-custom-icon': service.hasCustomIcon, |
@@ -253,13 +290,11 @@ const styles = { | |||
253 | })} | 290 | })} |
254 | onClick={clickHandler} | 291 | onClick={clickHandler} |
255 | onContextMenu={() => menu.popup(getCurrentWindow())} | 292 | onContextMenu={() => menu.popup(getCurrentWindow())} |
256 | data-tip={`${service.name} ${shortcutIndex <= 9 ? `(${ctrlKey}+${shortcutIndex})` : ''}`} | 293 | data-tip={`${service.name} ${ |
294 | shortcutIndex <= 9 ? `(${ctrlKey}+${shortcutIndex})` : '' | ||
295 | }`} | ||
257 | > | 296 | > |
258 | <img | 297 | <img src={service.icon} className="tab-item__icon" alt="" /> |
259 | src={service.icon} | ||
260 | className="tab-item__icon" | ||
261 | alt="" | ||
262 | /> | ||
263 | {notificationBadge} | 298 | {notificationBadge} |
264 | {IS_SERVICE_DEBUGGING_ENABLED && ( | 299 | {IS_SERVICE_DEBUGGING_ENABLED && ( |
265 | <> | 300 | <> |