diff --git a/js/models/conversations.js b/js/models/conversations.js index 3191f3319..da8347e8a 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -162,6 +162,10 @@ this.set({ isOnline: lokiP2pAPI.isOnline(this.id) }); }, + isOnline() { + return this.isMe() || this.get('isOnline'); + }, + isMe() { return this.id === this.ourNumber; }, @@ -391,7 +395,7 @@ status: this.lastMessageStatus, text: this.lastMessage, }, - isOnline: this.get('isOnline'), + isOnline: this.isOnline(), onClick: () => this.trigger('select', this), }; diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js index 9d054d16b..24df15e91 100644 --- a/js/views/conversation_view.js +++ b/js/views/conversation_view.js @@ -185,6 +185,7 @@ isMe: this.model.isMe(), isBlocked: this.model.isBlocked(), isGroup: !this.model.isPrivate(), + isOnline: this.model.isOnline(), expirationSettingName, showBackButton: Boolean(this.panels && this.panels.length), timerOptions: Whisper.ExpirationTimerOptions.map(item => ({ diff --git a/ts/components/Avatar.tsx b/ts/components/Avatar.tsx index 7b34b123e..a4f3e2ff9 100644 --- a/ts/components/Avatar.tsx +++ b/ts/components/Avatar.tsx @@ -14,6 +14,7 @@ interface Props { profileName?: string; size: number; borderColor?: string; + borderWidth?: number; } interface State { @@ -49,6 +50,7 @@ export class Avatar extends React.Component { phoneNumber, profileName, borderColor, + borderWidth, } = this.props; const { imageBroken } = this.state; const hasImage = avatarPath && !imageBroken; @@ -61,12 +63,7 @@ export class Avatar extends React.Component { !name && profileName ? ` ~${profileName}` : '' }`; - const borderStyle = borderColor - ? { - borderColor: borderColor, - borderStyle: 'solid', - } - : undefined; + const borderStyle = this.getBorderStyle(borderColor, borderWidth); return ( { } public renderNoImage() { - const { conversationType, name, size, borderColor } = this.props; + const { + conversationType, + name, + size, + borderColor, + borderWidth, + } = this.props; const initials = getInitials(name); const isGroup = conversationType === 'group'; - const borderStyle = borderColor - ? { - borderColor: borderColor, - borderStyle: 'solid', - } - : undefined; + const borderStyle = this.getBorderStyle(borderColor, borderWidth); if (!isGroup && initials) { return ( @@ -140,4 +138,16 @@ export class Avatar extends React.Component { ); } + + private getBorderStyle(color?: string, width?: number) { + const borderWidth = typeof width === 'number' ? width : 3; + + return color + ? { + borderColor: color, + borderStyle: 'solid', + borderWidth: borderWidth, + } + : undefined; + } } diff --git a/ts/components/ConversationListItem.tsx b/ts/components/ConversationListItem.tsx index bacf476f0..d472f80ab 100644 --- a/ts/components/ConversationListItem.tsx +++ b/ts/components/ConversationListItem.tsx @@ -7,7 +7,7 @@ import { Timestamp } from './conversation/Timestamp'; import { ContactName } from './conversation/ContactName'; import { TypingAnimation } from './conversation/TypingAnimation'; -import { Localizer } from '../types/Util'; +import { Colors, Localizer } from '../types/Util'; interface Props { phoneNumber: string; @@ -47,6 +47,8 @@ export class ConversationListItem extends React.Component { isOnline, } = this.props; + const borderColor = isOnline ? Colors.ONLINE : Colors.OFFLINE; + return (
{ phoneNumber={phoneNumber} profileName={profileName} size={48} - borderColor={isOnline ? '#1c8260' : '#3d3e44'} + borderColor={borderColor} /> {this.renderUnread()}
diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index e4c2c3973..e0b9813ab 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { ContactName } from './ContactName'; import { Avatar } from '../Avatar'; -import { Localizer } from '../../types/Util'; +import { Colors, Localizer } from '../../types/Util'; import { ContextMenu, ContextMenuTrigger, @@ -33,6 +33,7 @@ interface Props { isBlocked: boolean; isMe: boolean; isGroup: boolean; + isOnline?: boolean; expirationSettingName?: string; showBackButton: boolean; timerOptions: Array; @@ -118,8 +119,11 @@ export class ConversationHeader extends React.Component { name, phoneNumber, profileName, + isOnline, } = this.props; + const borderColor = isOnline ? Colors.ONLINE : Colors.OFFLINE_LIGHT; + return ( { phoneNumber={phoneNumber} profileName={profileName} size={28} + borderColor={borderColor} + borderWidth={2} /> ); diff --git a/ts/types/Util.ts b/ts/types/Util.ts index 79826adc7..c0b61f68e 100644 --- a/ts/types/Util.ts +++ b/ts/types/Util.ts @@ -18,3 +18,9 @@ export type Color = | 'purple' | 'red' | 'teal'; + +export enum Colors { + OFFLINE = '#3d3e44', + OFFLINE_LIGHT = '#cccece', + ONLINE = '#1c8260', +}