Merge pull request #1778 from Brice-W/focus-issue

Fix for focus issue
pull/1792/head
Audric Ackermann 4 years ago committed by GitHub
commit 6df84fbd1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -59,7 +59,7 @@
// If message is unread, we mark it read. Otherwise, we update the expiration
// timer to the time specified by the read sync if it's earlier than
// the previous read time.
if (message.isUnread()) {
if (message.isUnread() && window.isFocused()) {
await message.markRead(readAt);
// onReadMessage may result in messages older than this one being

@ -56,7 +56,7 @@ window.lokiFeatureFlags = {
useFileOnionRequests: true,
useFileOnionRequestsV2: true, // more compact encoding of files in response
padOutgoingAttachments: true,
enablePinConversations: false,
enablePinConversations: true,
};
if (typeof process.env.NODE_ENV === 'string' && process.env.NODE_ENV.includes('test-integration')) {

@ -63,6 +63,8 @@ const ConversationListItem = (props: Props) => {
isMe,
isPinned,
isTyping,
isPublic,
left,
type,
lastMessage,
memberAvatars,
@ -126,6 +128,8 @@ const ConversationListItem = (props: Props) => {
triggerId={triggerId}
type={type}
isMe={isMe}
isPublic={isPublic}
left={left}
notificationForConvo={notificationForConvo}
currentNotificationSetting={currentNotificationSetting}
/>

@ -42,6 +42,7 @@ import { MessageInteraction } from '../../interactions';
import autoBind from 'auto-bind';
import { AudioPlayerWithEncryptedFile } from './H5AudioPlayer';
import { ClickToTrustSender } from './message/ClickToTrustSender';
import { ReadableMessage } from './ReadableMessage';
// Same as MIN_WIDTH in ImageGrid.tsx
const MINIMUM_LINK_PREVIEW_IMAGE_WIDTH = 200;
@ -728,8 +729,8 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
divClasses.push('flash-green-once');
}
const onVisible = (inView: boolean) => {
if (inView && shouldMarkReadWhenVisible) {
const onVisible = (inView: boolean | Object) => {
if (inView === true && shouldMarkReadWhenVisible && window.isFocused()) {
// mark the message as read.
// this will trigger the expire timer.
void markRead(Date.now());
@ -737,14 +738,10 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
};
return (
<InView
<ReadableMessage
id={id}
as="div"
className={classNames(divClasses)}
onChange={onVisible}
threshold={1}
delay={200}
triggerOnce={true}
onContextMenu={this.handleContextMenu}
>
{this.renderAvatar()}
@ -818,7 +815,7 @@ class MessageInner extends React.PureComponent<MessageRegularProps, State> {
{this.renderError(!isIncoming)}
{this.renderContextMenu()}
</div>
</InView>
</ReadableMessage>
);
}

@ -0,0 +1,22 @@
import React from 'react';
import { useFocus } from '../../hooks/useFocus';
import { InView, useInView } from 'react-intersection-observer';
type ReadableMessageProps = {
children: React.ReactNode;
id: string;
className: string;
onChange: (inView: boolean) => void;
onContextMenu: (e: any) => void;
};
export const ReadableMessage = (props: ReadableMessageProps) => {
const { onChange } = props;
useFocus(onChange);
return (
<InView {...props} as="div" threshold={1} delay={200} triggerOnce={false}>
{props.children}
</InView>
);
};

@ -378,7 +378,7 @@ export class SessionMessagesList extends React.Component<Props, State> {
return;
}
if (this.getScrollOffsetBottomPx() === 0) {
if (this.getScrollOffsetBottomPx() === 0 && window.isFocused()) {
void conversation.markRead(messages[0].attributes.received_at);
}
}

@ -17,7 +17,7 @@ import {
import { fromHex } from '../../../session/utils/String';
import { TaskTimedOutError } from '../../../session/utils/Promise';
import { mn_decode } from '../../../session/crypto/mnemonic';
import { SwarmPolling } from '../../../session/snode_api/swarmPolling';
import { getSwarmPollingInstance } from '../../../session/snode_api/swarmPolling';
export const MAX_USERNAME_LENGTH = 20;
// tslint:disable: use-simple-attributes
@ -191,11 +191,9 @@ export async function signInWithLinking(signInDetails: {
try {
await resetRegistration();
await window.setPassword(password);
const pubkeyStr = await signInByLinkingDevice(userRecoveryPhrase, 'english');
await signInByLinkingDevice(userRecoveryPhrase, 'english');
let displayNameFromNetwork = '';
SwarmPolling.getInstance().addPubkey(pubkeyStr);
SwarmPolling.getInstance().start();
await getSwarmPollingInstance().start();
await PromiseUtils.waitForTask(done => {
window.Whisper.events.on('configurationMessageReceived', (displayName: string) => {

@ -0,0 +1,10 @@
import { useEffect } from 'react';
export const useFocus = (action: (param: any) => void) => {
useEffect(() => {
window.addEventListener('focus', action);
return () => {
window.removeEventListener('focus', action);
};
});
};

@ -173,6 +173,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
private typingRefreshTimer?: NodeJS.Timeout | null;
private typingPauseTimer?: NodeJS.Timeout | null;
private typingTimer?: NodeJS.Timeout | null;
private lastReadTimestamp: number;
private pending: any;
@ -188,11 +189,19 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
this.updateLastMessage = _.throttle(this.bouncyUpdateLastMessage.bind(this), 1000);
this.throttledNotify = _.debounce(this.notify, 500, { maxWait: 1000 });
//start right away the function is called, and wait 1sec before calling it again
this.markRead = _.debounce(this.markReadBouncy, 1000, { leading: true });
const markReadDebounced = _.debounce(this.markReadBouncy, 1000, { leading: true });
this.markRead = (newestUnreadDate: number) => {
const lastReadTimestamp = this.lastReadTimestamp;
if (newestUnreadDate > lastReadTimestamp) {
this.lastReadTimestamp = newestUnreadDate;
}
void markReadDebounced(newestUnreadDate);
};
// Listening for out-of-band data updates
this.typingRefreshTimer = null;
this.typingPauseTimer = null;
this.lastReadTimestamp = 0;
window.inboxStore?.dispatch(conversationActions.conversationChanged(this.id, this.getProps()));
}
@ -914,6 +923,11 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
public async markReadBouncy(newestUnreadDate: number, providedOptions: any = {}) {
const lastReadTimestamp = this.lastReadTimestamp;
if (newestUnreadDate < lastReadTimestamp) {
return;
}
const options = providedOptions || {};
_.defaults(options, { sendReadReceipts: true });
@ -959,7 +973,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const cachedUnreadCountOnConvo = this.get('unreadCount');
if (cachedUnreadCountOnConvo !== read.length) {
// reset the unreadCount on the convo to the real one coming from markRead messages on the db
this.set({ unreadCount: 0 });
this.set({ unreadCount: realUnreadCount });
await this.commit();
} else {
// window?.log?.info('markRead(): nothing newly read.');

@ -1047,6 +1047,8 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
public async markRead(readAt: number) {
this.markReadNoCommit(readAt);
this.getConversation()?.markRead(this.attributes.received_at);
await this.commit();
}

1
ts/window.d.ts vendored

@ -40,6 +40,7 @@ declare global {
getFriendsFromContacts: any;
getSettingValue: any;
i18n: LocalizerType;
isFocused: () => boolean;
libloki: Libloki;
libsignal: LibsignalProtocol;
log: any;

Loading…
Cancel
Save