From 52836cff91effd34191f6803eefb2f980bf4d426 Mon Sep 17 00:00:00 2001
From: Morgan Pretty <morgan.t.pretty@gmail.com>
Date: Thu, 21 Sep 2023 15:55:26 +1000
Subject: [PATCH] Fixed a couple more issues

Fixed an issue with the Emoji generation
Fixed the SessionThread 'isPinned' property
Fixed an issue when migrating from a pre 2.3.0 version to the latest version
---
 Scripts/EmojiGenerator.swift                           |  8 ++++----
 Session/Emoji/EmojiWithSkinTones+String.swift          |  2 +-
 Session/Meta/SessionApp.swift                          |  2 +-
 Session/Utilities/MockDataGenerator.swift              |  9 +++------
 .../Migrations/_001_InitialSetupMigration.swift        |  2 +-
 .../Database/Migrations/_003_YDBToGRDBMigration.swift  |  9 +++------
 .../Database/Migrations/_013_SessionUtilChanges.swift  |  2 +-
 SessionMessagingKit/Database/Models/Profile.swift      | 10 +++++-----
 .../Database/Models/SessionThread.swift                |  6 +++---
 .../Config Handling/SessionUtil+Contacts.swift         |  3 +--
 SessionMessagingKit/Utilities/ProfileManager.swift     |  2 +-
 .../Settings/ThreadSettingsViewModelSpec.swift         |  6 ++----
 .../Style Guide/Themes/Theme+ClassicDark.swift         |  8 ++++----
 .../Style Guide/Themes/Theme+ClassicLight.swift        |  2 +-
 SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift  |  4 ++--
 .../Database/Types/TypedTableDefinition.swift          |  4 ++++
 16 files changed, 37 insertions(+), 42 deletions(-)

diff --git a/Scripts/EmojiGenerator.swift b/Scripts/EmojiGenerator.swift
index 58e1cda55..680d86e5d 100755
--- a/Scripts/EmojiGenerator.swift
+++ b/Scripts/EmojiGenerator.swift
@@ -279,10 +279,10 @@ extension EmojiGenerator {
                 }
             }
             
-            func switchString(with variableName: String = "rawValue") -> String {
+            func switchString(with variableName: String = "rawValue", size: UInt32) -> String {
                 switch self {
-                    case .firstScalar: return "rawValue.unicodeScalars.map({ $0.value }).first"
-                    case .scalarSum: return "rawValue.unicodeScalars.map({ $0.value }).reduce(0, +)"
+                    case .firstScalar: return "rawValue.unicodeScalars.map({ $0.value }).first.map({ $0 / \(size) })"
+                    case .scalarSum: return "(rawValue.unicodeScalars.map({ $0.value }).reduce(0, +) / \(size))"
                 }
             }
         }
@@ -323,7 +323,7 @@ extension EmojiGenerator {
                         fileHandle.writeLine("init?(rawValue: String) {")
                         fileHandle.indent {
                             fileHandle.writeLine("guard rawValue.isSingleEmoji else { return nil }")
-                            fileHandle.writeLine("switch \(chunkType.switchString()) {")
+                            fileHandle.writeLine("switch \(chunkType.switchString(size: chunkSize)) {")
                             fileHandle.indent {
                                 chunkedEmojiInfo.forEach { chunk, _ in
                                     fileHandle.writeLine("case \(chunk): self = EmojiWithSkinTones.emojiFrom\(chunk)(rawValue)")
diff --git a/Session/Emoji/EmojiWithSkinTones+String.swift b/Session/Emoji/EmojiWithSkinTones+String.swift
index 8f4bd5d74..c57a6cba3 100644
--- a/Session/Emoji/EmojiWithSkinTones+String.swift
+++ b/Session/Emoji/EmojiWithSkinTones+String.swift
@@ -4,7 +4,7 @@
 extension EmojiWithSkinTones {
     init?(rawValue: String) {
         guard rawValue.isSingleEmoji else { return nil }
-        switch rawValue.unicodeScalars.map({ $0.value }).reduce(0, +) {
+        switch (rawValue.unicodeScalars.map({ $0.value }).reduce(0, +) / 100) {
             case 89: self = EmojiWithSkinTones.emojiFrom89(rawValue)
             case 91: self = EmojiWithSkinTones.emojiFrom91(rawValue)
             case 92: self = EmojiWithSkinTones.emojiFrom92(rawValue)
diff --git a/Session/Meta/SessionApp.swift b/Session/Meta/SessionApp.swift
index 7ffa9292c..94f52ae67 100644
--- a/Session/Meta/SessionApp.swift
+++ b/Session/Meta/SessionApp.swift
@@ -82,7 +82,7 @@ public struct SessionApp {
             )
         }
         
-        /// The thread should generally exist at the time of calling this method, but on the off change it doesn't then we need to `fetchOrCreate` it and
+        /// The thread should generally exist at the time of calling this method, but on the off chance it doesn't then we need to `fetchOrCreate` it and
         /// should do it on a background thread just in case something is keeping the DBWrite thread busy as in the past this could cause the app to hang
         guard threadInfo?.threadExists == true else {
             DispatchQueue.global(qos: .userInitiated).async {
diff --git a/Session/Utilities/MockDataGenerator.swift b/Session/Utilities/MockDataGenerator.swift
index e41c9be22..b268786c3 100644
--- a/Session/Utilities/MockDataGenerator.swift
+++ b/Session/Utilities/MockDataGenerator.swift
@@ -100,8 +100,7 @@ enum MockDataGenerator {
                         .compactMap { _ in stringContent.randomElement(using: &dmThreadRandomGenerator) }
                         .joined(),
                     lastNameUpdate: Date().timeIntervalSince1970,
-                    lastProfilePictureUpdate: Date().timeIntervalSince1970,
-                    lastBlocksCommunityMessageRequests: 0
+                    lastProfilePictureUpdate: Date().timeIntervalSince1970
                 )
                 .saved(db)
                 
@@ -182,8 +181,7 @@ enum MockDataGenerator {
                             .compactMap { _ in stringContent.randomElement(using: &cgThreadRandomGenerator) }
                             .joined(),
                         lastNameUpdate: Date().timeIntervalSince1970,
-                        lastProfilePictureUpdate: Date().timeIntervalSince1970,
-                        lastBlocksCommunityMessageRequests: 0
+                        lastProfilePictureUpdate: Date().timeIntervalSince1970
                     )
                     .saved(db)
                     
@@ -313,8 +311,7 @@ enum MockDataGenerator {
                             .compactMap { _ in stringContent.randomElement(using: &ogThreadRandomGenerator) }
                             .joined(),
                         lastNameUpdate: Date().timeIntervalSince1970,
-                        lastProfilePictureUpdate: Date().timeIntervalSince1970,
-                        lastBlocksCommunityMessageRequests: 0
+                        lastProfilePictureUpdate: Date().timeIntervalSince1970
                     )
                     .saved(db)
 
diff --git a/SessionMessagingKit/Database/Migrations/_001_InitialSetupMigration.swift b/SessionMessagingKit/Database/Migrations/_001_InitialSetupMigration.swift
index a553a5d6d..b140a8d20 100644
--- a/SessionMessagingKit/Database/Migrations/_001_InitialSetupMigration.swift
+++ b/SessionMessagingKit/Database/Migrations/_001_InitialSetupMigration.swift
@@ -65,7 +65,7 @@ enum _001_InitialSetupMigration: Migration {
             t.column(.variant, .integer).notNull()
             t.column(.creationDateTimestamp, .double).notNull()
             t.column(.shouldBeVisible, .boolean).notNull()
-            t.column(.isPinned, .boolean).notNull()
+            t.deprecatedColumn(name: "isPinned", .boolean).notNull()
             t.column(.messageDraft, .text)
             t.column(.notificationSound, .integer)
             t.column(.mutedUntilTimestamp, .double)
diff --git a/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift b/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift
index d7ac2eabf..4873cb107 100644
--- a/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift
+++ b/SessionMessagingKit/Database/Migrations/_003_YDBToGRDBMigration.swift
@@ -422,8 +422,7 @@ enum _003_YDBToGRDBMigration: Migration {
                     profilePictureUrl: legacyContact.profilePictureURL,
                     profilePictureFileName: legacyContact.profilePictureFileName,
                     profileEncryptionKey: legacyContact.profileEncryptionKey?.keyData,
-                    lastProfilePictureUpdate: 0,
-                    lastBlocksCommunityMessageRequests: 0
+                    lastProfilePictureUpdate: 0
                 ).migrationSafeInsert(db)
                 
                 /// **Note:** The blow "shouldForce" flags are here to allow us to avoid having to run legacy migrations they
@@ -646,8 +645,7 @@ enum _003_YDBToGRDBMigration: Migration {
                             id: profileId,
                             name: profileId,
                             lastNameUpdate: 0,
-                            lastProfilePictureUpdate: 0,
-                            lastBlocksCommunityMessageRequests: 0
+                            lastProfilePictureUpdate: 0
                         ).migrationSafeSave(db)
                     }
                     
@@ -1061,8 +1059,7 @@ enum _003_YDBToGRDBMigration: Migration {
                                     id: quotedMessage.authorId,
                                     name: quotedMessage.authorId,
                                     lastNameUpdate: 0,
-                                    lastProfilePictureUpdate: 0,
-                                    lastBlocksCommunityMessageRequests: 0
+                                    lastProfilePictureUpdate: 0
                                 ).migrationSafeSave(db)
                             }
                             
diff --git a/SessionMessagingKit/Database/Migrations/_013_SessionUtilChanges.swift b/SessionMessagingKit/Database/Migrations/_013_SessionUtilChanges.swift
index f70169fca..8f7ae09f8 100644
--- a/SessionMessagingKit/Database/Migrations/_013_SessionUtilChanges.swift
+++ b/SessionMessagingKit/Database/Migrations/_013_SessionUtilChanges.swift
@@ -180,7 +180,7 @@ enum _013_SessionUtilChanges: Migration {
         
         // Migrate the 'isPinned' value to 'pinnedPriority'
         try SessionThread
-            .filter(SessionThread.Columns.isPinned == true)
+            .filter(sql: "isPinned = true")
             .updateAll(
                 db,
                 SessionThread.Columns.pinnedPriority.set(to: 1)
diff --git a/SessionMessagingKit/Database/Models/Profile.swift b/SessionMessagingKit/Database/Models/Profile.swift
index 7b8695929..333f17ff9 100644
--- a/SessionMessagingKit/Database/Models/Profile.swift
+++ b/SessionMessagingKit/Database/Models/Profile.swift
@@ -60,7 +60,7 @@ public struct Profile: Codable, Identifiable, Equatable, Hashable, FetchableReco
     public let blocksCommunityMessageRequests: Bool?
     
     /// The timestamp (in seconds since epoch) that the `blocksCommunityMessageRequests` setting was last updated
-    public let lastBlocksCommunityMessageRequests: TimeInterval
+    public let lastBlocksCommunityMessageRequests: TimeInterval?
     
     // MARK: - Initialization
     
@@ -74,7 +74,7 @@ public struct Profile: Codable, Identifiable, Equatable, Hashable, FetchableReco
         profileEncryptionKey: Data? = nil,
         lastProfilePictureUpdate: TimeInterval,
         blocksCommunityMessageRequests: Bool? = nil,
-        lastBlocksCommunityMessageRequests: TimeInterval
+        lastBlocksCommunityMessageRequests: TimeInterval? = nil
     ) {
         self.id = id
         self.name = name
@@ -129,7 +129,7 @@ public extension Profile {
             profileEncryptionKey: profileKey,
             lastProfilePictureUpdate: try container.decode(TimeInterval.self, forKey: .lastProfilePictureUpdate),
             blocksCommunityMessageRequests: try? container.decode(Bool.self, forKey: .blocksCommunityMessageRequests),
-            lastBlocksCommunityMessageRequests: try container.decode(TimeInterval.self, forKey: .lastBlocksCommunityMessageRequests)
+            lastBlocksCommunityMessageRequests: try? container.decode(TimeInterval.self, forKey: .lastBlocksCommunityMessageRequests)
         )
     }
     
@@ -145,7 +145,7 @@ public extension Profile {
         try container.encodeIfPresent(profileEncryptionKey, forKey: .profileEncryptionKey)
         try container.encode(lastProfilePictureUpdate, forKey: .lastProfilePictureUpdate)
         try container.encodeIfPresent(blocksCommunityMessageRequests, forKey: .blocksCommunityMessageRequests)
-        try container.encode(lastBlocksCommunityMessageRequests, forKey: .lastBlocksCommunityMessageRequests)
+        try container.encodeIfPresent(lastBlocksCommunityMessageRequests, forKey: .lastBlocksCommunityMessageRequests)
     }
 }
 
@@ -263,7 +263,7 @@ public extension Profile {
             profileEncryptionKey: nil,
             lastProfilePictureUpdate: 0,
             blocksCommunityMessageRequests: nil,
-            lastBlocksCommunityMessageRequests: 0
+            lastBlocksCommunityMessageRequests: nil
         )
     }
     
diff --git a/SessionMessagingKit/Database/Models/SessionThread.swift b/SessionMessagingKit/Database/Models/SessionThread.swift
index fcb375fcf..699eb0786 100644
--- a/SessionMessagingKit/Database/Models/SessionThread.swift
+++ b/SessionMessagingKit/Database/Models/SessionThread.swift
@@ -27,7 +27,7 @@ public struct SessionThread: Codable, Identifiable, Equatable, FetchableRecord,
         case variant
         case creationDateTimestamp
         case shouldBeVisible
-        case isPinned
+        @available(*, deprecated, message: "use 'pinnedPriority > 0' instead") case isPinned
         case messageDraft
         case notificationSound
         case mutedUntilTimestamp
@@ -61,8 +61,8 @@ public struct SessionThread: Codable, Identifiable, Equatable, FetchableRecord,
     public let shouldBeVisible: Bool
     
     /// A flag indicating whether the thread is pinned
-//    @available(*, unavailable, message: "use 'pinnedPriority' instead")
-    public let isPinned: Bool = false
+    @available(*, deprecated, message: "use 'pinnedPriority > 0' instead")
+    private let isPinned: Bool = false
     
     /// The value the user started entering into the input field before they left the conversation screen
     public let messageDraft: String?
diff --git a/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift b/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift
index 745373060..4e07e7aad 100644
--- a/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift	
+++ b/SessionMessagingKit/SessionUtil/Config Handling/SessionUtil+Contacts.swift	
@@ -564,8 +564,7 @@ private extension SessionUtil {
                         count: ProfileManager.avatarAES256KeyByteLength
                     )
                 ),
-                lastProfilePictureUpdate: (TimeInterval(latestConfigSentTimestampMs) / 1000),
-                lastBlocksCommunityMessageRequests: 0
+                lastProfilePictureUpdate: (TimeInterval(latestConfigSentTimestampMs) / 1000)
             )
             
             result[contactId] = ContactData(
diff --git a/SessionMessagingKit/Utilities/ProfileManager.swift b/SessionMessagingKit/Utilities/ProfileManager.swift
index 1a1488984..7c206107d 100644
--- a/SessionMessagingKit/Utilities/ProfileManager.swift
+++ b/SessionMessagingKit/Utilities/ProfileManager.swift
@@ -517,7 +517,7 @@ public struct ProfileManager {
         }
         
         // Blocks community message requets flag
-        if let blocksCommunityMessageRequests: Bool = blocksCommunityMessageRequests, sentTimestamp > profile.lastBlocksCommunityMessageRequests {
+        if let blocksCommunityMessageRequests: Bool = blocksCommunityMessageRequests, sentTimestamp > (profile.lastBlocksCommunityMessageRequests ?? 0) {
             profileChanges.append(Profile.Columns.blocksCommunityMessageRequests.set(to: blocksCommunityMessageRequests))
             profileChanges.append(Profile.Columns.lastBlocksCommunityMessageRequests.set(to: sentTimestamp))
         }
diff --git a/SessionTests/Conversations/Settings/ThreadSettingsViewModelSpec.swift b/SessionTests/Conversations/Settings/ThreadSettingsViewModelSpec.swift
index 8ba49032b..e84e52368 100644
--- a/SessionTests/Conversations/Settings/ThreadSettingsViewModelSpec.swift
+++ b/SessionTests/Conversations/Settings/ThreadSettingsViewModelSpec.swift
@@ -61,16 +61,14 @@ class ThreadSettingsViewModelSpec: QuickSpec {
                         id: "05\(TestConstants.publicKey)",
                         name: "TestMe",
                         lastNameUpdate: 0,
-                        lastProfilePictureUpdate: 0,
-                        lastBlocksCommunityMessageRequests: 0
+                        lastProfilePictureUpdate: 0
                     ).insert(db)
                     
                     try Profile(
                         id: "TestId",
                         name: "TestUser",
                         lastNameUpdate: 0,
-                        lastProfilePictureUpdate: 0,
-                        lastBlocksCommunityMessageRequests: 0
+                        lastProfilePictureUpdate: 0
                     ).insert(db)
                 }
                 viewModel = ThreadSettingsViewModel(
diff --git a/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift b/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift
index 1bd0e039a..468356fc9 100644
--- a/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift	
+++ b/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift	
@@ -82,11 +82,11 @@ internal enum Theme_ClassicDark: ThemeColors {
         .alert_buttonBackground: .classicDark1,
         
         // ConversationButton
-        .conversationButton_background: .classicDark1,
-        .conversationButton_unreadBackground: .classicDark2,
+        .conversationButton_background: .classicDark0,
+        .conversationButton_unreadBackground: .classicDark1,
         .conversationButton_unreadStripBackground: .primary,
-        .conversationButton_unreadBubbleBackground: .classicDark3,
-        .conversationButton_unreadBubbleText: .classicDark6,
+        .conversationButton_unreadBubbleBackground: .primary,
+        .conversationButton_unreadBubbleText: .classicDark0,
         .conversationButton_swipeDestructive: .dangerDark,
         .conversationButton_swipeSecondary: .classicDark2,
         .conversationButton_swipeTertiary: Theme.PrimaryColor.orange.color,
diff --git a/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift b/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift
index b659a95e0..51caf802f 100644
--- a/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift	
+++ b/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift	
@@ -85,7 +85,7 @@ internal enum Theme_ClassicLight: ThemeColors {
         .conversationButton_background: .classicLight6,
         .conversationButton_unreadBackground: .classicLight6,
         .conversationButton_unreadStripBackground: .primary,
-        .conversationButton_unreadBubbleBackground: .classicLight3,
+        .conversationButton_unreadBubbleBackground: .primary,
         .conversationButton_unreadBubbleText: .classicLight0,
         .conversationButton_swipeDestructive: .dangerLight,
         .conversationButton_swipeSecondary: .classicLight1,
diff --git a/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift b/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift
index a87cf4d4d..23a15bc8e 100644
--- a/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift	
+++ b/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift	
@@ -82,8 +82,8 @@ internal enum Theme_OceanDark: ThemeColors {
         .alert_buttonBackground: .oceanDark3,
         
         // ConversationButton
-        .conversationButton_background: .oceanDark3,
-        .conversationButton_unreadBackground: .oceanDark4,
+        .conversationButton_background: .oceanDark2,
+        .conversationButton_unreadBackground: .oceanDark3,
         .conversationButton_unreadStripBackground: .primary,
         .conversationButton_unreadBubbleBackground: .primary,
         .conversationButton_unreadBubbleText: .oceanDark0,
diff --git a/SessionUtilitiesKit/Database/Types/TypedTableDefinition.swift b/SessionUtilitiesKit/Database/Types/TypedTableDefinition.swift
index 67ce68016..30ed50425 100644
--- a/SessionUtilitiesKit/Database/Types/TypedTableDefinition.swift
+++ b/SessionUtilitiesKit/Database/Types/TypedTableDefinition.swift
@@ -16,6 +16,10 @@ public class TypedTableDefinition<T> where T: TableRecord, T: ColumnExpressible
         return definition.column(key.name, type)
     }
     
+    @discardableResult public func deprecatedColumn(name: String, _ type: Database.ColumnType? = nil) -> ColumnDefinition {
+        return definition.column(name, type)
+    }
+    
     public func primaryKey(_ columns: [T.Columns], onConflict: Database.ConflictResolution? = nil) {
         definition.primaryKey(columns.map { $0.name }, onConflict: onConflict)
     }