commit
b7520ed1cb
|
@ -135,7 +135,6 @@
|
||||||
7B1581E2271E743B00848B49 /* OWSSounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E1271E743B00848B49 /* OWSSounds.swift */; };
|
7B1581E2271E743B00848B49 /* OWSSounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E1271E743B00848B49 /* OWSSounds.swift */; };
|
||||||
7B1D74AA27BCC16E0030B423 /* NSENotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74A927BCC16E0030B423 /* NSENotificationPresenter.swift */; };
|
7B1D74AA27BCC16E0030B423 /* NSENotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74A927BCC16E0030B423 /* NSENotificationPresenter.swift */; };
|
||||||
7B1D74AC27BDE7510030B423 /* Promise+Timeout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74AB27BDE7510030B423 /* Promise+Timeout.swift */; };
|
7B1D74AC27BDE7510030B423 /* Promise+Timeout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74AB27BDE7510030B423 /* Promise+Timeout.swift */; };
|
||||||
7B1D74AE27C346220030B423 /* UnreadMentionMigtation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74AD27C346220030B423 /* UnreadMentionMigtation.swift */; };
|
|
||||||
7B1D74B027C365960030B423 /* Timer+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74AF27C365960030B423 /* Timer+MainThread.swift */; };
|
7B1D74B027C365960030B423 /* Timer+MainThread.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74AF27C365960030B423 /* Timer+MainThread.swift */; };
|
||||||
7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */; };
|
7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */; };
|
||||||
7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */; };
|
7B4C75CD26BB92060000AC89 /* DeletedMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4C75CC26BB92060000AC89 /* DeletedMessageView.swift */; };
|
||||||
|
@ -1130,7 +1129,6 @@
|
||||||
7B1581E1271E743B00848B49 /* OWSSounds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSSounds.swift; sourceTree = "<group>"; };
|
7B1581E1271E743B00848B49 /* OWSSounds.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSSounds.swift; sourceTree = "<group>"; };
|
||||||
7B1D74A927BCC16E0030B423 /* NSENotificationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSENotificationPresenter.swift; sourceTree = "<group>"; };
|
7B1D74A927BCC16E0030B423 /* NSENotificationPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSENotificationPresenter.swift; sourceTree = "<group>"; };
|
||||||
7B1D74AB27BDE7510030B423 /* Promise+Timeout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+Timeout.swift"; sourceTree = "<group>"; };
|
7B1D74AB27BDE7510030B423 /* Promise+Timeout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Promise+Timeout.swift"; sourceTree = "<group>"; };
|
||||||
7B1D74AD27C346220030B423 /* UnreadMentionMigtation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnreadMentionMigtation.swift; sourceTree = "<group>"; };
|
|
||||||
7B1D74AF27C365960030B423 /* Timer+MainThread.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Timer+MainThread.swift"; sourceTree = "<group>"; };
|
7B1D74AF27C365960030B423 /* Timer+MainThread.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Timer+MainThread.swift"; sourceTree = "<group>"; };
|
||||||
7B2DB2AD26F1B0FF0035B509 /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Localizable.strings; sourceTree = "<group>"; };
|
7B2DB2AD26F1B0FF0035B509 /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsendRequest.swift; sourceTree = "<group>"; };
|
7B4C75CA26B37E0F0000AC89 /* UnsendRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsendRequest.swift; sourceTree = "<group>"; };
|
||||||
|
@ -3070,7 +3068,6 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
B8B32044258C117C0020074B /* ContactsMigration.swift */,
|
B8B32044258C117C0020074B /* ContactsMigration.swift */,
|
||||||
7B1D74AD27C346220030B423 /* UnreadMentionMigtation.swift */,
|
|
||||||
FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */,
|
FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */,
|
||||||
C38EF271255B6D79007E1867 /* OWSDatabaseMigration.h */,
|
C38EF271255B6D79007E1867 /* OWSDatabaseMigration.h */,
|
||||||
C38EF270255B6D79007E1867 /* OWSDatabaseMigration.m */,
|
C38EF270255B6D79007E1867 /* OWSDatabaseMigration.m */,
|
||||||
|
@ -4615,7 +4612,6 @@
|
||||||
C38EF40B255B6DF7007E1867 /* TappableStackView.swift in Sources */,
|
C38EF40B255B6DF7007E1867 /* TappableStackView.swift in Sources */,
|
||||||
C38EF31D255B6DBF007E1867 /* UIImage+OWS.swift in Sources */,
|
C38EF31D255B6DBF007E1867 /* UIImage+OWS.swift in Sources */,
|
||||||
C38EF359255B6DCC007E1867 /* SheetViewController.swift in Sources */,
|
C38EF359255B6DCC007E1867 /* SheetViewController.swift in Sources */,
|
||||||
7B1D74AE27C346220030B423 /* UnreadMentionMigtation.swift in Sources */,
|
|
||||||
B8F5F52925EC4F8A003BF8D4 /* BlockListUIUtils.m in Sources */,
|
B8F5F52925EC4F8A003BF8D4 /* BlockListUIUtils.m in Sources */,
|
||||||
C38EF386255B6DD2007E1867 /* AttachmentApprovalInputAccessoryView.swift in Sources */,
|
C38EF386255B6DD2007E1867 /* AttachmentApprovalInputAccessoryView.swift in Sources */,
|
||||||
B8C2B2C82563685C00551B4D /* CircleView.swift in Sources */,
|
B8C2B2C82563685C00551B4D /* CircleView.swift in Sources */,
|
||||||
|
@ -5189,7 +5185,7 @@
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 324;
|
CURRENT_PROJECT_VERSION = 325;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
|
@ -5262,7 +5258,7 @@
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 324;
|
CURRENT_PROJECT_VERSION = 325;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
@ -5328,7 +5324,7 @@
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 324;
|
CURRENT_PROJECT_VERSION = 325;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||||
|
@ -5402,7 +5398,7 @@
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 324;
|
CURRENT_PROJECT_VERSION = 325;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
@ -6338,7 +6334,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CURRENT_PROJECT_VERSION = 324;
|
CURRENT_PROJECT_VERSION = 325;
|
||||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
@ -6409,7 +6405,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CURRENT_PROJECT_VERSION = 324;
|
CURRENT_PROJECT_VERSION = 325;
|
||||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|
|
@ -613,6 +613,10 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
|
||||||
let updateType = conversationUpdate.conversationUpdateType
|
let updateType = conversationUpdate.conversationUpdateType
|
||||||
guard updateType != .minor else { return } // No view items were affected
|
guard updateType != .minor else { return } // No view items were affected
|
||||||
if updateType == .reload {
|
if updateType == .reload {
|
||||||
|
if threadStartedAsMessageRequest {
|
||||||
|
updateNavBarButtons() // In case the message request was approved
|
||||||
|
}
|
||||||
|
|
||||||
return messagesTableView.reloadData()
|
return messagesTableView.reloadData()
|
||||||
}
|
}
|
||||||
var shouldScrollToBottom = false
|
var shouldScrollToBottom = false
|
||||||
|
@ -633,6 +637,11 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
|
||||||
self.messagesTableView.reloadRows(at: [ IndexPath(row: Int(update.oldIndex), section: 0) ], with: .none)
|
self.messagesTableView.reloadRows(at: [ IndexPath(row: Int(update.oldIndex), section: 0) ], with: .none)
|
||||||
default: preconditionFailure()
|
default: preconditionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the nav items if the message request was approved
|
||||||
|
if (update.viewItem?.interaction as? TSInfoMessage)?.messageType == .messageRequestAccepted {
|
||||||
|
self.updateNavBarButtons()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UIView.performWithoutAnimation {
|
UIView.performWithoutAnimation {
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "warning.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,125 @@
|
||||||
|
%PDF-1.7
|
||||||
|
|
||||||
|
1 0 obj
|
||||||
|
<< >>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
2 0 obj
|
||||||
|
<< /Length 3 0 R >>
|
||||||
|
stream
|
||||||
|
/DeviceRGB CS
|
||||||
|
/DeviceRGB cs
|
||||||
|
q
|
||||||
|
1.000000 0.000000 -0.000000 1.000000 9.791016 13.111328 cm
|
||||||
|
0.000000 0.000000 0.000000 scn
|
||||||
|
13.476560 -0.000008 m
|
||||||
|
88.623062 -0.000008 l
|
||||||
|
91.389732 -0.000008 93.782394 0.602219 95.801064 1.806664 c
|
||||||
|
97.819061 3.011093 99.373398 4.630554 100.464066 6.665062 c
|
||||||
|
101.554733 8.699562 102.100060 10.970070 102.100060 13.476585 c
|
||||||
|
102.100060 14.583359 101.945396 15.706406 101.636063 16.845726 c
|
||||||
|
101.326729 17.985054 100.879059 19.075554 100.293060 20.117218 c
|
||||||
|
62.646458 85.693398 l
|
||||||
|
61.376923 87.939461 59.700493 89.640297 57.617161 90.795898 c
|
||||||
|
55.533829 91.951500 53.352856 92.529297 51.074257 92.529297 c
|
||||||
|
48.795589 92.529297 46.606461 91.951500 44.506859 90.795898 c
|
||||||
|
42.407257 89.640297 40.722694 87.939461 39.453159 85.693398 c
|
||||||
|
1.806660 20.068382 l
|
||||||
|
0.602220 17.985046 0.000000 15.787788 0.000000 13.476585 c
|
||||||
|
0.000000 10.970070 0.545253 8.699562 1.635759 6.665062 c
|
||||||
|
2.726226 4.630554 4.280593 3.011093 6.298860 1.806664 c
|
||||||
|
8.317060 0.602219 10.709626 -0.000008 13.476560 -0.000008 c
|
||||||
|
h
|
||||||
|
13.525359 7.666031 m
|
||||||
|
11.832692 7.666031 10.473660 8.260109 9.448260 9.448265 c
|
||||||
|
8.422860 10.636414 7.910159 11.979187 7.910159 13.476585 c
|
||||||
|
7.910159 13.932312 7.958992 14.412453 8.056659 14.917015 c
|
||||||
|
8.154325 15.421577 8.317092 15.917992 8.544959 16.406273 c
|
||||||
|
46.142559 81.982498 l
|
||||||
|
46.695957 82.926498 47.412125 83.618195 48.291058 84.057594 c
|
||||||
|
49.169926 84.497063 50.097656 84.716797 51.074257 84.716797 c
|
||||||
|
52.018257 84.716797 52.921558 84.497063 53.784157 84.057594 c
|
||||||
|
54.646824 83.618195 55.354828 82.926498 55.908161 81.982498 c
|
||||||
|
93.457062 16.357445 l
|
||||||
|
93.977730 15.445984 94.238060 14.485703 94.238060 13.476585 c
|
||||||
|
94.238060 11.979187 93.709061 10.636414 92.651062 9.448265 c
|
||||||
|
91.593063 8.260109 90.217827 7.666031 88.525360 7.666031 c
|
||||||
|
13.525359 7.666031 l
|
||||||
|
h
|
||||||
|
f
|
||||||
|
n
|
||||||
|
Q
|
||||||
|
q
|
||||||
|
1.000000 0.000000 -0.000000 1.000000 55.591797 30.201187 cm
|
||||||
|
0.000000 0.000000 0.000000 scn
|
||||||
|
5.273499 15.869133 m
|
||||||
|
7.714899 15.869133 8.951868 17.154930 8.984402 19.726532 c
|
||||||
|
9.716801 45.507832 l
|
||||||
|
9.749334 46.744831 9.334299 47.778366 8.471699 48.608433 c
|
||||||
|
7.609099 49.438499 6.526735 49.853531 5.224602 49.853531 c
|
||||||
|
3.890002 49.853531 2.807667 49.446632 1.977600 48.632832 c
|
||||||
|
1.147467 47.819031 0.748700 46.793633 0.781300 45.556633 c
|
||||||
|
1.416000 19.726532 l
|
||||||
|
1.481134 17.154930 2.766965 15.869133 5.273499 15.869133 c
|
||||||
|
h
|
||||||
|
5.273499 0.000000 m
|
||||||
|
6.673232 0.000000 7.902070 0.488285 8.960003 1.464851 c
|
||||||
|
10.017937 2.441410 10.546902 3.645840 10.546902 5.078133 c
|
||||||
|
10.546902 6.510399 10.026069 7.714832 8.984402 8.691433 c
|
||||||
|
7.942735 9.667965 6.705765 10.156235 5.273499 10.156235 c
|
||||||
|
3.841165 10.156235 2.604167 9.659832 1.562500 8.667030 c
|
||||||
|
0.520833 7.674164 0.000000 6.477867 0.000000 5.078133 c
|
||||||
|
0.000000 3.678394 0.520833 2.482101 1.562500 1.489262 c
|
||||||
|
2.604167 0.496422 3.841165 0.000000 5.273499 0.000000 c
|
||||||
|
h
|
||||||
|
f
|
||||||
|
n
|
||||||
|
Q
|
||||||
|
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
|
||||||
|
3 0 obj
|
||||||
|
2758
|
||||||
|
endobj
|
||||||
|
|
||||||
|
4 0 obj
|
||||||
|
<< /Annots []
|
||||||
|
/Type /Page
|
||||||
|
/MediaBox [ 0.000000 0.000000 122.000000 119.000000 ]
|
||||||
|
/Resources 1 0 R
|
||||||
|
/Contents 2 0 R
|
||||||
|
/Parent 5 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
5 0 obj
|
||||||
|
<< /Kids [ 4 0 R ]
|
||||||
|
/Count 1
|
||||||
|
/Type /Pages
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
6 0 obj
|
||||||
|
<< /Pages 5 0 R
|
||||||
|
/Type /Catalog
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
|
||||||
|
xref
|
||||||
|
0 7
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000010 00000 n
|
||||||
|
0000000034 00000 n
|
||||||
|
0000002848 00000 n
|
||||||
|
0000002871 00000 n
|
||||||
|
0000003046 00000 n
|
||||||
|
0000003120 00000 n
|
||||||
|
trailer
|
||||||
|
<< /ID [ (some) (id) ]
|
||||||
|
/Root 6 0 R
|
||||||
|
/Size 7
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
3179
|
||||||
|
%%EOF
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -628,3 +628,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -619,3 +619,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -618,3 +618,5 @@
|
||||||
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
"NEW_CONVERSATION_MENU_OPEN_GROUP" = "Open Group";
|
||||||
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
"NEW_CONVERSATION_MENU_DIRECT_MESSAGE" = "Direct Message";
|
||||||
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
"NEW_CONVERSATION_MENU_CLOSED_GROUP" = "Closed Group";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE" = "Oops, an error occurred";
|
||||||
|
"DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE" = "Please try again later";
|
||||||
|
|
|
@ -161,21 +161,22 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||||
public func notifyUser(for incomingMessage: TSIncomingMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) {
|
public func notifyUser(for incomingMessage: TSIncomingMessage, in thread: TSThread, transaction: YapDatabaseReadTransaction) {
|
||||||
guard !thread.isMuted else { return }
|
guard !thread.isMuted else { return }
|
||||||
guard let threadId = thread.uniqueId else { return }
|
guard let threadId = thread.uniqueId else { return }
|
||||||
|
let isMessageRequest = thread.isMessageRequest(using: transaction)
|
||||||
|
|
||||||
// If the thread is a message request and the user hasn't hidden message requests then we need
|
// If the thread is a message request and the user hasn't hidden message requests then we need
|
||||||
// to check if this is the only message request thread (group threads can't be message requests
|
// to check if this is the only message request thread (group threads can't be message requests
|
||||||
// so just ignore those and if the user has hidden message requests then we want to show the
|
// so just ignore those and if the user has hidden message requests then we want to show the
|
||||||
// notification regardless of how many message requests there are)
|
// notification regardless of how many message requests there are)
|
||||||
if !thread.isGroupThread() && thread.isMessageRequest() && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
if !thread.isGroupThread() && isMessageRequest && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
||||||
let threads = transaction.ext(TSThreadDatabaseViewExtensionName) as! YapDatabaseViewTransaction
|
let threads = transaction.ext(TSThreadDatabaseViewExtensionName) as! YapDatabaseViewTransaction
|
||||||
let numMessageRequests = threads.numberOfItems(inGroup: TSMessageRequestGroup)
|
let numMessageRequests = threads.numberOfItems(inGroup: TSMessageRequestGroup)
|
||||||
|
|
||||||
// Allow this to show a notification if there are no message requests (ie. this is the first one)
|
// Allow this to show a notification if there are no message requests (ie. this is the first one)
|
||||||
guard numMessageRequests == 0 else { return }
|
guard numMessageRequests == 0 else { return }
|
||||||
}
|
}
|
||||||
else if thread.isMessageRequest() && CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
else if isMessageRequest && CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
||||||
// If there are other interactions on this thread already then don't show the notification
|
// If there are other interactions on this thread already then don't show the notification
|
||||||
if thread.numberOfInteractions() > 1 { return }
|
if thread.numberOfInteractions(with: transaction) > 1 { return }
|
||||||
|
|
||||||
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = false
|
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = false
|
||||||
}
|
}
|
||||||
|
@ -214,7 +215,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||||
case .nameNoPreview, .namePreview:
|
case .nameNoPreview, .namePreview:
|
||||||
switch thread {
|
switch thread {
|
||||||
case is TSContactThread:
|
case is TSContactThread:
|
||||||
notificationTitle = (thread.isMessageRequest() ? "Session" : senderName)
|
notificationTitle = (isMessageRequest ? "Session" : senderName)
|
||||||
|
|
||||||
case is TSGroupThread:
|
case is TSGroupThread:
|
||||||
var groupName = thread.name(with: transaction)
|
var groupName = thread.name(with: transaction)
|
||||||
|
@ -240,7 +241,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
||||||
|
|
||||||
// If it's a message request then overwrite the body to be something generic (only show a notification
|
// If it's a message request then overwrite the body to be something generic (only show a notification
|
||||||
// when receiving a new message request if there aren't any others or the user had hidden them)
|
// when receiving a new message request if there aren't any others or the user had hidden them)
|
||||||
if thread.isMessageRequest() {
|
if isMessageRequest {
|
||||||
notificationBody = NSLocalizedString("MESSAGE_REQUESTS_NOTIFICATION", comment: "")
|
notificationBody = NSLocalizedString("MESSAGE_REQUESTS_NOTIFICATION", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import PromiseKit
|
import PromiseKit
|
||||||
import NVActivityIndicatorView
|
import NVActivityIndicatorView
|
||||||
|
import SessionUIKit
|
||||||
|
|
||||||
final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
|
final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
|
||||||
private let maxWidth: CGFloat
|
private let maxWidth: CGFloat
|
||||||
|
@ -32,6 +33,42 @@ final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UIColl
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
private lazy var errorView: UIView = {
|
||||||
|
let result: UIView = UIView()
|
||||||
|
result.isHidden = true
|
||||||
|
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var errorImageView: UIImageView = {
|
||||||
|
let result: UIImageView = UIImageView(image: #imageLiteral(resourceName: "warning").withRenderingMode(.alwaysTemplate))
|
||||||
|
result.tintColor = Colors.destructive
|
||||||
|
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var errorTitleLabel: UILabel = {
|
||||||
|
let result: UILabel = UILabel()
|
||||||
|
result.font = UIFont.systemFont(ofSize: Values.mediumFontSize, weight: .medium)
|
||||||
|
result.text = "DEFAULT_OPEN_GROUP_LOAD_ERROR_TITLE".localized()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.textAlignment = .center
|
||||||
|
result.numberOfLines = 0
|
||||||
|
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var errorSubtitleLabel: UILabel = {
|
||||||
|
let result: UILabel = UILabel()
|
||||||
|
result.font = UIFont.systemFont(ofSize: Values.smallFontSize, weight: .medium)
|
||||||
|
result.text = "DEFAULT_OPEN_GROUP_LOAD_ERROR_SUBTITLE".localized()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.textAlignment = .center
|
||||||
|
result.numberOfLines = 0
|
||||||
|
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
// MARK: Settings
|
// MARK: Settings
|
||||||
private static let cellHeight: CGFloat = 40
|
private static let cellHeight: CGFloat = 40
|
||||||
private static let separatorWidth = 1 / UIScreen.main.scale
|
private static let separatorWidth = 1 / UIScreen.main.scale
|
||||||
|
@ -54,17 +91,40 @@ final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UIColl
|
||||||
private func initialize() {
|
private func initialize() {
|
||||||
addSubview(collectionView)
|
addSubview(collectionView)
|
||||||
collectionView.pin(to: self)
|
collectionView.pin(to: self)
|
||||||
|
|
||||||
addSubview(spinner)
|
addSubview(spinner)
|
||||||
spinner.pin([ UIView.HorizontalEdge.left, UIView.VerticalEdge.top ], to: self)
|
spinner.pin(.top, to: .top, of: self)
|
||||||
|
spinner.center(.horizontal, in: self)
|
||||||
spinner.startAnimating()
|
spinner.startAnimating()
|
||||||
|
|
||||||
|
addSubview(errorView)
|
||||||
|
errorView.pin(.top, to: .top, of: self, withInset: 10)
|
||||||
|
errorView.pin( [HorizontalEdge.leading, HorizontalEdge.trailing], to: self)
|
||||||
|
|
||||||
|
errorView.addSubview(errorImageView)
|
||||||
|
errorImageView.pin(.top, to: .top, of: errorView)
|
||||||
|
errorImageView.center(.horizontal, in: errorView)
|
||||||
|
errorImageView.set(.width, to: 60)
|
||||||
|
errorImageView.set(.height, to: 60)
|
||||||
|
|
||||||
|
errorView.addSubview(errorTitleLabel)
|
||||||
|
errorTitleLabel.pin(.top, to: .bottom, of: errorImageView, withInset: 10)
|
||||||
|
errorTitleLabel.center(.horizontal, in: errorView)
|
||||||
|
|
||||||
|
errorView.addSubview(errorSubtitleLabel)
|
||||||
|
errorSubtitleLabel.pin(.top, to: .bottom, of: errorTitleLabel, withInset: 20)
|
||||||
|
errorSubtitleLabel.center(.horizontal, in: errorView)
|
||||||
|
|
||||||
heightConstraint = set(.height, to: OpenGroupSuggestionGrid.cellHeight)
|
heightConstraint = set(.height, to: OpenGroupSuggestionGrid.cellHeight)
|
||||||
widthAnchor.constraint(greaterThanOrEqualToConstant: OpenGroupSuggestionGrid.cellHeight).isActive = true
|
widthAnchor.constraint(greaterThanOrEqualToConstant: OpenGroupSuggestionGrid.cellHeight).isActive = true
|
||||||
if OpenGroupAPIV2.defaultRoomsPromise == nil {
|
|
||||||
OpenGroupAPIV2.getDefaultRoomsIfNeeded()
|
OpenGroupAPIV2.getDefaultRoomsIfNeeded()
|
||||||
}
|
.done { [weak self] rooms in
|
||||||
let _ = OpenGroupAPIV2.defaultRoomsPromise?.done { [weak self] rooms in
|
self?.rooms = rooms
|
||||||
self?.rooms = rooms
|
}
|
||||||
}
|
.catch { [weak self] _ in
|
||||||
|
self?.update()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Updating
|
// MARK: Updating
|
||||||
|
@ -75,6 +135,7 @@ final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UIColl
|
||||||
let height = OpenGroupSuggestionGrid.cellHeight * ceil(CGFloat(roomCount) / 2)
|
let height = OpenGroupSuggestionGrid.cellHeight * ceil(CGFloat(roomCount) / 2)
|
||||||
heightConstraint.constant = height
|
heightConstraint.constant = height
|
||||||
collectionView.reloadData()
|
collectionView.reloadData()
|
||||||
|
errorView.isHidden = (roomCount > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Layout
|
// MARK: Layout
|
||||||
|
@ -173,8 +234,22 @@ extension OpenGroupSuggestionGrid {
|
||||||
private func update() {
|
private func update() {
|
||||||
guard let room = room else { return }
|
guard let room = room else { return }
|
||||||
let promise = OpenGroupAPIV2.getGroupImage(for: room.id, on: OpenGroupAPIV2.defaultServer)
|
let promise = OpenGroupAPIV2.getGroupImage(for: room.id, on: OpenGroupAPIV2.defaultServer)
|
||||||
imageView.image = given(promise.value) { UIImage(data: $0)! }
|
|
||||||
imageView.isHidden = (imageView.image == nil)
|
if let imageData: Data = promise.value {
|
||||||
|
imageView.image = UIImage(data: imageData)
|
||||||
|
imageView.isHidden = (imageView.image == nil)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
imageView.isHidden = true
|
||||||
|
|
||||||
|
_ = promise.done { [weak self] imageData in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self?.imageView.image = UIImage(data: imageData)
|
||||||
|
self?.imageView.isHidden = (self?.imageView.image == nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
label.text = room.name
|
label.text = room.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,6 @@ final class ConversationCell : UITableViewCell {
|
||||||
// Contact
|
// Contact
|
||||||
if threadViewModel.isGroupThread, let thread = threadViewModel.threadRecord as? TSGroupThread {
|
if threadViewModel.isGroupThread, let thread = threadViewModel.threadRecord as? TSGroupThread {
|
||||||
displayNameLabel.attributedText = getHighlightedSnippet(snippet: getDisplayName(), searchText: normalizedSearchText, fontSize: Values.mediumFontSize)
|
displayNameLabel.attributedText = getHighlightedSnippet(snippet: getDisplayName(), searchText: normalizedSearchText, fontSize: Values.mediumFontSize)
|
||||||
bottomLabelStackView.isHidden = false
|
|
||||||
let context: Contact.Context = thread.isOpenGroup ? .openGroup : .regular
|
let context: Contact.Context = thread.isOpenGroup ? .openGroup : .regular
|
||||||
var rawSnippet: String = ""
|
var rawSnippet: String = ""
|
||||||
thread.groupModel.groupMemberIds.forEach{ id in
|
thread.groupModel.groupMemberIds.forEach{ id in
|
||||||
|
@ -252,7 +251,12 @@ final class ConversationCell : UITableViewCell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
snippetLabel.attributedText = getHighlightedSnippet(snippet: rawSnippet, searchText: normalizedSearchText, fontSize: Values.smallFontSize)
|
if rawSnippet.isEmpty {
|
||||||
|
bottomLabelStackView.isHidden = true
|
||||||
|
} else {
|
||||||
|
bottomLabelStackView.isHidden = false
|
||||||
|
snippetLabel.attributedText = getHighlightedSnippet(snippet: rawSnippet, searchText: normalizedSearchText, fontSize: Values.smallFontSize)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
displayNameLabel.attributedText = getHighlightedSnippet(snippet: getDisplayNameForSearch(threadViewModel.contactSessionID!), searchText: normalizedSearchText, fontSize: Values.mediumFontSize)
|
displayNameLabel.attributedText = getHighlightedSnippet(snippet: getDisplayNameForSearch(threadViewModel.contactSessionID!), searchText: normalizedSearchText, fontSize: Values.mediumFontSize)
|
||||||
bottomLabelStackView.isHidden = true
|
bottomLabelStackView.isHidden = true
|
||||||
|
|
|
@ -173,6 +173,7 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
|
||||||
withName:[TSDatabaseSecondaryIndexes registerTimeStampIndexExtensionName]];
|
withName:[TSDatabaseSecondaryIndexes registerTimeStampIndexExtensionName]];
|
||||||
|
|
||||||
[TSDatabaseView asyncRegisterUnseenDatabaseView:self];
|
[TSDatabaseView asyncRegisterUnseenDatabaseView:self];
|
||||||
|
[TSDatabaseView asyncRegisterUnreadMentionDatabaseView:self];
|
||||||
[TSDatabaseView asyncRegisterThreadOutgoingMessagesDatabaseView:self];
|
[TSDatabaseView asyncRegisterThreadOutgoingMessagesDatabaseView:self];
|
||||||
|
|
||||||
[FullTextSearchFinder asyncRegisterDatabaseExtensionWithStorage:self];
|
[FullTextSearchFinder asyncRegisterDatabaseExtensionWithStorage:self];
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern NSString *const TSMessageDatabaseViewExtensionName_Legacy;
|
||||||
|
|
||||||
extern NSString *const TSUnreadDatabaseViewExtensionName;
|
extern NSString *const TSUnreadDatabaseViewExtensionName;
|
||||||
extern NSString *const TSUnseenDatabaseViewExtensionName;
|
extern NSString *const TSUnseenDatabaseViewExtensionName;
|
||||||
|
extern NSString *const TSUnreadMentionDatabaseViewExtensionName;
|
||||||
extern NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName;
|
extern NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName;
|
||||||
extern NSString *const TSThreadSpecialMessagesDatabaseViewExtensionName;
|
extern NSString *const TSThreadSpecialMessagesDatabaseViewExtensionName;
|
||||||
|
|
||||||
|
@ -66,6 +67,11 @@ extern NSString *const TSLazyRestoreAttachmentsDatabaseViewExtensionName;
|
||||||
// Instances of OWSReadTracking for wasRead is NO.
|
// Instances of OWSReadTracking for wasRead is NO.
|
||||||
+ (void)asyncRegisterUnseenDatabaseView:(OWSStorage *)storage;
|
+ (void)asyncRegisterUnseenDatabaseView:(OWSStorage *)storage;
|
||||||
|
|
||||||
|
// Should be used for "mention indicator".
|
||||||
|
//
|
||||||
|
// Instances of OWSReadTracking for wasRead is NO and isUserMentioned is YES.
|
||||||
|
+ (void)asyncRegisterUnreadMentionDatabaseView:(OWSStorage *)storage;
|
||||||
|
|
||||||
+ (void)asyncRegisterLazyRestoreAttachmentsDatabaseView:(OWSStorage *)storage;
|
+ (void)asyncRegisterLazyRestoreAttachmentsDatabaseView:(OWSStorage *)storage;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -47,6 +47,7 @@ NSString *const TSMessageDatabaseViewExtensionName_Legacy = @"TSMessageDatabaseV
|
||||||
NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName = @"TSThreadOutgoingMessageDatabaseViewExtensionName";
|
NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName = @"TSThreadOutgoingMessageDatabaseViewExtensionName";
|
||||||
NSString *const TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName";
|
NSString *const TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName";
|
||||||
NSString *const TSUnseenDatabaseViewExtensionName = @"TSUnseenDatabaseViewExtensionName";
|
NSString *const TSUnseenDatabaseViewExtensionName = @"TSUnseenDatabaseViewExtensionName";
|
||||||
|
NSString *const TSUnreadMentionDatabaseViewExtensionName = @"TSUnreadMentionDatabaseViewExtensionName";
|
||||||
NSString *const TSThreadSpecialMessagesDatabaseViewExtensionName = @"TSThreadSpecialMessagesDatabaseViewExtensionName";
|
NSString *const TSThreadSpecialMessagesDatabaseViewExtensionName = @"TSThreadSpecialMessagesDatabaseViewExtensionName";
|
||||||
NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevicesDatabaseViewExtensionName";
|
NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevicesDatabaseViewExtensionName";
|
||||||
NSString *const TSLazyRestoreAttachmentsDatabaseViewExtensionName
|
NSString *const TSLazyRestoreAttachmentsDatabaseViewExtensionName
|
||||||
|
@ -134,6 +135,25 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
|
||||||
storage:storage];
|
storage:storage];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)asyncRegisterUnreadMentionDatabaseView:(OWSStorage *)storage
|
||||||
|
{
|
||||||
|
YapDatabaseViewGrouping *viewGrouping = [YapDatabaseViewGrouping withObjectBlock:^NSString *(
|
||||||
|
YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object) {
|
||||||
|
if ([object isKindOfClass:[TSIncomingMessage class]]) {
|
||||||
|
TSIncomingMessage *message = (TSIncomingMessage *)object;
|
||||||
|
if (!message.wasRead && message.isUserMentioned) {
|
||||||
|
return message.uniqueThreadId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self registerMessageDatabaseViewWithName:TSUnreadMentionDatabaseViewExtensionName
|
||||||
|
viewGrouping:viewGrouping
|
||||||
|
version:@"2"
|
||||||
|
storage:storage];
|
||||||
|
}
|
||||||
|
|
||||||
+ (void)asyncRegisterLegacyThreadInteractionsDatabaseView:(OWSStorage *)storage
|
+ (void)asyncRegisterLegacyThreadInteractionsDatabaseView:(OWSStorage *)storage
|
||||||
{
|
{
|
||||||
YapDatabaseView *existingView = [storage registeredExtension:TSMessageDatabaseViewExtensionName_Legacy];
|
YapDatabaseView *existingView = [storage registeredExtension:TSMessageDatabaseViewExtensionName_Legacy];
|
||||||
|
@ -287,7 +307,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
|
||||||
}
|
}
|
||||||
TSThread *thread = (TSThread *)object;
|
TSThread *thread = (TSThread *)object;
|
||||||
|
|
||||||
if (thread.isMessageRequest) {
|
if ([thread isMessageRequestUsingTransaction:transaction]) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -55,17 +55,16 @@ extension ConfigurationMessage {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// Skip the current user
|
// Skip the current user
|
||||||
contact.sessionID != currentUserPublicKey && (
|
contact.sessionID != currentUserPublicKey &&
|
||||||
|
// Contacts which have visible threads
|
||||||
|
TSContactThread.fetch(uniqueId: threadID, transaction: transaction)?.shouldBeVisible == true && (
|
||||||
|
|
||||||
// Include already approved contacts
|
// Include already approved contacts
|
||||||
contact.isApproved ||
|
contact.isApproved ||
|
||||||
contact.didApproveMe ||
|
contact.didApproveMe ||
|
||||||
|
|
||||||
// Sync blocked contacts
|
// Sync blocked contacts
|
||||||
SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(contact.sessionID) ||
|
SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(contact.sessionID)
|
||||||
|
|
||||||
// Contacts which have visible threads (sanity check - should be included as already approved)
|
|
||||||
TSContactThread.fetch(uniqueId: threadID, transaction: transaction)?.shouldBeVisible == true
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,6 @@ extension OpenGroupAPIV2 {
|
||||||
|
|
||||||
@objc(getDefaultRoomsIfNeeded)
|
@objc(getDefaultRoomsIfNeeded)
|
||||||
public static func objc_getDefaultRoomsIfNeeded() {
|
public static func objc_getDefaultRoomsIfNeeded() {
|
||||||
return getDefaultRoomsIfNeeded()
|
getDefaultRoomsIfNeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,21 +422,37 @@ public final class OpenGroupAPIV2 : NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: General
|
// MARK: General
|
||||||
public static func getDefaultRoomsIfNeeded() {
|
|
||||||
|
@discardableResult public static func getDefaultRoomsIfNeeded() -> Promise<[OpenGroupAPIV2.Info]> {
|
||||||
|
if let existingPromise: Promise<[OpenGroupAPIV2.Info]> = defaultRoomsPromise {
|
||||||
|
return existingPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
let (promise, seal) = Promise<[OpenGroupAPIV2.Info]>.pending()
|
||||||
|
|
||||||
Storage.shared.write(with: { transaction in
|
Storage.shared.write(with: { transaction in
|
||||||
Storage.shared.setOpenGroupPublicKey(for: defaultServer, to: defaultServerPublicKey, using: transaction)
|
Storage.shared.setOpenGroupPublicKey(for: defaultServer, to: defaultServerPublicKey, using: transaction)
|
||||||
}, completion: {
|
}, completion: {
|
||||||
let promise = attempt(maxRetryCount: 8, recoveringOn: DispatchQueue.main) {
|
let internalPromise: Promise<[OpenGroupAPIV2.Info]> = attempt(maxRetryCount: 8, recoveringOn: DispatchQueue.main) {
|
||||||
OpenGroupAPIV2.getAllRooms(from: defaultServer)
|
OpenGroupAPIV2.getAllRooms(from: defaultServer)
|
||||||
}
|
}
|
||||||
let _ = promise.done(on: OpenGroupAPIV2.workQueue) { items in
|
|
||||||
items.forEach { getGroupImage(for: $0.id, on: defaultServer).retainUntilComplete() }
|
internalPromise
|
||||||
}
|
.done(on: OpenGroupAPIV2.workQueue) { items in
|
||||||
promise.catch(on: OpenGroupAPIV2.workQueue) { _ in
|
items.forEach { getGroupImage(for: $0.id, on: defaultServer).retainUntilComplete() }
|
||||||
OpenGroupAPIV2.defaultRoomsPromise = nil
|
seal.fulfill(items)
|
||||||
}
|
}
|
||||||
defaultRoomsPromise = promise
|
.retainUntilComplete()
|
||||||
|
|
||||||
|
internalPromise
|
||||||
|
.catch(on: OpenGroupAPIV2.workQueue) { error in
|
||||||
|
OpenGroupAPIV2.defaultRoomsPromise = nil
|
||||||
|
seal.reject(error)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
defaultRoomsPromise = promise
|
||||||
|
return promise
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func getInfo(for room: String, on server: String) -> Promise<Info> {
|
public static func getInfo(for room: String, on server: String) -> Promise<Info> {
|
||||||
|
|
|
@ -30,6 +30,15 @@ public final class OpenGroupManagerV2 : NSObject {
|
||||||
|
|
||||||
// MARK: Adding & Removing
|
// MARK: Adding & Removing
|
||||||
public func add(room: String, server: String, publicKey: String, using transaction: Any) -> Promise<Void> {
|
public func add(room: String, server: String, publicKey: String, using transaction: Any) -> Promise<Void> {
|
||||||
|
// If we are currently polling for this server and already have a TSGroupThread for this room the do nothing
|
||||||
|
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||||
|
let groupId: Data = LKGroupUtilities.getEncodedOpenGroupIDAsData("\(server).\(room)")
|
||||||
|
|
||||||
|
if OpenGroupManagerV2.shared.pollers[server] != nil && TSGroupThread.fetch(uniqueId: TSGroupThread.threadId(fromGroupId: groupId), transaction: transaction) != nil {
|
||||||
|
SNLog("Ignoring join open group attempt (already joined)")
|
||||||
|
return Promise.value(())
|
||||||
|
}
|
||||||
|
|
||||||
let storage = Storage.shared
|
let storage = Storage.shared
|
||||||
// Clear any existing data if needed
|
// Clear any existing data if needed
|
||||||
storage.removeLastMessageServerID(for: room, on: server, using: transaction)
|
storage.removeLastMessageServerID(for: room, on: server, using: transaction)
|
||||||
|
@ -38,7 +47,7 @@ public final class OpenGroupManagerV2 : NSObject {
|
||||||
// Store the public key
|
// Store the public key
|
||||||
storage.setOpenGroupPublicKey(for: server, to: publicKey, using: transaction)
|
storage.setOpenGroupPublicKey(for: server, to: publicKey, using: transaction)
|
||||||
let (promise, seal) = Promise<Void>.pending()
|
let (promise, seal) = Promise<Void>.pending()
|
||||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
|
||||||
transaction.addCompletionQueue(DispatchQueue.global(qos: .userInitiated)) {
|
transaction.addCompletionQueue(DispatchQueue.global(qos: .userInitiated)) {
|
||||||
// Get the group info
|
// Get the group info
|
||||||
OpenGroupAPIV2.getInfo(for: room, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { info in
|
OpenGroupAPIV2.getInfo(for: room, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { info in
|
||||||
|
|
|
@ -211,7 +211,7 @@ extension MessageReceiver {
|
||||||
// Contacts
|
// Contacts
|
||||||
for contactInfo in message.contacts {
|
for contactInfo in message.contacts {
|
||||||
let sessionID = contactInfo.publicKey!
|
let sessionID = contactInfo.publicKey!
|
||||||
let contact = Contact(sessionID: sessionID)
|
let contact = (Storage.shared.getContact(with: sessionID, using: transaction) ?? Contact(sessionID: sessionID))
|
||||||
if let profileKey = contactInfo.profileKey { contact.profileEncryptionKey = OWSAES256Key(data: profileKey) }
|
if let profileKey = contactInfo.profileKey { contact.profileEncryptionKey = OWSAES256Key(data: profileKey) }
|
||||||
contact.profilePictureURL = contactInfo.profilePictureURL
|
contact.profilePictureURL = contactInfo.profilePictureURL
|
||||||
contact.name = contactInfo.displayName
|
contact.name = contactInfo.displayName
|
||||||
|
@ -417,11 +417,7 @@ extension MessageReceiver {
|
||||||
// Use the same identifier for notifications when in backgroud polling to prevent spam
|
// Use the same identifier for notifications when in backgroud polling to prevent spam
|
||||||
let notificationIdentifier = isBackgroundPoll ? thread.uniqueId : UUID().uuidString
|
let notificationIdentifier = isBackgroundPoll ? thread.uniqueId : UUID().uuidString
|
||||||
tsIncomingMessage.setNotificationIdentifier(notificationIdentifier, transaction: transaction)
|
tsIncomingMessage.setNotificationIdentifier(notificationIdentifier, transaction: transaction)
|
||||||
DispatchQueue.main.async {
|
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||||
Storage.read { transaction in
|
|
||||||
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tsMessageID
|
return tsMessageID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,10 +287,6 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
|
||||||
for (id<OWSReadTracking> readItem in newlyReadList) {
|
for (id<OWSReadTracking> readItem in newlyReadList) {
|
||||||
[readItem markAsReadAtTimestamp:readTimestamp trySendReadReceipt:trySendReadReceipt transaction:transaction];
|
[readItem markAsReadAtTimestamp:readTimestamp trySendReadReceipt:trySendReadReceipt transaction:transaction];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update unread mention.
|
|
||||||
thread.hasUnreadMentionMessage = false;
|
|
||||||
[thread saveWithTransaction:transaction];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Settings
|
#pragma mark - Settings
|
||||||
|
|
|
@ -16,7 +16,6 @@ BOOL IsNoteToSelfEnabled(void);
|
||||||
*/
|
*/
|
||||||
@interface TSThread : TSYapDatabaseObject
|
@interface TSThread : TSYapDatabaseObject
|
||||||
|
|
||||||
@property (nonatomic) BOOL hasUnreadMentionMessage;
|
|
||||||
@property (nonatomic) BOOL isPinned;
|
@property (nonatomic) BOOL isPinned;
|
||||||
@property (nonatomic) BOOL shouldBeVisible;
|
@property (nonatomic) BOOL shouldBeVisible;
|
||||||
@property (nonatomic, readonly) NSDate *creationDate;
|
@property (nonatomic, readonly) NSDate *creationDate;
|
||||||
|
@ -67,9 +66,18 @@ BOOL IsNoteToSelfEnabled(void);
|
||||||
*/
|
*/
|
||||||
- (NSUInteger)numberOfInteractions;
|
- (NSUInteger)numberOfInteractions;
|
||||||
|
|
||||||
|
- (NSUInteger)numberOfInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
|
|
||||||
- (NSUInteger)unreadMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction
|
- (NSUInteger)unreadMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||||
NS_SWIFT_NAME(unreadMessageCount(transaction:));
|
NS_SWIFT_NAME(unreadMessageCount(transaction:));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return If there is any message mentioning current user in this thread.
|
||||||
|
*/
|
||||||
|
- (NSUInteger)unreadMentionMessageCount;
|
||||||
|
|
||||||
|
- (NSUInteger)unreadMentionMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||||
|
|
||||||
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -233,12 +233,17 @@ BOOL IsNoteToSelfEnabled(void)
|
||||||
{
|
{
|
||||||
__block NSUInteger count;
|
__block NSUInteger count;
|
||||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
count = [self numberOfInteractionsWithTransaction:transaction];
|
||||||
count = [interactionsByThread numberOfItemsInGroup:self.uniqueId];
|
|
||||||
}];
|
}];
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)numberOfInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||||
|
{
|
||||||
|
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||||
|
return [interactionsByThread numberOfItemsInGroup:self.uniqueId];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray<id<OWSReadTracking>> *)unseenMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction
|
- (NSArray<id<OWSReadTracking>> *)unseenMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||||
{
|
{
|
||||||
NSMutableArray<id<OWSReadTracking>> *messages = [NSMutableArray new];
|
NSMutableArray<id<OWSReadTracking>> *messages = [NSMutableArray new];
|
||||||
|
@ -285,14 +290,27 @@ BOOL IsNoteToSelfEnabled(void)
|
||||||
// return count;
|
// return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)unreadMentionMessageCount
|
||||||
|
{
|
||||||
|
__block NSUInteger unreadMentionMessageCount;
|
||||||
|
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||||
|
unreadMentionMessageCount = [self unreadMentionMessageCountWithTransaction:transaction];
|
||||||
|
}];
|
||||||
|
return unreadMentionMessageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)unreadMentionMessageCountWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||||
|
{
|
||||||
|
YapDatabaseViewTransaction *unreadMentions = [transaction ext:TSUnreadMentionDatabaseViewExtensionName];
|
||||||
|
return [unreadMentions numberOfItemsInGroup:self.uniqueId];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
- (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction
|
||||||
{
|
{
|
||||||
for (id<OWSReadTracking> message in [self unseenMessagesWithTransaction:transaction]) {
|
for (id<OWSReadTracking> message in [self unseenMessagesWithTransaction:transaction]) {
|
||||||
[message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] trySendReadReceipt:YES transaction:transaction];
|
[message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] trySendReadReceipt:YES transaction:transaction];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update unread mention.
|
|
||||||
self.hasUnreadMentionMessage = false;
|
|
||||||
[super saveWithTransaction:transaction];
|
[super saveWithTransaction:transaction];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,12 +377,6 @@ BOOL IsNoteToSelfEnabled(void)
|
||||||
_lastInteractionDate = lastMessage.receivedAtDate;
|
_lastInteractionDate = lastMessage.receivedAtDate;
|
||||||
[super saveWithTransaction:transaction];
|
[super saveWithTransaction:transaction];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update unread mention if there is a new incoming message.
|
|
||||||
if ([lastMessage isKindOfClass:[TSIncomingMessage class]] && ((TSIncomingMessage *)lastMessage).isUserMentioned) {
|
|
||||||
self.hasUnreadMentionMessage = true;
|
|
||||||
[super saveWithTransaction:transaction];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self.shouldBeVisible) {
|
if (!self.shouldBeVisible) {
|
||||||
self.shouldBeVisible = YES;
|
self.shouldBeVisible = YES;
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol {
|
||||||
}
|
}
|
||||||
else if thread.isMessageRequest() && CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
else if thread.isMessageRequest() && CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
||||||
// If there are other interactions on this thread already then don't show the notification
|
// If there are other interactions on this thread already then don't show the notification
|
||||||
if thread.numberOfInteractions() > 1 { return }
|
if thread.numberOfInteractions(with: transaction) > 1 { return }
|
||||||
|
|
||||||
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = false
|
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = false
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,7 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol {
|
||||||
// If it's a message request then overwrite the body to be something generic (only show a notification
|
// If it's a message request then overwrite the body to be something generic (only show a notification
|
||||||
// when receiving a new message request if there aren't any others or the user had hidden them)
|
// when receiving a new message request if there aren't any others or the user had hidden them)
|
||||||
if thread.isMessageRequest() {
|
if thread.isMessageRequest() {
|
||||||
|
notificationContent.title = "Session"
|
||||||
notificationContent.body = "MESSAGE_REQUESTS_NOTIFICATION".localized()
|
notificationContent.body = "MESSAGE_REQUESTS_NOTIFICATION".localized()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
- (NSArray<OWSDatabaseMigration *> *)allMigrations
|
- (NSArray<OWSDatabaseMigration *> *)allMigrations
|
||||||
{
|
{
|
||||||
return @[
|
return @[
|
||||||
[SNUnreadMentionMigration new],
|
|
||||||
[SNMessageRequestsMigration new],
|
[SNMessageRequestsMigration new],
|
||||||
[SNContactsMigration new]
|
[SNContactsMigration new]
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
|
||||||
|
|
||||||
@objc(SNUnreadMentionMigration)
|
|
||||||
public class UnreadMentionMigration : OWSDatabaseMigration {
|
|
||||||
|
|
||||||
@objc
|
|
||||||
class func migrationId() -> String {
|
|
||||||
return "003" // leave "002" for message request migration
|
|
||||||
}
|
|
||||||
|
|
||||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
|
||||||
self.doMigrationAsync(completion: completion)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func doMigrationAsync(completion: @escaping OWSDatabaseMigrationCompletion) {
|
|
||||||
var threads: [TSThread] = []
|
|
||||||
Storage.read { transaction in
|
|
||||||
TSThread.enumerateCollectionObjects(with: transaction) { object, _ in
|
|
||||||
guard let thread = object as? TSThread, let threadID = thread.uniqueId else { return }
|
|
||||||
let unreadMessages = transaction.ext(TSUnreadDatabaseViewExtensionName) as! YapDatabaseViewTransaction
|
|
||||||
unreadMessages.enumerateKeysAndObjects(inGroup: threadID) { collection, key, object, index, stop in
|
|
||||||
guard let unreadMessage = object as? TSIncomingMessage else { return }
|
|
||||||
if unreadMessage.wasRead { return }
|
|
||||||
if unreadMessage.isUserMentioned {
|
|
||||||
thread.hasUnreadMentionMessage = true
|
|
||||||
stop.pointee = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
threads.append(thread)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Storage.write(with: { transaction in
|
|
||||||
threads.forEach { thread in
|
|
||||||
thread.save(with: transaction)
|
|
||||||
}
|
|
||||||
self.save(with: transaction) // Intentionally capture self
|
|
||||||
}, completion: {
|
|
||||||
completion()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -81,25 +81,12 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
BOOL isGroupThread = thread.isGroupThread;
|
BOOL isGroupThread = thread.isGroupThread;
|
||||||
|
|
||||||
[unreadMessages enumerateKeysAndObjectsInGroup:groupID
|
// For groups that only notifiy for mentions
|
||||||
usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) {
|
if (isGroupThread && ((TSGroupThread *)thread).isOnlyNotifyingForMentions) {
|
||||||
if (![object conformsToProtocol:@protocol(OWSReadTracking)]) {
|
count += [thread unreadMentionMessageCountWithTransaction:transaction];
|
||||||
return;
|
} else {
|
||||||
}
|
count += [thread unreadMessageCountWithTransaction:transaction];
|
||||||
id<OWSReadTracking> unread = (id<OWSReadTracking>)object;
|
}
|
||||||
if (unread.read) {
|
|
||||||
NSLog(@"Found an already read message in the * unread * messages list.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// We have to filter those unread messages for groups that only notifiy for mentions
|
|
||||||
if ([object isKindOfClass:TSIncomingMessage.class] && isGroupThread) {
|
|
||||||
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)object;
|
|
||||||
if (((TSGroupThread *)thread).isOnlyNotifyingForMentions && !incomingMessage.isUserMentioned) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count += 1;
|
|
||||||
}];
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class ThreadViewModel: NSObject {
|
||||||
|
|
||||||
self.unreadCount = thread.unreadMessageCount(transaction: transaction)
|
self.unreadCount = thread.unreadMessageCount(transaction: transaction)
|
||||||
self.hasUnreadMessages = unreadCount > 0
|
self.hasUnreadMessages = unreadCount > 0
|
||||||
self.hasUnreadMentions = thread.hasUnreadMentionMessage
|
self.hasUnreadMentions = thread.unreadMentionMessageCount(with: transaction) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc
|
@objc
|
||||||
|
|
|
@ -8,7 +8,17 @@ public final class Identicon : NSObject {
|
||||||
if content.count > 2 && content.hasPrefix("05") {
|
if content.count > 2 && content.hasPrefix("05") {
|
||||||
content.removeFirst(2)
|
content.removeFirst(2)
|
||||||
}
|
}
|
||||||
let layer = icon.generateLayer(with: size, text: content.substring(to: 1))
|
let initials: String = content
|
||||||
|
.split(separator: " ")
|
||||||
|
.compactMap { word in word.first.map { String($0) } }
|
||||||
|
.joined()
|
||||||
|
let layer = icon.generateLayer(
|
||||||
|
with: size,
|
||||||
|
text: (initials.count >= 2 ?
|
||||||
|
initials.substring(to: 2).uppercased() :
|
||||||
|
content.substring(to: 2).uppercased()
|
||||||
|
)
|
||||||
|
)
|
||||||
let rect = CGRect(origin: CGPoint.zero, size: layer.frame.size)
|
let rect = CGRect(origin: CGPoint.zero, size: layer.frame.size)
|
||||||
let renderer = UIGraphicsImageRenderer(size: rect.size)
|
let renderer = UIGraphicsImageRenderer(size: rect.size)
|
||||||
return renderer.image { layer.render(in: $0.cgContext) }
|
return renderer.image { layer.render(in: $0.cgContext) }
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class PlaceholderIcon {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getTextLayer(with diameter: CGFloat, colour: CGColor? = nil, text: String) -> CALayer {
|
private func getTextLayer(with diameter: CGFloat, colour: CGColor? = nil, text: String) -> CALayer {
|
||||||
let text = text.capitalized
|
|
||||||
let font = UIFont.boldSystemFont(ofSize: diameter / 2)
|
let font = UIFont.boldSystemFont(ofSize: diameter / 2)
|
||||||
let height = NSString(string: text).boundingRect(with: CGSize(width: diameter, height: CGFloat.greatestFiniteMagnitude),
|
let height = NSString(string: text).boundingRect(with: CGSize(width: diameter, height: CGFloat.greatestFiniteMagnitude),
|
||||||
options: .usesLineFragmentOrigin, attributes: [ NSAttributedString.Key.font : font ], context: nil).height
|
options: .usesLineFragmentOrigin, attributes: [ NSAttributedString.Key.font : font ], context: nil).height
|
||||||
|
|
Loading…
Reference in New Issue