Story reactions improvements

This commit is contained in:
Ilya Laktyushin 2023-08-28 23:56:33 +04:00
parent 930420c0f0
commit d0e9953d28
8 changed files with 90 additions and 29 deletions

View File

@ -453,7 +453,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) } dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) }
dict[-1300094593] = { return Api.MediaArea.parse_inputMediaAreaVenue($0) } dict[-1300094593] = { return Api.MediaArea.parse_inputMediaAreaVenue($0) }
dict[-544523486] = { return Api.MediaArea.parse_mediaAreaGeoPoint($0) } dict[-544523486] = { return Api.MediaArea.parse_mediaAreaGeoPoint($0) }
dict[1272429760] = { return Api.MediaArea.parse_mediaAreaSuggestedReaction($0) } dict[340088945] = { return Api.MediaArea.parse_mediaAreaSuggestedReaction($0) }
dict[-1098720356] = { return Api.MediaArea.parse_mediaAreaVenue($0) } dict[-1098720356] = { return Api.MediaArea.parse_mediaAreaVenue($0) }
dict[64088654] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) } dict[64088654] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) }
dict[940666592] = { return Api.Message.parse_message($0) } dict[940666592] = { return Api.Message.parse_message($0) }

View File

@ -50,7 +50,7 @@ public extension Api {
enum MediaArea: TypeConstructorDescription { enum MediaArea: TypeConstructorDescription {
case inputMediaAreaVenue(coordinates: Api.MediaAreaCoordinates, queryId: Int64, resultId: String) case inputMediaAreaVenue(coordinates: Api.MediaAreaCoordinates, queryId: Int64, resultId: String)
case mediaAreaGeoPoint(coordinates: Api.MediaAreaCoordinates, geo: Api.GeoPoint) case mediaAreaGeoPoint(coordinates: Api.MediaAreaCoordinates, geo: Api.GeoPoint)
case mediaAreaSuggestedReaction(coordinates: Api.MediaAreaCoordinates, reaction: Api.Reaction) case mediaAreaSuggestedReaction(flags: Int32, coordinates: Api.MediaAreaCoordinates, reaction: Api.Reaction)
case mediaAreaVenue(coordinates: Api.MediaAreaCoordinates, geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String) case mediaAreaVenue(coordinates: Api.MediaAreaCoordinates, geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
@ -70,10 +70,11 @@ public extension Api {
coordinates.serialize(buffer, true) coordinates.serialize(buffer, true)
geo.serialize(buffer, true) geo.serialize(buffer, true)
break break
case .mediaAreaSuggestedReaction(let coordinates, let reaction): case .mediaAreaSuggestedReaction(let flags, let coordinates, let reaction):
if boxed { if boxed {
buffer.appendInt32(1272429760) buffer.appendInt32(340088945)
} }
serializeInt32(flags, buffer: buffer, boxed: false)
coordinates.serialize(buffer, true) coordinates.serialize(buffer, true)
reaction.serialize(buffer, true) reaction.serialize(buffer, true)
break break
@ -98,8 +99,8 @@ public extension Api {
return ("inputMediaAreaVenue", [("coordinates", coordinates as Any), ("queryId", queryId as Any), ("resultId", resultId as Any)]) return ("inputMediaAreaVenue", [("coordinates", coordinates as Any), ("queryId", queryId as Any), ("resultId", resultId as Any)])
case .mediaAreaGeoPoint(let coordinates, let geo): case .mediaAreaGeoPoint(let coordinates, let geo):
return ("mediaAreaGeoPoint", [("coordinates", coordinates as Any), ("geo", geo as Any)]) return ("mediaAreaGeoPoint", [("coordinates", coordinates as Any), ("geo", geo as Any)])
case .mediaAreaSuggestedReaction(let coordinates, let reaction): case .mediaAreaSuggestedReaction(let flags, let coordinates, let reaction):
return ("mediaAreaSuggestedReaction", [("coordinates", coordinates as Any), ("reaction", reaction as Any)]) return ("mediaAreaSuggestedReaction", [("flags", flags as Any), ("coordinates", coordinates as Any), ("reaction", reaction as Any)])
case .mediaAreaVenue(let coordinates, let geo, let title, let address, let provider, let venueId, let venueType): case .mediaAreaVenue(let coordinates, let geo, let title, let address, let provider, let venueId, let venueType):
return ("mediaAreaVenue", [("coordinates", coordinates as Any), ("geo", geo as Any), ("title", title as Any), ("address", address as Any), ("provider", provider as Any), ("venueId", venueId as Any), ("venueType", venueType as Any)]) return ("mediaAreaVenue", [("coordinates", coordinates as Any), ("geo", geo as Any), ("title", title as Any), ("address", address as Any), ("provider", provider as Any), ("venueId", venueId as Any), ("venueType", venueType as Any)])
} }
@ -143,18 +144,21 @@ public extension Api {
} }
} }
public static func parse_mediaAreaSuggestedReaction(_ reader: BufferReader) -> MediaArea? { public static func parse_mediaAreaSuggestedReaction(_ reader: BufferReader) -> MediaArea? {
var _1: Api.MediaAreaCoordinates? var _1: Int32?
_1 = reader.readInt32()
var _2: Api.MediaAreaCoordinates?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates _2 = Api.parse(reader, signature: signature) as? Api.MediaAreaCoordinates
} }
var _2: Api.Reaction? var _3: Api.Reaction?
if let signature = reader.readInt32() { if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Reaction _3 = Api.parse(reader, signature: signature) as? Api.Reaction
} }
let _c1 = _1 != nil let _c1 = _1 != nil
let _c2 = _2 != nil let _c2 = _2 != nil
if _c1 && _c2 { let _c3 = _3 != nil
return Api.MediaArea.mediaAreaSuggestedReaction(coordinates: _1!, reaction: _2!) if _c1 && _c2 && _c3 {
return Api.MediaArea.mediaAreaSuggestedReaction(flags: _1!, coordinates: _2!, reaction: _3!)
} }
else { else {
return nil return nil

View File

@ -423,9 +423,16 @@ func mediaAreaFromApiMediaArea(_ mediaArea: Api.MediaArea) -> MediaArea? {
longitude = 0.0 longitude = 0.0
} }
return .venue(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), venue: MediaArea.Venue(latitude: latitude, longitude: longitude, venue: MapVenue(title: title, address: address, provider: provider, id: venueId, type: venueType), queryId: nil, resultId: nil)) return .venue(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), venue: MediaArea.Venue(latitude: latitude, longitude: longitude, venue: MapVenue(title: title, address: address, provider: provider, id: venueId, type: venueType), queryId: nil, resultId: nil))
case let .mediaAreaSuggestedReaction(coordinates, reaction): case let .mediaAreaSuggestedReaction(flags, coordinates, reaction):
if let reaction = MessageReaction.Reaction(apiReaction: reaction) { if let reaction = MessageReaction.Reaction(apiReaction: reaction) {
return .reaction(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), reaction: reaction) var parsedFlags = MediaArea.ReactionFlags()
if (flags & (1 << 0)) != 0 {
parsedFlags.insert(.isDark)
}
if (flags & (1 << 1)) != 0 {
parsedFlags.insert(.isFlipped)
}
return .reaction(coordinates: coodinatesFromApiMediaAreaCoordinates(coordinates), reaction: reaction, flags: parsedFlags)
} else { } else {
return nil return nil
} }
@ -446,8 +453,15 @@ func apiMediaAreasFromMediaAreas(_ mediaAreas: [MediaArea]) -> [Api.MediaArea] {
} else { } else {
apiMediaAreas.append(.mediaAreaGeoPoint(coordinates: inputCoordinates, geo: .geoPoint(flags: 0, long: venue.longitude, lat: venue.latitude, accessHash: 0, accuracyRadius: nil))) apiMediaAreas.append(.mediaAreaGeoPoint(coordinates: inputCoordinates, geo: .geoPoint(flags: 0, long: venue.longitude, lat: venue.latitude, accessHash: 0, accuracyRadius: nil)))
} }
case let .reaction(_, reaction): case let .reaction(_, reaction, flags):
apiMediaAreas.append(.mediaAreaSuggestedReaction(coordinates: inputCoordinates, reaction: reaction.apiReaction)) var apiFlags: Int32 = 0
if flags.contains(.isDark) {
apiFlags |= (1 << 0)
}
if flags.contains(.isFlipped) {
apiFlags |= (1 << 1)
}
apiMediaAreas.append(.mediaAreaSuggestedReaction(flags: apiFlags, coordinates: inputCoordinates, reaction: reaction.apiReaction))
} }
} }
return apiMediaAreas return apiMediaAreas

View File

@ -6,6 +6,7 @@ public enum MediaArea: Codable, Equatable {
case type case type
case coordinates case coordinates
case value case value
case flags
} }
public struct Coordinates: Codable, Equatable { public struct Coordinates: Codable, Equatable {
@ -122,7 +123,23 @@ public enum MediaArea: Codable, Equatable {
} }
case venue(coordinates: Coordinates, venue: Venue) case venue(coordinates: Coordinates, venue: Venue)
case reaction(coordinates: Coordinates, reaction: MessageReaction.Reaction) case reaction(coordinates: Coordinates, reaction: MessageReaction.Reaction, flags: ReactionFlags)
public struct ReactionFlags: OptionSet {
public var rawValue: Int32
public init(rawValue: Int32) {
self.rawValue = rawValue
}
public init() {
self.rawValue = 0
}
public static let isDark = ReactionFlags(rawValue: 1 << 0)
public static let isFlipped = ReactionFlags(rawValue: 1 << 1)
}
private enum MediaAreaType: Int32 { private enum MediaAreaType: Int32 {
case venue case venue
@ -143,7 +160,8 @@ public enum MediaArea: Codable, Equatable {
case .reaction: case .reaction:
let coordinates = try container.decode(MediaArea.Coordinates.self, forKey: .coordinates) let coordinates = try container.decode(MediaArea.Coordinates.self, forKey: .coordinates)
let reaction = try container.decode(MessageReaction.Reaction.self, forKey: .value) let reaction = try container.decode(MessageReaction.Reaction.self, forKey: .value)
self = .reaction(coordinates: coordinates, reaction: reaction) let flags = ReactionFlags(rawValue: try container.decodeIfPresent(Int32.self, forKey: .flags) ?? 0)
self = .reaction(coordinates: coordinates, reaction: reaction, flags: flags)
} }
} }
@ -155,10 +173,11 @@ public enum MediaArea: Codable, Equatable {
try container.encode(MediaAreaType.venue.rawValue, forKey: .type) try container.encode(MediaAreaType.venue.rawValue, forKey: .type)
try container.encode(coordinates, forKey: .coordinates) try container.encode(coordinates, forKey: .coordinates)
try container.encode(venue, forKey: .value) try container.encode(venue, forKey: .value)
case let .reaction(coordinates, reaction): case let .reaction(coordinates, reaction, flags):
try container.encode(MediaAreaType.reaction.rawValue, forKey: .type) try container.encode(MediaAreaType.reaction.rawValue, forKey: .type)
try container.encode(coordinates, forKey: .coordinates) try container.encode(coordinates, forKey: .coordinates)
try container.encode(reaction, forKey: .value) try container.encode(reaction, forKey: .value)
try container.encode(flags.rawValue, forKey: .flags)
} }
} }
} }
@ -168,7 +187,7 @@ public extension MediaArea {
switch self { switch self {
case let .venue(coordinates, _): case let .venue(coordinates, _):
return coordinates return coordinates
case let .reaction(coordinates, _): case let .reaction(coordinates, _, _):
return coordinates return coordinates
} }
} }

View File

@ -99,10 +99,18 @@ public enum CodableDrawingEntity: Equatable {
) )
) )
case let .sticker(entity): case let .sticker(entity):
if case let .file(_, type) = entity.content, case let .reaction(reaction, _) = type { if case let .file(_, type) = entity.content, case let .reaction(reaction, style) = type {
var flags: MediaArea.ReactionFlags = []
if case .black = style {
flags.insert(.isDark)
}
if entity.mirrored {
flags.insert(.isFlipped)
}
return .reaction( return .reaction(
coordinates: coordinates, coordinates: coordinates,
reaction: reaction reaction: reaction,
flags: flags
) )
} else { } else {
return nil return nil

View File

@ -700,10 +700,12 @@ public final class PeerListItemComponent: Component {
self.iconFrame = CGRect(origin: CGPoint(x: availableSize.width - (contextInset * 2.0 + 14.0 + component.sideInset) - imageSize.width, y: floor((height - verticalInset * 2.0 - imageSize.height) * 0.5)), size: imageSize) self.iconFrame = CGRect(origin: CGPoint(x: availableSize.width - (contextInset * 2.0 + 14.0 + component.sideInset) - imageSize.width, y: floor((height - verticalInset * 2.0 - imageSize.height) * 0.5)), size: imageSize)
if case .none = component.rightAccessory { if case .none = component.rightAccessory {
if case .none = component.subtitleAccessory {
if let iconView = self.iconView { if let iconView = self.iconView {
self.iconView = nil self.iconView = nil
iconView.removeFromSuperview() iconView.removeFromSuperview()
} }
}
} else { } else {
let iconView: UIImageView let iconView: UIImageView
if let current = self.iconView { if let current = self.iconView {

View File

@ -74,6 +74,7 @@ final class StoryItemOverlaysView: UIView {
func update( func update(
context: AccountContext, context: AccountContext,
reaction: MessageReaction.Reaction, reaction: MessageReaction.Reaction,
flags: MediaArea.ReactionFlags,
availableReactions: StoryAvailableReactions?, availableReactions: StoryAvailableReactions?,
synchronous: Bool, synchronous: Bool,
size: CGSize size: CGSize
@ -84,6 +85,12 @@ final class StoryItemOverlaysView: UIView {
self.coverView.frame = CGRect(origin: CGPoint(x: size.width * insets.left, y: size.height * insets.top), size: CGSize(width: size.width - size.width * insets.left - size.width * insets.right, height: size.height - size.height * insets.top - size.height * insets.bottom)) self.coverView.frame = CGRect(origin: CGPoint(x: size.width * insets.left, y: size.height * insets.top), size: CGSize(width: size.width - size.width * insets.left - size.width * insets.right, height: size.height - size.height * insets.top - size.height * insets.bottom))
self.shadowView.frame = self.coverView.frame self.shadowView.frame = self.coverView.frame
if flags.contains(.isFlipped) {
self.coverView.transform = CGAffineTransformMakeScale(-1.0, 1.0)
self.shadowView.transform = self.coverView.transform
}
self.coverView.tintColor = flags.contains(.isDark) ? UIColor(rgb: 0x000000, alpha: 0.5) : UIColor.white
let minSide = floor(min(200.0, min(size.width, size.height)) * 0.65) let minSide = floor(min(200.0, min(size.width, size.height)) * 0.65)
let itemSize = CGSize(width: minSide, height: minSide) let itemSize = CGSize(width: minSide, height: minSide)
@ -172,7 +179,7 @@ final class StoryItemOverlaysView: UIView {
var nextId = 0 var nextId = 0
for mediaArea in story.mediaAreas { for mediaArea in story.mediaAreas {
switch mediaArea { switch mediaArea {
case let .reaction(coordinates, reaction): case let .reaction(coordinates, reaction, flags):
let referenceSize = size let referenceSize = size
let areaSize = CGSize(width: coordinates.width / 100.0 * referenceSize.width, height: coordinates.height / 100.0 * referenceSize.height) let areaSize = CGSize(width: coordinates.width / 100.0 * referenceSize.width, height: coordinates.height / 100.0 * referenceSize.height)
let targetFrame = CGRect(x: coordinates.x / 100.0 * referenceSize.width - areaSize.width * 0.5, y: coordinates.y / 100.0 * referenceSize.height - areaSize.height * 0.5, width: areaSize.width, height: areaSize.height) let targetFrame = CGRect(x: coordinates.x / 100.0 * referenceSize.width - areaSize.width * 0.5, y: coordinates.y / 100.0 * referenceSize.height - areaSize.height * 0.5, width: areaSize.width, height: areaSize.height)
@ -199,6 +206,7 @@ final class StoryItemOverlaysView: UIView {
itemView.update( itemView.update(
context: context, context: context,
reaction: reaction, reaction: reaction,
flags: flags,
availableReactions: availableReactions, availableReactions: availableReactions,
synchronous: attemptSynchronous, synchronous: attemptSynchronous,
size: targetFrame.size size: targetFrame.size

View File

@ -1135,7 +1135,7 @@ public final class WebAppController: ViewController, AttachmentContainable {
self.webView?.sendEvent(name: "phone_requested", data: paramsString) self.webView?.sendEvent(name: "phone_requested", data: paramsString)
} }
controller.present(textAlertController(context: self.context, updatedPresentationData: controller.updatedPresentationData, title: self.presentationData.strings.Conversation_ShareBotContactConfirmationTitle, text: self.presentationData.strings.Conversation_ShareBotContactConfirmation, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: { let alertController = textAlertController(context: self.context, updatedPresentationData: controller.updatedPresentationData, title: self.presentationData.strings.Conversation_ShareBotContactConfirmationTitle, text: self.presentationData.strings.Conversation_ShareBotContactConfirmation, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {
sendEvent(false) sendEvent(false)
}), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { [weak self] in }), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { [weak self] in
guard let self else { guard let self else {
@ -1150,7 +1150,13 @@ public final class WebAppController: ViewController, AttachmentContainable {
sendEvent(true) sendEvent(true)
} }
}) })
})]), in: .window(.root)) })])
alertController.dismissed = { byOutsideTap in
if byOutsideTap {
sendEvent(false)
}
}
controller.present(alertController, in: .window(.root))
} }
fileprivate func invokeCustomMethod(requestId: String, method: String, params: String) { fileprivate func invokeCustomMethod(requestId: String, method: String, params: String) {