diff --git a/submodules/DatePickerNode/Sources/DatePickerNode.swift b/submodules/DatePickerNode/Sources/DatePickerNode.swift index a65721bace..2768d29fdf 100644 --- a/submodules/DatePickerNode/Sources/DatePickerNode.swift +++ b/submodules/DatePickerNode/Sources/DatePickerNode.swift @@ -209,6 +209,9 @@ public final class DatePickerNode: ASDisplayNode { started = true } weekday += 1 + if weekday > 7 { + weekday = 1 + } let textNode = self.dateNodes[i] if started && !ended { @@ -322,6 +325,7 @@ public final class DatePickerNode: ASDisplayNode { self.updateState(updatedState, animated: false) self.pickerNode.minimumDate = newValue + self.timePickerNode.minimumDate = newValue if let size = self.validLayout { let _ = self.updateLayout(size: size, transition: .immediate) @@ -342,6 +346,7 @@ public final class DatePickerNode: ASDisplayNode { self.updateState(updatedState, animated: false) self.pickerNode.maximumDate = newValue + self.timePickerNode.maximumDate = newValue if let size = self.validLayout { let _ = self.updateLayout(size: size, transition: .immediate) @@ -396,6 +401,9 @@ public final class DatePickerNode: ASDisplayNode { self.pickerNode.minimumDate = self.state.minDate self.pickerNode.maximumDate = self.state.maxDate + self.timePickerNode.minimumDate = self.state.minDate + self.timePickerNode.maximumDate = self.state.maxDate + self.monthButtonNode = HighlightTrackingButtonNode() self.monthTextNode = ImmediateTextNode() self.monthArrowNode = ASImageNode() @@ -921,9 +929,7 @@ private class TimeInputView: UIView, UIKeyInput { var textUpdated: ((String) -> Void)? override func becomeFirstResponder() -> Bool { - if self.isFirstResponder { - self.didReset = false - } + self.didReset = false let result = super.becomeFirstResponder() self.focusUpdated?(true) return result @@ -937,7 +943,7 @@ private class TimeInputView: UIView, UIKeyInput { var length: Int = 4 - private var didReset = false + var didReset = false private let nonDigits = CharacterSet.decimalDigits.inverted func insertText(_ text: String) { if text.rangeOfCharacter(from: nonDigits) != nil { @@ -1024,6 +1030,12 @@ private class TimeInputNode: ASDisplayNode { view.textUpdated = self.textUpdated } } + + func reset() { + if let view = self.view as? TimeInputView { + view.didReset = false + } + } } private final class TimePickerNode: ASDisplayNode { @@ -1064,8 +1076,9 @@ private final class TimePickerNode: ASDisplayNode { } } } - var minDate: Date? - var maxDate: Date? + + var minimumDate: Date? + var maximumDate: Date? var valueChanged: ((Date) -> Void)? @@ -1205,23 +1218,7 @@ private final class TimePickerNode: ASDisplayNode { } } self.hoursNode.selected = { [weak self] index in - guard let strongSelf = self else { - return - } - switch dateTimeFormat.timeFormat { - case .military: - let hour = index - if let date = strongSelf.date { - var components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: date) - components.hour = hour - if let newDate = calendar.date(from: components) { - strongSelf.date = newDate - strongSelf.valueChanged?(newDate) - } - } - case .regular: - break - } + self?.updateTime() } self.minutesNode.count = { @@ -1248,29 +1245,59 @@ private final class TimePickerNode: ASDisplayNode { } } } - self.minutesNode.selected = { [weak self] index in - guard let strongSelf = self else { - return - } - switch dateTimeFormat.timeFormat { - case .military: - let minute = index - if let date = strongSelf.date { - var components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: date) - components.minute = minute - if let newDate = calendar.date(from: components) { - strongSelf.date = newDate - strongSelf.valueChanged?(newDate) - } - } - case .regular: - break - } + self.minutesNode.selected = { [weak self] _ in + self?.updateTime() } self.update() } + private func updateTime() { + switch self.dateTimeFormat.timeFormat { + case .military: + let hour = self.hoursNode.currentSelectedIndex + let minute = self.minutesNode.currentSelectedIndex + + let date = self.date ?? Date() + + var components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: date) + components.hour = hour + components.minute = minute + if var newDate = calendar.date(from: components) { + if let minDate = self.minimumDate, newDate <= minDate { + if let nextDate = calendar.date(byAdding: .day, value: 1, to: newDate) { + newDate = nextDate + } + } + self.date = newDate + self.valueChanged?(newDate) + } + + case .regular: + let hour = self.hoursNode.currentSelectedIndex + let minute = self.minutesNode.currentSelectedIndex + + let date = self.date ?? Date() + + var components = calendar.dateComponents([.year, .month, .day, .hour, .minute], from: date) + if self.amPMSelectorNode.selectedIndex == 0 { + components.hour = hour >= 12 ? hour - 12 : hour + } else if self.amPMSelectorNode.selectedIndex == 1 { + components.hour = hour < 12 ? hour + 12 : hour + } + components.minute = minute + if var newDate = calendar.date(from: components) { + if let minDate = self.minimumDate, newDate <= minDate { + if let nextDate = calendar.date(byAdding: .day, value: 1, to: newDate) { + newDate = nextDate + } + } + self.date = newDate + self.valueChanged?(newDate) + } + } + } + override func didLoad() { super.didLoad() @@ -1355,6 +1382,23 @@ private final class TimePickerNode: ASDisplayNode { private var selection: Selection { didSet { + self.typing = false + self.inputNode.reset() + switch self.selection { + case .none: + break + case .hours: + self.inputNode.text = self.hoursNode.titleAt?(self.hoursNode.currentSelectedIndex) ?? "" + self.inputNode.length = 2 + case .minutes: + self.inputNode.text = self.minutesNode.titleAt?(self.minutesNode.currentSelectedIndex) ?? "" + self.inputNode.length = 2 + case .all: + let hours = self.minutesNode.titleAt?(self.hoursNode.currentSelectedIndex) ?? "" + let minutes = self.minutesNode.titleAt?(self.minutesNode.currentSelectedIndex) ?? "" + self.inputNode.text = "\(hours)\(minutes)" + self.inputNode.length = 4 + } self.update() } } @@ -1417,8 +1461,6 @@ private final class TimePickerNode: ASDisplayNode { self.hoursNode.isHidden = false self.minutesNode.isHidden = false } - - self.inputNode.length = 2 case .minutes: colonColor = self.theme.textColor self.colonNode.alpha = 0.35 @@ -1446,8 +1488,6 @@ private final class TimePickerNode: ASDisplayNode { self.hoursNode.isHidden = false self.minutesNode.isHidden = false } - - self.inputNode.length = 2 case .all: colonColor = self.theme.accentColor self.colonNode.alpha = 1.0 @@ -1475,8 +1515,6 @@ private final class TimePickerNode: ASDisplayNode { self.hoursNode.isHidden = false self.minutesNode.isHidden = false } - - self.inputNode.length = 4 } if let size = self.validLayout { diff --git a/submodules/DatePickerNode/Sources/TapeNode.swift b/submodules/DatePickerNode/Sources/TapeNode.swift index d72a7e074c..a1ad195d49 100644 --- a/submodules/DatePickerNode/Sources/TapeNode.swift +++ b/submodules/DatePickerNode/Sources/TapeNode.swift @@ -63,7 +63,9 @@ open class TapeNode: ASDisplayNode { return UITableView() }() - private var infinityRowsMultiplier: Int = 1 + private var infinityRowsMultiplier: Int { + return generateInfinityRowsMultiplier() + } var currentSelectedRow: Int? var currentSelectedIndex: Int { @@ -86,8 +88,6 @@ open class TapeNode: ASDisplayNode { } fileprivate func setup() { - self.infinityRowsMultiplier = self.generateInfinityRowsMultiplier() - if #available(iOS 11.0, *) { self.tableView.contentInsetAdjustmentBehavior = .never } @@ -162,23 +162,41 @@ open class TapeNode: ASDisplayNode { if self.currentSelectedIndex == self.indexForRow(row) { return } - var finalRow = row + var finalRow = row if row <= self.numberOfRows { - let middleMultiplier = (self.infinityRowsMultiplier / 2) + let middleMultiplier = self.infinityRowsMultiplier / 2 let middleIndex = self.numberOfRows * middleMultiplier finalRow = middleIndex - (self.numberOfRows - finalRow) } - self.currentSelectedRow = finalRow + if let currentSelectedRow = self.currentSelectedRow { self.tableView.setContentOffset(CGPoint(x: 0.0, y: CGFloat(currentSelectedRow) * self.rowHeight), animated: animated) } } + func selectMiddleRow() { + var finalRow = self.currentSelectedIndex + let middleMultiplier = self.infinityRowsMultiplier / 2 + let middleIndex = self.numberOfRows * middleMultiplier + finalRow = middleIndex - (self.numberOfRows - finalRow) + + self.currentSelectedRow = finalRow + + if let currentSelectedRow = self.currentSelectedRow { + self.tableView.setContentOffset(CGPoint(x: 0.0, y: CGFloat(currentSelectedRow) * self.rowHeight), animated: false) + } + } + open func reloadPickerView() { self.tableView.reloadData() } + + private func hapticTap() { + self.hapticFeedback.impact(.light) + AudioServicesPlaySystemSound(1157) + } } extension TapeNode: UITableViewDataSource { @@ -248,15 +266,18 @@ extension TapeNode: UIScrollViewDelegate { if !decelerate { self.isScrolling = false self.isScrollingUpdated?(false) + + self.selectMiddleRow() } } public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { self.isScrolling = false self.isScrollingUpdated?(false) + + self.selectMiddleRow() } - public func scrollViewDidScroll(_ scrollView: UIScrollView) { let partialRow = Float(scrollView.contentOffset.y / self.rowHeight) let roundedRow = Int(lroundf(partialRow)) @@ -264,8 +285,7 @@ extension TapeNode: UIScrollViewDelegate { if self.previousRoundedRow != roundedRow && self.isScrolling { self.previousRoundedRow = roundedRow - self.hapticFeedback.impact() - AudioServicesPlaySystemSound(1157) + self.hapticTap() } } } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift b/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift index 7f1244c470..bc25d13400 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkQRCodeController.swift @@ -11,7 +11,7 @@ import AccountContext import SolidRoundedButtonNode import AnimatedStickerNode -private func shareQrCode(context: AccountContext, link: String) { +private func shareQrCode(context: AccountContext, link: String, view: UIView) { let _ = (qrCode(string: link, color: .black, backgroundColor: .white, icon: .custom(UIImage(bundleImageName: "Chat/Links/QrLogo"))) |> map { _, generator -> UIImage? in let imageSize = CGSize(width: 768.0, height: 768.0) @@ -24,6 +24,11 @@ private func shareQrCode(context: AccountContext, link: String) { } let activityController = UIActivityViewController(activityItems: [image], applicationActivities: nil) + if let window = view.window, let rootViewController = window.rootViewController { + activityController.popoverPresentationController?.sourceView = window + activityController.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint(x: window.bounds.width / 2.0, y: window.bounds.size.height - 1.0), size: CGSize(width: 1.0, height: 1.0)) + rootViewController.present(activityController, animated: true, completion: nil) + } context.sharedContext.applicationBindings.presentNativeController(activityController) }) } @@ -253,7 +258,7 @@ public final class InviteLinkQRCodeController: ViewController { self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside) self.buttonNode.pressed = { [weak self] in if let strongSelf = self{ - shareQrCode(context: strongSelf.context, link: strongSelf.invite.link) + shareQrCode(context: strongSelf.context, link: strongSelf.invite.link, view: strongSelf.view) } } @@ -285,7 +290,7 @@ public final class InviteLinkQRCodeController: ViewController { } @objc private func qrPressed() { - shareQrCode(context: self.context, link: self.invite.link) + shareQrCode(context: self.context, link: self.invite.link, view: self.view) } func updatePresentationData(_ presentationData: PresentationData) { diff --git a/submodules/LegacyComponents/Sources/TGMediaPickerCaptionInputPanel.m b/submodules/LegacyComponents/Sources/TGMediaPickerCaptionInputPanel.m index dbf7f8f746..fab9ac16ad 100644 --- a/submodules/LegacyComponents/Sources/TGMediaPickerCaptionInputPanel.m +++ b/submodules/LegacyComponents/Sources/TGMediaPickerCaptionInputPanel.m @@ -230,7 +230,7 @@ static void setViewFrame(UIView *view, CGRect frame) if (_inputField.internalTextView.isFirstResponder) [TGHacks applyCurrentKeyboardAutocorrectionVariant]; - NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithAttributedString:_inputField.text == nil ? [[NSAttributedString alloc] initWithString:@""] : _inputField.attributedText]; //[[NSMutableAttributedString alloc] initWithString:_inputField.text == nil ? @"" : _inputField.text]; + NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithAttributedString:_inputField.text == nil ? [[NSAttributedString alloc] initWithString:@""] : _inputField.attributedText]; NSMutableString *usualString = [text.string mutableCopy]; int textLength = (int)text.length; for (int i = 0; i < textLength; i++) @@ -247,21 +247,7 @@ static void setViewFrame(UIView *view, CGRect frame) else break; } - - for (int i = textLength - 1; i >= 0; i--) - { - unichar c = [usualString characterAtIndex:i]; - if (c == ' ' || c == '\t' || c == '\n') - { - [text deleteCharactersInRange:NSMakeRange(i, 1)]; - [usualString deleteCharactersInRange:NSMakeRange(i, 1)]; - textLength--; - } - else - break; - } - _inputField.internalTextView.attributedText = text; __autoreleasing NSArray *entities = nil; diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.h b/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.h index 097b7fd84a..c22aac6f4d 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.h +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.h @@ -3,6 +3,6 @@ @interface TGPhotoEditorHUDView : UIView - (void)setText:(NSString *)text; -- (void)setAttributedText:(NSAttributedString *)text; +- (void)setTitle:(NSString *)title value:(NSString *)value; @end diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.m b/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.m index dc6bfce8a3..f8b7f74300 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorHUDView.m @@ -9,6 +9,7 @@ { UIImageView *_backgroundView; UILabel *_label; + UILabel *_valueLabel; } @end @@ -41,12 +42,37 @@ _backgroundView.image = background; [self addSubview:_backgroundView]; + UIFont *font; + + if (iosMajorVersion() >= 13) { + UIFontDescriptor *fontDescriptor = [UIFont systemFontOfSize:14.0f weight:UIFontWeightMedium].fontDescriptor; + NSArray *monospacedSetting = @[@{UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType), + UIFontFeatureSelectorIdentifierKey: @(kMonospacedNumbersSelector)}]; + UIFontDescriptor *updatedDescriptor = [fontDescriptor fontDescriptorByAddingAttributes:@{ + UIFontDescriptorFeatureSettingsAttribute: monospacedSetting + }]; + if (updatedDescriptor != nil) { + font = [UIFont fontWithDescriptor:updatedDescriptor size:14.0]; + } else { + font = [UIFont systemFontOfSize:14]; + } + } else { + font = [UIFont systemFontOfSize:14]; + } + _label = [[UILabel alloc] initWithFrame:CGRectZero]; _label.backgroundColor = [UIColor clearColor]; - _label.font = TGSystemFontOfSize(14); - _label.textAlignment = NSTextAlignmentCenter; + _label.font = [UIFont systemFontOfSize:14]; + _label.textAlignment = NSTextAlignmentLeft; _label.textColor = [UIColor whiteColor]; [_backgroundView addSubview:_label]; + + _valueLabel = [[UILabel alloc] initWithFrame:CGRectZero]; + _valueLabel.backgroundColor = [UIColor clearColor]; + _valueLabel.font = font; + _valueLabel.textAlignment = NSTextAlignmentRight; + _valueLabel.textColor = [TGPhotoEditorInterfaceAssets accentColor]; + [_backgroundView addSubview:_valueLabel]; } return self; } @@ -62,22 +88,27 @@ _label.text = text; [_label sizeToFit]; + _valueLabel.hidden = true; + [self setNeedsLayout]; [self setHidden:false animated:true]; } -- (void)setAttributedText:(NSAttributedString *)text +- (void)setTitle:(NSString *)title value:(NSString *)value { - if (text.length == 0) + if (title.length == 0) { [self setHidden:true animated:true]; return; } - _label.attributedText = text; + _label.text = title; [_label sizeToFit]; + _valueLabel.text = value; + [_valueLabel sizeToFit]; + [self setNeedsLayout]; [self setHidden:false animated:true]; @@ -104,7 +135,15 @@ _label.frame = CGRectMake(padding, 6.0f, CGCeil(_label.frame.size.width), CGCeil(_label.frame.size.height)); - CGFloat width = _label.frame.size.width + 2.0f * padding; + CGFloat width; + if (_valueLabel.isHidden) { + width = _label.frame.size.width + 2.0f * padding; + } else { + width = 2.0f * padding + _label.frame.size.width + 50.0f + 3.0f; + } + + _valueLabel.frame = CGRectMake(width - padding - 50.0f, 6.0f, 50.0f, CGCeil(_valueLabel.frame.size.height)); + _backgroundView.frame = CGRectMake((self.frame.size.width - width) / 2, 15, width, 30); } diff --git a/submodules/LegacyComponents/Sources/TGPhotoToolsController.m b/submodules/LegacyComponents/Sources/TGPhotoToolsController.m index ab13e98dd0..ac04824727 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoToolsController.m +++ b/submodules/LegacyComponents/Sources/TGPhotoToolsController.m @@ -336,9 +336,7 @@ const CGFloat TGPhotoEditorToolsLandscapePanelSize = TGPhotoEditorToolsPanelSize return; } - NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@ %@", tool.title, [tool stringValue:true]] attributes:@{NSFontAttributeName: TGMediumSystemFontOfSize(14.0f), NSForegroundColorAttributeName: [TGPhotoEditorInterfaceAssets accentColor]}]; - [text addAttributes:@{NSFontAttributeName: TGSystemFontOfSize(14.0f), NSForegroundColorAttributeName: [UIColor whiteColor]} range:NSMakeRange(0, tool.title.length)]; - [_hudView setAttributedText:text]; + [_hudView setTitle:tool.title value:[tool stringValue:true]]; } #pragma mark - Transition diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsEmptyStateItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsEmptyStateItem.swift index 1564ac61fd..f0302a7bbd 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsEmptyStateItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/RecentSessionsEmptyStateItem.swift @@ -78,7 +78,7 @@ final class RecentSessionsEmptyStateItemNode: ItemListControllerEmptyStateItemNo override func updateLayout(layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { self.validLayout = (layout, navigationBarHeight) var insets = layout.insets(options: []) - insets.top += navigationBarHeight + 128.0 + insets.top += navigationBarHeight + 200.0 let imageSpacing: CGFloat = 8.0 let textSpacing: CGFloat = 8.0 @@ -86,15 +86,32 @@ final class RecentSessionsEmptyStateItemNode: ItemListControllerEmptyStateItemNo let imageSize = self.imageNode.image?.size ?? CGSize() let imageHeight = layout.size.width < layout.size.height ? imageSize.height + imageSpacing : 0.0 + var textVisible = true + if layout.size.width == 320 { + textVisible = false + } + + self.backgroundColor = .red + let titleSize = self.titleNode.measure(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - layout.intrinsicInsets.left - layout.intrinsicInsets.right - 50.0, height: max(1.0, layout.size.height - insets.top - insets.bottom))) let textSize = self.textNode.measure(CGSize(width: layout.size.width - layout.safeInsets.left - layout.safeInsets.right - layout.intrinsicInsets.left - layout.intrinsicInsets.right - 50.0, height: max(1.0, layout.size.height - insets.top - insets.bottom))) - let totalHeight = imageHeight + titleSize.height + textSpacing + textSize.height + var totalHeight = imageHeight + titleSize.height + if textVisible { + totalHeight += textSpacing + textSize.height + } let topOffset = insets.top + floor((layout.size.height - insets.top - insets.bottom - totalHeight) / 2.0) - transition.updateAlpha(node: self.imageNode, alpha: imageHeight > 0.0 ? 1.0 : 0.0) + var visible = true + if case .compact = layout.metrics.widthClass, layout.size.width > layout.size.height { + visible = false + } + + transition.updateAlpha(node: self.imageNode, alpha: visible ? 1.0 : 0.0) + transition.updateAlpha(node: self.titleNode, alpha: visible ? 1.0 : 0.0) + transition.updateAlpha(node: self.textNode, alpha: visible && textVisible ? 1.0 : 0.0) transition.updateFrame(node: self.imageNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - imageSize.width) / 2.0), y: topOffset), size: imageSize)) - transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width - layout.safeInsets.left - layout.safeInsets.right - layout.intrinsicInsets.left - layout.intrinsicInsets.right) / 2.0), y: topOffset + imageHeight), size: titleSize)) - transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width - layout.safeInsets.left - layout.safeInsets.right - layout.intrinsicInsets.left - layout.intrinsicInsets.right) / 2.0), y: self.titleNode.frame.maxY + textSpacing), size: textSize)) + transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - titleSize.width) / 2.0), y: topOffset + imageHeight), size: titleSize)) + transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - textSize.width) / 2.0), y: self.titleNode.frame.maxY + textSpacing), size: textSize)) } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 71e55316a8..eec34ce746 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1337,7 +1337,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr })) } - if (isCreator || (channel.adminRights != nil && channel.hasPermission(.pinMessages))) && cachedData.peerGeoLocation != nil { + if (isCreator || (channel.adminRights != nil && channel.hasPermission(.pinMessages))) && cachedData.peerGeoLocation == nil { if cachedData.flags.contains(.canChangeUsername) { if let linkedDiscussionPeer = data.linkedDiscussionPeer { let peerTitle: String