Update Ghostgram features

This commit is contained in:
ichmagmaus 812
2026-03-07 18:15:32 +01:00
parent 1a3303b059
commit 24a7ec39d9
902 changed files with 148295 additions and 62348 deletions
@@ -1,3 +1,6 @@
import SGSimpleSettings
import SGIAP
import SGStatus
import Foundation
import UIKit
import AsyncDisplayKit
@@ -185,16 +188,6 @@ public enum WallpaperUrlParameter {
case gradient([UInt32], Int32?)
}
public enum ResolvedUrlSettingsSection {
case theme
case devices
case autoremoveMessages
case twoStepAuth
case enableLog
case phonePrivacy
case loginEmail
}
public struct ResolvedBotChoosePeerTypes: OptionSet {
public var rawValue: UInt32
@@ -315,19 +308,17 @@ public enum ResolvedUrl {
case share(url: String?, text: String?, to: String?)
case wallpaper(WallpaperUrlParameter)
case theme(String)
case settings(ResolvedUrlSettingsSection)
case joinVoiceChat(PeerId, String?)
case importStickers
case startAttach(peerId: PeerId, payload: String?, choose: ResolvedBotChoosePeerTypes?)
case invoice(slug: String, invoice: TelegramMediaInvoice?)
case premiumOffer(reference: String?)
case starsTopup(amount: Int64, purpose: String?)
case starsTopup(amount: Int64?, purpose: String?)
case chatFolder(slug: String)
case story(peerId: PeerId, id: Int32)
case boost(peerId: PeerId?, status: ChannelBoostStatus?, myBoostStatus: MyBoostStatus?)
case premiumGiftCode(slug: String)
case premiumMultiGift(reference: String?)
case collectible(gift: StarGift.UniqueGift?)
case auction(auction: GiftAuctionContext?)
case messageLink(link: TelegramResolvedMessageLink?)
case stars
@@ -336,6 +327,60 @@ public enum ResolvedUrl {
case storyFolder(peerId: PeerId, id: Int64)
case giftCollection(peerId: PeerId, id: Int64)
case sendGift(peerId: PeerId?)
case unknownDeepLink(path: String)
case oauth(url: String)
public enum ResolvedCollectible {
case gift(StarGift.UniqueGift)
case invalidSlug
case alreadyBurned
}
case collectible(ResolvedCollectible)
public enum ChatsSection {
case search
case edit
case emojiStatus
}
case chats(ChatsSection?)
public enum ComposeSection {
case group
case channel
case contact
}
case compose(ComposeSection?)
public enum PostStorySection {
case photo
case video
case live
}
case postStory(PostStorySection?)
public enum ContactsSection {
case search
case sort
case new
case invite
case manage
}
case contacts(ContactsSection?)
public enum SettingsSection {
public enum Legacy {
case theme
case devices
case autoremoveMessages
case enableLog
case phonePrivacy
case loginEmail
}
case legacy(Legacy)
case path(String)
}
case settings(SettingsSection)
}
public enum ResolveUrlResult {
@@ -696,6 +741,11 @@ public enum DeviceContactInfoSubject {
}
public enum PeerInfoControllerMode {
public enum PeerInfoMediaKind {
case photoVideo
case file
}
case generic
case calls(messages: [Message])
case nearbyPeer(distance: Int32)
@@ -711,6 +761,7 @@ public enum PeerInfoControllerMode {
case monoforum(EnginePeer.Id)
case storyAlbum(id: Int64)
case giftCollection(id: Int64)
case media(kind: PeerInfoMediaKind, messageIndex: EngineMessage.Index)
}
public enum ContactListActionItemInlineIconPosition {
@@ -972,18 +1023,32 @@ public protocol MediaEditorScreenResult {
var target: Stories.PendingTarget { get }
}
public enum StoryCameraMode {
case photo
case video
case live
}
public protocol TelegramRootControllerInterface: NavigationController {
var accountSettingsController: PeerInfoScreen? { get set }
@discardableResult
func openStoryCamera(customTarget: Stories.PendingTarget?, resumeLiveStream: Bool, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator?
func openStoryCamera(mode: StoryCameraMode, customTarget: Stories.PendingTarget?, resumeLiveStream: Bool, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator?
func proceedWithStoryUpload(target: Stories.PendingTarget, results: [MediaEditorScreenResult], existingMedia: EngineMedia?, forwardInfo: Stories.PendingForwardInfo?, externalState: MediaEditorTransitionOutExternalState, commit: @escaping (@escaping () -> Void) -> Void)
func getContactsController() -> ViewController?
func getChatsController() -> ViewController?
func getSettingsController() -> ViewController?
func getPrivacySettings() -> Promise<AccountPrivacySettings?>?
func openSettings()
func getTwoStepAuthData() -> Promise<TwoStepAuthData?>?
func openContacts()
func openSettings(edit: Bool)
func openBirthdaySetup()
func openPhotoSetup(completedWithUploadingImage: @escaping (UIImage, Signal<PeerInfoAvatarUploadStatus, NoError>) -> UIView?)
func openAvatars()
func startNewCall()
}
public protocol QuickReplySetupScreenInitialData: AnyObject {
@@ -1185,6 +1250,7 @@ public enum ChannelMembersSearchControllerMode {
case promote
case ban
case inviteToCall
case ownershipTransfer
}
public enum ChannelMembersSearchFilter {
@@ -1241,10 +1307,18 @@ public protocol SharedAccountContext: AnyObject {
var automaticMediaDownloadSettings: Signal<MediaAutoDownloadSettings, NoError> { get }
var currentAutodownloadSettings: Atomic<AutodownloadSettings> { get }
var immediateExperimentalUISettings: ExperimentalUISettings { get }
// MARK: Swiftgram
var immediateSGStatus: SGStatus { get }
var SGIAP: SGIAPManager? { get }
func makeSGProController(context: AccountContext) -> ViewController
func makeSGPayWallController(context: AccountContext) -> ViewController?
func makeSGUpdateIOSController() -> ViewController
var currentInAppNotificationSettings: Atomic<InAppNotificationSettings> { get }
var currentMediaInputSettings: Atomic<MediaInputSettings> { get }
var currentStickerSettings: Atomic<StickerSettings> { get }
var currentMediaDisplaySettings: Atomic<MediaDisplaySettings> { get }
var currentChatSettings: Atomic<ChatSettings> { get }
var energyUsageSettings: EnergyUsageSettings { get }
@@ -1404,14 +1478,15 @@ public protocol SharedAccountContext: AnyObject {
func makeGiftViewScreen(context: AccountContext, message: EngineMessage, shareStory: ((StarGift.UniqueGift) -> Void)?) -> ViewController
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: ((StarGift.UniqueGift) -> Void)?, openChatTheme: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift, attributes: [StarGift.UniqueGift.Attribute]?) -> ViewController
func makeGiftUpgradePreviewScreen(context: AccountContext, attributes: [StarGift.UniqueGift.Attribute], peerName: String) -> ViewController
func makeGiftUpgradePreviewScreen(context: AccountContext, gift: StarGift.Gift, attributes: [StarGift.UniqueGift.Attribute], peerName: String) -> ViewController
func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController
func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?) -> ViewController
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, peerId: EnginePeer.Id?, completion: @escaping (Signal<[GiftAuctionAcquiredGift], NoError>, [StarGift.UniqueGift.Attribute]?) -> Void) -> ViewController
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
func makeGiftOfferScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, gift: StarGift.UniqueGift, peer: EnginePeer, amount: CurrencyAmount, commit: @escaping () -> Void) -> ViewController
func makeGiftUpgradeVariantsScreen(context: AccountContext, gift: StarGift, attributes: [StarGift.UniqueGift.Attribute], selectedAttributes: [StarGift.UniqueGift.Attribute]?, focusedAttribute: StarGift.UniqueGift.Attribute?) -> ViewController
func makeGiftUpgradeVariantsScreen(context: AccountContext, gift: StarGift, crafted: Bool, attributes: [StarGift.UniqueGift.Attribute], selectedAttributes: [StarGift.UniqueGift.Attribute]?, focusedAttribute: StarGift.UniqueGift.Attribute?) -> ViewController
func makeGiftAuctionWearPreviewScreen(context: AccountContext, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?, attributes: [StarGift.UniqueGift.Attribute], completion: @escaping () -> Void) -> ViewController
func makeGiftCraftScreen(context: AccountContext, gift: StarGift.UniqueGift, profileGiftsContext: ProfileGiftsContext?) -> ViewController
func makeGiftDemoScreen(context: AccountContext) -> ViewController
func makeStorySharingScreen(context: AccountContext, subject: StorySharingSubject, parentController: ViewController) -> ViewController
func makeContentReportScreen(context: AccountContext, subject: ReportContentSubject, forceDark: Bool, present: @escaping (ViewController) -> Void, completion: @escaping () -> Void, requestSelectMessages: ((String, Data, String?) -> Void)?)
@@ -1526,6 +1601,7 @@ public protocol AccountContext: AnyObject {
var downloadedMediaStoreManager: DownloadedMediaStoreManager { get }
var peerChannelMemberCategoriesContextsManager: PeerChannelMemberCategoriesContextsManager { get }
var wallpaperUploadManager: WallpaperUploadManager? { get }
var watchManager: WatchManager? { get }
var inAppPurchaseManager: InAppPurchaseManager? { get }
var starsContext: StarsContext? { get }
var tonContext: StarsContext? { get }
@@ -55,6 +55,7 @@ public final class ChatMessageItemAssociatedData: Equatable {
public let accountPeer: EnginePeer?
public let topicAuthorId: EnginePeer.Id?
public let hasBots: Bool
public let translationSettings: TranslationSettings?
public let translateToLanguage: String?
public let maxReadStoryId: Int32?
public let recommendedChannels: RecommendedChannels?
@@ -91,6 +92,7 @@ public final class ChatMessageItemAssociatedData: Equatable {
alwaysDisplayTranscribeButton: DisplayTranscribeButton = DisplayTranscribeButton(canBeDisplayed: false, displayForNotConsumed: false, providedByGroupBoost: false),
topicAuthorId: EnginePeer.Id? = nil,
hasBots: Bool = false,
translationSettings: TranslationSettings? = nil,
translateToLanguage: String? = nil,
maxReadStoryId: Int32? = nil,
recommendedChannels: RecommendedChannels? = nil,
@@ -126,6 +128,7 @@ public final class ChatMessageItemAssociatedData: Equatable {
self.topicAuthorId = topicAuthorId
self.alwaysDisplayTranscribeButton = alwaysDisplayTranscribeButton
self.hasBots = hasBots
self.translationSettings = translationSettings
self.translateToLanguage = translateToLanguage
self.maxReadStoryId = maxReadStoryId
self.recommendedChannels = recommendedChannels
@@ -202,6 +205,9 @@ public final class ChatMessageItemAssociatedData: Equatable {
if lhs.hasBots != rhs.hasBots {
return false
}
if lhs.translationSettings != rhs.translationSettings {
return false
}
if lhs.translateToLanguage != rhs.translateToLanguage {
return false
}
@@ -237,6 +243,10 @@ public final class ChatMessageItemAssociatedData: Equatable {
}
public extension ChatMessageItemAssociatedData {
var translateToLanguageSG: String? {
return self.translateToLanguage
}
var isInPinnedListMode: Bool {
if case .pinnedMessages = self.subject {
return true
@@ -976,7 +986,9 @@ public enum PeerInfoAvatarUploadStatus {
public protocol PeerInfoScreen: ViewController {
var peerId: PeerId { get }
var privacySettings: Promise<AccountPrivacySettings?> { get }
var twoStepAuthData: Promise<TwoStepAuthData?> { get }
func activateEdit()
func openBirthdaySetup()
func toggleStorySelection(ids: [Int32], isSelected: Bool)
func togglePaneIsReordering(isReordering: Bool)
@@ -1093,6 +1105,12 @@ public protocol ChatController: ViewController {
func restrictedSendingContentsText() -> String
}
public extension ChatController {
var overlayTitle: String? {
return self.title
}
}
public protocol ChatMessagePreviewItemNode: AnyObject {
var forwardInfoReferenceNode: ASDisplayNode? { get }
}
@@ -1,3 +1,4 @@
import SGSimpleSettings
import Foundation
import UIKit
import TelegramCore
@@ -7,16 +8,16 @@ private extension PeerNameColors.Colors {
if colors.colors.isEmpty {
return nil
}
self.main = UIColor(rgb: colors.colors[0])
self._main = UIColor(rgb: colors.colors[0])
if colors.colors.count > 1 {
self.secondary = UIColor(rgb: colors.colors[1])
self._secondary = UIColor(rgb: colors.colors[1])
} else {
self.secondary = nil
self._secondary = nil
}
if colors.colors.count > 2 {
self.tertiary = UIColor(rgb: colors.colors[2])
self._tertiary = UIColor(rgb: colors.colors[2])
} else {
self.tertiary = nil
self._tertiary = nil
}
}
}
@@ -29,39 +30,67 @@ public class PeerNameColors: Equatable {
}
public struct Colors: Equatable {
public let main: UIColor
public let secondary: UIColor?
public let tertiary: UIColor?
private let _main: UIColor
private let _secondary: UIColor?
private let _tertiary: UIColor?
// MARK: Swiftgram
public var main: UIColor {
let currentSaturation = SGSimpleSettings.shared.accountColorsSaturation
if currentSaturation == 0 {
return _main
} else {
return _main.withReducedSaturation(CGFloat(currentSaturation) / 100.0)
}
}
public var secondary: UIColor? {
let currentSaturation = SGSimpleSettings.shared.accountColorsSaturation
if currentSaturation == 0 {
return _secondary
} else {
return _secondary?.withReducedSaturation(CGFloat(currentSaturation) / 100.0)
}
}
public var tertiary: UIColor? {
let currentSaturation = SGSimpleSettings.shared.accountColorsSaturation
if currentSaturation == 0 {
return _tertiary
} else {
return _tertiary?.withReducedSaturation(CGFloat(currentSaturation) / 100.0)
}
}
public init(main: UIColor, secondary: UIColor?, tertiary: UIColor?) {
self.main = main
self.secondary = secondary
self.tertiary = tertiary
self._main = main
self._secondary = secondary
self._tertiary = tertiary
}
public init(main: UIColor) {
self.main = main
self.secondary = nil
self.tertiary = nil
self._main = main
self._secondary = nil
self._tertiary = nil
}
public init?(colors: [UIColor]) {
guard let first = colors.first else {
return nil
}
self.main = first
self._main = first
if colors.count == 3 {
self.secondary = colors[1]
self.tertiary = colors[2]
self._secondary = colors[1]
self._tertiary = colors[2]
} else if colors.count == 2, let second = colors.last {
self.secondary = second
self.tertiary = nil
self._secondary = second
self._tertiary = nil
} else {
self.secondary = nil
self.tertiary = nil
self._secondary = nil
self._tertiary = nil
}
}
}
public static var defaultSingleColors: [Int32: Colors] {
return [
@@ -361,3 +390,20 @@ public extension PeerCollectibleColor {
}
}
}
// MARK: Swiftgram
extension UIColor {
func withReducedSaturation(_ factor: CGFloat) -> UIColor {
var hue: CGFloat = 0
var saturation: CGFloat = 0
var brightness: CGFloat = 0
var alpha: CGFloat = 0
if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
let newSaturation = max(0, min(1, saturation * factor))
return UIColor(hue: hue, saturation: newSaturation, brightness: brightness, alpha: alpha)
}
return self
}
}
@@ -62,6 +62,7 @@ public final class PeerSelectionControllerParams {
public let multipleSelection: Bool
public let multipleSelectionLimit: Int32?
public let forwardedMessageIds: [EngineMessage.Id]
public let initialForwardOptionsState: ChatInterfaceForwardOptionsState?
public let hasTypeHeaders: Bool
public let selectForumThreads: Bool
public let hasCreation: Bool
@@ -84,6 +85,7 @@ public final class PeerSelectionControllerParams {
multipleSelection: Bool = false,
multipleSelectionLimit: Int32? = nil,
forwardedMessageIds: [EngineMessage.Id] = [],
initialForwardOptionsState: ChatInterfaceForwardOptionsState? = nil,
hasTypeHeaders: Bool = false,
selectForumThreads: Bool = false,
hasCreation: Bool = false,
@@ -105,6 +107,7 @@ public final class PeerSelectionControllerParams {
self.multipleSelection = multipleSelection
self.multipleSelectionLimit = multipleSelectionLimit
self.forwardedMessageIds = forwardedMessageIds
self.initialForwardOptionsState = initialForwardOptionsState
self.hasTypeHeaders = hasTypeHeaders
self.selectForumThreads = selectForumThreads
self.hasCreation = hasCreation
@@ -0,0 +1,23 @@
import Foundation
import SwiftSignalKit
import TelegramCore
public struct WatchRunningTasks: Equatable {
public let running: Bool
public let version: Int32
public init(running: Bool, version: Int32) {
self.running = running
self.version = version
}
public static func ==(lhs: WatchRunningTasks, rhs: WatchRunningTasks) -> Bool {
return lhs.running == rhs.running && lhs.version == rhs.version
}
}
public protocol WatchManager: AnyObject {
var watchAppInstalled: Signal<Bool, NoError> { get }
var navigateToMessageRequested: Signal<EngineMessage.Id, NoError> { get }
var runningTasks: Signal<WatchRunningTasks?, NoError> { get }
}