commit
b7520ed1cb
|
@ -135,7 +135,6 @@
|
|||
7B1581E2271E743B00848B49 /* OWSSounds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1581E1271E743B00848B49 /* OWSSounds.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 */; };
|
||||
7B1D74AE27C346220030B423 /* UnreadMentionMigtation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B1D74AD27C346220030B423 /* UnreadMentionMigtation.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 */; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
|
@ -3070,7 +3068,6 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
B8B32044258C117C0020074B /* ContactsMigration.swift */,
|
||||
7B1D74AD27C346220030B423 /* UnreadMentionMigtation.swift */,
|
||||
FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */,
|
||||
C38EF271255B6D79007E1867 /* OWSDatabaseMigration.h */,
|
||||
C38EF270255B6D79007E1867 /* OWSDatabaseMigration.m */,
|
||||
|
@ -4615,7 +4612,6 @@
|
|||
C38EF40B255B6DF7007E1867 /* TappableStackView.swift in Sources */,
|
||||
C38EF31D255B6DBF007E1867 /* UIImage+OWS.swift in Sources */,
|
||||
C38EF359255B6DCC007E1867 /* SheetViewController.swift in Sources */,
|
||||
7B1D74AE27C346220030B423 /* UnreadMentionMigtation.swift in Sources */,
|
||||
B8F5F52925EC4F8A003BF8D4 /* BlockListUIUtils.m in Sources */,
|
||||
C38EF386255B6DD2007E1867 /* AttachmentApprovalInputAccessoryView.swift in Sources */,
|
||||
B8C2B2C82563685C00551B4D /* CircleView.swift in Sources */,
|
||||
|
@ -5189,7 +5185,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 324;
|
||||
CURRENT_PROJECT_VERSION = 325;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
|
@ -5262,7 +5258,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 324;
|
||||
CURRENT_PROJECT_VERSION = 325;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
|
@ -5328,7 +5324,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 324;
|
||||
CURRENT_PROJECT_VERSION = 325;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
|
||||
|
@ -5402,7 +5398,7 @@
|
|||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 324;
|
||||
CURRENT_PROJECT_VERSION = 325;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
|
@ -6338,7 +6334,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 324;
|
||||
CURRENT_PROJECT_VERSION = 325;
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
@ -6409,7 +6405,7 @@
|
|||
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 324;
|
||||
CURRENT_PROJECT_VERSION = 325;
|
||||
DEVELOPMENT_TEAM = SUQ8J2PCT7;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
|
|
@ -613,6 +613,10 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
|
|||
let updateType = conversationUpdate.conversationUpdateType
|
||||
guard updateType != .minor else { return } // No view items were affected
|
||||
if updateType == .reload {
|
||||
if threadStartedAsMessageRequest {
|
||||
updateNavBarButtons() // In case the message request was approved
|
||||
}
|
||||
|
||||
return messagesTableView.reloadData()
|
||||
}
|
||||
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)
|
||||
default: preconditionFailure()
|
||||
}
|
||||
|
||||
// Update the nav items if the message request was approved
|
||||
if (update.viewItem?.interaction as? TSInfoMessage)?.messageType == .messageRequestAccepted {
|
||||
self.updateNavBarButtons()
|
||||
}
|
||||
}
|
||||
}
|
||||
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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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_DIRECT_MESSAGE" = "Direct Message";
|
||||
"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) {
|
||||
guard !thread.isMuted 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
|
||||
// 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
|
||||
// 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 numMessageRequests = threads.numberOfItems(inGroup: TSMessageRequestGroup)
|
||||
|
||||
// Allow this to show a notification if there are no message requests (ie. this is the first one)
|
||||
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 thread.numberOfInteractions() > 1 { return }
|
||||
if thread.numberOfInteractions(with: transaction) > 1 { return }
|
||||
|
||||
CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = false
|
||||
}
|
||||
|
@ -214,7 +215,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol {
|
|||
case .nameNoPreview, .namePreview:
|
||||
switch thread {
|
||||
case is TSContactThread:
|
||||
notificationTitle = (thread.isMessageRequest() ? "Session" : senderName)
|
||||
notificationTitle = (isMessageRequest ? "Session" : senderName)
|
||||
|
||||
case is TSGroupThread:
|
||||
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
|
||||
// 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: "")
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import PromiseKit
|
||||
import NVActivityIndicatorView
|
||||
import SessionUIKit
|
||||
|
||||
final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
|
||||
private let maxWidth: CGFloat
|
||||
|
@ -32,6 +33,42 @@ final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UIColl
|
|||
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
|
||||
private static let cellHeight: CGFloat = 40
|
||||
private static let separatorWidth = 1 / UIScreen.main.scale
|
||||
|
@ -54,17 +91,40 @@ final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UIColl
|
|||
private func initialize() {
|
||||
addSubview(collectionView)
|
||||
collectionView.pin(to: self)
|
||||
|
||||
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()
|
||||
|
||||
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)
|
||||
widthAnchor.constraint(greaterThanOrEqualToConstant: OpenGroupSuggestionGrid.cellHeight).isActive = true
|
||||
if OpenGroupAPIV2.defaultRoomsPromise == nil {
|
||||
OpenGroupAPIV2.getDefaultRoomsIfNeeded()
|
||||
}
|
||||
let _ = OpenGroupAPIV2.defaultRoomsPromise?.done { [weak self] rooms in
|
||||
self?.rooms = rooms
|
||||
}
|
||||
|
||||
OpenGroupAPIV2.getDefaultRoomsIfNeeded()
|
||||
.done { [weak self] rooms in
|
||||
self?.rooms = rooms
|
||||
}
|
||||
.catch { [weak self] _ in
|
||||
self?.update()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Updating
|
||||
|
@ -75,6 +135,7 @@ final class OpenGroupSuggestionGrid : UIView, UICollectionViewDataSource, UIColl
|
|||
let height = OpenGroupSuggestionGrid.cellHeight * ceil(CGFloat(roomCount) / 2)
|
||||
heightConstraint.constant = height
|
||||
collectionView.reloadData()
|
||||
errorView.isHidden = (roomCount > 0)
|
||||
}
|
||||
|
||||
// MARK: Layout
|
||||
|
@ -173,8 +234,22 @@ extension OpenGroupSuggestionGrid {
|
|||
private func update() {
|
||||
guard let room = room else { return }
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,7 +239,6 @@ final class ConversationCell : UITableViewCell {
|
|||
// Contact
|
||||
if threadViewModel.isGroupThread, let thread = threadViewModel.threadRecord as? TSGroupThread {
|
||||
displayNameLabel.attributedText = getHighlightedSnippet(snippet: getDisplayName(), searchText: normalizedSearchText, fontSize: Values.mediumFontSize)
|
||||
bottomLabelStackView.isHidden = false
|
||||
let context: Contact.Context = thread.isOpenGroup ? .openGroup : .regular
|
||||
var rawSnippet: String = ""
|
||||
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 {
|
||||
displayNameLabel.attributedText = getHighlightedSnippet(snippet: getDisplayNameForSearch(threadViewModel.contactSessionID!), searchText: normalizedSearchText, fontSize: Values.mediumFontSize)
|
||||
bottomLabelStackView.isHidden = true
|
||||
|
|
|
@ -173,6 +173,7 @@ void VerifyRegistrationsForPrimaryStorage(OWSStorage *storage)
|
|||
withName:[TSDatabaseSecondaryIndexes registerTimeStampIndexExtensionName]];
|
||||
|
||||
[TSDatabaseView asyncRegisterUnseenDatabaseView:self];
|
||||
[TSDatabaseView asyncRegisterUnreadMentionDatabaseView:self];
|
||||
[TSDatabaseView asyncRegisterThreadOutgoingMessagesDatabaseView:self];
|
||||
|
||||
[FullTextSearchFinder asyncRegisterDatabaseExtensionWithStorage:self];
|
||||
|
|
|
@ -22,6 +22,7 @@ extern NSString *const TSMessageDatabaseViewExtensionName_Legacy;
|
|||
|
||||
extern NSString *const TSUnreadDatabaseViewExtensionName;
|
||||
extern NSString *const TSUnseenDatabaseViewExtensionName;
|
||||
extern NSString *const TSUnreadMentionDatabaseViewExtensionName;
|
||||
extern NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName;
|
||||
extern NSString *const TSThreadSpecialMessagesDatabaseViewExtensionName;
|
||||
|
||||
|
@ -66,6 +67,11 @@ extern NSString *const TSLazyRestoreAttachmentsDatabaseViewExtensionName;
|
|||
// Instances of OWSReadTracking for wasRead is NO.
|
||||
+ (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;
|
||||
|
||||
@end
|
||||
|
|
|
@ -47,6 +47,7 @@ NSString *const TSMessageDatabaseViewExtensionName_Legacy = @"TSMessageDatabaseV
|
|||
NSString *const TSThreadOutgoingMessageDatabaseViewExtensionName = @"TSThreadOutgoingMessageDatabaseViewExtensionName";
|
||||
NSString *const TSUnreadDatabaseViewExtensionName = @"TSUnreadDatabaseViewExtensionName";
|
||||
NSString *const TSUnseenDatabaseViewExtensionName = @"TSUnseenDatabaseViewExtensionName";
|
||||
NSString *const TSUnreadMentionDatabaseViewExtensionName = @"TSUnreadMentionDatabaseViewExtensionName";
|
||||
NSString *const TSThreadSpecialMessagesDatabaseViewExtensionName = @"TSThreadSpecialMessagesDatabaseViewExtensionName";
|
||||
NSString *const TSSecondaryDevicesDatabaseViewExtensionName = @"TSSecondaryDevicesDatabaseViewExtensionName";
|
||||
NSString *const TSLazyRestoreAttachmentsDatabaseViewExtensionName
|
||||
|
@ -134,6 +135,25 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
|
|||
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
|
||||
{
|
||||
YapDatabaseView *existingView = [storage registeredExtension:TSMessageDatabaseViewExtensionName_Legacy];
|
||||
|
@ -287,7 +307,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup"
|
|||
}
|
||||
TSThread *thread = (TSThread *)object;
|
||||
|
||||
if (thread.isMessageRequest) {
|
||||
if ([thread isMessageRequestUsingTransaction:transaction]) {
|
||||
return nil;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -55,17 +55,16 @@ extension ConfigurationMessage {
|
|||
|
||||
return (
|
||||
// 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
|
||||
contact.isApproved ||
|
||||
contact.didApproveMe ||
|
||||
|
||||
// Sync blocked contacts
|
||||
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
|
||||
SSKEnvironment.shared.blockingManager.isRecipientIdBlocked(contact.sessionID)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,6 @@ extension OpenGroupAPIV2 {
|
|||
|
||||
@objc(getDefaultRoomsIfNeeded)
|
||||
public static func objc_getDefaultRoomsIfNeeded() {
|
||||
return getDefaultRoomsIfNeeded()
|
||||
getDefaultRoomsIfNeeded()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -422,21 +422,37 @@ public final class OpenGroupAPIV2 : NSObject {
|
|||
}
|
||||
|
||||
// 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.setOpenGroupPublicKey(for: defaultServer, to: defaultServerPublicKey, using: transaction)
|
||||
}, completion: {
|
||||
let promise = attempt(maxRetryCount: 8, recoveringOn: DispatchQueue.main) {
|
||||
let internalPromise: Promise<[OpenGroupAPIV2.Info]> = attempt(maxRetryCount: 8, recoveringOn: DispatchQueue.main) {
|
||||
OpenGroupAPIV2.getAllRooms(from: defaultServer)
|
||||
}
|
||||
let _ = promise.done(on: OpenGroupAPIV2.workQueue) { items in
|
||||
items.forEach { getGroupImage(for: $0.id, on: defaultServer).retainUntilComplete() }
|
||||
}
|
||||
promise.catch(on: OpenGroupAPIV2.workQueue) { _ in
|
||||
OpenGroupAPIV2.defaultRoomsPromise = nil
|
||||
}
|
||||
defaultRoomsPromise = promise
|
||||
|
||||
internalPromise
|
||||
.done(on: OpenGroupAPIV2.workQueue) { items in
|
||||
items.forEach { getGroupImage(for: $0.id, on: defaultServer).retainUntilComplete() }
|
||||
seal.fulfill(items)
|
||||
}
|
||||
.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> {
|
||||
|
|
|
@ -30,6 +30,15 @@ public final class OpenGroupManagerV2 : NSObject {
|
|||
|
||||
// MARK: Adding & Removing
|
||||
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
|
||||
// Clear any existing data if needed
|
||||
storage.removeLastMessageServerID(for: room, on: server, using: transaction)
|
||||
|
@ -38,7 +47,7 @@ public final class OpenGroupManagerV2 : NSObject {
|
|||
// Store the public key
|
||||
storage.setOpenGroupPublicKey(for: server, to: publicKey, using: transaction)
|
||||
let (promise, seal) = Promise<Void>.pending()
|
||||
let transaction = transaction as! YapDatabaseReadWriteTransaction
|
||||
|
||||
transaction.addCompletionQueue(DispatchQueue.global(qos: .userInitiated)) {
|
||||
// Get the group info
|
||||
OpenGroupAPIV2.getInfo(for: room, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { info in
|
||||
|
|
|
@ -211,7 +211,7 @@ extension MessageReceiver {
|
|||
// Contacts
|
||||
for contactInfo in message.contacts {
|
||||
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) }
|
||||
contact.profilePictureURL = contactInfo.profilePictureURL
|
||||
contact.name = contactInfo.displayName
|
||||
|
@ -417,11 +417,7 @@ extension MessageReceiver {
|
|||
// Use the same identifier for notifications when in backgroud polling to prevent spam
|
||||
let notificationIdentifier = isBackgroundPoll ? thread.uniqueId : UUID().uuidString
|
||||
tsIncomingMessage.setNotificationIdentifier(notificationIdentifier, transaction: transaction)
|
||||
DispatchQueue.main.async {
|
||||
Storage.read { transaction in
|
||||
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||
}
|
||||
}
|
||||
SSKEnvironment.shared.notificationsManager!.notifyUser(for: tsIncomingMessage, in: thread, transaction: transaction)
|
||||
return tsMessageID
|
||||
}
|
||||
|
||||
|
|
|
@ -287,10 +287,6 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE
|
|||
for (id<OWSReadTracking> readItem in newlyReadList) {
|
||||
[readItem markAsReadAtTimestamp:readTimestamp trySendReadReceipt:trySendReadReceipt transaction:transaction];
|
||||
}
|
||||
|
||||
// Update unread mention.
|
||||
thread.hasUnreadMentionMessage = false;
|
||||
[thread saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
#pragma mark - Settings
|
||||
|
|
|
@ -16,7 +16,6 @@ BOOL IsNoteToSelfEnabled(void);
|
|||
*/
|
||||
@interface TSThread : TSYapDatabaseObject
|
||||
|
||||
@property (nonatomic) BOOL hasUnreadMentionMessage;
|
||||
@property (nonatomic) BOOL isPinned;
|
||||
@property (nonatomic) BOOL shouldBeVisible;
|
||||
@property (nonatomic, readonly) NSDate *creationDate;
|
||||
|
@ -67,9 +66,18 @@ BOOL IsNoteToSelfEnabled(void);
|
|||
*/
|
||||
- (NSUInteger)numberOfInteractions;
|
||||
|
||||
- (NSUInteger)numberOfInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction;
|
||||
|
||||
- (NSUInteger)unreadMessageCountWithTransaction:(YapDatabaseReadTransaction *)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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -233,12 +233,17 @@ BOOL IsNoteToSelfEnabled(void)
|
|||
{
|
||||
__block NSUInteger count;
|
||||
[[self dbReadConnection] readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
count = [interactionsByThread numberOfItemsInGroup:self.uniqueId];
|
||||
count = [self numberOfInteractionsWithTransaction:transaction];
|
||||
}];
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSUInteger)numberOfInteractionsWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
YapDatabaseViewTransaction *interactionsByThread = [transaction ext:TSMessageDatabaseViewExtensionName];
|
||||
return [interactionsByThread numberOfItemsInGroup:self.uniqueId];
|
||||
}
|
||||
|
||||
- (NSArray<id<OWSReadTracking>> *)unseenMessagesWithTransaction:(YapDatabaseReadTransaction *)transaction
|
||||
{
|
||||
NSMutableArray<id<OWSReadTracking>> *messages = [NSMutableArray new];
|
||||
|
@ -285,14 +290,27 @@ BOOL IsNoteToSelfEnabled(void)
|
|||
// 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
|
||||
{
|
||||
for (id<OWSReadTracking> message in [self unseenMessagesWithTransaction:transaction]) {
|
||||
[message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] trySendReadReceipt:YES transaction:transaction];
|
||||
}
|
||||
|
||||
// Update unread mention.
|
||||
self.hasUnreadMentionMessage = false;
|
||||
[super saveWithTransaction:transaction];
|
||||
}
|
||||
|
||||
|
@ -359,12 +377,6 @@ BOOL IsNoteToSelfEnabled(void)
|
|||
_lastInteractionDate = lastMessage.receivedAtDate;
|
||||
[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) {
|
||||
self.shouldBeVisible = YES;
|
||||
|
|
|
@ -22,7 +22,7 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol {
|
|||
}
|
||||
else if thread.isMessageRequest() && CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] {
|
||||
// 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
|
||||
}
|
||||
|
@ -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
|
||||
// when receiving a new message request if there aren't any others or the user had hidden them)
|
||||
if thread.isMessageRequest() {
|
||||
notificationContent.title = "Session"
|
||||
notificationContent.body = "MESSAGE_REQUESTS_NOTIFICATION".localized()
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (NSArray<OWSDatabaseMigration *> *)allMigrations
|
||||
{
|
||||
return @[
|
||||
[SNUnreadMentionMigration new],
|
||||
[SNMessageRequestsMigration 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;
|
||||
|
||||
[unreadMessages enumerateKeysAndObjectsInGroup:groupID
|
||||
usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) {
|
||||
if (![object conformsToProtocol:@protocol(OWSReadTracking)]) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}];
|
||||
// For groups that only notifiy for mentions
|
||||
if (isGroupThread && ((TSGroupThread *)thread).isOnlyNotifyingForMentions) {
|
||||
count += [thread unreadMentionMessageCountWithTransaction:transaction];
|
||||
} else {
|
||||
count += [thread unreadMessageCountWithTransaction:transaction];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class ThreadViewModel: NSObject {
|
|||
|
||||
self.unreadCount = thread.unreadMessageCount(transaction: transaction)
|
||||
self.hasUnreadMessages = unreadCount > 0
|
||||
self.hasUnreadMentions = thread.hasUnreadMentionMessage
|
||||
self.hasUnreadMentions = thread.unreadMentionMessageCount(with: transaction) > 0
|
||||
}
|
||||
|
||||
@objc
|
||||
|
|
|
@ -8,7 +8,17 @@ public final class Identicon : NSObject {
|
|||
if content.count > 2 && content.hasPrefix("05") {
|
||||
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 renderer = UIGraphicsImageRenderer(size: rect.size)
|
||||
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 {
|
||||
let text = text.capitalized
|
||||
let font = UIFont.boldSystemFont(ofSize: diameter / 2)
|
||||
let height = NSString(string: text).boundingRect(with: CGSize(width: diameter, height: CGFloat.greatestFiniteMagnitude),
|
||||
options: .usesLineFragmentOrigin, attributes: [ NSAttributedString.Key.font : font ], context: nil).height
|
||||
|
|
Loading…
Reference in New Issue