Merge pull request #2332 from oxen-io/clearnet

Session 1.8.6
pull/2465/head v1.8.6
Audric Ackermann 3 years ago committed by GitHub
commit 4c8b2d632b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -124,6 +124,15 @@ yarn start-prod # start the app on production mode (currently this is the only o
### Commands
The `rpm` package is required for running the build-release script. Run the appropriate command to install the `rpm` package:
```sh
sudo pacman -S rpm # Arch
```
```sh
sudo apt install rpm # Ubuntu/Debian
```
Run the following to build the binaries for your specific system OS.
```

@ -2,7 +2,7 @@
"name": "session-desktop",
"productName": "Session",
"description": "Private messaging from your desktop",
"version": "1.8.5",
"version": "1.8.6",
"license": "GPL-3.0",
"author": {
"name": "Oxen Labs",

@ -18,9 +18,10 @@ export const AudioPlayerWithEncryptedFile = (props: {
contentType: string;
messageId: string;
}) => {
const { messageId, contentType, src } = props;
const dispatch = useDispatch();
const [playbackSpeed, setPlaybackSpeed] = useState(1.0);
const { urlToLoad } = useEncryptedFileFetch(props.src, props.contentType, false);
const { urlToLoad } = useEncryptedFileFetch(src, contentType, false);
const player = useRef<H5AudioPlayer | null>(null);
const autoPlaySetting = useSelector(getAudioAutoplay);
@ -30,16 +31,19 @@ export const AudioPlayerWithEncryptedFile = (props: {
useEffect(() => {
// updates playback speed to value selected in context menu
if (player.current?.audio.current?.playbackRate) {
if (
player.current?.audio.current &&
player.current?.audio.current?.playbackRate !== playbackSpeed
) {
player.current.audio.current.playbackRate = playbackSpeed;
}
}, [playbackSpeed, player]);
useEffect(() => {
if (props.messageId === nextMessageToPlayId) {
if (messageId !== undefined && messageId === nextMessageToPlayId) {
player.current?.audio.current?.play();
}
}, [props.messageId, nextMessageToPlayId, player]);
}, [messageId, nextMessageToPlayId, player]);
const triggerPlayNextMessageIfNeeded = (endedMessageId: string) => {
const justEndedMessageIndex = messageProps.findIndex(
@ -75,8 +79,8 @@ export const AudioPlayerWithEncryptedFile = (props: {
const onEnded = () => {
// if audio autoplay is enabled, call method to start playing
// the next playable message
if (autoPlaySetting === true && props.messageId) {
triggerPlayNextMessageIfNeeded(props.messageId);
if (autoPlaySetting === true && messageId) {
triggerPlayNextMessageIfNeeded(messageId);
}
};
@ -87,6 +91,8 @@ export const AudioPlayerWithEncryptedFile = (props: {
style={{ pointerEvents: multiSelectMode ? 'none' : 'inherit' }}
layout="horizontal-reverse"
showSkipControls={false}
autoPlay={false}
autoPlayAfterSrcChange={false}
showJumpControls={false}
showDownloadProgress={false}
listenInterval={100}

@ -144,9 +144,18 @@ export const ReadableMessage = (props: ReadableMessageProps) => {
const found = await getMessageById(messageId);
if (found && Boolean(found.get('unread'))) {
const foundReceivedAt = found.get('received_at');
// mark the message as read.
// this will trigger the expire timer.
await found.markRead(Date.now());
// we should stack those and send them in a single message once every 5secs or something.
// this would be part of an redesign of the sending pipeline
if (foundReceivedAt) {
void getConversationController()
.get(found.id)
?.sendReadReceiptsIfNeeded([foundReceivedAt]);
}
}
}
}

@ -90,6 +90,12 @@ function _cleanData(data: any): any {
data[key] = value.map(_cleanData);
} else if (_.isObject(value) && value instanceof File) {
data[key] = { name: value.name, path: value.path, size: value.size, type: value.type };
} else if (_.isObject(value) && value instanceof ArrayBuffer) {
window.log.error(
'Trying to save an ArrayBuffer to the db is most likely an error. This specific field should be removed before the cleanData call'
);
/// just skip it
continue;
} else if (_.isObject(value)) {
data[key] = _cleanData(value);
} else if (_.isBoolean(value)) {

@ -231,7 +231,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
if (newestUnreadDate > lastReadTimestamp) {
this.lastReadTimestamp = newestUnreadDate;
}
void markReadDebounced(newestUnreadDate);
if (newestUnreadDate !== lastReadTimestamp) {
void markReadDebounced(newestUnreadDate);
}
};
// Listening for out-of-band data updates
@ -1059,6 +1062,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
}
}
// tslint:disable-next-line: cyclomatic-complexity
public async markReadBouncy(newestUnreadDate: number, providedOptions: any = {}) {
const lastReadTimestamp = this.lastReadTimestamp;
if (newestUnreadDate < lastReadTimestamp) {
@ -1107,7 +1111,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const realUnreadCount = await this.getUnreadCount();
if (read.length === 0) {
const cachedUnreadCountOnConvo = this.get('unreadCount');
if (cachedUnreadCountOnConvo !== read.length) {
if (cachedUnreadCountOnConvo !== realUnreadCount) {
// reset the unreadCount on the convo to the real one coming from markRead messages on the db
this.set({ unreadCount: realUnreadCount });
await this.commit();
@ -1142,25 +1146,31 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
// conversation is viewed, another error message shows up for the contact
read = read.filter(item => !item.hasErrors);
if (this.isPublic()) {
if (read.length && options.sendReadReceipts) {
const timestamps = _.map(read, 'timestamp').filter(t => !!t) as Array<number>;
await this.sendReadReceiptsIfNeeded(timestamps);
}
}
public async sendReadReceiptsIfNeeded(timestamps: Array<number>) {
if (!this.isPrivate() || !timestamps.length) {
return;
}
if (this.isPrivate() && read.length && options.sendReadReceipts) {
window?.log?.info(
`Sending ${read.length} read receipts?`,
Storage.get(SettingsKey.settingsReadReceipt) || false
);
const dontSendReceipt = this.isBlocked() || this.isIncomingRequest();
if (Storage.get(SettingsKey.settingsReadReceipt) && !dontSendReceipt) {
const timestamps = _.map(read, 'timestamp').filter(t => !!t) as Array<number>;
const receiptMessage = new ReadReceiptMessage({
timestamp: Date.now(),
timestamps,
});
const settingsReadReceiptEnabled = Storage.get(SettingsKey.settingsReadReceipt) || false;
const sendReceipt =
settingsReadReceiptEnabled && !this.isBlocked() && !this.isIncomingRequest();
const device = new PubKey(this.id);
await getMessageQueue().sendToPubKey(device, receiptMessage);
}
if (sendReceipt) {
window?.log?.info(`Sending ${timestamps.length} read receipts.`);
// we should probably stack read receipts and send them every 5 seconds for instance per conversation
const receiptMessage = new ReadReceiptMessage({
timestamp: Date.now(),
timestamps,
});
const device = new PubKey(this.id);
await getMessageQueue().sendToPubKey(device, receiptMessage);
}
}

@ -1048,7 +1048,8 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
}
perfStart(`messageCommit-${this.attributes.id}`);
const id = await saveMessage(this.attributes);
// because the saving to db calls _cleanData which mutates the field for cleaning, we need to save a copy
const id = await saveMessage(_.cloneDeep(this.attributes));
if (triggerUIUpdate) {
this.dispatchMessageUpdate();
}

@ -447,11 +447,9 @@ export async function innerHandleSwarmContentMessage(
}
function onReadReceipt(readAt: number, timestamp: number, source: string) {
const { storage } = window;
window?.log?.info('read receipt', source, timestamp);
if (!storage.get(SettingsKey.settingsReadReceipt)) {
if (!Storage.get(SettingsKey.settingsReadReceipt)) {
return;
}

@ -201,7 +201,7 @@ export async function handleSwarmDataMessage(
);
window?.log?.info(
`Handle dataMessage about convo ${convoIdToAddTheMessageTo} from user: ${convoIdOfSender}: ${cleanDataMessage}`
`Handle dataMessage about convo ${convoIdToAddTheMessageTo} from user: ${convoIdOfSender}`
);
// remove the prefix from the source object so this is correct for all other

@ -75,7 +75,7 @@ export async function addJob(attachment: any, job: any = {}) {
const toSave = {
...job,
id,
attachment,
attachment: omit(attachment, ['toJSON']), // when addJob is called from the receiver we get an object with a toJSON call we don't care
timestamp,
pending: 0,
attempts: 0,

@ -25,6 +25,11 @@ export const getSearchResults = createSelector(
searchState.contactsAndGroups.map(id => {
const value = lookup[id];
// on some edges cases, we have an id but no corresponding convo because it matches a query but the conversation was removed.
if (!value) {
return null;
}
// Don't return anything when activeAt is unset (i.e. no current conversations with this user)
if (value.activeAt === undefined || value.activeAt === 0) {
//activeAt can be 0 when linking device

Loading…
Cancel
Save