From ff656de82b26d23e0618bfb351650e52656ad0f2 Mon Sep 17 00:00:00 2001
From: William Grant <willmgrant@gmail.com>
Date: Mon, 4 Sep 2023 16:33:59 +1000
Subject: [PATCH 1/4] fix: lint-staged ignores files using eslintignore

---
 .lintstagedrc.js | 53 ++++++++++++++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 20 deletions(-)

diff --git a/.lintstagedrc.js b/.lintstagedrc.js
index 61152b6fb..d1b83dbc7 100644
--- a/.lintstagedrc.js
+++ b/.lintstagedrc.js
@@ -1,25 +1,38 @@
-const ignoredFiles = [
-  'package.json',
-  'yarn.lock',
-  'tsconfig.json',
-  '.lintstagedrc.js',
-  '.eslintrc.js',
-];
-
-const path = require('path');
-
-const buildFormatCommand = filenames => {
-  const results = filenames
-    .map(f => path.relative(process.cwd(), f))
-    .filter(f => !ignoredFiles.includes(f));
-
-  return results.length ? `prettier --list-different --write ${results.join(' ')}` : '';
+const { ESLint } = require('eslint');
+
+const removeIgnoredFiles = async files => {
+  const eslint = new ESLint();
+  const isIgnored = await Promise.all(
+    files.map(file => {
+      return eslint.isPathIgnored(file);
+    })
+  );
+  const filteredFiles = files.filter((_, i) => !isIgnored[i]);
+  return filteredFiles.join(' ');
+};
+
+const buildFormatCommand = async files => {
+  const filesToLint = await removeIgnoredFiles(files);
+
+  if (!filesToLint || !filesToLint.length) {
+    return '';
+  }
+
+  const results = filesToLint.map(f => path.relative(process.cwd(), f));
+
+  return results.length
+    ? `prettier --ignore-unknown --list-different --write ${results.join(' ')}`
+    : '';
 };
 
-const buildLintCommand = filenames => {
-  const results = filenames
-    .map(f => path.relative(process.cwd(), f))
-    .filter(f => !ignoredFiles.includes(f));
+const buildLintCommand = async files => {
+  const filesToLint = await removeIgnoredFiles(files);
+
+  if (!filesToLint || !filesToLint.length) {
+    return '';
+  }
+
+  const results = filesToLint.map(f => path.relative(process.cwd(), f));
 
   return results.length ? `eslint --cache ${results.join(' ')}` : '';
 };

From 153a6499ef2c8137cb32d1521185dc0707b7b204 Mon Sep 17 00:00:00 2001
From: William Grant <willmgrant@gmail.com>
Date: Mon, 4 Sep 2023 16:37:46 +1000
Subject: [PATCH 2/4] chore: disable pre commit lint-staged hook for now

buildLintCommand is broken if you have a lint error in a file the commit fails silently
---
 .husky/pre-commit | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/.husky/pre-commit b/.husky/pre-commit
index d24fdfc60..9d4f45ace 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -1,4 +1,5 @@
 #!/usr/bin/env sh
 . "$(dirname -- "$0")/_/husky.sh"
 
-npx lint-staged
+# Disabling this hook for now because the BuildLintCommand has issues. If you have an error in a file that eslint catches the commit fails silently instead of explaining the error (Will 04/09/2023)
+# npx lint-staged

From a973f62f6375e44a0b84c3b6eb68e265f60f97f6 Mon Sep 17 00:00:00 2001
From: Audric Ackermann <audric@loki.network>
Date: Tue, 5 Sep 2023 10:51:48 +1000
Subject: [PATCH 3/4] chore: add supported platforms in readme

---
 README.md | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.md b/README.md
index 3e2dd66d3..3c938cad6 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,10 @@ Session integrates directly with [Oxen Service Nodes](https://docs.oxen.io/about
 
 Please search for any [existing issues](https://github.com/oxen-io/session-desktop/issues) that describe your bug in order to avoid duplicate submissions. <br><br>Submissions can be made by making a pull request to our development branch.If you don't know where to start contributing please read [Contributing.md](CONTRIBUTING.md) and refer to issues tagged with the [Good-first-issue](https://github.com/oxen-io/session-desktop/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) tag.
 
+## Supported platforms
+
+Session requires Windows 10 or later, macOS Catalina (10.15) or later, or a linux distribution with glibc 2.28 or later like Debian 10 or Ubuntu 20.04.
+
 ## Build instruction
 
 Build instructions can be found in [Contributing.md](CONTRIBUTING.md).

From e98c9720c80ddddb9dc151128ff3689241c1c342 Mon Sep 17 00:00:00 2001
From: Audric Ackermann <audric@loki.network>
Date: Tue, 5 Sep 2023 16:40:16 +1000
Subject: [PATCH 4/4] fix: fix synced messages sometimes not appearing

---
 ts/receiver/contentMessage.ts | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts
index 1a1ff95cd..d7b7db7ca 100644
--- a/ts/receiver/contentMessage.ts
+++ b/ts/receiver/contentMessage.ts
@@ -35,6 +35,7 @@ import { getAllCachedECKeyPair, sentAtMoreRecentThanWrapper } from './closedGrou
 import { ConfigMessageHandler } from './configMessage';
 import { ECKeyPair } from './keypairs';
 import { ContactsWrapperActions } from '../webworker/workers/browser/libsession_worker_interface';
+import { isUsFromCache } from '../session/utils/User';
 
 export async function handleSwarmContentMessage(envelope: EnvelopePlus, messageHash: string) {
   try {
@@ -292,27 +293,42 @@ async function decrypt(envelope: EnvelopePlus): Promise<any> {
   return plaintext;
 }
 
-async function shouldDropIncomingPrivateMessage(sentAtTimestamp: number, envelope: EnvelopePlus) {
+async function shouldDropIncomingPrivateMessage(
+  sentAtTimestamp: number,
+  envelope: EnvelopePlus,
+  content: SignalService.Content
+) {
   // sentAtMoreRecentThanWrapper is going to be true, if the latest contact wrapper we processed was roughly more recent that this message timestamp
   const moreRecentOrNah = await sentAtMoreRecentThanWrapper(sentAtTimestamp, 'ContactsConfig');
+  const isSyncedMessage = isUsFromCache(envelope.source);
 
   if (moreRecentOrNah === 'wrapper_more_recent') {
-    // we need to check if that conversation is already in the wrapper, and if yes
+    // we need to check if that conversation is already in the wrapper
     try {
-      const privateConvoInWrapper = await ContactsWrapperActions.get(envelope.source);
+      // let's check if the corresponding conversation is hidden in the contacts wrapper or not.
+      // the corresponding conversation is syncTarget when this is a synced message only, so we need to rely on it first, then the envelope.source.
+      const syncTargetOrSource = isSyncedMessage
+        ? content.dataMessage?.syncTarget || undefined
+        : envelope.source;
+
+      if (!syncTargetOrSource) {
+        return false;
+      }
+
+      const privateConvoInWrapper = await ContactsWrapperActions.get(syncTargetOrSource);
       if (
         !privateConvoInWrapper ||
         privateConvoInWrapper.priority <= CONVERSATION_PRIORITIES.hidden
       ) {
         // the wrapper is more recent that this message and there is no such private conversation. Just drop this incoming message.
         window.log.info(
-          `received message from contact ${envelope.source} which appears to be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. Dropping it`
+          `received message on conversation ${syncTargetOrSource} which appears to be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. Dropping it`
         );
         return true;
       }
 
       window.log.info(
-        `received message from contact ${envelope.source} which appears to NOT be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. `
+        `received message on conversation ${syncTargetOrSource} which appears to NOT be hidden/removed in our most recent libsession contactconfig, sentAt: ${sentAtTimestamp}. `
       );
     } catch (e) {
       window.log.warn(
@@ -409,7 +425,7 @@ export async function innerHandleSwarmContentMessage(
     const isPrivateConversationMessage = !envelope.senderIdentity;
 
     if (isPrivateConversationMessage) {
-      if (await shouldDropIncomingPrivateMessage(sentAtTimestamp, envelope)) {
+      if (await shouldDropIncomingPrivateMessage(sentAtTimestamp, envelope, content)) {
         await removeFromCache(envelope);
         return;
       }