diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 84f8c8f406..e72541198b 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -15960,3 +15960,16 @@ Error: %8$@"; "Channel.Management.DismissAdmin" = "Dismiss"; "Attachment.ScanDocument" = "Scan Document"; + +"Month.NomJanuary" = "January"; +"Month.NomFebruary" = "February"; +"Month.NomMarch" = "March"; +"Month.NomApril" = "April"; +"Month.NomMay" = "May"; +"Month.NomJune" = "June"; +"Month.NomJuly" = "July"; +"Month.NomAugust" = "August"; +"Month.NomSeptember" = "September"; +"Month.NomOctober" = "October"; +"Month.NomNovember" = "November"; +"Month.NomDecember" = "December"; diff --git a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift index e4150b8966..d46b90abf3 100644 --- a/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift +++ b/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift @@ -830,7 +830,6 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode { if let rightLabelText = item.rightLabelText { let rightLabelTextLayoutAndApplyValue = makeRightLabelTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: rightLabelText.text, font: statusFont, textColor: rightLabelText.color), maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 20.0, height: 100.0))) rightLabelTextLayoutAndApply = rightLabelTextLayoutAndApplyValue - rightInset -= 6.0 + rightLabelTextLayoutAndApplyValue.0.size.width } var searchAdIcon: UIImage? diff --git a/submodules/DatePickerNode/Sources/DatePickerNode.swift b/submodules/DatePickerNode/Sources/DatePickerNode.swift index fbf04197e6..fd0b9cbeef 100644 --- a/submodules/DatePickerNode/Sources/DatePickerNode.swift +++ b/submodules/DatePickerNode/Sources/DatePickerNode.swift @@ -1021,7 +1021,7 @@ private final class MonthPickerNode: ASDisplayNode, UIPickerViewDelegate, UIPick if component == 1 { string = "\(self.yearRange.startIndex + row)" } else { - string = stringForMonth(strings: self.strings, month: Int32(row)) + string = stringForNominativeMonth(strings: self.strings, month: Int32(row)) } return NSAttributedString(string: string, font: Font.medium(15.0), textColor: self.theme.textColor) } diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift index 1aec3ba690..c8ca63b995 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift @@ -151,44 +151,78 @@ private final class ChannelMembersSearchEntry: Comparable, Identifiable { func item(context: AccountContext, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchContainerInteraction) -> ListViewItem { switch self.content { - case let .peer(peer): - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) }), action: { _ in - interaction.peerSelected(peer, nil) - }) - case let .participant(participant, label, revealActions, revealed, enabled): - let status: ContactsPeerItemStatus - if let label = label { - status = .custom(string: NSAttributedString(string: label), multiline: false, isActive: false, icon: nil) - } else if let presence = participant.presences[participant.peer.id], self.addIcon { - status = .presence(EnginePeer.Presence(presence), dateTimeFormat) + case let .peer(peer): + return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) }), action: { _ in + interaction.peerSelected(peer, nil) + }) + case let .participant(participant, _, revealActions, revealed, enabled): + let status: ContactsPeerItemStatus + if let presence = participant.presences[participant.peer.id] { + status = .presence(EnginePeer.Presence(presence), dateTimeFormat) + } else { + status = .none + } + + var options: [ItemListPeerItemRevealOption] = [] + for action in revealActions { + options.append(ItemListPeerItemRevealOption(type: action.type, title: action.title, action: { + switch action.action { + case .promote: + interaction.promotePeer(participant) + break + case .restrict: + interaction.restrictPeer(participant) + break + case .remove: + interaction.removePeer(participant.peer.id) + break + } + })) + } + var actionIcon: ContactsPeerItemActionIcon = .none + if self.addIcon { + actionIcon = .add + } + + let label: String? + var labelColor = presentationData.theme.list.itemSecondaryTextColor + var labelBackground = false + switch participant.participant { + case let .creator(_, _, rank): + label = rank ?? presentationData.strings.GroupInfo_LabelOwner + labelBackground = true + labelColor = UIColor(rgb: 0x956ac8) + case let .member(_, _, adminInfo, _, rank, _): + if let _ = adminInfo { + label = rank ?? presentationData.strings.GroupInfo_LabelAdmin + labelBackground = true + labelColor = UIColor(rgb: 0x49a355) } else { - status = .none + label = rank } - - var options: [ItemListPeerItemRevealOption] = [] - for action in revealActions { - options.append(ItemListPeerItemRevealOption(type: action.type, title: action.title, action: { - switch action.action { - case .promote: - interaction.promotePeer(participant) - break - case .restrict: - interaction.restrictPeer(participant) - break - case .remove: - interaction.removePeer(participant.peer.id) - break - } - })) - } - var actionIcon: ContactsPeerItemActionIcon = .none - if self.addIcon { - actionIcon = .add - } - - return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: EnginePeer(participant.peer), chatPeer: EnginePeer(participant.peer)), status: status, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: revealed), options: options, actionIcon: actionIcon, index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) }), action: { _ in + } + + return ContactsPeerItem( + presentationData: ItemListPresentationData(presentationData), + systemStyle: .glass, + sortOrder: nameSortOrder, + displayOrder: nameDisplayOrder, + context: context, + peerMode: .peer, + peer: .peer(peer: EnginePeer(participant.peer), chatPeer: EnginePeer(participant.peer)), + status: status, + rightLabelText: label.flatMap { .init(text: $0, color: labelColor, hasBackground: labelBackground) }, + enabled: enabled, + selection: .none, + editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: revealed), + options: options, + actionIcon: actionIcon, + index: nil, + header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) }), + action: { _ in interaction.peerSelected(EnginePeer(participant.peer), participant) - }, setPeerIdWithRevealedOptions: { peerId, fromPeerId in + }, + setPeerIdWithRevealedOptions: { peerId, fromPeerId in interaction.setPeerIdWithRevealedOptions(RevealedPeerId(peerId: participant.peer.id, section: self.section), fromPeerId.flatMap({ RevealedPeerId(peerId: $0, section: self.section) })) }) } @@ -538,17 +572,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon } } - var label: String? var enabled = true - if case .searchMembers = mode { - switch participant.participant { - case .creator: - label = presentationData.strings.Channel_Management_LabelOwner - default: - break - } - } - if state.removingParticipantIds.contains(participant.peer.id) { enabled = false } @@ -564,7 +588,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon } } - entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat)) + entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: nil, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat)) index += 1 } @@ -771,18 +795,8 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon var enabled = true if case .banAndPromoteActions = mode { if case .creator = participant.participant { - label = presentationData.strings.Channel_Management_LabelOwner enabled = false } - } else if case .searchMembers = mode { - switch participant.participant { - case .creator: - label = presentationData.strings.Channel_Management_LabelOwner - case let .member(_, _, adminInfo, _, _, _): - if adminInfo != nil { - label = presentationData.strings.Channel_Management_LabelEditor - } - } } if state.removingParticipantIds.contains(participant.peer.id) { @@ -878,16 +892,14 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon section = .none } - var label: String? var enabled = true if case .banAndPromoteActions = mode { if case .creator = participant.participant { - label = presentationData.strings.Channel_Management_LabelOwner enabled = false } } - entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: [], revealed: false, enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat, addIcon: addIcon)) + entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: nil, revealActions: [], revealed: false, enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat, addIcon: addIcon)) index += 1 } } @@ -1050,18 +1062,8 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon var enabled = true if case .banAndPromoteActions = mode { if case .creator = participant.participant { - label = presentationData.strings.Channel_Management_LabelOwner enabled = false } - } else if case .searchMembers = mode { - switch participant.participant { - case .creator: - label = presentationData.strings.Channel_Management_LabelOwner - case let .member(_, _, adminInfo, _, _, _): - if adminInfo != nil { - label = presentationData.strings.Channel_Management_LabelEditor - } - } } if state.removingParticipantIds.contains(participant.peer.id) { @@ -1072,7 +1074,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon case .searchAdmins: switch participant.participant { case .creator: - label = presentationData.strings.Channel_Management_LabelOwner + break case let .member(_, _, adminInfo, _, _, _): if let adminInfo = adminInfo { if let peer = participant.peers[adminInfo.promotedBy] { diff --git a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift index 1254868edb..2fd373977b 100644 --- a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift @@ -47,6 +47,37 @@ public func shortStringForDayOfWeek(strings: PresentationStrings, day: Int32) -> } } +public func stringForNominativeMonth(strings: PresentationStrings, month: Int32) -> String { + switch month { + case 0: + return strings.Month_NomJanuary + case 1: + return strings.Month_NomFebruary + case 2: + return strings.Month_NomMarch + case 3: + return strings.Month_NomApril + case 4: + return strings.Month_NomMay + case 5: + return strings.Month_NomJune + case 6: + return strings.Month_NomJuly + case 7: + return strings.Month_NomAugust + case 8: + return strings.Month_NomSeptember + case 9: + return strings.Month_NomOctober + case 10: + return strings.Month_NomNovember + case 11: + return strings.Month_NomDecember + default: + return "" + } +} + public func stringForMonth(strings: PresentationStrings, month: Int32) -> String { switch month { case 0: diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index dafa22125a..47bb5140f4 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -5386,6 +5386,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID ) if trackId != 0 && !isCollage { + items.append(.separator) items.append( .action( ContextMenuActionItem( diff --git a/submodules/TelegramUI/Components/VolumeSliderContextItem/Sources/VolumeSliderContextItem.swift b/submodules/TelegramUI/Components/VolumeSliderContextItem/Sources/VolumeSliderContextItem.swift index a1c9465026..3571e1927e 100644 --- a/submodules/TelegramUI/Components/VolumeSliderContextItem/Sources/VolumeSliderContextItem.swift +++ b/submodules/TelegramUI/Components/VolumeSliderContextItem/Sources/VolumeSliderContextItem.swift @@ -155,11 +155,21 @@ private final class VolumeSliderContextItemNode: ASDisplayNode, ContextMenuCusto } private func updateValue(transition: ContainedViewLayoutTransition = .immediate) { - let width = self.frame.width + let sideInset: CGFloat = 10.0 + let width = self.frame.width - sideInset * 2.0 let range = self.maxValue - self.minValue - let value = self.value - transition.updateFrameAdditive(node: self.foregroundNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: value / range * width, height: self.frame.height))) + let value = (self.value - self.minValue) / range + var foregroundFrame = CGRect(origin: CGPoint(x: sideInset, y: 0.0), size: CGSize(width: value * width, height: self.frame.height)) + var foregroundOffset: CGFloat = 0.0 + if foregroundFrame.width < 40.0 { + foregroundOffset = (40.0 - foregroundFrame.width) * 0.5 + foregroundFrame = foregroundFrame.insetBy(dx: 0.0, dy: foregroundOffset) + } + transition.updateFrameAdditive(node: self.foregroundNode, frame: foregroundFrame) + transition.updateSublayerTransformOffset(layer: self.foregroundNode.layer, offset: CGPoint(x: 0.0, y: -foregroundOffset)) + + transition.updateCornerRadius(node: self.foregroundNode, cornerRadius: min(20.0, foregroundFrame.width * 0.5)) let stringValue = "\(Int(self.value * 100.0))%"