diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index a8a00a3930..64452d13b1 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -6321,6 +6321,13 @@ Sorry for the inconvenience."; "VoiceChat.EditBioSave" = "Save"; "VoiceChat.EditBioSuccess" = "Your bio is changed."; +"VoiceChat.EditDescription" = "Edit Description"; +"VoiceChat.EditDescriptionTitle" = "Description"; +"VoiceChat.EditDescriptionText" = "Any details such as age, occupation or city."; +"VoiceChat.EditDescriptionPlaceholder" = "Description"; +"VoiceChat.EditDescriptionSave" = "Save"; +"VoiceChat.EditDescriptionSuccess" = "Description is changed."; + "VoiceChat.SendPublicLinkText" = "%1$@ isn't a member of \"%2$@\" yet. Send them a public invite link instead?"; "VoiceChat.SendPublicLinkSend" = "Send"; diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index 0afd735957..4678c1d123 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -595,6 +595,13 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate self.animateOut(shared: true, completion: { }) self.completed?(peerIds) + + Queue.mainQueue().after(0.44) { + if self.hapticFeedback == nil { + self.hapticFeedback = HapticFeedback() + } + self.hapticFeedback?.success() + } } let fromForeignApp = self.fromForeignApp self.shareDisposable.set((signal diff --git a/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift b/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift index c9830ff2b3..90d0e21530 100644 --- a/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallStatusBarNode.swift @@ -17,11 +17,14 @@ private let green = UIColor(rgb: 0x33c659) private let activeBlue = UIColor(rgb: 0x00a0b9) private let purple = UIColor(rgb: 0x3252ef) private let pink = UIColor(rgb: 0xef436c) +private let latePurple = UIColor(rgb: 0xaa56a6) +private let latePink = UIColor(rgb: 0xef476f) private class CallStatusBarBackgroundNode: ASDisplayNode { enum State { case connecting case cantSpeak + case late case active case speaking } @@ -64,6 +67,8 @@ private class CallStatusBarBackgroundNode: ASDisplayNode { targetColors = [green.cgColor, activeBlue.cgColor] case .cantSpeak: targetColors = [purple.cgColor, pink.cgColor] + case .late: + targetColors = [latePurple.cgColor, latePink.cgColor] } if CACurrentMediaTime() - self.initialTimestamp > 0.1 { @@ -200,6 +205,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { private var currentGroupCallState: PresentationGroupCallSummaryState? private var currentIsMuted = true private var currentCantSpeak = false + private var currentScheduleTimestamp: Int32? private var currentMembers: PresentationGroupCallMembers? private var currentIsConnected = true @@ -314,6 +320,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { } strongSelf.currentIsMuted = isMuted strongSelf.currentCantSpeak = cantSpeak + strongSelf.currentScheduleTimestamp = state?.callState.scheduleTimestamp let currentIsConnected: Bool if let state = state, case .connected = state.callState.networkState { @@ -351,6 +358,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { let textColor = UIColor.white var segments: [AnimatedCountLabelNode.Segment] = [] var displaySpeakerSubtitle = false + var isLate = false if let presentationData = self.presentationData { if let voiceChatTitle = self.currentGroupCallState?.info?.title, !voiceChatTitle.isEmpty { @@ -389,8 +397,9 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { let elapsedTime = scheduleTime - currentTime let timerText: String if elapsedTime >= 86400 { - timerText = scheduledTimeIntervalString(strings: presentationData.strings, value: elapsedTime) + timerText = presentationData.strings.VoiceChat_StatusStartsIn(scheduledTimeIntervalString(strings: presentationData.strings, value: elapsedTime)).0 } else if elapsedTime < 0 { + isLate = true timerText = presentationData.strings.VoiceChat_StatusLateBy(textForTimeout(value: abs(elapsedTime))).0 } else { timerText = presentationData.strings.VoiceChat_StatusStartsIn(textForTimeout(value: elapsedTime)).0 @@ -501,7 +510,7 @@ public class CallStatusBarNodeImpl: CallStatusBarNode { let state: CallStatusBarBackgroundNode.State if self.currentIsConnected { if self.currentCantSpeak { - state = .cantSpeak + state = isLate ? .late : .cantSpeak } else if self.currentIsMuted { state = .active } else { diff --git a/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift b/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift index ee4a674a93..8c8ad11003 100644 --- a/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift +++ b/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift @@ -281,13 +281,9 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode { self.dateTimeFormat = presentationData.dateTimeFormat self.contentNode.backgroundColor = self.theme.rootController.navigationBar.backgroundColor - - self.theme = presentationData.theme - self.separatorNode.backgroundColor = presentationData.theme.chat.historyNavigation.strokeColor - self.joinButtonTitleNode.attributedText = NSAttributedString(string: self.joinButtonTitleNode.attributedText?.string ?? "", font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: presentationData.theme.chat.inputPanel.actionControlForegroundColor) - + self.joinButtonTitleNode.attributedText = NSAttributedString(string: self.joinButtonTitleNode.attributedText?.string ?? "", font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.isScheduled ? .white : presentationData.theme.chat.inputPanel.actionControlForegroundColor) self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: Font.regular(13.0), textColor: presentationData.theme.chat.inputPanel.secondaryTextColor) self.muteIconNode.image = PresentationResourcesChat.chatTitleMuteIcon(presentationData.theme) @@ -305,23 +301,21 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode { let pink = UIColor(rgb: 0xea436f) let latePurple = UIColor(rgb: 0xaa56a6) let latePink = UIColor(rgb: 0xef476f) - let colors: [UIColor] if self.isLate { colors = [latePurple, latePink] } else { colors = [purple, pink] } - if self.joinButtonBackgroundNode.image != nil, let snapshotView = self.joinButtonBackgroundNode.view.snapshotContentTree() { self.joinButtonBackgroundNode.view.superview?.insertSubview(snapshotView, aboveSubview: self.joinButtonBackgroundNode.view) - snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 1.0, removeOnCompletion: false, completion: { [weak snapshotView] _ in snapshotView?.removeFromSuperview() }) } - self.joinButtonBackgroundNode.image = generateGradientImage(size: CGSize(width: 100.0, height: 1.0), colors: [purple, pink], locations: [0.0, 1.0], direction: .horizontal) + self.joinButtonBackgroundNode.image = generateGradientImage(size: CGSize(width: 100.0, height: 1.0), colors: colors, locations: [0.0, 1.0], direction: .horizontal) self.joinButtonBackgroundNode.backgroundColor = nil } else { self.joinButtonBackgroundNode.image = nil @@ -533,10 +527,10 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode { isScheduled = true if let voiceChatTitle = self.currentData?.info.title { title = voiceChatTitle - text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, format: HumanReadableStringFormat(dateFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsOn($0).0 }, tomorrowFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTomorrow($0).0 }, todayFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsToday($0).0 }, yesterdayFormatString: { $0 })) + text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, alwaysShowTime: true, format: HumanReadableStringFormat(dateFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsOn($0).0 }, tomorrowFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTomorrow($0).0 }, todayFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsToday($0).0 }, yesterdayFormatString: { $0 })) } else { title = self.strings.Conversation_ScheduledVoiceChat - text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, format: HumanReadableStringFormat(dateFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsOnShort($0).0 }, tomorrowFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTomorrowShort($0).0 }, todayFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTodayShort($0).0 }, yesterdayFormatString: { $0 })) + text = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, alwaysShowTime: true, format: HumanReadableStringFormat(dateFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsOnShort($0).0 }, tomorrowFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTomorrowShort($0).0 }, todayFormatString: { self.strings.Conversation_ScheduledVoiceChatStartsTodayShort($0).0 }, yesterdayFormatString: { $0 })) } let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) @@ -575,7 +569,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode { self.updateJoinButton() } - self.joinButtonTitleNode.attributedText = NSAttributedString(string: joinText.uppercased(), font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: self.theme.chat.inputPanel.actionControlForegroundColor) + self.joinButtonTitleNode.attributedText = NSAttributedString(string: joinText.uppercased(), font: Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers]), textColor: isScheduled ? .white : self.theme.chat.inputPanel.actionControlForegroundColor) let joinButtonTitleSize = self.joinButtonTitleNode.updateLayout(CGSize(width: 150.0, height: .greatestFiniteMagnitude)) let joinButtonSize = CGSize(width: joinButtonTitleSize.width + 20.0, height: 28.0) diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 6f3707bec6..38aece12cf 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -1105,7 +1105,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { nextParticipantsFetchOffset: nil, adminIds: Set(), isCreator: false, - defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: self.stateValue.defaultParticipantMuteState == .muted, canChange: false), + defaultParticipantsAreMuted: GroupCallParticipantsContext.State.DefaultParticipantsAreMuted(isMuted: self.stateValue.defaultParticipantMuteState == .muted, canChange: true), sortAscending: true, recordingStartTimestamp: nil, title: self.stateValue.title, diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatActionButton.swift b/submodules/TelegramCallsUI/Sources/VoiceChatActionButton.swift index c62ee3870d..3132e264db 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatActionButton.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatActionButton.swift @@ -656,11 +656,11 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode { let previousValue = self.foregroundGradientLayer.startPoint let newValue: CGPoint if self.maskBlobView.presentationAudioLevel > 0.22 { - newValue = CGPoint(x: CGFloat.random(in: 0.9 ..< 1.0), y: CGFloat.random(in: 0.1 ..< 0.35)) + newValue = CGPoint(x: CGFloat.random(in: 0.9 ..< 1.0), y: CGFloat.random(in: 0.15 ..< 0.35)) } else if self.maskBlobView.presentationAudioLevel > 0.01 { - newValue = CGPoint(x: CGFloat.random(in: 0.77 ..< 0.95), y: CGFloat.random(in: 0.1 ..< 0.35)) + newValue = CGPoint(x: CGFloat.random(in: 0.57 ..< 0.85), y: CGFloat.random(in: 0.15 ..< 0.45)) } else { - newValue = CGPoint(x: CGFloat.random(in: 0.65 ..< 0.85), y: CGFloat.random(in: 0.1 ..< 0.45)) + newValue = CGPoint(x: CGFloat.random(in: 0.6 ..< 0.75), y: CGFloat.random(in: 0.25 ..< 0.45)) } self.foregroundGradientLayer.startPoint = newValue diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 49c06fdad5..a30933b2ce 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -2895,7 +2895,7 @@ public final class VoiceChatController: ViewController { self.floatingHeaderOffset = offset if bottomEdge.isZero { - bottomEdge = self.listNode.frame.minY + 46.0 + 56.0 + bottomEdge = self.listNode.frame.minY + 46.0 + 56.0 + 46 } let rawPanelOffset = offset + listTopInset - topPanelHeight @@ -3497,9 +3497,9 @@ public final class VoiceChatController: ViewController { if let callState = self.callState { if callState.scheduleTimestamp != nil && self.listNode.alpha > 0.0 { - if !callState.canManageCall && (self.peer?.addressName?.isEmpty ?? true) { - self.audioButton.isHidden = true - } +// if !callState.canManageCall && (self.peer?.addressName?.isEmpty ?? true) { +// self.audioButton.isHidden = true +// } self.timerNode.isHidden = false self.listNode.alpha = 0.0 self.listNode.isUserInteractionEnabled = false @@ -3609,7 +3609,7 @@ public final class VoiceChatController: ViewController { } } if canInvite && self.peer != nil { - entries.append(.invite(self.presentationData.theme, self.presentationData.strings, self.presentationData.strings.VoiceChat_InviteMember, inviteIsLink)) + entries.append(.invite(self.presentationData.theme, self.presentationData.strings, inviteIsLink ? self.presentationData.strings.VoiceChat_Share : self.presentationData.strings.VoiceChat_InviteMember, inviteIsLink)) } for member in callMembers.0 { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatTimerNode.swift b/submodules/TelegramCallsUI/Sources/VoiceChatTimerNode.swift index 3f8770e647..4917041309 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatTimerNode.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatTimerNode.swift @@ -156,7 +156,7 @@ final class VoiceChatTimerNode: ASDisplayNode { timer.start() } - let subtitle = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime) + let subtitle = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: scheduleTime, alwaysShowTime: true) self.titleNode.attributedText = NSAttributedString(string: elapsedTime < 0 ? self.strings.VoiceChat_LateBy : self.strings.VoiceChat_StartsIn, font: Font.with(size: 23.0, design: .round, weight: .semibold, traits: []), textColor: .white) let titleSize = self.titleNode.updateLayout(size) diff --git a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift index 6a20b7ae9a..a5d034c976 100644 --- a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift @@ -157,7 +157,7 @@ public struct HumanReadableStringFormat { } } -public func humanReadableStringForTimestamp(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, timestamp: Int32, format: HumanReadableStringFormat? = nil) -> String { +public func humanReadableStringForTimestamp(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, timestamp: Int32, alwaysShowTime: Bool = false, format: HumanReadableStringFormat? = nil) -> String { var t: time_t = time_t(timestamp) var timeinfo: tm = tm() localtime_r(&t, &timeinfo) @@ -168,7 +168,12 @@ public func humanReadableStringForTimestamp(strings: PresentationStrings, dateTi localtime_r(&now, &timeinfoNow) if timeinfo.tm_year != timeinfoNow.tm_year { - let string = "\(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat))" + let string: String + if alwaysShowTime { + string = stringForMediumDate(timestamp: timestamp, strings: strings, dateTimeFormat: dateTimeFormat) + } else { + string = stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat) + } return format?.dateFormatString(string) ?? string } @@ -184,7 +189,12 @@ public func humanReadableStringForTimestamp(strings: PresentationStrings, dateTi } return humanReadableStringForTimestamp(strings: strings, day: day, dateTimeFormat: dateTimeFormat, hours: timeinfo.tm_hour, minutes: timeinfo.tm_min, format: format) } else { - let string = "\(stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat))" + let string: String + if alwaysShowTime { + string = stringForMediumDate(timestamp: timestamp, strings: strings, dateTimeFormat: dateTimeFormat) + } else { + string = stringForTimestamp(day: timeinfo.tm_mday, month: timeinfo.tm_mon + 1, year: timeinfo.tm_year, dateTimeFormat: dateTimeFormat) + } return format?.dateFormatString(string) ?? string } }