pin conversations
This commit is contained in:
parent
365231f309
commit
1cc2f17469
|
@ -356,6 +356,21 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
|
||||||
self.present(alert, animated: true, completion: nil)
|
self.present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
delete.backgroundColor = Colors.destructive
|
delete.backgroundColor = Colors.destructive
|
||||||
|
|
||||||
|
let isPinned = thread.isPinned
|
||||||
|
let pin = UITableViewRowAction(style: .normal, title: NSLocalizedString("PIN_BUTTON_TEXT", comment: "")) { _, _ in
|
||||||
|
thread.isPinned = true
|
||||||
|
thread.save()
|
||||||
|
tableView.reloadRows(at: [ indexPath ], with: UITableView.RowAnimation.fade)
|
||||||
|
}
|
||||||
|
pin.backgroundColor = Colors.pathsBuilding
|
||||||
|
let unpin = UITableViewRowAction(style: .normal, title: NSLocalizedString("UNPIN_BUTTON_TEXT", comment: "")) { _, _ in
|
||||||
|
thread.isPinned = false
|
||||||
|
thread.save()
|
||||||
|
tableView.reloadRows(at: [ indexPath ], with: UITableView.RowAnimation.fade)
|
||||||
|
}
|
||||||
|
unpin.backgroundColor = Colors.pathsBuilding
|
||||||
|
|
||||||
if let thread = thread as? TSContactThread {
|
if let thread = thread as? TSContactThread {
|
||||||
let publicKey = thread.contactSessionID()
|
let publicKey = thread.contactSessionID()
|
||||||
let blockingManager = SSKEnvironment.shared.blockingManager
|
let blockingManager = SSKEnvironment.shared.blockingManager
|
||||||
|
@ -370,9 +385,9 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
|
||||||
tableView.reloadRows(at: [ indexPath ], with: UITableView.RowAnimation.fade)
|
tableView.reloadRows(at: [ indexPath ], with: UITableView.RowAnimation.fade)
|
||||||
}
|
}
|
||||||
unblock.backgroundColor = Colors.unimportant
|
unblock.backgroundColor = Colors.unimportant
|
||||||
return [ delete, (isBlocked ? unblock : block) ]
|
return [ delete, (isBlocked ? unblock : block), (isPinned ? unpin : pin) ]
|
||||||
} else {
|
} else {
|
||||||
return [ delete ]
|
return [ delete, (isPinned ? unpin : pin) ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "pin.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
|
@ -576,3 +576,5 @@
|
||||||
"system_mode_theme" = "System";
|
"system_mode_theme" = "System";
|
||||||
"dark_mode_theme" = "Dark";
|
"dark_mode_theme" = "Dark";
|
||||||
"light_mode_theme" = "Light";
|
"light_mode_theme" = "Light";
|
||||||
|
"PIN_BUTTON_TEXT" = "Pin";
|
||||||
|
"UNPIN_BUTTON_TEXT" = "Unpin";
|
||||||
|
|
|
@ -58,6 +58,17 @@ final class ConversationCell : UITableViewCell {
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
private lazy var isPinnedIcon: UIImageView = {
|
||||||
|
let result = UIImageView(image: UIImage(named: "Pin")!.withRenderingMode(.alwaysTemplate))
|
||||||
|
result.contentMode = .scaleAspectFit
|
||||||
|
let size = ConversationCell.unreadCountViewSize
|
||||||
|
result.set(.width, to: size)
|
||||||
|
result.set(.height, to: size)
|
||||||
|
result.tintColor = Colors.text
|
||||||
|
result.layer.masksToBounds = true
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
private lazy var timestampLabel: UILabel = {
|
private lazy var timestampLabel: UILabel = {
|
||||||
let result = UILabel()
|
let result = UILabel()
|
||||||
result.font = .systemFont(ofSize: Values.smallFontSize)
|
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
|
@ -124,7 +135,7 @@ final class ConversationCell : UITableViewCell {
|
||||||
hasMentionLabel.pin(to: hasMentionView)
|
hasMentionLabel.pin(to: hasMentionView)
|
||||||
// Label stack view
|
// Label stack view
|
||||||
let topLabelSpacer = UIView.hStretchingSpacer()
|
let topLabelSpacer = UIView.hStretchingSpacer()
|
||||||
let topLabelStackView = UIStackView(arrangedSubviews: [ displayNameLabel, unreadCountView, hasMentionView, topLabelSpacer, timestampLabel ])
|
let topLabelStackView = UIStackView(arrangedSubviews: [ displayNameLabel, isPinnedIcon, unreadCountView, hasMentionView, topLabelSpacer, timestampLabel ])
|
||||||
topLabelStackView.axis = .horizontal
|
topLabelStackView.axis = .horizontal
|
||||||
topLabelStackView.alignment = .center
|
topLabelStackView.alignment = .center
|
||||||
topLabelStackView.spacing = Values.smallSpacing / 2 // Effectively Values.smallSpacing because there'll be spacing before and after the invisible spacer
|
topLabelStackView.spacing = Values.smallSpacing / 2 // Effectively Values.smallSpacing because there'll be spacing before and after the invisible spacer
|
||||||
|
@ -182,6 +193,7 @@ final class ConversationCell : UITableViewCell {
|
||||||
private func update() {
|
private func update() {
|
||||||
AssertIsOnMainThread()
|
AssertIsOnMainThread()
|
||||||
guard let thread = threadViewModel?.threadRecord else { return }
|
guard let thread = threadViewModel?.threadRecord else { return }
|
||||||
|
backgroundColor = thread.isPinned ? Colors.cellPinned : Colors.cellBackground
|
||||||
let isBlocked: Bool
|
let isBlocked: Bool
|
||||||
if let thread = thread as? TSContactThread {
|
if let thread = thread as? TSContactThread {
|
||||||
isBlocked = SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(thread.contactSessionID())
|
isBlocked = SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(thread.contactSessionID())
|
||||||
|
@ -195,6 +207,7 @@ final class ConversationCell : UITableViewCell {
|
||||||
accentLineView.backgroundColor = Colors.accent
|
accentLineView.backgroundColor = Colors.accent
|
||||||
accentLineView.alpha = threadViewModel.hasUnreadMessages ? 1 : 0.0001 // Setting the alpha to exactly 0 causes an issue on iOS 12
|
accentLineView.alpha = threadViewModel.hasUnreadMessages ? 1 : 0.0001 // Setting the alpha to exactly 0 causes an issue on iOS 12
|
||||||
}
|
}
|
||||||
|
isPinnedIcon.isHidden = !threadViewModel.isPinned
|
||||||
unreadCountView.isHidden = !threadViewModel.hasUnreadMessages
|
unreadCountView.isHidden = !threadViewModel.hasUnreadMessages
|
||||||
let unreadCount = threadViewModel.unreadCount
|
let unreadCount = threadViewModel.unreadCount
|
||||||
unreadCountLabel.text = unreadCount < 100 ? "\(unreadCount)" : "99+"
|
unreadCountLabel.text = unreadCount < 100 ? "\(unreadCount)" : "99+"
|
||||||
|
|
|
@ -278,7 +278,10 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
|
||||||
TSThread *thread1 = (TSThread *)object1;
|
TSThread *thread1 = (TSThread *)object1;
|
||||||
TSThread *thread2 = (TSThread *)object2;
|
TSThread *thread2 = (TSThread *)object2;
|
||||||
if ([group isEqualToString:TSArchiveGroup] || [group isEqualToString:TSInboxGroup]) {
|
if ([group isEqualToString:TSArchiveGroup] || [group isEqualToString:TSInboxGroup]) {
|
||||||
|
if (thread1.isPinned != thread2.isPinned) {
|
||||||
|
if (thread1.isPinned) { return NSOrderedDescending; }
|
||||||
|
if (thread2.isPinned) { return NSOrderedAscending; }
|
||||||
|
}
|
||||||
TSInteraction *_Nullable lastInteractionForInbox1 =
|
TSInteraction *_Nullable lastInteractionForInbox1 =
|
||||||
[thread1 lastInteractionForInboxWithTransaction:transaction];
|
[thread1 lastInteractionForInboxWithTransaction:transaction];
|
||||||
NSDate *lastInteractionForInboxDate1 = lastInteractionForInbox1 ? lastInteractionForInbox1.receivedAtDate : thread1.creationDate;
|
NSDate *lastInteractionForInboxDate1 = lastInteractionForInbox1 ? lastInteractionForInbox1.receivedAtDate : thread1.creationDate;
|
||||||
|
|
|
@ -16,6 +16,7 @@ BOOL IsNoteToSelfEnabled(void);
|
||||||
*/
|
*/
|
||||||
@interface TSThread : TSYapDatabaseObject
|
@interface TSThread : TSYapDatabaseObject
|
||||||
|
|
||||||
|
@property (nonatomic) BOOL isPinned;
|
||||||
@property (nonatomic) BOOL shouldBeVisible;
|
@property (nonatomic) BOOL shouldBeVisible;
|
||||||
@property (nonatomic, readonly) NSDate *creationDate;
|
@property (nonatomic, readonly) NSDate *creationDate;
|
||||||
@property (nonatomic, readonly, nullable) NSDate *lastInteractionDate;
|
@property (nonatomic, readonly, nullable) NSDate *lastInteractionDate;
|
||||||
|
|
|
@ -20,6 +20,7 @@ public final class Colors : NSObject {
|
||||||
@objc public static var border: UIColor { UIColor(named: "session_border")! }
|
@objc public static var border: UIColor { UIColor(named: "session_border")! }
|
||||||
@objc public static var cellBackground: UIColor { UIColor(named: "session_cell_background")! }
|
@objc public static var cellBackground: UIColor { UIColor(named: "session_cell_background")! }
|
||||||
@objc public static var cellSelected: UIColor { UIColor(named: "session_cell_selected")! }
|
@objc public static var cellSelected: UIColor { UIColor(named: "session_cell_selected")! }
|
||||||
|
@objc public static var cellPinned: UIColor { UIColor(named: "session_cell_pinned")! }
|
||||||
@objc public static var navigationBarBackground: UIColor { UIColor(named: "session_navigation_bar_background")! }
|
@objc public static var navigationBarBackground: UIColor { UIColor(named: "session_navigation_bar_background")! }
|
||||||
@objc public static var searchBarPlaceholder: UIColor { UIColor(named: "session_search_bar_placeholder")! } // Also used for the icons
|
@objc public static var searchBarPlaceholder: UIColor { UIColor(named: "session_search_bar_placeholder")! } // Also used for the icons
|
||||||
@objc public static var searchBarBackground: UIColor { UIColor(named: "session_search_bar_background")! }
|
@objc public static var searchBarBackground: UIColor { UIColor(named: "session_search_bar_background")! }
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0xF0",
|
||||||
|
"green" : "0xF0",
|
||||||
|
"red" : "0xF0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0x40",
|
||||||
|
"green" : "0x40",
|
||||||
|
"red" : "0x40"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ public class ThreadViewModel: NSObject {
|
||||||
@objc public let contactSessionID: String?
|
@objc public let contactSessionID: String?
|
||||||
@objc public let name: String
|
@objc public let name: String
|
||||||
@objc public let isMuted: Bool
|
@objc public let isMuted: Bool
|
||||||
|
@objc public let isPinned: Bool
|
||||||
@objc public let isOnlyNotifyingForMentions: Bool
|
@objc public let isOnlyNotifyingForMentions: Bool
|
||||||
@objc public let hasUnreadMentions: Bool
|
@objc public let hasUnreadMentions: Bool
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ public class ThreadViewModel: NSObject {
|
||||||
self.isGroupThread = thread.isGroupThread()
|
self.isGroupThread = thread.isGroupThread()
|
||||||
self.name = thread.name()
|
self.name = thread.name()
|
||||||
self.isMuted = thread.isMuted
|
self.isMuted = thread.isMuted
|
||||||
|
self.isPinned = thread.isPinned
|
||||||
self.lastMessageText = thread.lastMessageText(transaction: transaction)
|
self.lastMessageText = thread.lastMessageText(transaction: transaction)
|
||||||
let lastInteraction = thread.lastInteractionForInbox(transaction: transaction)
|
let lastInteraction = thread.lastInteractionForInbox(transaction: transaction)
|
||||||
self.lastMessageForInbox = lastInteraction
|
self.lastMessageForInbox = lastInteraction
|
||||||
|
|
Loading…
Reference in New Issue