mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Animation and theme improvements
This commit is contained in:
parent
1fdf09cbda
commit
2af9c675a7
@ -150,8 +150,7 @@ final class ChatListTitleView: UIView, NavigationBarTitleView, NavigationBarTitl
|
||||
return
|
||||
}
|
||||
strongSelf.openStatusSetup?(titleCredibilityIconView)
|
||||
},
|
||||
longTapAction: nil
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 22.0, height: 22.0)
|
||||
@ -379,8 +378,7 @@ final class ChatListTitleView: UIView, NavigationBarTitleView, NavigationBarTitl
|
||||
return
|
||||
}
|
||||
strongSelf.openStatusSetup?(titleCredibilityIconView)
|
||||
},
|
||||
longTapAction: nil
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 22.0, height: 22.0)
|
||||
|
||||
@ -2073,8 +2073,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
animationRenderer: item.interaction.animationRenderer,
|
||||
content: currentCredibilityIconContent,
|
||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||
action: nil,
|
||||
longTapAction: nil
|
||||
action: nil
|
||||
)
|
||||
strongSelf.credibilityIconComponent = credibilityIconComponent
|
||||
|
||||
|
||||
@ -1026,7 +1026,6 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
content: credibilityIcon,
|
||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||
action: nil,
|
||||
longTapAction: nil,
|
||||
emojiFileUpdated: nil
|
||||
)
|
||||
strongSelf.credibilityIconComponent = credibilityIconComponent
|
||||
|
||||
@ -1124,7 +1124,6 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
content: credibilityIcon,
|
||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||
action: nil,
|
||||
longTapAction: nil,
|
||||
emojiFileUpdated: nil
|
||||
)
|
||||
strongSelf.credibilityIconComponent = credibilityIconComponent
|
||||
|
||||
@ -151,8 +151,7 @@ class EmojiHeaderComponent: Component {
|
||||
loopMode: .forever
|
||||
),
|
||||
isVisibleForAnimations: true,
|
||||
action: nil,
|
||||
longTapAction: nil
|
||||
action: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 96.0, height: 96.0)
|
||||
|
||||
@ -291,7 +291,9 @@ public class ItemListReactionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
context: item.context,
|
||||
animationCache: item.context.animationCache,
|
||||
animationRenderer: item.context.animationRenderer,
|
||||
content: .animation(content: animationContent, size: iconBoundingSize, placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .forever), isVisibleForAnimations: true, action: nil, longTapAction: nil
|
||||
content: .animation(content: animationContent, size: iconBoundingSize, placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .forever),
|
||||
isVisibleForAnimations: true,
|
||||
action: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: iconBoundingSize
|
||||
|
||||
@ -1036,7 +1036,6 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
|
||||
content: credibilityIcon,
|
||||
isVisibleForAnimations: true,
|
||||
action: nil,
|
||||
longTapAction: nil,
|
||||
emojiFileUpdated: nil
|
||||
)),
|
||||
environment: {},
|
||||
|
||||
@ -52,7 +52,6 @@ public final class EmojiStatusComponent: Component {
|
||||
public let content: Content
|
||||
public let isVisibleForAnimations: Bool
|
||||
public let action: (() -> Void)?
|
||||
public let longTapAction: (() -> Void)?
|
||||
public let emojiFileUpdated: ((TelegramMediaFile?) -> Void)?
|
||||
|
||||
public init(
|
||||
@ -62,7 +61,6 @@ public final class EmojiStatusComponent: Component {
|
||||
content: Content,
|
||||
isVisibleForAnimations: Bool,
|
||||
action: (() -> Void)?,
|
||||
longTapAction: (() -> Void)?,
|
||||
emojiFileUpdated: ((TelegramMediaFile?) -> Void)? = nil
|
||||
) {
|
||||
self.context = context
|
||||
@ -71,7 +69,6 @@ public final class EmojiStatusComponent: Component {
|
||||
self.content = content
|
||||
self.isVisibleForAnimations = isVisibleForAnimations
|
||||
self.action = action
|
||||
self.longTapAction = longTapAction
|
||||
self.emojiFileUpdated = emojiFileUpdated
|
||||
}
|
||||
|
||||
@ -83,7 +80,6 @@ public final class EmojiStatusComponent: Component {
|
||||
content: self.content,
|
||||
isVisibleForAnimations: isVisibleForAnimations,
|
||||
action: self.action,
|
||||
longTapAction: self.longTapAction,
|
||||
emojiFileUpdated: self.emojiFileUpdated
|
||||
)
|
||||
}
|
||||
@ -157,7 +153,6 @@ public final class EmojiStatusComponent: Component {
|
||||
self.layer.addSublayer(self.hierarchyTrackingLayer)
|
||||
|
||||
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||
self.addGestureRecognizer(UILongPressGestureRecognizer(target: self, action: #selector(self.longPressGesture(_:))))
|
||||
|
||||
self.hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
@ -184,12 +179,6 @@ public final class EmojiStatusComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func longPressGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .began = recognizer.state {
|
||||
self.component?.longTapAction?()
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: EmojiStatusComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: Transition) -> CGSize {
|
||||
self.state = state
|
||||
|
||||
@ -200,6 +189,8 @@ public final class EmojiStatusComponent: Component {
|
||||
var emojiLoopMode: LoopMode?
|
||||
var emojiSize = CGSize()
|
||||
|
||||
self.isUserInteractionEnabled = component.action != nil
|
||||
|
||||
//let previousContent = self.component?.content
|
||||
if self.component?.content != component.content {
|
||||
switch component.content {
|
||||
|
||||
@ -223,6 +223,7 @@ public final class EmojiStatusSelectionController: ViewController {
|
||||
|
||||
private var emojiContentDisposable: Disposable?
|
||||
private var emojiContent: EmojiPagerContentComponent?
|
||||
private var freezeUpdates: Bool = false
|
||||
private var scheduledEmojiContentAnimationHint: EmojiPagerContentComponent.ContentAnimation?
|
||||
|
||||
private var availableReactions: AvailableReactions?
|
||||
@ -281,7 +282,9 @@ public final class EmojiStatusSelectionController: ViewController {
|
||||
return
|
||||
}
|
||||
strongSelf.controller?._ready.set(.single(true))
|
||||
if strongSelf.emojiContent == nil || !strongSelf.freezeUpdates {
|
||||
strongSelf.emojiContent = emojiContent
|
||||
}
|
||||
|
||||
emojiContent.inputInteractionHolder.inputInteraction = EmojiPagerContentComponent.InputInteraction(
|
||||
performItemAction: { groupId, item, _, _, _, _ in
|
||||
@ -524,12 +527,6 @@ public final class EmojiStatusSelectionController: ViewController {
|
||||
itemCompleted = true
|
||||
}
|
||||
|
||||
/*if let availableReactions = self.availableReactions, let availableReaction = availableReactions.reactions.first(where: { $0.value == }) {
|
||||
|
||||
} else {
|
||||
effectCompleted = true
|
||||
}*/
|
||||
|
||||
self.animateOut(completion: {
|
||||
contentCompleted = true
|
||||
completion()
|
||||
@ -699,6 +696,19 @@ public final class EmojiStatusSelectionController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
self.freezeUpdates = true
|
||||
|
||||
if let _ = item, let destinationView = controller.destinationItemView() {
|
||||
if let snapshotView = destinationView.snapshotView(afterScreenUpdates: false) {
|
||||
snapshotView.frame = destinationView.frame
|
||||
destinationView.superview?.insertSubview(snapshotView, belowSubview: destinationView)
|
||||
snapshotView.layer.animateScale(from: 1.0, to: 0.001, duration: 0.15, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
}
|
||||
destinationView.isHidden = true
|
||||
}
|
||||
|
||||
switch controller.mode {
|
||||
case .statusSelection:
|
||||
let _ = (self.context.engine.accountData.setEmojiStatus(file: item?.itemFile)
|
||||
|
||||
@ -1717,7 +1717,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
public let isPremiumLocked: Bool
|
||||
public let isEmbedded: Bool
|
||||
public let hasClear: Bool
|
||||
public let isExpandable: Bool
|
||||
public let collapsedLineCount: Int?
|
||||
public let displayPremiumBadges: Bool
|
||||
public let headerItem: EntityKeyboardAnimationData?
|
||||
public let items: [Item]
|
||||
@ -1732,7 +1732,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
isPremiumLocked: Bool,
|
||||
isEmbedded: Bool,
|
||||
hasClear: Bool,
|
||||
isExpandable: Bool,
|
||||
collapsedLineCount: Int?,
|
||||
displayPremiumBadges: Bool,
|
||||
headerItem: EntityKeyboardAnimationData?,
|
||||
items: [Item]
|
||||
@ -1746,7 +1746,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
self.isPremiumLocked = isPremiumLocked
|
||||
self.isEmbedded = isEmbedded
|
||||
self.hasClear = hasClear
|
||||
self.isExpandable = isExpandable
|
||||
self.collapsedLineCount = collapsedLineCount
|
||||
self.displayPremiumBadges = displayPremiumBadges
|
||||
self.headerItem = headerItem
|
||||
self.items = items
|
||||
@ -1783,7 +1783,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
if lhs.hasClear != rhs.hasClear {
|
||||
return false
|
||||
}
|
||||
if lhs.isExpandable != rhs.isExpandable {
|
||||
if lhs.collapsedLineCount != rhs.collapsedLineCount {
|
||||
return false
|
||||
}
|
||||
if lhs.displayPremiumBadges != rhs.displayPremiumBadges {
|
||||
@ -1900,7 +1900,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
let isFeatured: Bool
|
||||
let itemCount: Int
|
||||
let isEmbedded: Bool
|
||||
let isExpandable: Bool
|
||||
let collapsedLineCount: Int?
|
||||
}
|
||||
|
||||
private struct ItemGroupLayout: Equatable {
|
||||
@ -2034,13 +2034,8 @@ public final class EmojiPagerContentComponent: Component {
|
||||
let visibleItemCount: Int
|
||||
if itemGroup.isEmbedded {
|
||||
visibleItemCount = 0
|
||||
} else if itemGroup.isExpandable && !expandedGroupIds.contains(itemGroup.groupId) {
|
||||
let maxLines: Int
|
||||
#if DEBUG
|
||||
maxLines = 2
|
||||
#else
|
||||
maxLines = 3
|
||||
#endif
|
||||
} else if let collapsedLineCount = itemGroup.collapsedLineCount, !expandedGroupIds.contains(itemGroup.groupId) {
|
||||
let maxLines: Int = collapsedLineCount
|
||||
if numRowsInGroup > maxLines {
|
||||
visibleItemCount = self.itemsPerRow * maxLines - 1
|
||||
collapsedItemIndex = visibleItemCount
|
||||
@ -4562,7 +4557,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
isFeatured: itemGroup.isFeatured,
|
||||
itemCount: itemGroup.items.count,
|
||||
isEmbedded: itemGroup.isEmbedded,
|
||||
isExpandable: itemGroup.isExpandable
|
||||
collapsedLineCount: itemGroup.collapsedLineCount
|
||||
))
|
||||
}
|
||||
|
||||
@ -4789,7 +4784,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
var subtitle: String?
|
||||
var isPremiumLocked: Bool
|
||||
var isFeatured: Bool
|
||||
var isExpandable: Bool
|
||||
var collapsedLineCount: Int?
|
||||
var isClearable: Bool
|
||||
var headerItem: EntityKeyboardAnimationData?
|
||||
var items: [EmojiPagerContentComponent.Item]
|
||||
@ -4831,7 +4826,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
itemGroups[groupIndex].items.append(resultItem)
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: true, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: 5, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
|
||||
var existingIds = Set<MediaId>()
|
||||
@ -4986,7 +4981,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
}
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -5039,7 +5034,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
itemGroups[groupIndex].items.append(resultItem)
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: hasRecent && !isQuickReactionSelection, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && !isQuickReactionSelection, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
} else {
|
||||
let groupId = "recent"
|
||||
@ -5051,7 +5046,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
}
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: nil, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5118,7 +5113,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
popularInsertIndex += 1
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: hasRecent && !isQuickReactionSelection, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: popularTitle, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: hasRecent && !isQuickReactionSelection, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5166,7 +5161,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
itemGroups[groupIndex].items.append(resultItem)
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: true, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Emoji_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: true, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5188,7 +5183,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
itemGroups[groupIndex].items.append(resultItem)
|
||||
} else {
|
||||
itemGroupIndexById[groupId] = itemGroups.count
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: nil, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5260,7 +5255,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
break inner
|
||||
}
|
||||
}
|
||||
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, isExpandable: false, isClearable: false, headerItem: headerItem, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, collapsedLineCount: nil, isClearable: false, headerItem: headerItem, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -5316,7 +5311,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
)
|
||||
}
|
||||
|
||||
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: true, isExpandable: true, isClearable: false, headerItem: headerItem, items: [resultItem]))
|
||||
itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: true, collapsedLineCount: 3, isClearable: false, headerItem: headerItem, items: [resultItem]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5358,7 +5353,7 @@ public final class EmojiPagerContentComponent: Component {
|
||||
isPremiumLocked: group.isPremiumLocked,
|
||||
isEmbedded: false,
|
||||
hasClear: group.isClearable,
|
||||
isExpandable: group.isExpandable,
|
||||
collapsedLineCount: group.collapsedLineCount,
|
||||
displayPremiumBadges: false,
|
||||
headerItem: headerItem,
|
||||
items: group.items
|
||||
|
||||
@ -505,7 +505,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode {
|
||||
isPremiumLocked: group.isPremiumLocked,
|
||||
isEmbedded: isEmbedded,
|
||||
hasClear: hasClear,
|
||||
isExpandable: false,
|
||||
collapsedLineCount: nil,
|
||||
displayPremiumBadges: group.displayPremiumBadges,
|
||||
headerItem: group.headerItem,
|
||||
items: group.items
|
||||
|
||||
@ -2458,8 +2458,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
animationRenderer: item.context.animationRenderer,
|
||||
content: currentCredibilityIcon,
|
||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||
action: nil,
|
||||
longTapAction: nil
|
||||
action: nil
|
||||
)
|
||||
|
||||
let credibilityIconSize = credibilityIconView.update(
|
||||
|
||||
@ -690,8 +690,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
animationRenderer: self.animationRenderer,
|
||||
content: titleCredibilityContent,
|
||||
isVisibleForAnimations: true,
|
||||
action: nil,
|
||||
longTapAction: nil
|
||||
action: nil
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 20.0, height: 20.0)
|
||||
|
||||
@ -2373,12 +2373,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
strongSelf.displayPremiumIntro?(strongSelf.titleCredibilityIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), false)
|
||||
},
|
||||
longTapAction: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.engine.accountData.setEmojiStatus(file: nil).start()
|
||||
}, emojiFileUpdated: { [weak self] emojiFile in
|
||||
emojiFileUpdated: { [weak self] emojiFile in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -2432,12 +2427,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
strongSelf.displayPremiumIntro?(strongSelf.titleExpandedCredibilityIconView, currentEmojiStatus, strongSelf.emojiStatusFileAndPackTitle.get(), true)
|
||||
},
|
||||
longTapAction: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = strongSelf.context.engine.accountData.setEmojiStatus(file: nil).start()
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user