Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce per message timestamps as a configurable option. #2184

Open
wants to merge 5 commits into
base: unstable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@
"noteToSelf": "Note to Self",
"hideMenuBarTitle": "Hide Menu Bar",
"hideMenuBarDescription": "Toggle system menu bar visibility",
"perMessageTimestampsTitle": "Per Message Timestamps",
"perMessageTimestampsDescription": "Place timestamp in message bubble instead of between messages",
"startConversation": "Start New Conversation",
"invalidNumberError": "Invalid Session ID or ONS Name",
"failedResolveOns": "Failed to resolve ONS name",
Expand Down
7 changes: 7 additions & 0 deletions stylesheets/_session_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
background: var(--color-cell-background);
}

.module-message-clock--incoming {
color: var(--color-message-timestamp-text);
}
.module-message-clock--outgoing {
color: var(--color-message-timestamp-text);
}

.module-message {
position: relative;
display: inline-flex;
Expand Down
19 changes: 19 additions & 0 deletions ts/components/conversation/MessageClock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import moment from 'moment';

type Props = {
time: number;
};

export const MessageClock = (props: Props): JSX.Element => {
const { time } = props;

moment.locale('en-gb');
return <div style={{ paddingRight: '8px',
paddingLeft: '8px',
paddingBottom: '2px',
fontSize: '0.8em',
float: 'right' }}>
{moment(time).format('LT')}
</div>;
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { MessagePreview } from './MessagePreview';
import { MessageQuote } from './MessageQuote';
import { MessageText } from './MessageText';
import { ScrollToLoadedMessageContext } from '../../SessionMessagesListContainer';
import { MessageClock } from '../../MessageClock';

export type MessageContentSelectorProps = Pick<
MessageRenderingProps,
Expand Down Expand Up @@ -212,6 +213,7 @@ export const MessageContent = (props: Props) => {
rootMargin="500px 0px 500px 0px"
triggerOnce={false}
>
<div className={`module-message-clock--${direction}`}>
<IsMessageVisibleContext.Provider value={isMessageVisible}>
{!isDeleted && (
<>
Expand All @@ -234,6 +236,8 @@ export const MessageContent = (props: Props) => {
</>
) : null}
</IsMessageVisibleContext.Provider>
{window.getSettingValue('per-message-timestamps') && <MessageClock time={timestamp} />}
</div>
</InView>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const MessageText = (props: Props) => {
>
{isDeleted && <SessionIcon iconType="delete" iconSize="small" />}
<MessageBody
text={contents || ''}
text={contents}
disableLinks={multiSelectMode}
disableJumbomoji={false}
isGroup={conversationType === 'group'}
Expand Down
17 changes: 14 additions & 3 deletions ts/components/conversation/message/message-item/DateBreak.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ const DateBreakText = styled.div`

export const MessageDateBreak = (props: { timestamp: number; messageId: string }) => {
const { timestamp, messageId } = props;
const text = moment(timestamp).calendar(undefined, {
sameElse: 'llll',
});
let dateFormat;
if (window.getSettingValue('per-message-timestamps')) {
dateFormat = {
sameDay: '[Today]',
lastDay: '[Yesterday]',
lastWeek: 'LL',
sameElse: 'LL',
}
} else {
dateFormat = {
sameElse: 'llll',
}
}
const text = moment(timestamp).calendar(undefined, dateFormat);

return (
<DateBreakContainer id={`date-break-${messageId}`}>
Expand Down
14 changes: 14 additions & 0 deletions ts/components/settings/section/CategoryAppearance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null
? true
: window.getSettingValue(SettingsKey.settingsMenuBar);

const isPerMessageTimestampsActive =
window.getSettingValue(SettingsKey.settingsPerMessageTimestamps) === undefined
? true
: window.getSettingValue(SettingsKey.settingsPerMessageTimestamps);

const isSpellCheckActive =
window.getSettingValue(SettingsKey.settingsSpellCheck) === undefined
? true
Expand All @@ -78,6 +83,15 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null
active={isHideMenuBarActive}
/>
)}
<SessionToggleWithDescription
onClickToggle={() => {
window.togglePerMessageTimestamps();
forceUpdate();
}}
title={window.i18n('perMessageTimestampsTitle')}
description={window.i18n('perMessageTimestampsDescription')}
active={isPerMessageTimestampsActive}
/>
<SessionToggleWithDescription
onClickToggle={() => {
window.toggleSpellCheck();
Expand Down
3 changes: 3 additions & 0 deletions ts/data/settings-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const settingsLinkPreview = 'link-preview-setting';
const settingsStartInTray = 'start-in-tray-setting';
const settingsOpengroupPruning = 'prune-setting';

const settingsPerMessageTimestamps = 'per-message-timestamps';

export const SettingsKey = {
settingsReadReceipt,
settingsTypingIndicator,
Expand All @@ -17,4 +19,5 @@ export const SettingsKey = {
settingsLinkPreview,
settingsStartInTray,
settingsOpengroupPruning,
settingsPerMessageTimestamps
};
11 changes: 11 additions & 0 deletions ts/mains/main_renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ Storage.onready(async () => {
window.setMenuBarVisibility(!value);
},

getPerMessageTimestamps: () => Storage.get('per-message-timestamps', true),
setPerMessageTimestamps: async (value: boolean) => {
await Storage.put('per-message-timestamps', value);
},

getSpellCheck: () => Storage.get('spell-check', true),
setSpellCheck: async (value: boolean) => {
await Storage.put('spell-check', value);
Expand Down Expand Up @@ -291,6 +296,12 @@ async function start() {
window.Events.setHideMenuBar(!current);
};

window.togglePerMessageTimestamps= () => {
const currentValue = window.getSettingValue('per-message-timestamps');
const newValue = currentValue !== undefined ? !currentValue : true;
window.Events.setPerMessageTimestamps(newValue);
};

window.toggleSpellCheck = () => {
const currentValue = window.getSettingValue('spell-check');
// if undefined, it means 'default' so true. but we have to toggle it, so false
Expand Down
17 changes: 17 additions & 0 deletions ts/state/ducks/SessionTheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const darkColorSessionBorderColor = borderDarkThemeColor;
const darkColorRecoveryPhraseBannerBg = '#1f1f1f';
const darkColorPillDivider = '#353535';
const darkColorLastSeenIndicator = accentDarkTheme;
const darkColorMessageTimestampText = '#8e9091';
const darkColorQuoteBottomBarBg = '#404040';
const darkColorCellBackground = '#1b1b1b';
const darkColorReceivedMessageBg = '#2d2d2d';
Expand Down Expand Up @@ -94,6 +95,10 @@ export const switchHtmlToDarkTheme = () => {
'--color-last-seen-indicator',
darkColorLastSeenIndicator
);
document.documentElement.style.setProperty(
'--color-message-timestamp-text',
darkColorMessageTimestampText
);
document.documentElement.style.setProperty(
'--color-quote-bottom-bar-background',
darkColorQuoteBottomBarBg
Expand Down Expand Up @@ -175,6 +180,8 @@ const lightColorSessionBorder = `1px solid ${lightColorSessionBorderColor}`;
const lightColorRecoveryPhraseBannerBg = white;
const lightColorPillDivider = `${black}1A`;
const lightColorLastSeenIndicator = black;
const lightColorLastSeenIndicatorText = '#070c14';
const lightColorMessageTimestampText = '#070c14';
const lightColorQuoteBottomBarBg = '#f0f0f0';
const lightColorCellBackground = '#f9f9f9';
const lightColorReceivedMessageBg = '#f5f5f5';
Expand Down Expand Up @@ -244,6 +251,14 @@ export const switchHtmlToLightTheme = () => {
'--color-last-seen-indicator',
lightColorLastSeenIndicator
);
document.documentElement.style.setProperty(
'--color-last-seen-indicator-text',
lightColorLastSeenIndicatorText
);
document.documentElement.style.setProperty(
'--color-message-timestamp-text',
lightColorMessageTimestampText
);
document.documentElement.style.setProperty(
'--color-quote-bottom-bar-background',
lightColorQuoteBottomBarBg
Expand Down Expand Up @@ -356,6 +371,8 @@ export const SessionGlobalStyles = createGlobalStyle`
--color-recovery-phrase-banner-background: ${lightColorRecoveryPhraseBannerBg};
--color-pill-divider: ${lightColorPillDivider};
--color-last-seen-indicator: ${lightColorLastSeenIndicator};
--color-last-seen-indicator-text: ${lightColorLastSeenIndicatorText};
--color-message-timestamp-text: ${lightColorMessageTimestampText};
--color-quote-bottom-bar-background: ${lightColorQuoteBottomBarBg};
--color-cell-background: ${lightColorCellBackground};
--color-pill-divider-text: ${lightColorPillDividerText};
Expand Down
11 changes: 8 additions & 3 deletions ts/state/selectors/conversations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,15 @@ export const getSortedMessagesTypesOfSelectedConversation = createSelector(
: sortedMessages[index + 1].propsForMessage.serverTimestamp ||
sortedMessages[index + 1].propsForMessage.timestamp;

const hoursPreviousMessage = new Date(previousMessageTimestamp).getHours();
const hoursMessage = new Date(messageTimestamp).getHours();
const showDateBreak =
messageTimestamp - previousMessageTimestamp > maxMessagesBetweenTwoDateBreaks * 60 * 1000
? messageTimestamp
: undefined;
window.getSettingValue('per-message-timestamps')
? hoursMessage < hoursPreviousMessage ? messageTimestamp : undefined
: messageTimestamp - previousMessageTimestamp >
maxMessagesBetweenTwoDateBreaks * 60 * 1000
? messageTimestamp
: undefined;

if (msg.propsForDataExtractionNotification) {
return {
Expand Down
2 changes: 2 additions & 0 deletions ts/types/LocalizerKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export type LocalizerKeys =
| 'fileSizeWarning'
| 'openGroupURL'
| 'hideMenuBarDescription'
| 'perMessageTimestampsDescription'
| 'pickClosedGroupMember'
| 'ByUsingThisService...'
| 'startConversation'
Expand Down Expand Up @@ -246,6 +247,7 @@ export type LocalizerKeys =
| 'setPassword'
| 'editMenuDeleteContact'
| 'hideMenuBarTitle'
| 'perMessageTimestampsTitle'
| 'imageCaptionIconAlt'
| 'sendRecoveryPhraseTitle'
| 'multipleJoinedTheGroup'
Expand Down
3 changes: 3 additions & 0 deletions ts/util/accountManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ async function createAccount(identityKeyPair: any) {
await Storage.put(SettingsKey.settingsOpengroupPruning, true);
await window.setOpengroupPruning(true);

// Enable per-message timestamps by default.
await Storage.put(SettingsKey.settingsPerMessageTimestamps, true);

await setLocalPubKey(pubKeyString);
}

Expand Down
1 change: 1 addition & 0 deletions ts/window.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ declare global {
toggleCallMediaPermissionsTo: (enabled: boolean) => Promise<void>;
getCallMediaPermissions: () => boolean;
toggleMenuBar: () => void;
togglePerMessageTimestamps: () => void;
toggleSpellCheck: any;
setTheme: (newTheme: string) => any;
isDev?: () => boolean;
Expand Down