mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
8f51eec89b
commit
3314a18165
@ -10641,10 +10641,6 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Story.ViewList.TitleReactions" = "Reactions";
|
||||
|
||||
"Wallpaper.ApplyForChannel" = "Apply For This Channel";
|
||||
|
||||
"Notification.ChannelChangedWallpaper" = "Channel set a new wallpaper";
|
||||
|
||||
"Chat.Giveaway.Message.WinnersSelectedTitle.One" = "Winner Selected!";
|
||||
"Chat.Giveaway.Message.WinnersSelectedTitle.Many" = "Winners Selected!";
|
||||
"Chat.Giveaway.Message.WinnersSelectedText_1" = "**%@** winner of the [Giveaway]() was randomly selected by Telegram.";
|
||||
@ -10751,3 +10747,15 @@ Sorry for the inconvenience.";
|
||||
|
||||
"ChannelBoost.CustomWallpaper" = "Set Custom Channel Background";
|
||||
"ChannelBoost.EnableCustomWallpaperLevelText" = "Your channel needs **Level %1$@** to set custom channel background.";
|
||||
|
||||
"WallpaperPreview.ChannelHeader" = "All subscribers will see this wallpaper";
|
||||
"WallpaperPreview.ChannelTopText" = "Details to follow shortly.\nStay tuned!";
|
||||
"WallpaperPreview.ChannelReplyText" = "Breaking News";
|
||||
|
||||
"Wallpaper.ApplyForChannel" = "Apply Background";
|
||||
"Notification.ChannelChangedWallpaper" = "Channel set a new wallpaper";
|
||||
|
||||
"Story.MessageReposted.Personal" = "Message reposted to your stories.";
|
||||
"Story.MessageReposted.Channel" = "Message reposted to **%@**.";
|
||||
|
||||
"Story.Views.Commented" = " • commented";
|
||||
|
@ -462,6 +462,11 @@ private final class ContextControllerActionsListActionItemNode: HighlightTrackin
|
||||
} else {
|
||||
minSize.width += sideInset
|
||||
}
|
||||
if self.item.additionalLeftIcon != nil {
|
||||
minSize.width += 24.0
|
||||
minSize.width += iconSideInset
|
||||
minSize.width += iconSpacing
|
||||
}
|
||||
if let forcedHeight {
|
||||
minSize.height = forcedHeight
|
||||
} else {
|
||||
|
@ -2,10 +2,12 @@ import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import TelegramCore
|
||||
import LegacyComponents
|
||||
import TelegramPresentationData
|
||||
import DeviceAccess
|
||||
import AccountContext
|
||||
import LocalMediaResources
|
||||
|
||||
public func legacyWallpaperPicker(context: AccountContext, presentationData: PresentationData, subject: DeviceAccessMediaLibrarySubject = .wallpaper) -> Signal<(LegacyComponentsContext) -> TGMediaAssetsController, Void> {
|
||||
return Signal { subscriber in
|
||||
@ -45,3 +47,76 @@ public func legacyWallpaperPicker(context: AccountContext, presentationData: Pre
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LegacyWallpaperItem: NSObject, TGMediaEditableItem, TGMediaSelectableItem {
|
||||
public var isVideo: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public var uniqueIdentifier: String! {
|
||||
return self.asset.localIdentifier
|
||||
}
|
||||
|
||||
let asset: PHAsset
|
||||
let screenImage: UIImage
|
||||
private(set) var thumbnailResource: TelegramMediaResource?
|
||||
private(set) var imageResource: TelegramMediaResource?
|
||||
let dimensions: CGSize
|
||||
|
||||
public init(asset: PHAsset, screenImage: UIImage, dimensions: CGSize) {
|
||||
self.asset = asset
|
||||
self.screenImage = screenImage
|
||||
self.dimensions = dimensions
|
||||
}
|
||||
|
||||
public var originalSize: CGSize {
|
||||
return self.dimensions
|
||||
}
|
||||
|
||||
public func thumbnailImageSignal() -> SSignal! {
|
||||
return SSignal.complete()
|
||||
// return SSignal(generator: { subscriber -> SDisposable? in
|
||||
// let disposable = self.thumbnailImage.start(next: { image in
|
||||
// subscriber.putNext(image)
|
||||
// subscriber.putCompletion()
|
||||
// })
|
||||
//
|
||||
// return SBlockDisposable(block: {
|
||||
// disposable.dispose()
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
public func screenImageSignal(_ position: TimeInterval) -> SSignal! {
|
||||
return SSignal.single(self.screenImage)
|
||||
}
|
||||
|
||||
public var originalImage: Signal<UIImage, NoError> {
|
||||
return fetchPhotoLibraryImage(localIdentifier: self.asset.localIdentifier, thumbnail: false)
|
||||
|> filter { value in
|
||||
return !(value?.1 ?? true)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<UIImage, NoError> in
|
||||
if let result = result {
|
||||
return .single(result.0)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func originalImageSignal(_ position: TimeInterval) -> SSignal! {
|
||||
return SSignal(generator: { subscriber -> SDisposable? in
|
||||
let disposable = self.originalImage.start(next: { image in
|
||||
subscriber.putNext(image)
|
||||
if !image.degraded() {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
})
|
||||
|
||||
return SBlockDisposable(block: {
|
||||
disposable.dispose()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ public func PremiumBoostScreen(
|
||||
let controller = context.sharedContext.makePremiumGiftController(context: context)
|
||||
pushController(controller)
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Close, action: {})
|
||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Close, action: {})
|
||||
],
|
||||
actionLayout: .vertical,
|
||||
parseMarkdown: true
|
||||
|
@ -119,6 +119,8 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Settings/QuickReactionSetupController",
|
||||
"//submodules/TelegramUI/Components/Settings/ThemeCarouselItem",
|
||||
"//submodules/TelegramUI/Components/Settings/ThemeSettingsThemeItem",
|
||||
"//submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen",
|
||||
"//submodules/TelegramUI/Components/Settings/SettingsThemeWallpaperNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -12,6 +12,7 @@ import LegacyUI
|
||||
import LegacyMediaPickerUI
|
||||
import LocalMediaResources
|
||||
import ImageBlur
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
func presentCustomWallpaperPicker(context: AccountContext, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -318,77 +319,3 @@ public func uploadCustomPeerWallpaper(context: AccountContext, wallpaper: Wallpa
|
||||
return croppedImage
|
||||
}).start()
|
||||
}
|
||||
|
||||
class LegacyWallpaperItem: NSObject, TGMediaEditableItem, TGMediaSelectableItem {
|
||||
var isVideo: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var uniqueIdentifier: String! {
|
||||
return self.asset.localIdentifier
|
||||
}
|
||||
|
||||
let asset: PHAsset
|
||||
let screenImage: UIImage
|
||||
private(set) var thumbnailResource: TelegramMediaResource?
|
||||
private(set) var imageResource: TelegramMediaResource?
|
||||
let dimensions: CGSize
|
||||
|
||||
|
||||
init(asset: PHAsset, screenImage: UIImage, dimensions: CGSize) {
|
||||
self.asset = asset
|
||||
self.screenImage = screenImage
|
||||
self.dimensions = dimensions
|
||||
}
|
||||
|
||||
var originalSize: CGSize {
|
||||
return self.dimensions
|
||||
}
|
||||
|
||||
func thumbnailImageSignal() -> SSignal! {
|
||||
return SSignal.complete()
|
||||
// return SSignal(generator: { subscriber -> SDisposable? in
|
||||
// let disposable = self.thumbnailImage.start(next: { image in
|
||||
// subscriber.putNext(image)
|
||||
// subscriber.putCompletion()
|
||||
// })
|
||||
//
|
||||
// return SBlockDisposable(block: {
|
||||
// disposable.dispose()
|
||||
// })
|
||||
// })
|
||||
}
|
||||
|
||||
func screenImageSignal(_ position: TimeInterval) -> SSignal! {
|
||||
return SSignal.single(self.screenImage)
|
||||
}
|
||||
|
||||
var originalImage: Signal<UIImage, NoError> {
|
||||
return fetchPhotoLibraryImage(localIdentifier: self.asset.localIdentifier, thumbnail: false)
|
||||
|> filter { value in
|
||||
return !(value?.1 ?? true)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<UIImage, NoError> in
|
||||
if let result = result {
|
||||
return .single(result.0)
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func originalImageSignal(_ position: TimeInterval) -> SSignal! {
|
||||
return SSignal(generator: { subscriber -> SDisposable? in
|
||||
let disposable = self.originalImage.start(next: { image in
|
||||
subscriber.putNext(image)
|
||||
if !image.degraded() {
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
})
|
||||
|
||||
return SBlockDisposable(block: {
|
||||
disposable.dispose()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import TelegramUIPreferences
|
||||
import AccountContext
|
||||
import PresentationDataUtils
|
||||
import MediaResources
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
private let randomBackgroundColors: [Int32] = [0x007aff, 0x00c2ed, 0x29b327, 0xeb6ca4, 0xf08200, 0x9472ee, 0xd33213, 0xedb400, 0x6d839e]
|
||||
|
||||
|
@ -14,6 +14,7 @@ import PresentationDataUtils
|
||||
import WallpaperBackgroundNode
|
||||
import AnimationCache
|
||||
import MultiAnimationRenderer
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
private func generateMaskImage(color: UIColor) -> UIImage? {
|
||||
return generateImage(CGSize(width: 1.0, height: 80.0), opaque: false, rotatedContext: { size, context in
|
||||
|
@ -9,6 +9,7 @@ import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import AccountContext
|
||||
import AttachmentUI
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
private func availableGradients(dark: Bool) -> [[UInt32]] {
|
||||
if dark {
|
||||
|
@ -6,6 +6,7 @@ import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import AccountContext
|
||||
import GridMessageSelectionNode
|
||||
import SettingsThemeWallpaperNode
|
||||
|
||||
final class ThemeColorsGridControllerItem: GridItem {
|
||||
let context: AccountContext
|
||||
|
@ -9,6 +9,7 @@ import MergeLists
|
||||
import ItemListUI
|
||||
import PresentationDataUtils
|
||||
import AccountContext
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
final class ThemeColorsGridControllerInteraction {
|
||||
let openWallpaper: (TelegramWallpaper) -> Void
|
||||
|
@ -15,6 +15,7 @@ import SearchUI
|
||||
import HexColor
|
||||
import PresentationDataUtils
|
||||
import MediaPickerUI
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
public final class ThemeGridController: ViewController {
|
||||
private var controllerNode: ThemeGridControllerNode {
|
||||
|
@ -7,6 +7,7 @@ import AsyncDisplayKit
|
||||
import Postbox
|
||||
import AccountContext
|
||||
import GridMessageSelectionNode
|
||||
import SettingsThemeWallpaperNode
|
||||
|
||||
final class ThemeGridControllerItem: GridItem {
|
||||
let context: AccountContext
|
||||
|
@ -15,6 +15,7 @@ import AccountContext
|
||||
import SearchBarNode
|
||||
import SearchUI
|
||||
import WallpaperResources
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
struct ThemeGridControllerNodeState: Equatable {
|
||||
var editing: Bool
|
||||
|
@ -14,6 +14,7 @@ import LegacyComponents
|
||||
import WallpaperBackgroundNode
|
||||
import AnimationCache
|
||||
import MultiAnimationRenderer
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
private func generateMaskImage(color: UIColor) -> UIImage? {
|
||||
return generateImage(CGSize(width: 1.0, height: 80.0), opaque: false, rotatedContext: { size, context in
|
||||
|
@ -417,6 +417,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Chat/ChatQrCodeScreen",
|
||||
"//submodules/UIKitRuntimeUtils",
|
||||
"//submodules/TelegramUI/Components/SavedMessages/SavedMessagesScreen",
|
||||
"//submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen",
|
||||
] + select({
|
||||
"@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets,
|
||||
"//build-system:ios_sim_arm64": [],
|
||||
|
@ -580,7 +580,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
var viewCount: Int?
|
||||
var dateReplies = 0
|
||||
var dateReactionsAndPeers = mergedMessageReactionsAndPeers(accountPeer: associatedData.accountPeer, message: message)
|
||||
if message.isRestricted(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) {
|
||||
if message.isRestricted(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) || presentationData.isPreview {
|
||||
dateReactionsAndPeers = ([], [])
|
||||
}
|
||||
for attribute in message.attributes {
|
||||
|
@ -531,7 +531,6 @@ private final class PeerInfoInteraction {
|
||||
let performBotCommand: (PeerInfoBotCommand) -> Void
|
||||
let editingOpenPublicLinkSetup: () -> Void
|
||||
let editingOpenNameColorSetup: () -> Void
|
||||
let editingOpenPeerWallpaperSetup: () -> Void
|
||||
let editingOpenInviteLinksSetup: () -> Void
|
||||
let editingOpenDiscussionGroupSetup: () -> Void
|
||||
let editingToggleMessageSignatures: (Bool) -> Void
|
||||
@ -587,7 +586,6 @@ private final class PeerInfoInteraction {
|
||||
performBotCommand: @escaping (PeerInfoBotCommand) -> Void,
|
||||
editingOpenPublicLinkSetup: @escaping () -> Void,
|
||||
editingOpenNameColorSetup: @escaping () -> Void,
|
||||
editingOpenPeerWallpaperSetup: @escaping () -> Void,
|
||||
editingOpenInviteLinksSetup: @escaping () -> Void,
|
||||
editingOpenDiscussionGroupSetup: @escaping () -> Void,
|
||||
editingToggleMessageSignatures: @escaping (Bool) -> Void,
|
||||
@ -642,7 +640,6 @@ private final class PeerInfoInteraction {
|
||||
self.performBotCommand = performBotCommand
|
||||
self.editingOpenPublicLinkSetup = editingOpenPublicLinkSetup
|
||||
self.editingOpenNameColorSetup = editingOpenNameColorSetup
|
||||
self.editingOpenPeerWallpaperSetup = editingOpenPeerWallpaperSetup
|
||||
self.editingOpenInviteLinksSetup = editingOpenInviteLinksSetup
|
||||
self.editingOpenDiscussionGroupSetup = editingOpenDiscussionGroupSetup
|
||||
self.editingToggleMessageSignatures = editingToggleMessageSignatures
|
||||
@ -1581,7 +1578,6 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
case .broadcast:
|
||||
let ItemUsername = 1
|
||||
let ItemPeerColor = 2
|
||||
let ItemPeerWallpaper = 3
|
||||
let ItemInviteLinks = 4
|
||||
let ItemDiscussionGroup = 5
|
||||
let ItemSignMessages = 6
|
||||
@ -1683,10 +1679,6 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerColor, label: .image(colorImage, colorImage.size), additionalBadgeIcon: boostIcon, text: "Appearance", icon: UIImage(bundleImageName: "Chat/Info/NameColorIcon"), action: {
|
||||
interaction.editingOpenNameColorSetup()
|
||||
}))
|
||||
|
||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerWallpaper, label: .none, text: "Wallpaper", icon: UIImage(bundleImageName: "Settings/Menu/Appearance"), action: {
|
||||
interaction.editingOpenPeerWallpaperSetup()
|
||||
}))
|
||||
}
|
||||
|
||||
if isCreator || (channel.adminRights != nil && channel.hasPermission(.sendSomething)) {
|
||||
@ -2364,9 +2356,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
editingOpenNameColorSetup: { [weak self] in
|
||||
self?.editingOpenNameColorSetup()
|
||||
},
|
||||
editingOpenPeerWallpaperSetup: { [weak self] in
|
||||
self?.editingOpenPeerWallpaperSetup()
|
||||
},
|
||||
editingOpenInviteLinksSetup: { [weak self] in
|
||||
self?.editingOpenInviteLinksSetup()
|
||||
},
|
||||
@ -7209,80 +7198,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
self.controller?.push(ChannelAppearanceScreen(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId))
|
||||
}
|
||||
}
|
||||
|
||||
private func editingOpenPeerWallpaperSetup() {
|
||||
// let link = status.url
|
||||
// let controller = PremiumLimitScreen(context: context, subject: .storiesChannelBoost(peer: peer, boostSubject: .nameColors, isCurrent: true, level: Int32(status.level), currentLevelBoosts: Int32(status.currentLevelBoosts), nextLevelBoosts: status.nextLevelBoosts.flatMap(Int32.init), link: link, myBoostCount: 0, canBoostAgain: false), count: Int32(status.boosts), action: {
|
||||
// UIPasteboard.general.string = link
|
||||
// let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
// presentImpl?(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.ChannelBoost_BoostLinkCopied), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }))
|
||||
// return true
|
||||
// }, openStats: nil, openGift: premiumConfiguration.giveawayGiftsPurchaseAvailable ? {
|
||||
// let controller = createGiveawayController(context: context, peerId: peerId, subject: .generic)
|
||||
// pushImpl?(controller)
|
||||
// } : nil)
|
||||
// pushImpl?(controller)
|
||||
|
||||
let dismissControllers = { [weak self] in
|
||||
if let self, let navigationController = self.controller?.navigationController as? NavigationController {
|
||||
let controllers = navigationController.viewControllers.filter({ controller in
|
||||
if controller is WallpaperGalleryController || controller is AttachmentController || controller is PeerInfoScreenImpl {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
}
|
||||
var openWallpaperPickerImpl: ((Bool) -> Void)?
|
||||
let openWallpaperPicker: (Bool) -> Void = { [weak self] animateAppearance in
|
||||
guard let self, let peer = self.data?.peer else {
|
||||
return
|
||||
}
|
||||
let controller = wallpaperMediaPickerController(
|
||||
context: self.context,
|
||||
updatedPresentationData: self.controller?.updatedPresentationData,
|
||||
peer: EnginePeer(peer),
|
||||
animateAppearance: true,
|
||||
completion: { [weak self] _, result in
|
||||
guard let strongSelf = self, let asset = result as? PHAsset else {
|
||||
return
|
||||
}
|
||||
let controller = WallpaperGalleryController(context: strongSelf.context, source: .asset(asset), mode: .peer(EnginePeer(peer), false))
|
||||
controller.navigationPresentation = .modal
|
||||
controller.apply = { [weak self] wallpaper, options, editedImage, cropRect, brightness, forBoth in
|
||||
if let strongSelf = self {
|
||||
uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, editedImage: editedImage, cropRect: cropRect, brightness: brightness, peerId: peer.id, forBoth: forBoth, completion: {
|
||||
Queue.mainQueue().after(0.3, {
|
||||
dismissControllers()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
strongSelf.controller?.push(controller)
|
||||
},
|
||||
openColors: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let controller = standaloneColorPickerController(context: strongSelf.context, peer: EnginePeer(peer), push: { [weak self] controller in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controller?.push(controller)
|
||||
}
|
||||
}, openGallery: {
|
||||
openWallpaperPickerImpl?(false)
|
||||
})
|
||||
controller.navigationPresentation = .flatModal
|
||||
strongSelf.controller?.push(controller)
|
||||
}
|
||||
)
|
||||
controller.navigationPresentation = .flatModal
|
||||
self.controller?.push(controller)
|
||||
}
|
||||
openWallpaperPickerImpl = openWallpaperPicker
|
||||
openWallpaperPicker(true)
|
||||
}
|
||||
|
||||
private func editingOpenInviteLinksSetup() {
|
||||
self.controller?.push(inviteLinkListController(context: self.context, updatedPresentationData: self.controller?.updatedPresentationData, peerId: self.peerId, admin: nil))
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/DynamicCornerRadiusView",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
"//submodules/WallpaperResources",
|
||||
"//submodules/MediaPickerUI",
|
||||
"//submodules/TelegramUI/Components/Settings/WallpaperGalleryScreen",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Photos
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
@ -29,6 +30,8 @@ import EmojiStatusComponent
|
||||
import DynamicCornerRadiusView
|
||||
import ComponentDisplayAdapters
|
||||
import WallpaperResources
|
||||
import MediaPickerUI
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
private final class EmojiActionIconComponent: Component {
|
||||
let context: AccountContext
|
||||
@ -590,6 +593,58 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
self.environment?.controller()?.push(statsController)
|
||||
}
|
||||
|
||||
private func openCustomWallpaperSetup() {
|
||||
guard let _ = self.component, let contentsData = self.contentsData else {
|
||||
return
|
||||
}
|
||||
// let dismissControllers = { [weak self] in
|
||||
// if let self, let navigationController = self.controller?.navigationController as? NavigationController {
|
||||
// let controllers = navigationController.viewControllers.filter({ controller in
|
||||
// if controller is WallpaperGalleryController || controller is AttachmentController || controller is PeerInfoScreenImpl {
|
||||
// return false
|
||||
// }
|
||||
// return true
|
||||
// })
|
||||
// navigationController.setViewControllers(controllers, animated: true)
|
||||
// }
|
||||
// }
|
||||
// var openWallpaperPickerImpl: ((Bool) -> Void)?
|
||||
let openWallpaperPicker: (Bool) -> Void = { [weak self] animateAppearance in
|
||||
guard let self, let component = self.component, let peer = contentsData.peer else {
|
||||
return
|
||||
}
|
||||
let controller = wallpaperMediaPickerController(
|
||||
context: component.context,
|
||||
updatedPresentationData: nil,
|
||||
peer: peer,
|
||||
animateAppearance: true,
|
||||
completion: { [weak self] _, result in
|
||||
guard let self, let component = self.component, let asset = result as? PHAsset else {
|
||||
return
|
||||
}
|
||||
let controller = WallpaperGalleryController(context: component.context, source: .asset(asset), mode: .peer(peer, false))
|
||||
controller.navigationPresentation = .modal
|
||||
controller.apply = { wallpaper, options, editedImage, cropRect, brightness, forBoth in
|
||||
// if let strongSelf = self {
|
||||
// uploadCustomPeerWallpaper(context: strongSelf.context, wallpaper: wallpaper, mode: options, editedImage: editedImage, cropRect: cropRect, brightness: brightness, peerId: peer.id, forBoth: forBoth, completion: {
|
||||
// Queue.mainQueue().after(0.3, {
|
||||
// dismissControllers()
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
}
|
||||
self.environment?.controller()?.push(controller)
|
||||
},
|
||||
openColors: {
|
||||
}
|
||||
)
|
||||
controller.navigationPresentation = .flatModal
|
||||
self.environment?.controller()?.push(controller)
|
||||
}
|
||||
// openWallpaperPickerImpl = openWallpaperPicker
|
||||
openWallpaperPicker(true)
|
||||
}
|
||||
|
||||
private enum EmojiSetupSubject {
|
||||
case reply
|
||||
case profile
|
||||
@ -1055,7 +1110,7 @@ final class ChannelAppearanceScreenComponent: Component {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let _ = self
|
||||
self.openCustomWallpaperSetup()
|
||||
}
|
||||
)))
|
||||
]
|
||||
|
@ -0,0 +1,27 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "SettingsThemeWallpaperNode",
|
||||
module_name = "SettingsThemeWallpaperNode",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/Display",
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/SSignalKit/SwiftSignalKit",
|
||||
"//submodules/Postbox",
|
||||
"//submodules/TelegramCore",
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/GradientBackground",
|
||||
"//submodules/WallpaperResources",
|
||||
"//submodules/AccountContext",
|
||||
"//submodules/RadialStatusNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
@ -42,17 +42,17 @@ private let blackColorImage: UIImage? = {
|
||||
return context.generateImage()
|
||||
}()
|
||||
|
||||
final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
var wallpaper: TelegramWallpaper?
|
||||
public final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
public var wallpaper: TelegramWallpaper?
|
||||
private var arguments: PatternWallpaperArguments?
|
||||
|
||||
let buttonNode = HighlightTrackingButtonNode()
|
||||
let backgroundNode = ASImageNode()
|
||||
let imageNode = TransformImageNode()
|
||||
public let buttonNode = HighlightTrackingButtonNode()
|
||||
public let backgroundNode = ASImageNode()
|
||||
public let imageNode = TransformImageNode()
|
||||
private var gradientNode: GradientBackgroundNode?
|
||||
private let statusNode: RadialStatusNode
|
||||
|
||||
var pressed: (() -> Void)?
|
||||
public var pressed: (() -> Void)?
|
||||
|
||||
private let displayLoading: Bool
|
||||
private var isSelected: Bool = false
|
||||
@ -60,7 +60,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
|
||||
private let isLoadedDisposable = MetaDisposable()
|
||||
|
||||
init(displayLoading: Bool = false, overlayBackgroundColor: UIColor = UIColor(white: 0.0, alpha: 0.3)) {
|
||||
public init(displayLoading: Bool = false, overlayBackgroundColor: UIColor = UIColor(white: 0.0, alpha: 0.3)) {
|
||||
self.displayLoading = displayLoading
|
||||
self.imageNode.contentAnimations = [.subsequentUpdates]
|
||||
|
||||
@ -83,7 +83,7 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
self.isLoadedDisposable.dispose()
|
||||
}
|
||||
|
||||
func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||
public func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||
if self.isSelected != selected {
|
||||
self.isSelected = selected
|
||||
|
||||
@ -110,11 +110,11 @@ final class SettingsThemeWallpaperNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func setOverlayBackgroundColor(_ color: UIColor) {
|
||||
public func setOverlayBackgroundColor(_ color: UIColor) {
|
||||
self.statusNode.backgroundNodeColor = color
|
||||
}
|
||||
|
||||
func setWallpaper(context: AccountContext, wallpaper: TelegramWallpaper, selected: Bool, size: CGSize, cornerRadius: CGFloat = 0.0, synchronousLoad: Bool = false) {
|
||||
public func setWallpaper(context: AccountContext, wallpaper: TelegramWallpaper, selected: Bool, size: CGSize, cornerRadius: CGFloat = 0.0, synchronousLoad: Bool = false) {
|
||||
self.buttonNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
self.imageNode.frame = CGRect(origin: CGPoint(), size: size)
|
@ -0,0 +1,38 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "WallpaperGalleryScreen",
|
||||
module_name = "WallpaperGalleryScreen",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/Display",
|
||||
"//submodules/Postbox",
|
||||
"//submodules/TelegramCore",
|
||||
"//submodules/SSignalKit/SwiftSignalKit",
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/AccountContext",
|
||||
"//submodules/PresentationDataUtils",
|
||||
"//submodules/WallpaperBackgroundNode",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/SolidRoundedButtonNode",
|
||||
"//submodules/AppBundle",
|
||||
"//submodules/PremiumUI",
|
||||
"//submodules/WallpaperResources",
|
||||
"//submodules/HexColor",
|
||||
"//submodules/MergeLists",
|
||||
"//submodules/ShareController",
|
||||
"//submodules/GalleryUI",
|
||||
"//submodules/CounterContollerTitleView",
|
||||
"//submodules/LegacyMediaPickerUI",
|
||||
"//submodules/TelegramUI/Components/Settings/SettingsThemeWallpaperNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
@ -56,8 +56,8 @@ private class BlurLayer: CALayer {
|
||||
}
|
||||
}
|
||||
|
||||
class BlurView: UIView {
|
||||
override class var layerClass : AnyClass {
|
||||
public class BlurView: UIView {
|
||||
public override class var layerClass : AnyClass {
|
||||
return BlurLayer.self
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ class BlurView: UIView {
|
||||
return Queue(name: nil, qos: .userInteractive)
|
||||
}()
|
||||
|
||||
open var blurRadius: CGFloat {
|
||||
public var blurRadius: CGFloat {
|
||||
set { self.blurLayer.blurRadius = newValue }
|
||||
get { return self.blurLayer.blurRadius }
|
||||
}
|
||||
@ -104,7 +104,7 @@ class BlurView: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
override func display(_ layer: CALayer) {
|
||||
public override func display(_ layer: CALayer) {
|
||||
let blurRadius = self.blurLayer.presentationRadius
|
||||
if let image = self.image {
|
||||
self.draw(image, blurRadius: blurRadius)
|
||||
@ -112,19 +112,19 @@ class BlurView: UIView {
|
||||
}
|
||||
}
|
||||
|
||||
final class BlurredImageNode: ASDisplayNode {
|
||||
var image: UIImage? {
|
||||
public final class BlurredImageNode: ASDisplayNode {
|
||||
public var image: UIImage? {
|
||||
didSet {
|
||||
self.blurView.image = self.image
|
||||
self.blurView.layer.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
var blurView: BlurView {
|
||||
public var blurView: BlurView {
|
||||
return (self.view as? BlurView)!
|
||||
}
|
||||
|
||||
override init() {
|
||||
public override init() {
|
||||
super.init()
|
||||
|
||||
self.setViewBlock({
|
@ -313,15 +313,26 @@ private class ColorInputFieldNode: ASDisplayNode, UITextFieldDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
struct WallpaperColorPanelNodeState: Equatable {
|
||||
var selection: Int?
|
||||
var colors: [HSBColor]
|
||||
var maximumNumberOfColors: Int
|
||||
var rotateAvailable: Bool
|
||||
var rotation: Int32
|
||||
var preview: Bool
|
||||
var simpleGradientGeneration: Bool
|
||||
var suggestedNewColor: HSBColor?
|
||||
public struct WallpaperColorPanelNodeState: Equatable {
|
||||
public var selection: Int?
|
||||
public var colors: [HSBColor]
|
||||
public var maximumNumberOfColors: Int
|
||||
public var rotateAvailable: Bool
|
||||
public var rotation: Int32
|
||||
public var preview: Bool
|
||||
public var simpleGradientGeneration: Bool
|
||||
public var suggestedNewColor: HSBColor?
|
||||
|
||||
public init(selection: Int? = nil, colors: [HSBColor], maximumNumberOfColors: Int, rotateAvailable: Bool, rotation: Int32, preview: Bool, simpleGradientGeneration: Bool, suggestedNewColor: HSBColor? = nil) {
|
||||
self.selection = selection
|
||||
self.colors = colors
|
||||
self.maximumNumberOfColors = maximumNumberOfColors
|
||||
self.rotateAvailable = rotateAvailable
|
||||
self.rotation = rotation
|
||||
self.preview = preview
|
||||
self.simpleGradientGeneration = simpleGradientGeneration
|
||||
self.suggestedNewColor = suggestedNewColor
|
||||
}
|
||||
}
|
||||
|
||||
private final class ColorSampleItemNode: ASImageNode {
|
||||
@ -377,7 +388,7 @@ private final class ColorSampleItemNode: ASImageNode {
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
public final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
private var theme: PresentationTheme
|
||||
|
||||
private var state: WallpaperColorPanelNodeState
|
||||
@ -394,16 +405,16 @@ final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
private var sampleItemNodes: [ColorSampleItemNode] = []
|
||||
private let multiColorFieldNode: ColorInputFieldNode
|
||||
|
||||
var colorsChanged: (([HSBColor], Int, Bool) -> Void)?
|
||||
var colorSelected: (() -> Void)?
|
||||
var rotate: (() -> Void)?
|
||||
public var colorsChanged: (([HSBColor], Int, Bool) -> Void)?
|
||||
public var colorSelected: (() -> Void)?
|
||||
public var rotate: (() -> Void)?
|
||||
|
||||
var colorAdded: (() -> Void)?
|
||||
var colorRemoved: (() -> Void)?
|
||||
public var colorAdded: (() -> Void)?
|
||||
public var colorRemoved: (() -> Void)?
|
||||
|
||||
private var validLayout: (CGSize, CGFloat)?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self.theme = theme
|
||||
|
||||
self.backgroundNode = NavigationBackgroundNode(color: theme.chat.inputPanel.panelBackgroundColor)
|
||||
@ -512,7 +523,7 @@ final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
public func updateTheme(_ theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
self.backgroundNode.updateColor(color: self.theme.chat.inputPanel.panelBackgroundColor, transition: .immediate)
|
||||
self.topSeparatorNode.backgroundColor = self.theme.chat.inputPanel.panelSeparatorColor
|
||||
@ -520,7 +531,7 @@ final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
self.multiColorFieldNode.updateTheme(theme)
|
||||
}
|
||||
|
||||
func updateState(_ f: (WallpaperColorPanelNodeState) -> WallpaperColorPanelNodeState, updateLayout: Bool = true, animated: Bool = true) {
|
||||
public func updateState(_ f: (WallpaperColorPanelNodeState) -> WallpaperColorPanelNodeState, updateLayout: Bool = true, animated: Bool = true) {
|
||||
var updateLayout = updateLayout
|
||||
let previousColors = self.state.colors
|
||||
let previousPreview = self.state.preview
|
||||
@ -560,7 +571,7 @@ final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
public func updateLayout(size: CGSize, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, bottomInset)
|
||||
|
||||
let condensedLayout = size.width < 375.0
|
||||
@ -724,7 +735,7 @@ final class WallpaperColorPanelNode: ASDisplayNode {
|
||||
})
|
||||
}
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if let result = super.hitTest(point, with: event) {
|
||||
return result
|
||||
}
|
@ -266,50 +266,50 @@ private final class WallpaperColorBrightnessNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
struct HSBColor: Equatable {
|
||||
static func == (lhs: HSBColor, rhs: HSBColor) -> Bool {
|
||||
public struct HSBColor: Equatable {
|
||||
public static func == (lhs: HSBColor, rhs: HSBColor) -> Bool {
|
||||
return lhs.values.h == rhs.values.h && lhs.values.s == rhs.values.s && lhs.values.b == rhs.values.b
|
||||
}
|
||||
|
||||
let values: (h: CGFloat, s: CGFloat, b: CGFloat)
|
||||
let backingColor: UIColor
|
||||
public let values: (h: CGFloat, s: CGFloat, b: CGFloat)
|
||||
public let backingColor: UIColor
|
||||
|
||||
var hue: CGFloat {
|
||||
public var hue: CGFloat {
|
||||
return self.values.h
|
||||
}
|
||||
|
||||
var saturation: CGFloat {
|
||||
public var saturation: CGFloat {
|
||||
return self.values.s
|
||||
}
|
||||
|
||||
var brightness: CGFloat {
|
||||
public var brightness: CGFloat {
|
||||
return self.values.b
|
||||
}
|
||||
|
||||
var rgb: UInt32 {
|
||||
public var rgb: UInt32 {
|
||||
return self.color.argb
|
||||
}
|
||||
|
||||
init(values: (h: CGFloat, s: CGFloat, b: CGFloat)) {
|
||||
public init(values: (h: CGFloat, s: CGFloat, b: CGFloat)) {
|
||||
self.values = values
|
||||
self.backingColor = UIColor(hue: values.h, saturation: values.s, brightness: values.b, alpha: 1.0)
|
||||
}
|
||||
|
||||
init(hue: CGFloat, saturation: CGFloat, brightness: CGFloat) {
|
||||
public init(hue: CGFloat, saturation: CGFloat, brightness: CGFloat) {
|
||||
self.values = (h: hue, s: saturation, b: brightness)
|
||||
self.backingColor = UIColor(hue: self.values.h, saturation: self.values.s, brightness: self.values.b, alpha: 1.0)
|
||||
}
|
||||
|
||||
init(color: UIColor) {
|
||||
public init(color: UIColor) {
|
||||
self.values = color.hsb
|
||||
self.backingColor = color
|
||||
}
|
||||
|
||||
init(rgb: UInt32) {
|
||||
public init(rgb: UInt32) {
|
||||
self.init(color: UIColor(rgb: rgb))
|
||||
}
|
||||
|
||||
var color: UIColor {
|
||||
public var color: UIColor {
|
||||
return self.backingColor
|
||||
}
|
||||
}
|
@ -401,7 +401,7 @@ public class WallpaperGalleryController: ViewController {
|
||||
self.colorsPanelNode?.updateTheme(self.presentationData.theme)
|
||||
}
|
||||
|
||||
func dismiss(forceAway: Bool) {
|
||||
public func dismiss(forceAway: Bool) {
|
||||
// let completion: () -> Void = { [weak self] in
|
||||
// self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
// }
|
@ -1370,7 +1370,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
let editFrame = CGRect(origin: CGPoint(x: layout.size.width - 16.0 - 28.0 + offset.x - 46.0, y: 16.0), size: CGSize(width: 28.0, height: 28.0))
|
||||
|
||||
let centerOffset: CGFloat = 32.0
|
||||
|
||||
|
||||
if let entry = self.entry {
|
||||
switch entry {
|
||||
case .asset:
|
||||
@ -1451,6 +1451,11 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
if let mode = self.mode, case let .peer(peer, _) = mode, case .channel = peer {
|
||||
motionAlpha = 0.0
|
||||
blurFrame = centerButtonFrame
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.patternButtonNode, frame: patternFrame)
|
||||
transition.updateAlpha(node: self.patternButtonNode, alpha: patternAlpha * alpha)
|
||||
|
||||
@ -1487,13 +1492,29 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
|
||||
var items: [ListViewItem] = []
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1))
|
||||
var peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1))
|
||||
let otherPeerId = self.context.account.peerId
|
||||
var peers = SimpleDictionary<PeerId, Peer>()
|
||||
let messages = SimpleDictionary<MessageId, Message>()
|
||||
peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
|
||||
peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
|
||||
var messages = SimpleDictionary<MessageId, Message>()
|
||||
|
||||
let replyAuthor = self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName
|
||||
|
||||
var messageAuthor: Peer = TelegramUser(id: peerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_PreviewReplyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
|
||||
let otherAuthor = TelegramUser(id: otherPeerId, accessHash: nil, firstName: replyAuthor, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: .blue, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil)
|
||||
peers[otherPeerId] = otherAuthor
|
||||
|
||||
var messageAttributes: [MessageAttribute] = []
|
||||
if let mode = self.mode, case let .peer(peer, _) = mode, case .channel = peer {
|
||||
peerId = peer.id
|
||||
messageAuthor = peer._asPeer()
|
||||
|
||||
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
|
||||
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageAuthor, text: self.presentationData.strings.WallpaperPreview_ChannelReplyText, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
messageAttributes = [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)]
|
||||
}
|
||||
|
||||
peers[peerId] = messageAuthor
|
||||
|
||||
var topMessageText = ""
|
||||
var bottomMessageText = ""
|
||||
var serviceMessageText: String?
|
||||
@ -1566,10 +1587,16 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
}
|
||||
|
||||
if let mode = self.mode, case let .peer(peer, existing) = mode {
|
||||
topMessageText = presentationData.strings.WallpaperPreview_ChatTopText
|
||||
bottomMessageText = presentationData.strings.WallpaperPreview_ChatBottomText
|
||||
if !existing {
|
||||
serviceMessageText = presentationData.strings.WallpaperPreview_NotAppliedInfo(peer.compactDisplayTitle).string
|
||||
if case .channel = peer {
|
||||
topMessageText = presentationData.strings.WallpaperPreview_ChannelTopText
|
||||
bottomMessageText = ""
|
||||
serviceMessageText = presentationData.strings.WallpaperPreview_ChannelHeader
|
||||
} else {
|
||||
topMessageText = presentationData.strings.WallpaperPreview_ChatTopText
|
||||
bottomMessageText = presentationData.strings.WallpaperPreview_ChatBottomText
|
||||
if !existing {
|
||||
serviceMessageText = presentationData.strings.WallpaperPreview_NotAppliedInfo(peer.compactDisplayTitle).string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1579,10 +1606,13 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
let theme = self.presentationData.theme
|
||||
|
||||
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false))
|
||||
if !bottomMessageText.isEmpty {
|
||||
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false))
|
||||
}
|
||||
|
||||
|
||||
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: messageAttributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, accountPeer: nil, isCentered: false))
|
||||
|
||||
if let serviceMessageText {
|
@ -5,12 +5,12 @@ import Display
|
||||
import TelegramPresentationData
|
||||
import ManagedAnimationNode
|
||||
|
||||
enum WallpaperGalleryToolbarCancelButtonType {
|
||||
public enum WallpaperGalleryToolbarCancelButtonType {
|
||||
case cancel
|
||||
case discard
|
||||
}
|
||||
|
||||
enum WallpaperGalleryToolbarDoneButtonType {
|
||||
public enum WallpaperGalleryToolbarDoneButtonType {
|
||||
case set
|
||||
case setPeer(String, Bool)
|
||||
case setChannel
|
||||
@ -19,7 +19,7 @@ enum WallpaperGalleryToolbarDoneButtonType {
|
||||
case none
|
||||
}
|
||||
|
||||
protocol WallpaperGalleryToolbar: ASDisplayNode {
|
||||
public protocol WallpaperGalleryToolbar: ASDisplayNode {
|
||||
var cancelButtonType: WallpaperGalleryToolbarCancelButtonType { get set }
|
||||
var doneButtonType: WallpaperGalleryToolbarDoneButtonType { get set }
|
||||
|
||||
@ -31,7 +31,7 @@ protocol WallpaperGalleryToolbar: ASDisplayNode {
|
||||
func updateLayout(size: CGSize, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition)
|
||||
}
|
||||
|
||||
final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar {
|
||||
public final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar {
|
||||
class ButtonNode: ASDisplayNode {
|
||||
private let doneButton = HighlightTrackingButtonNode()
|
||||
private var doneButtonBackgroundNode: ASDisplayNode
|
||||
@ -205,18 +205,18 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar
|
||||
private var theme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
|
||||
var cancelButtonType: WallpaperGalleryToolbarCancelButtonType {
|
||||
public var cancelButtonType: WallpaperGalleryToolbarCancelButtonType {
|
||||
didSet {
|
||||
self.updateThemeAndStrings(theme: self.theme, strings: self.strings)
|
||||
}
|
||||
}
|
||||
var doneButtonType: WallpaperGalleryToolbarDoneButtonType {
|
||||
public var doneButtonType: WallpaperGalleryToolbarDoneButtonType {
|
||||
didSet {
|
||||
self.updateThemeAndStrings(theme: self.theme, strings: self.strings)
|
||||
}
|
||||
}
|
||||
|
||||
var dark: Bool = false {
|
||||
public var dark: Bool = false {
|
||||
didSet {
|
||||
self.applyButton.dark = self.dark
|
||||
self.applyForBothButton.dark = self.dark
|
||||
@ -226,10 +226,10 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar
|
||||
private let applyButton = ButtonNode()
|
||||
private let applyForBothButton = ButtonNode()
|
||||
|
||||
var cancel: (() -> Void)?
|
||||
var done: ((Bool) -> Void)?
|
||||
public var cancel: (() -> Void)?
|
||||
public var done: ((Bool) -> Void)?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, cancelButtonType: WallpaperGalleryToolbarCancelButtonType = .cancel, doneButtonType: WallpaperGalleryToolbarDoneButtonType = .set) {
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, cancelButtonType: WallpaperGalleryToolbarCancelButtonType = .cancel, doneButtonType: WallpaperGalleryToolbarDoneButtonType = .set) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.cancelButtonType = cancelButtonType
|
||||
@ -256,13 +256,13 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar
|
||||
}
|
||||
}
|
||||
|
||||
func setDoneEnabled(_ enabled: Bool) {
|
||||
public func setDoneEnabled(_ enabled: Bool) {
|
||||
self.applyButton.setEnabled(enabled)
|
||||
self.applyForBothButton.setEnabled(enabled)
|
||||
}
|
||||
|
||||
private var isSolid = false
|
||||
func setDoneIsSolid(_ isSolid: Bool, transition: ContainedViewLayoutTransition) {
|
||||
public func setDoneIsSolid(_ isSolid: Bool, transition: ContainedViewLayoutTransition) {
|
||||
guard self.isSolid != isSolid else {
|
||||
return
|
||||
}
|
||||
@ -272,7 +272,7 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar
|
||||
self.applyForBothButton.setIsSolid(isSolid, transition: transition)
|
||||
}
|
||||
|
||||
func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
public func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self.theme = theme
|
||||
|
||||
let applyTitle: String
|
||||
@ -303,7 +303,7 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar
|
||||
self.applyForBothButton.isLocked = applyForBothLocked
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
public func updateLayout(size: CGSize, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
let inset: CGFloat = 16.0
|
||||
let buttonHeight: CGFloat = 50.0
|
||||
|
||||
@ -329,16 +329,16 @@ final class WallpaperGalleryToolbarNode: ASDisplayNode, WallpaperGalleryToolbar
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperGalleryOldToolbarNode: ASDisplayNode, WallpaperGalleryToolbar {
|
||||
public final class WallpaperGalleryOldToolbarNode: ASDisplayNode, WallpaperGalleryToolbar {
|
||||
private var theme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
|
||||
var cancelButtonType: WallpaperGalleryToolbarCancelButtonType {
|
||||
public var cancelButtonType: WallpaperGalleryToolbarCancelButtonType {
|
||||
didSet {
|
||||
self.updateThemeAndStrings(theme: self.theme, strings: self.strings)
|
||||
}
|
||||
}
|
||||
var doneButtonType: WallpaperGalleryToolbarDoneButtonType {
|
||||
public var doneButtonType: WallpaperGalleryToolbarDoneButtonType {
|
||||
didSet {
|
||||
self.updateThemeAndStrings(theme: self.theme, strings: self.strings)
|
||||
}
|
||||
@ -352,10 +352,10 @@ final class WallpaperGalleryOldToolbarNode: ASDisplayNode, WallpaperGalleryToolb
|
||||
private let separatorNode = ASDisplayNode()
|
||||
private let topSeparatorNode = ASDisplayNode()
|
||||
|
||||
var cancel: (() -> Void)?
|
||||
var done: ((Bool) -> Void)?
|
||||
public var cancel: (() -> Void)?
|
||||
public var done: ((Bool) -> Void)?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, cancelButtonType: WallpaperGalleryToolbarCancelButtonType = .cancel, doneButtonType: WallpaperGalleryToolbarDoneButtonType = .set) {
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, cancelButtonType: WallpaperGalleryToolbarCancelButtonType = .cancel, doneButtonType: WallpaperGalleryToolbarDoneButtonType = .set) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.cancelButtonType = cancelButtonType
|
||||
@ -404,12 +404,12 @@ final class WallpaperGalleryOldToolbarNode: ASDisplayNode, WallpaperGalleryToolb
|
||||
self.doneButton.addTarget(self, action: #selector(self.donePressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
func setDoneEnabled(_ enabled: Bool) {
|
||||
public func setDoneEnabled(_ enabled: Bool) {
|
||||
self.doneButton.alpha = enabled ? 1.0 : 0.4
|
||||
self.doneButton.isUserInteractionEnabled = enabled
|
||||
}
|
||||
|
||||
func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
public func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self.theme = theme
|
||||
self.backgroundNode.updateColor(color: theme.rootController.tabBar.backgroundColor, transition: .immediate)
|
||||
self.separatorNode.backgroundColor = theme.rootController.tabBar.separatorColor
|
||||
@ -440,7 +440,7 @@ final class WallpaperGalleryOldToolbarNode: ASDisplayNode, WallpaperGalleryToolb
|
||||
self.doneButton.setTitle(doneTitle, with: Font.regular(17.0), with: theme.list.itemPrimaryTextColor, for: [])
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
public func updateLayout(size: CGSize, layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.cancelButton.frame = CGRect(origin: CGPoint(), size: CGSize(width: floor(size.width / 2.0), height: size.height))
|
||||
self.cancelHighlightBackgroundNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: floor(size.width / 2.0), height: size.height))
|
||||
self.doneButton.frame = CGRect(origin: CGPoint(x: floor(size.width / 2.0), y: 0.0), size: CGSize(width: size.width - floor(size.width / 2.0), height: size.height))
|
@ -6,7 +6,7 @@ import SwiftSignalKit
|
||||
import CheckNode
|
||||
import AnimationUI
|
||||
|
||||
enum WallpaperOptionButtonValue {
|
||||
public enum WallpaperOptionButtonValue {
|
||||
case check(Bool)
|
||||
case color(Bool, UIColor)
|
||||
case colors(Bool, [UIColor])
|
||||
@ -270,7 +270,7 @@ final class WallpaperNavigationButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
|
||||
|
||||
final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
public final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
let backgroundNode: WallpaperOptionBackgroundNode
|
||||
|
||||
private let checkNode: CheckNode
|
||||
@ -281,7 +281,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
private var textSize: CGSize?
|
||||
|
||||
private var _value: WallpaperOptionButtonValue
|
||||
override var isSelected: Bool {
|
||||
public override var isSelected: Bool {
|
||||
get {
|
||||
switch self._value {
|
||||
case let .check(selected), let .color(selected, _), let .colors(selected, _):
|
||||
@ -301,13 +301,13 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
}
|
||||
|
||||
var title: String {
|
||||
public var title: String {
|
||||
didSet {
|
||||
self.textNode.attributedText = NSAttributedString(string: title, font: Font.medium(13), textColor: .white)
|
||||
}
|
||||
}
|
||||
|
||||
init(title: String, value: WallpaperOptionButtonValue) {
|
||||
public init(title: String, value: WallpaperOptionButtonValue) {
|
||||
self._value = value
|
||||
self.title = title
|
||||
|
||||
@ -368,12 +368,12 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
}
|
||||
|
||||
var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||
public var buttonColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.3) {
|
||||
didSet {
|
||||
}
|
||||
}
|
||||
|
||||
var color: UIColor? {
|
||||
public var color: UIColor? {
|
||||
get {
|
||||
switch self._value {
|
||||
case let .color(_, color):
|
||||
@ -395,7 +395,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
}
|
||||
|
||||
var colors: [UIColor]? {
|
||||
public var colors: [UIColor]? {
|
||||
get {
|
||||
switch self._value {
|
||||
case let .colors(_, colors):
|
||||
@ -429,7 +429,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
}
|
||||
}
|
||||
|
||||
func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||
public func setSelected(_ selected: Bool, animated: Bool = false) {
|
||||
switch self._value {
|
||||
case .check:
|
||||
self._value = .check(selected)
|
||||
@ -441,7 +441,7 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
self.checkNode.setSelected(selected, animated: animated)
|
||||
}
|
||||
|
||||
func setEnabled(_ enabled: Bool) {
|
||||
public func setEnabled(_ enabled: Bool) {
|
||||
let alpha: CGFloat = enabled ? 1.0 : 0.4
|
||||
self.checkNode.alpha = alpha
|
||||
self.colorNode.alpha = alpha
|
||||
@ -449,13 +449,13 @@ final class WallpaperOptionButtonNode: HighlightTrackingButtonNode {
|
||||
self.isUserInteractionEnabled = enabled
|
||||
}
|
||||
|
||||
override func measure(_ constrainedSize: CGSize) -> CGSize {
|
||||
public override func measure(_ constrainedSize: CGSize) -> CGSize {
|
||||
let size = self.textNode.updateLayout(constrainedSize)
|
||||
self.textSize = size
|
||||
return CGSize(width: ceil(size.width) + 48.0, height: 30.0)
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
public override func layout() {
|
||||
super.layout()
|
||||
|
||||
self.backgroundNode.frame = self.bounds
|
@ -9,6 +9,7 @@ import LegacyComponents
|
||||
import AccountContext
|
||||
import MergeLists
|
||||
import Postbox
|
||||
import SettingsThemeWallpaperNode
|
||||
|
||||
private let itemSize = CGSize(width: 88.0, height: 88.0)
|
||||
private let inset: CGFloat = 12.0
|
||||
@ -172,24 +173,24 @@ private final class WallpaperPatternItemNode : ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
public final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
private let context: AccountContext
|
||||
private var theme: PresentationTheme
|
||||
|
||||
private let backgroundNode: NavigationBackgroundNode
|
||||
private let topSeparatorNode: ASDisplayNode
|
||||
|
||||
let scrollNode: ASScrollNode
|
||||
public let scrollNode: ASScrollNode
|
||||
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let labelNode: ImmediateTextNode
|
||||
private var sliderView: TGPhotoEditorSliderView?
|
||||
|
||||
private var disposable: Disposable?
|
||||
var wallpapers: [TelegramWallpaper] = []
|
||||
public var wallpapers: [TelegramWallpaper] = []
|
||||
private var currentWallpaper: TelegramWallpaper?
|
||||
|
||||
var serviceBackgroundColor: UIColor = UIColor(rgb: 0x748698) {
|
||||
public var serviceBackgroundColor: UIColor = UIColor(rgb: 0x748698) {
|
||||
didSet {
|
||||
guard let nodes = self.scrollNode.subnodes else {
|
||||
return
|
||||
@ -200,7 +201,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var backgroundColors: ([HSBColor], Int32?, Int32?)? = nil {
|
||||
public var backgroundColors: ([HSBColor], Int32?, Int32?)? = nil {
|
||||
didSet {
|
||||
var updated = false
|
||||
if oldValue?.0 != self.backgroundColors?.0 || oldValue?.1 != self.backgroundColors?.1 {
|
||||
@ -223,11 +224,11 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
|
||||
private var validLayout: (CGSize, CGFloat)?
|
||||
|
||||
var patternChanged: ((TelegramWallpaper?, Int32?, Bool) -> Void)?
|
||||
public var patternChanged: ((TelegramWallpaper?, Int32?, Bool) -> Void)?
|
||||
|
||||
private let allowDark: Bool
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
|
||||
public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.allowDark = theme.overallDarkAppearance
|
||||
@ -287,7 +288,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
self.disposable?.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
public override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.scrollNode.view.showsHorizontalScrollIndicator = false
|
||||
@ -320,7 +321,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
self.sliderView = sliderView
|
||||
}
|
||||
|
||||
func updateWallpapers() {
|
||||
public func updateWallpapers() {
|
||||
guard let subnodes = self.scrollNode.subnodes else {
|
||||
return
|
||||
}
|
||||
@ -386,7 +387,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
self.layoutItemNodes(transition: .immediate)
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
public func updateTheme(_ theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.backgroundNode.updateColor(color: self.theme.chat.inputPanel.panelBackgroundColor, transition: .immediate)
|
||||
@ -416,7 +417,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func didAppear(initialWallpaper: TelegramWallpaper? = nil, intensity: Int32? = nil) {
|
||||
public func didAppear(initialWallpaper: TelegramWallpaper? = nil, intensity: Int32? = nil) {
|
||||
let wallpaper: TelegramWallpaper?
|
||||
|
||||
if self.wallpapers.isEmpty {
|
||||
@ -482,7 +483,7 @@ final class WallpaperPatternPanelNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
public func updateLayout(size: CGSize, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, bottomInset)
|
||||
|
||||
let backgroundFrame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height + bottomInset)
|
@ -2578,119 +2578,123 @@ final class ShareWithPeersScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
let presentAlert: ([String]) -> Void = { usernames in
|
||||
let usernamesString = String(usernames.map { "@\($0)" }.joined(separator: ", "))
|
||||
let alertController = textAlertController(
|
||||
context: component.context,
|
||||
forceTheme: defaultDarkColorPresentationTheme,
|
||||
title: environment.strings.Story_Privacy_MentionRestrictedTitle,
|
||||
text: environment.strings.Story_Privacy_MentionRestrictedText(usernamesString).string,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: environment.strings.Story_Privacy_MentionRestrictedProceed, action: {
|
||||
proceed()
|
||||
}),
|
||||
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {})
|
||||
],
|
||||
actionLayout: .vertical
|
||||
)
|
||||
controller.present(alertController, in: .window(.root))
|
||||
}
|
||||
|
||||
func matchingUsername(user: TelegramUser, usernames: Set<String>) -> String? {
|
||||
for username in user.usernames {
|
||||
if usernames.contains(username.username) {
|
||||
return username.username
|
||||
}
|
||||
if let sendAsPeerId = self.sendAsPeerId, sendAsPeerId.isGroupOrChannel {
|
||||
proceed()
|
||||
} else {
|
||||
let presentAlert: ([String]) -> Void = { usernames in
|
||||
let usernamesString = String(usernames.map { "@\($0)" }.joined(separator: ", "))
|
||||
let alertController = textAlertController(
|
||||
context: component.context,
|
||||
forceTheme: defaultDarkColorPresentationTheme,
|
||||
title: environment.strings.Story_Privacy_MentionRestrictedTitle,
|
||||
text: environment.strings.Story_Privacy_MentionRestrictedText(usernamesString).string,
|
||||
actions: [
|
||||
TextAlertAction(type: .defaultAction, title: environment.strings.Story_Privacy_MentionRestrictedProceed, action: {
|
||||
proceed()
|
||||
}),
|
||||
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {})
|
||||
],
|
||||
actionLayout: .vertical
|
||||
)
|
||||
controller.present(alertController, in: .window(.root))
|
||||
}
|
||||
if let username = user.username {
|
||||
if usernames.contains(username) {
|
||||
return username
|
||||
|
||||
func matchingUsername(user: TelegramUser, usernames: Set<String>) -> String? {
|
||||
for username in user.usernames {
|
||||
if usernames.contains(username.username) {
|
||||
return username.username
|
||||
}
|
||||
}
|
||||
if let username = user.username {
|
||||
if usernames.contains(username) {
|
||||
return username
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
let context = component.context
|
||||
let selectedPeerIds = self.selectedPeers
|
||||
|
||||
if case .stories = component.stateContext.subject {
|
||||
if component.mentions.isEmpty {
|
||||
proceed()
|
||||
} else if case .nobody = base {
|
||||
if selectedPeerIds.isEmpty {
|
||||
presentAlert(component.mentions)
|
||||
} else {
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
var filteredMentions = Set(component.mentions)
|
||||
for peerId in selectedPeerIds {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let user = peer as? TelegramUser {
|
||||
if let username = matchingUsername(user: user, usernames: filteredMentions) {
|
||||
filteredMentions.remove(username)
|
||||
}
|
||||
} else {
|
||||
if let username = peer.addressName {
|
||||
filteredMentions.remove(username)
|
||||
|
||||
let context = component.context
|
||||
let selectedPeerIds = self.selectedPeers
|
||||
|
||||
if case .stories = component.stateContext.subject {
|
||||
if component.mentions.isEmpty {
|
||||
proceed()
|
||||
} else if case .nobody = base {
|
||||
if selectedPeerIds.isEmpty {
|
||||
presentAlert(component.mentions)
|
||||
} else {
|
||||
let _ = (context.account.postbox.transaction { transaction in
|
||||
var filteredMentions = Set(component.mentions)
|
||||
for peerId in selectedPeerIds {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let user = peer as? TelegramUser {
|
||||
if let username = matchingUsername(user: user, usernames: filteredMentions) {
|
||||
filteredMentions.remove(username)
|
||||
}
|
||||
} else {
|
||||
if let username = peer.addressName {
|
||||
filteredMentions.remove(username)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array(filteredMentions)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { mentions in
|
||||
if mentions.isEmpty {
|
||||
proceed()
|
||||
} else {
|
||||
presentAlert(mentions)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if case .contacts = base {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: false))
|
||||
|> map { contacts -> [String] in
|
||||
var filteredMentions = Set(component.mentions)
|
||||
let peers = contacts.peers
|
||||
for peer in peers {
|
||||
if selectedPeerIds.contains(peer.id) {
|
||||
continue
|
||||
}
|
||||
if case let .user(user) = peer, let username = matchingUsername(user: user, usernames: filteredMentions) {
|
||||
filteredMentions.remove(username)
|
||||
}
|
||||
}
|
||||
return Array(filteredMentions)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { mentions in
|
||||
|> deliverOnMainQueue).start(next: { mentions in
|
||||
if mentions.isEmpty {
|
||||
proceed()
|
||||
} else {
|
||||
presentAlert(mentions)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if case .contacts = base {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: false))
|
||||
|> map { contacts -> [String] in
|
||||
var filteredMentions = Set(component.mentions)
|
||||
let peers = contacts.peers
|
||||
for peer in peers {
|
||||
if selectedPeerIds.contains(peer.id) {
|
||||
continue
|
||||
} else if case .closeFriends = base {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: false))
|
||||
|> map { contacts -> [String] in
|
||||
var filteredMentions = Set(component.mentions)
|
||||
let peers = contacts.peers
|
||||
for peer in peers {
|
||||
if case let .user(user) = peer, user.flags.contains(.isCloseFriend), let username = matchingUsername(user: user, usernames: filteredMentions) {
|
||||
filteredMentions.remove(username)
|
||||
}
|
||||
}
|
||||
if case let .user(user) = peer, let username = matchingUsername(user: user, usernames: filteredMentions) {
|
||||
filteredMentions.remove(username)
|
||||
return Array(filteredMentions)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { mentions in
|
||||
if mentions.isEmpty {
|
||||
proceed()
|
||||
} else {
|
||||
presentAlert(mentions)
|
||||
}
|
||||
}
|
||||
return Array(filteredMentions)
|
||||
})
|
||||
} else {
|
||||
proceed()
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { mentions in
|
||||
if mentions.isEmpty {
|
||||
proceed()
|
||||
} else {
|
||||
presentAlert(mentions)
|
||||
}
|
||||
})
|
||||
} else if case .closeFriends = base {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: false))
|
||||
|> map { contacts -> [String] in
|
||||
var filteredMentions = Set(component.mentions)
|
||||
let peers = contacts.peers
|
||||
for peer in peers {
|
||||
if case let .user(user) = peer, user.flags.contains(.isCloseFriend), let username = matchingUsername(user: user, usernames: filteredMentions) {
|
||||
filteredMentions.remove(username)
|
||||
}
|
||||
}
|
||||
return Array(filteredMentions)
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { mentions in
|
||||
if mentions.isEmpty {
|
||||
proceed()
|
||||
} else {
|
||||
presentAlert(mentions)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
proceed()
|
||||
}
|
||||
} else {
|
||||
proceed()
|
||||
}
|
||||
}
|
||||
)),
|
||||
|
@ -96,6 +96,7 @@ public final class ForwardInfoPanelComponent: Component {
|
||||
iconView.alpha = 0.55
|
||||
iconView.tintColor = .white
|
||||
self.addSubview(iconView)
|
||||
self.iconView = iconView
|
||||
}
|
||||
if let image = iconView.image {
|
||||
iconView.frame = CGRect(origin: CGPoint(x: sideInset + UIScreenPixel, y: 5.0), size: image.size)
|
||||
|
@ -112,6 +112,10 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if case let .channelMessage(_, messageId) = mediaArea {
|
||||
if let peer = transaction.getPeer(messageId.peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -216,6 +220,17 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
guard let media = item.media else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var forwardInfo = item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) }
|
||||
if forwardInfo == nil {
|
||||
for mediaArea in item.mediaAreas {
|
||||
if case let .channelMessage(_, messageId) = mediaArea, let peer = peers[messageId.peerId] {
|
||||
forwardInfo = .known(peer: EnginePeer(peer), storyId: 0, isModified: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EngineStoryItem(
|
||||
id: item.id,
|
||||
timestamp: item.timestamp,
|
||||
@ -248,7 +263,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
||||
isEdited: item.isEdited,
|
||||
isMy: item.isMy,
|
||||
myReaction: item.myReaction,
|
||||
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) }
|
||||
forwardInfo: forwardInfo
|
||||
)
|
||||
}
|
||||
var totalCount = peerStoryItemsView.items.count
|
||||
@ -1131,6 +1146,10 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if case let .channelMessage(_, messageId) = mediaArea {
|
||||
if let peer = transaction.getPeer(messageId.peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1186,6 +1205,16 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
||||
}
|
||||
|
||||
if let item, case let .item(itemValue) = item, let media = itemValue.media {
|
||||
var forwardInfo = itemValue.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) }
|
||||
if forwardInfo == nil {
|
||||
for mediaArea in itemValue.mediaAreas {
|
||||
if case let .channelMessage(_, messageId) = mediaArea, let peer = peers[messageId.peerId] {
|
||||
forwardInfo = .known(peer: EnginePeer(peer), storyId: 0, isModified: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mappedItem = EngineStoryItem(
|
||||
id: itemValue.id,
|
||||
timestamp: itemValue.timestamp,
|
||||
@ -1218,7 +1247,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
|
||||
isEdited: itemValue.isEdited,
|
||||
isMy: itemValue.isMy,
|
||||
myReaction: itemValue.myReaction,
|
||||
forwardInfo: itemValue.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) }
|
||||
forwardInfo: forwardInfo
|
||||
)
|
||||
|
||||
let mainItem = StoryContentItem(
|
||||
@ -2073,13 +2102,22 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
|
||||
private var currentForwardInfoStories: [StoryId: Promise<EngineStoryItem?>] = [:]
|
||||
|
||||
init(context: AccountContext, peerId: EnginePeer.Id, focusedId initialFocusedId: Int32?, items: [EngineStoryItem]) {
|
||||
init(
|
||||
context: AccountContext,
|
||||
originalPeerId: EnginePeer.Id,
|
||||
originalStory: EngineStoryItem,
|
||||
peerId: EnginePeer.Id,
|
||||
focusedId initialFocusedId: Int32?,
|
||||
items: [EngineStoryItem]
|
||||
) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
|
||||
self.currentFocusedId = initialFocusedId
|
||||
self.currentFocusedIdUpdatedPromise.set(.single(Void()))
|
||||
|
||||
let originalStoryId = StoryId(peerId: originalPeerId, id: originalStory.id)
|
||||
|
||||
let inputKeys: [PostboxViewKey] = [
|
||||
PostboxViewKey.basicPeer(peerId),
|
||||
PostboxViewKey.cachedPeerData(peerId: peerId),
|
||||
@ -2098,53 +2136,43 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
var forwardInfoStories: [StoryId: EngineStoryItem?] = [:]
|
||||
var allEntityFiles: [MediaId: TelegramMediaFile] = [:]
|
||||
|
||||
if let itemsView = views.views[PostboxViewKey.storyItems(peerId: peerId)] as? StoryItemsView {
|
||||
for item in itemsView.items {
|
||||
if let item = item.value.get(Stories.StoredItem.self), case let .item(itemValue) = item {
|
||||
if let views = itemValue.views {
|
||||
for peerId in views.seenPeerIds {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
if let forwardInfo = itemValue.forwardInfo, case let .known(peerId, id, _) = forwardInfo {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
let storyId = StoryId(peerId: peerId, id: id)
|
||||
if let story = getCachedStory(storyId: storyId, transaction: transaction) {
|
||||
forwardInfoStories[storyId] = story
|
||||
} else {
|
||||
forwardInfoStories.updateValue(nil, forKey: storyId)
|
||||
}
|
||||
}
|
||||
for entity in itemValue.entities {
|
||||
if case let .CustomEmoji(_, fileId) = entity.type {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if allEntityFiles[mediaId] == nil {
|
||||
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
|
||||
allEntityFiles[file.fileId] = file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for mediaArea in itemValue.mediaAreas {
|
||||
if case let .reaction(_, reaction, _) = mediaArea {
|
||||
if case let .custom(fileId) = reaction {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if allEntityFiles[mediaId] == nil {
|
||||
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
|
||||
allEntityFiles[file.fileId] = file
|
||||
}
|
||||
}
|
||||
}
|
||||
for item in items {
|
||||
if let forwardInfo = item.forwardInfo, case let .known(peer, id, _) = forwardInfo {
|
||||
let storyId = StoryId(peerId: peer.id, id: id)
|
||||
if storyId == originalStoryId {
|
||||
forwardInfoStories[storyId] = originalStory
|
||||
} else {
|
||||
forwardInfoStories.updateValue(nil, forKey: storyId)
|
||||
}
|
||||
}
|
||||
for entity in item.entities {
|
||||
if case let .CustomEmoji(_, fileId) = entity.type {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if allEntityFiles[mediaId] == nil {
|
||||
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
|
||||
allEntityFiles[file.fileId] = file
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for mediaArea in item.mediaAreas {
|
||||
if case let .reaction(_, reaction, _) = mediaArea {
|
||||
if case let .custom(fileId) = reaction {
|
||||
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
|
||||
if allEntityFiles[mediaId] == nil {
|
||||
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
|
||||
allEntityFiles[file.fileId] = file
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if case let .channelMessage(_, messageId) = mediaArea {
|
||||
if let peer = transaction.getPeer(messageId.peerId) {
|
||||
peers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (views, peers, globalNotificationSettings, allEntityFiles, forwardInfoStories)
|
||||
}
|
||||
}
|
||||
@ -2163,7 +2191,6 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
if let presencesView = views.views[PostboxViewKey.peerPresences(peerIds: Set([peerId]))] as? PeerPresencesView {
|
||||
peerPresence = presencesView.presences[peerId]
|
||||
}
|
||||
|
||||
for (storyId, story) in forwardInfoStories {
|
||||
let promise: Promise<EngineStoryItem?>
|
||||
var added = false
|
||||
@ -2174,7 +2201,9 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
self.currentForwardInfoStories[storyId] = promise
|
||||
added = true
|
||||
}
|
||||
if let story {
|
||||
if storyId == originalStoryId {
|
||||
promise.set(.single(originalStory))
|
||||
} else if let story {
|
||||
promise.set(.single(story))
|
||||
} else if added {
|
||||
promise.set(self.context.engine.messages.getStory(peerId: storyId.peerId, id: storyId.id))
|
||||
@ -2274,7 +2303,6 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
|
||||
let mappedFocusedIndex = mappedItems.firstIndex(where: { $0.id == mappedItems[focusedIndex].id })
|
||||
|
||||
|
||||
do {
|
||||
let mappedItem = mappedItems[focusedIndex]
|
||||
|
||||
@ -2416,6 +2444,8 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let originalPeerId: EnginePeer.Id
|
||||
private let originalStory: EngineStoryItem
|
||||
private let viewListContext: EngineStoryViewListContext
|
||||
private let readGlobally: Bool
|
||||
|
||||
@ -2449,11 +2479,15 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
originalPeerId: EnginePeer.Id,
|
||||
originalStory: EngineStoryItem,
|
||||
focusedStoryId: StoryId,
|
||||
viewListContext: EngineStoryViewListContext,
|
||||
readGlobally: Bool
|
||||
) {
|
||||
self.context = context
|
||||
self.originalPeerId = originalPeerId
|
||||
self.originalStory = originalStory
|
||||
self.focusedItem = (focusedStoryId.peerId, focusedStoryId.id)
|
||||
self.viewListContext = viewListContext
|
||||
self.readGlobally = readGlobally
|
||||
@ -2530,7 +2564,7 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: currentStoryItems[centralIndex].peer.id) {
|
||||
centralPeerContext = existingContext
|
||||
} else {
|
||||
centralPeerContext = PeerContext(context: self.context, peerId: currentStoryItems[centralIndex].peer.id, focusedId: nil, items: [currentStoryItems[centralIndex].story])
|
||||
centralPeerContext = PeerContext(context: self.context, originalPeerId: self.originalPeerId, originalStory: self.originalStory, peerId: currentStoryItems[centralIndex].peer.id, focusedId: nil, items: [currentStoryItems[centralIndex].story])
|
||||
}
|
||||
|
||||
var previousPeerContext: PeerContext?
|
||||
@ -2538,7 +2572,7 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: currentStoryItems[centralIndex - 1].peer.id) {
|
||||
previousPeerContext = existingContext
|
||||
} else {
|
||||
previousPeerContext = PeerContext(context: self.context, peerId: currentStoryItems[centralIndex - 1].peer.id, focusedId: nil, items: [currentStoryItems[centralIndex - 1].story])
|
||||
previousPeerContext = PeerContext(context: self.context, originalPeerId: self.originalPeerId, originalStory: self.originalStory, peerId: currentStoryItems[centralIndex - 1].peer.id, focusedId: nil, items: [currentStoryItems[centralIndex - 1].story])
|
||||
}
|
||||
}
|
||||
|
||||
@ -2547,7 +2581,7 @@ public final class RepostStoriesContentContextImpl: StoryContentContext {
|
||||
if let currentState = self.currentState, let existingContext = currentState.findPeerContext(id: currentStoryItems[centralIndex + 1].peer.id) {
|
||||
nextPeerContext = existingContext
|
||||
} else {
|
||||
nextPeerContext = PeerContext(context: self.context, peerId: currentStoryItems[centralIndex + 1].peer.id, focusedId: nil, items: [currentStoryItems[centralIndex + 1].story])
|
||||
nextPeerContext = PeerContext(context: self.context, originalPeerId: self.originalPeerId, originalStory: self.originalStory, peerId: currentStoryItems[centralIndex + 1].peer.id, focusedId: nil, items: [currentStoryItems[centralIndex + 1].story])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ final class StoryContentCaptionComponent: Component {
|
||||
let longTapAction: (Action) -> Void
|
||||
let textSelectionAction: (NSAttributedString, TextSelectionAction) -> Void
|
||||
let controller: () -> ViewController?
|
||||
let openStory: (EnginePeer, EngineStoryItem) -> Void
|
||||
let openStory: (EnginePeer, EngineStoryItem?) -> Void
|
||||
|
||||
init(
|
||||
externalState: ExternalState,
|
||||
@ -85,7 +85,7 @@ final class StoryContentCaptionComponent: Component {
|
||||
longTapAction: @escaping (Action) -> Void,
|
||||
textSelectionAction: @escaping (NSAttributedString, TextSelectionAction) -> Void,
|
||||
controller: @escaping () -> ViewController?,
|
||||
openStory: @escaping (EnginePeer, EngineStoryItem) -> Void
|
||||
openStory: @escaping (EnginePeer, EngineStoryItem?) -> Void
|
||||
) {
|
||||
self.externalState = externalState
|
||||
self.context = context
|
||||
@ -692,9 +692,9 @@ final class StoryContentCaptionComponent: Component {
|
||||
}
|
||||
}
|
||||
})
|
||||
text = nil
|
||||
text = ""
|
||||
} else {
|
||||
text = nil
|
||||
text = ""
|
||||
}
|
||||
case let .unknown(name, _):
|
||||
authorName = name
|
||||
@ -727,8 +727,8 @@ final class StoryContentCaptionComponent: Component {
|
||||
effectAlignment: .center,
|
||||
minSize: nil,
|
||||
action: { [weak self] in
|
||||
if let self, case let .known(peer, _, _) = forwardInfo, let story = self.forwardInfoStory {
|
||||
self.component?.openStory(peer, story)
|
||||
if let self, case let .known(peer, _, _) = forwardInfo {
|
||||
self.component?.openStory(peer, self.forwardInfoStory)
|
||||
} else if let controller = self?.component?.controller() as? StoryContainerScreen {
|
||||
let tooltipController = TooltipController(content: .text(component.strings.Story_ForwardAuthorHiddenTooltip), baseFontSize: 17.0, isBlurred: true, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
|
||||
controller.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: { [weak self, weak controller] in
|
||||
|
@ -4246,46 +4246,55 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
let context = component.context
|
||||
let peerId = component.slice.peer.id
|
||||
let currentResult: ResolvedUrl = .story(peerId: peerId, id: component.slice.item.storyItem.id)
|
||||
|
||||
self.sendMessageContext.openResolved(view: self, result: .story(peerId: peer.id, id: story.id), completion: { [weak self] in
|
||||
guard let self, let controller = self.component?.controller() as? StoryContainerScreen else {
|
||||
return
|
||||
}
|
||||
if let nextController = controller.navigationController?.viewControllers.last as? StoryContainerScreen {
|
||||
nextController.customBackAction = { [weak nextController] in
|
||||
context.sharedContext.openResolvedUrl(
|
||||
currentResult,
|
||||
context: context,
|
||||
urlContext: .generic,
|
||||
navigationController: nextController?.navigationController as? NavigationController,
|
||||
forceExternal: false,
|
||||
openPeer: { _, _ in
|
||||
},
|
||||
sendFile: nil,
|
||||
sendSticker: nil,
|
||||
requestMessageActionUrlAuth: nil,
|
||||
joinVoiceChat: nil,
|
||||
present: { _, _ in
|
||||
},
|
||||
dismissInput: {
|
||||
},
|
||||
contentContext: nil,
|
||||
progress: nil,
|
||||
completion: { [weak nextController] in
|
||||
Queue.mainQueue().after(0.5) {
|
||||
nextController?.dismissWithoutTransitionOut()
|
||||
if let story {
|
||||
let context = component.context
|
||||
let peerId = component.slice.peer.id
|
||||
let currentResult: ResolvedUrl = .story(peerId: peerId, id: component.slice.item.storyItem.id)
|
||||
|
||||
self.sendMessageContext.openResolved(view: self, result: .story(peerId: peer.id, id: story.id), completion: { [weak self] in
|
||||
guard let self, let controller = self.component?.controller() as? StoryContainerScreen else {
|
||||
return
|
||||
}
|
||||
if let nextController = controller.navigationController?.viewControllers.last as? StoryContainerScreen {
|
||||
nextController.customBackAction = { [weak nextController] in
|
||||
context.sharedContext.openResolvedUrl(
|
||||
currentResult,
|
||||
context: context,
|
||||
urlContext: .generic,
|
||||
navigationController: nextController?.navigationController as? NavigationController,
|
||||
forceExternal: false,
|
||||
openPeer: { _, _ in
|
||||
},
|
||||
sendFile: nil,
|
||||
sendSticker: nil,
|
||||
requestMessageActionUrlAuth: nil,
|
||||
joinVoiceChat: nil,
|
||||
present: { _, _ in
|
||||
},
|
||||
dismissInput: {
|
||||
},
|
||||
contentContext: nil,
|
||||
progress: nil,
|
||||
completion: { [weak nextController] in
|
||||
Queue.mainQueue().after(0.5) {
|
||||
nextController?.dismissWithoutTransitionOut()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
Queue.mainQueue().after(0.5) {
|
||||
controller.dismissWithoutTransitionOut()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
for mediaArea in component.slice.item.storyItem.mediaAreas {
|
||||
if case .channelMessage = mediaArea {
|
||||
self.sendMessageContext.activateMediaArea(view: self, mediaArea: mediaArea, immediate: true)
|
||||
break
|
||||
}
|
||||
}
|
||||
Queue.mainQueue().after(0.5) {
|
||||
controller.dismissWithoutTransitionOut()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
@ -5196,7 +5205,7 @@ public final class StoryItemSetContainerComponent: Component {
|
||||
}
|
||||
|
||||
let context = component.context
|
||||
let storyContent = RepostStoriesContentContextImpl(context: context, focusedStoryId: StoryId(peerId: peer.id, id: id), viewListContext: viewListContext, readGlobally: false)
|
||||
let storyContent = RepostStoriesContentContextImpl(context: context, originalPeerId: component.slice.peer.id, originalStory: component.slice.item.storyItem, focusedStoryId: StoryId(peerId: peer.id, id: id), viewListContext: viewListContext, readGlobally: false)
|
||||
let _ = (storyContent.state
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak controller, weak viewListView, weak sourceView] _ in
|
||||
|
@ -3264,8 +3264,8 @@ final class StoryItemSetContainerSendMessage {
|
||||
controller.push(sheet)
|
||||
})
|
||||
}
|
||||
|
||||
func activateMediaArea(view: StoryItemSetContainerComponent.View, mediaArea: MediaArea) {
|
||||
|
||||
func activateMediaArea(view: StoryItemSetContainerComponent.View, mediaArea: MediaArea, immediate: Bool = false) {
|
||||
guard let component = view.component, let controller = component.controller() else {
|
||||
return
|
||||
}
|
||||
@ -3278,8 +3278,8 @@ final class StoryItemSetContainerSendMessage {
|
||||
var actions: [ContextMenuAction] = []
|
||||
switch mediaArea {
|
||||
case let .venue(_, venue):
|
||||
let subject = EngineMessage(stableId: 0, stableVersion: 0, id: EngineMessage.Id(peerId: PeerId(0), namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [.geo(TelegramMediaMap(latitude: venue.latitude, longitude: venue.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue.venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))], peers: [:], associatedMessages: [:], associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
actions.append(ContextMenuAction(content: .textWithIcon(title: updatedPresentationData.initial.strings.Story_ViewLocation, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: { [weak controller, weak view] in
|
||||
let action = { [weak controller, weak view] in
|
||||
let subject = EngineMessage(stableId: 0, stableVersion: 0, id: EngineMessage.Id(peerId: PeerId(0), namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [.geo(TelegramMediaMap(latitude: venue.latitude, longitude: venue.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: venue.venue, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil))], peers: [:], associatedMessages: [:], associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let locationController = LocationViewController(
|
||||
context: context,
|
||||
updatedPresentationData: updatedPresentationData,
|
||||
@ -3302,9 +3302,16 @@ final class StoryItemSetContainerSendMessage {
|
||||
})
|
||||
}
|
||||
controller?.push(locationController)
|
||||
}
|
||||
if immediate {
|
||||
action()
|
||||
return
|
||||
}
|
||||
actions.append(ContextMenuAction(content: .textWithIcon(title: updatedPresentationData.initial.strings.Story_ViewLocation, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: {
|
||||
action()
|
||||
}))
|
||||
case let .channelMessage(_, messageId):
|
||||
actions.append(ContextMenuAction(content: .textWithIcon(title: updatedPresentationData.initial.strings.Story_ViewMessage, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: {
|
||||
let action = { [weak self, weak view] in
|
||||
let _ = ((context.engine.messages.getMessagesLoadIfNecessary([messageId], strategy: .local)
|
||||
|> mapToSignal { result -> Signal<Message?, NoError> in
|
||||
if case let .result(messages) = result {
|
||||
@ -3312,12 +3319,21 @@ final class StoryItemSetContainerSendMessage {
|
||||
}
|
||||
return .single(nil)
|
||||
})
|
||||
|> deliverOnMainQueue).startStandalone(next: { message in
|
||||
guard let message else {
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak view] message in
|
||||
guard let self, let view else {
|
||||
return
|
||||
}
|
||||
context.sharedContext.navigateToChat(accountId: context.account.id, peerId: message.id.peerId, messageId: message.id)
|
||||
if let message, let peer = message.peers[message.id.peerId] {
|
||||
self.openResolved(view: view, result: .channelMessage(peer: peer, messageId: message.id, timecode: nil))
|
||||
}
|
||||
})
|
||||
}
|
||||
if immediate {
|
||||
action()
|
||||
return
|
||||
}
|
||||
actions.append(ContextMenuAction(content: .textWithIcon(title: updatedPresentationData.initial.strings.Story_ViewMessage, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: {
|
||||
action()
|
||||
}))
|
||||
case .reaction:
|
||||
return
|
||||
|
@ -518,7 +518,7 @@ final class StoryItemSetViewListComponent: Component {
|
||||
)).string
|
||||
|
||||
if let story = item.story, !story.text.isEmpty {
|
||||
dateText += " • commented"
|
||||
dateText += component.strings.Story_Views_Commented
|
||||
}
|
||||
|
||||
let subtitleAccessory: PeerListItemComponent.SubtitleAccessory
|
||||
|
@ -118,6 +118,7 @@ import WebsiteType
|
||||
import ChatQrCodeScreen
|
||||
import PeerInfoScreen
|
||||
import MediaEditorScreen
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
public enum ChatControllerPeekActions {
|
||||
case standard
|
||||
@ -18780,10 +18781,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let context = self.context
|
||||
let subject: Signal<MediaEditorScreen.Subject?, NoError> = .single(.message(messages.map { $0.id }))
|
||||
|
||||
let initialCaption: NSAttributedString? = nil
|
||||
let initialPrivacy: EngineStoryPrivacy? = nil
|
||||
let initialMediaAreas: [MediaArea] = []
|
||||
|
||||
let externalState = MediaEditorTransitionOutExternalState(
|
||||
storyTarget: nil,
|
||||
isPeerArchived: false,
|
||||
@ -18793,28 +18790,43 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
let controller = MediaEditorScreen(
|
||||
context: context,
|
||||
subject: subject,
|
||||
isEditing: false,
|
||||
forwardSource: nil,
|
||||
initialCaption: initialCaption,
|
||||
initialPrivacy: initialPrivacy,
|
||||
initialMediaAreas: initialMediaAreas,
|
||||
initialVideoPosition: nil,
|
||||
transitionIn: nil,
|
||||
transitionOut: { _, _ in
|
||||
return nil
|
||||
},
|
||||
completion: { result, commit in
|
||||
completion: { [weak self] result, commit in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let targetPeerId: EnginePeer.Id
|
||||
let target: Stories.PendingTarget
|
||||
if let sendAsPeerId = result.options.sendAsPeerId {
|
||||
target = .peer(sendAsPeerId)
|
||||
targetPeerId = sendAsPeerId
|
||||
} else {
|
||||
target = .myStories
|
||||
targetPeerId = self.context.account.peerId
|
||||
}
|
||||
externalState.storyTarget = target
|
||||
|
||||
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||
rootController.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit)
|
||||
}
|
||||
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: targetPeerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
guard let self, let peer else {
|
||||
return
|
||||
}
|
||||
let text: String
|
||||
if case .channel = peer {
|
||||
text = self.presentationData.strings.Story_MessageReposted_Channel(peer.compactDisplayTitle).string
|
||||
} else {
|
||||
text = self.presentationData.strings.Story_MessageReposted_Personal
|
||||
}
|
||||
self.present(UndoOverlayController(presentationData: self.presentationData, content: .succeed(text: text, timeout: nil, customUndoText: nil), elevatedLayout: false, action: { _ in return false }), in: .current)
|
||||
})
|
||||
|
||||
}
|
||||
)
|
||||
self.push(controller)
|
||||
|
@ -19,6 +19,7 @@ import CameraScreen
|
||||
import MediaEditorScreen
|
||||
import ChatControllerInteraction
|
||||
import SavedMessagesScreen
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParams) {
|
||||
if case let .peer(peer) = params.chatLocation {
|
||||
|
@ -23,6 +23,7 @@ import UndoUI
|
||||
import WebsiteType
|
||||
import GalleryData
|
||||
import StoryContainerScreen
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
||||
var story: TelegramMediaStory?
|
||||
|
@ -31,6 +31,7 @@ import PremiumUI
|
||||
import AuthorizationUI
|
||||
import ChatFolderLinkPreviewScreen
|
||||
import StoryContainerScreen
|
||||
import WallpaperGalleryScreen
|
||||
|
||||
private func defaultNavigationForPeerId(_ peerId: PeerId?, navigation: ChatControllerInteractionNavigateToPeer) -> ChatControllerInteractionNavigateToPeer {
|
||||
if case .default = navigation {
|
||||
|
Loading…
x
Reference in New Issue
Block a user