Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thread Notifications & Badges #5257

Merged
merged 56 commits into from
Feb 3, 2022
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
6993f85
Add thread notification dots
ismailgulek Dec 1, 2021
7bd9883
Use thread image as template
ismailgulek Dec 1, 2021
2ddb654
Create `BadgedBarButtonItem` class and use it for thread list item
ismailgulek Dec 1, 2021
ac29d71
Update logic for thread list bar button item
ismailgulek Dec 2, 2021
1fac638
Mark thread as read when viewed
ismailgulek Dec 2, 2021
a4b3198
Use event method to check redaction
ismailgulek Dec 2, 2021
0cc223f
Specify event formatting was successful
ismailgulek Dec 2, 2021
9562267
Use attributed string for thread root message
ismailgulek Dec 2, 2021
42185a2
Use attributed string for thread last message
ismailgulek Dec 2, 2021
9eef855
Clear highlighted event when view gone
ismailgulek Dec 2, 2021
21f843c
Use simpler methods for thread check
ismailgulek Dec 7, 2021
4e44219
Pass threadId as nil for template chat service
ismailgulek Dec 7, 2021
98cd9dc
Build alpha release
ismailgulek Dec 7, 2021
e593422
Hide read receipt avatars on threads, fix #5239
ismailgulek Dec 8, 2021
e8da2f4
Revert Podfile change
ismailgulek Dec 8, 2021
cd91378
Hide typing notifications in threads, fix #5271
ismailgulek Dec 8, 2021
3f14b00
Disable partial text message on threads
ismailgulek Dec 8, 2021
117461d
Do not send typing notifications from threads, part of #5271
ismailgulek Dec 8, 2021
075495f
Hide jump to unread button on threads, override scroll to bottom acti…
ismailgulek Dec 8, 2021
ccead52
Fix thread display configuration
ismailgulek Dec 8, 2021
50f7a01
Disable thread filtering on regular timeline when threads disabled
ismailgulek Dec 9, 2021
a803aeb
Merge branch 'ismail/5095_thread_search_results' into ismail/5096_thr…
ismailgulek Dec 10, 2021
57a26d8
Fix build
ismailgulek Dec 10, 2021
2f07693
Adapt MXEventTimeline changes
ismailgulek Dec 14, 2021
b74975e
Merge branch 'ismail/5068_start_thread' into ismail/5096_thread_notif…
ismailgulek Dec 16, 2021
d954e18
Use live timeline of a thread
ismailgulek Dec 21, 2021
e47c1c4
Add view in room action for attachments
ismailgulek Dec 21, 2021
1412ba7
Make remove and report actions destructive
ismailgulek Dec 21, 2021
f8bb457
Open thread on an initial event, fetch the event if doesn't exist
ismailgulek Dec 24, 2021
586f2e5
Merge branch 'ismail/5068_design_tweaks' into ismail/5096_thread_noti…
ismailgulek Jan 12, 2022
b64a9ac
Remove old code
ismailgulek Jan 12, 2022
ff9c264
Persist rendering mode when resizing an image
ismailgulek Jan 12, 2022
f3e492a
Merge branch 'ismail/5068_start_thread' into ismail/5096_thread_notif…
ismailgulek Jan 17, 2022
09ee13e
Merge branch 'ismail/5068_start_thread' into ismail/5096_thread_notif…
ismailgulek Jan 17, 2022
ec8acd0
Merge branch 'ismail/5068_design_tweaks' into ismail/5096_thread_noti…
ismailgulek Jan 18, 2022
a00293b
Disable thread timelines for now
ismailgulek Jan 18, 2022
1599456
Fix test build
ismailgulek Jan 19, 2022
54e344c
Merge branch 'ismail/5068_design_tweaks' into ismail/5096_thread_noti…
ismailgulek Jan 20, 2022
10ada55
Do not stack room screen when opening threads from permalinks
ismailgulek Jan 20, 2022
1e3ec62
Fix toast bottom margin for header action
ismailgulek Jan 20, 2022
caf5672
Do not show badge for not participated threads
ismailgulek Jan 20, 2022
d2217b5
Scroll to highlighted event better
ismailgulek Jan 20, 2022
03977b8
Implement going back to live room data sources for threads, fix bugs …
ismailgulek Jan 20, 2022
1fcb4f7
Fix thread root decorations on search results
ismailgulek Jan 20, 2022
3dec412
Merge branch 'develop' into ismail/5096_thread_notifications
ismailgulek Jan 27, 2022
3d76d82
Fix redundant check
ismailgulek Jan 27, 2022
9b6f2e3
Fix tapping on user avatar
ismailgulek Jan 27, 2022
ad83173
Use replied event in fallback events
ismailgulek Jan 28, 2022
9d83aee
Display redacted events only if threads enabled
ismailgulek Jan 28, 2022
bd12487
Feed threading option in the SDK
ismailgulek Jan 28, 2022
ce1dd57
Merge branch 'develop' into ismail/5096_thread_notifications
ismailgulek Jan 31, 2022
61b741e
Merge branch 'develop' into ismail/5096_thread_notifications
ismailgulek Feb 2, 2022
2303498
Add thread setting check to permalinks and search results
ismailgulek Feb 2, 2022
516479a
Merge branch 'develop' into ismail/5096_thread_notifications
ismailgulek Feb 3, 2022
146a5bc
Fix files search build error
ismailgulek Feb 3, 2022
9f686da
Fix review remarks
ismailgulek Feb 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Config/CommonConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class CommonConfiguration: NSObject, Configurable {

// Disable key backup on common
sdkOptions.enableKeyBackupWhenStartingMXCrypto = false

// Pass threading option to the SDK
sdkOptions.enableThreads = RiotSettings.shared.enableThreads

sdkOptions.clientPermalinkBaseUrl = BuildSettings.clientPermalinkBaseUrl

Expand Down
3 changes: 2 additions & 1 deletion Riot/Categories/UIImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ extension UIImage {

// Based on https://stackoverflow.com/a/31314494
@objc func vc_resized(with targetSize: CGSize) -> UIImage? {
let originalRenderingMode = self.renderingMode
let size = self.size

let widthRatio = targetSize.width/size.width
Expand All @@ -79,7 +80,7 @@ extension UIImage {
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return newImage
return newImage?.withRenderingMode(originalRenderingMode)
}

@objc func vc_notRenderedImage() -> UIImage {
Expand Down
84 changes: 59 additions & 25 deletions Riot/Modules/Application/LegacyAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,8 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin
{
NSString *fragment = universalLinkParameters.fragment;
NSURL *universalLinkURL = universalLinkParameters.universalLinkURL;
ScreenPresentationParameters *screenPresentationParameters = universalLinkParameters.presentationParameters;
BOOL restoreInitialDisplay = screenPresentationParameters.restoreInitialDisplay;
ScreenPresentationParameters *presentationParameters = universalLinkParameters.presentationParameters;
BOOL restoreInitialDisplay = presentationParameters.restoreInitialDisplay;

BOOL continueUserActivity = NO;
MXKAccountManager *accountManager = [MXKAccountManager sharedManager];
Expand Down Expand Up @@ -1281,7 +1281,6 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin
}

NSString *roomIdOrAlias;
ThreadParameters *threadParameters;
NSString *eventId;
NSString *userId;
NSString *groupId;
Expand Down Expand Up @@ -1356,7 +1355,7 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin

if (room.summary.roomType == MXRoomTypeSpace)
{
SpaceNavigationParameters *spaceNavigationParameters = [[SpaceNavigationParameters alloc] initWithRoomId:room.roomId mxSession:account.mxSession presentationParameters:screenPresentationParameters];
SpaceNavigationParameters *spaceNavigationParameters = [[SpaceNavigationParameters alloc] initWithRoomId:room.roomId mxSession:account.mxSession presentationParameters:presentationParameters];

[self showSpaceWithParameters:spaceNavigationParameters];
}
Expand All @@ -1365,25 +1364,60 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin
// Open the room page
if (eventId)
{
MXEvent *event = [account.mxSession.store eventWithEventId:eventId inRoom:roomId];
if (event.threadId)
{
threadParameters = [[ThreadParameters alloc] initWithThreadId:event.threadId
stackRoomScreen:YES];
}
else if ([account.mxSession.threadingService isEventThreadRoot:event])
__block MXEvent *event = [account.mxSession.store eventWithEventId:eventId inRoom:roomId];
dispatch_group_t eventDispatchGroup = dispatch_group_create();

if (event == nil)
{
threadParameters = [[ThreadParameters alloc] initWithThreadId:event.eventId
stackRoomScreen:YES];
dispatch_group_enter(eventDispatchGroup);
// event doesn't exist in the store
[account.mxSession eventWithEventId:eventId
inRoom:roomId
success:^(MXEvent *eventFromServer) {
event = eventFromServer;
dispatch_group_leave(eventDispatchGroup);
} failure:^(NSError *error) {
dispatch_group_leave(eventDispatchGroup);
}];
}

dispatch_group_notify(eventDispatchGroup, dispatch_get_main_queue(), ^{
if (event == nil)
{
return;
}

ThreadParameters *threadParameters = nil;
if (event.threadId)
{
threadParameters = [[ThreadParameters alloc] initWithThreadId:event.threadId
stackRoomScreen:NO];
}
else if ([account.mxSession.threadingService threadWithId:eventId])
{
threadParameters = [[ThreadParameters alloc] initWithThreadId:eventId
stackRoomScreen:NO];
}

RoomNavigationParameters *parameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId
eventId:eventId
mxSession:account.mxSession
threadParameters:threadParameters
presentationParameters:presentationParameters];
[self showRoomWithParameters:parameters];
});
}
else
{
// open the regular room timeline
RoomNavigationParameters *parameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId
eventId:eventId
mxSession:account.mxSession
threadParameters:nil
presentationParameters:presentationParameters];

[self showRoomWithParameters:parameters];
}
RoomNavigationParameters *roomNavigationParameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId
eventId:eventId
mxSession:account.mxSession
threadParameters:threadParameters
presentationParameters:screenPresentationParameters];

[self showRoomWithParameters:roomNavigationParameters];
}

continueUserActivity = YES;
Expand Down Expand Up @@ -1431,7 +1465,7 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin
{
universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias};

UniversalLinkParameters *newParameters = [[UniversalLinkParameters alloc] initWithFragment:newUniversalLinkFragment universalLinkURL:universalLinkURL presentationParameters:screenPresentationParameters];
UniversalLinkParameters *newParameters = [[UniversalLinkParameters alloc] initWithFragment:newUniversalLinkFragment universalLinkURL:universalLinkURL presentationParameters:presentationParameters];

[self handleUniversalLinkWithParameters:newParameters];
}
Expand Down Expand Up @@ -1490,14 +1524,14 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin
roomPreviewData.viaServers = queryParams[@"via"];
}

RoomPreviewNavigationParameters *roomPreviewNavigationParameters = [[RoomPreviewNavigationParameters alloc] initWithPreviewData:roomPreviewData presentationParameters:screenPresentationParameters];
RoomPreviewNavigationParameters *roomPreviewNavigationParameters = [[RoomPreviewNavigationParameters alloc] initWithPreviewData:roomPreviewData presentationParameters:presentationParameters];

[account.mxSession.matrixRestClient roomSummaryWith:roomIdOrAlias via:roomPreviewData.viaServers success:^(MXPublicRoom *room) {
if ([room.roomTypeString isEqualToString:MXRoomTypeStringSpace])
{
[homeViewController stopActivityIndicator];

SpacePreviewNavigationParameters *spacePreviewNavigationParameters = [[SpacePreviewNavigationParameters alloc] initWithPublicRoom:room mxSession:account.mxSession presentationParameters:screenPresentationParameters];
SpacePreviewNavigationParameters *spacePreviewNavigationParameters = [[SpacePreviewNavigationParameters alloc] initWithPublicRoom:room mxSession:account.mxSession presentationParameters:presentationParameters];

[self showSpacePreviewWithParameters:spacePreviewNavigationParameters];
}
Expand Down Expand Up @@ -1575,7 +1609,7 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin

// Create the contact related to this member
MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:displayName andMatrixID:userId];
[self showContact:contact presentationParameters:screenPresentationParameters];
[self showContact:contact presentationParameters:presentationParameters];

continueUserActivity = YES;
}
Expand All @@ -1594,7 +1628,7 @@ - (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLin
}

// Display the group details
[self showGroup:group withMatrixSession:account.mxSession presentationParamters:screenPresentationParameters];
[self showGroup:group withMatrixSession:account.mxSession presentationParamters:presentationParameters];

continueUserActivity = YES;
}
Expand Down
121 changes: 121 additions & 0 deletions Riot/Modules/Common/Views/BadgedBarButtonItem.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import UIKit

@objcMembers
class BadgedBarButtonItem: UIBarButtonItem {

var baseButton: UIButton
private var badgeLabel: UILabel

private var theme: Theme = ThemeService.shared().theme
ismailgulek marked this conversation as resolved.
Show resolved Hide resolved

var badgeText: String? {
didSet {
updateBadgeLabel()
}
}
var badgeBackgroundColor: UIColor {
didSet {
updateBadgeLabel()
}
}
var badgeTextColor: UIColor {
didSet {
updateBadgeLabel()
}
}
var badgeFont: UIFont {
didSet {
updateBadgeLabel()
}
}
var badgePadding: UIOffset {
didSet {
updateBadgeLabel()
}
}

private var shouldHideBadge: Bool {
guard let text = badgeText else {
return true
}
return text.isEmpty || text == "0" || text == "nil" || text == "null"
}

init(withBaseButton baseButton: UIButton) {
self.baseButton = baseButton
badgeBackgroundColor = .gray
badgeTextColor = .white
badgeFont = .systemFont(ofSize: 12, weight: .semibold)
badgePadding = UIOffset(horizontal: 8, vertical: 2)
badgeLabel = UILabel(frame: .zero)
badgeLabel.textAlignment = .center
badgeLabel.clipsToBounds = true
baseButton.addSubview(badgeLabel)
super.init()
ismailgulek marked this conversation as resolved.
Show resolved Hide resolved
customView = baseButton
update(theme: theme)
updateBadgeLabel()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func updateBadgeLabel() {
badgeLabel.isHidden = shouldHideBadge
badgeLabel.backgroundColor = badgeBackgroundColor
badgeLabel.font = badgeFont
badgeLabel.textColor = badgeTextColor

let labelSize = calculateLabelSize()
var width = labelSize.width + badgePadding.horizontal
let height = labelSize.height + badgePadding.vertical
if width < height {
// let width at least be as height
width = height
}
baseButton.sizeToFit()
badgeLabel.frame = CGRect(x: baseButton.frame.width - baseButton.contentEdgeInsets.right - width/2,
y: baseButton.contentEdgeInsets.top - height/2,
width: width,
height: height)
badgeLabel.text = badgeText
badgeLabel.layer.cornerRadius = badgeLabel.frame.height/2
}

private func calculateLabelSize() -> CGSize {
let tmpLabel = UILabel(frame: badgeLabel.frame)
tmpLabel.font = badgeFont
tmpLabel.text = badgeText
tmpLabel.sizeToFit()
return tmpLabel.frame.size
}

}

extension BadgedBarButtonItem: Themable {

func update(theme: Theme) {
self.theme = theme

tintColor = theme.colors.accent
baseButton.tintColor = theme.colors.accent
}

}
Loading