Files
GLEGram-iOS/docs/LOCAL_PREMIUM_GUIDE.md
Leeksov 4647310322 GLEGram 12.5 — Initial public release
Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
2026-04-06 09:48:12 +03:00

45 KiB
Raw Permalink Blame History

Local Premium (Emulate Premium) - Полная документация реализации

📋 Описание

Local Premium — это функция, которая эмулирует Premium подписку Telegram локально на устройстве без реальной подписки.

Важно: Все функции работают только на стороне клиента и видны только вам. Сервер Telegram не видит эти изменения.


🎯 Реализованная функциональность

Основные функции

  1. Premium Badge - Показывает значок Premium рядом с вашим именем везде в приложении
  2. Безлимитные закрепленные чаты - Закрепляйте сколько угодно чатов (вместо лимита 5)
  3. Безлимитные папки - Создавайте сколько угодно папок (вместо лимита 10)
  4. Безлимитные чаты в папке - Добавляйте сколько угодно чатов в папку (вместо лимита 100)
  5. Безлимитные теги в Избранном - Добавляйте теги к сообщениям в Saved Messages
  6. Переупорядочивание папок - Перемещайте любую папку на первую позицию (включая "Все чаты")

Отключение серверной синхронизации

  • Закрепленные чаты: Сервер не будет откреплять чаты при превышении лимита
  • Папки: Сервер не будет удалять папки при превышении лимита
  • Чаты в папках: Сервер не будет удалять чаты из папок при превышении лимита
  • Порядок папок: Сервер не будет изменять порядок папок
  • Теги в Избранном: Сервер не будет синхронизировать теги

Расположение настроек

Settings → IAppsGram → Local Premium:

  • Один переключатель "Emulate Premium"
  • Подробное описание всех включенных функций
  • Предупреждение о клиентской природе функций

🏗️ Архитектура решения

Ключевая инновация: Модификация Peer.isPremium

Главное архитектурное решение - модификация свойства Peer.isPremium в PeerUtils.swift:

var isPremium: Bool {
    switch self {
    case let user as TelegramUser:
        // MARK: Swiftgram Local Premium - Override isPremium for current user
        if user.id.id._internalGetInt64Value() == SGLocalPremium.shared.currentAccountPeerId?.id && 
           user.id.namespace._internalGetInt32Value() == SGLocalPremium.shared.currentAccountPeerId?.namespace {
            return user.flags.contains(.isPremium) || SGLocalPremium.shared.showPremiumBadge
        }
        return user.flags.contains(.isPremium)
    default:
        return false
    }
}

Почему это работает:

  • Peer.isPremium используется везде в приложении для проверки Premium статуса
  • Модификация в одном месте автоматически работает во всех UI компонентах
  • Premium Badge отображается везде автоматически
  • Не исчезает после обновлений с сервера (сервер возвращает isPremium = false, но наша проверка добавляет || SGLocalPremium.shared.showPremiumBadge)

📦 Модуль SGLocalPremium

Файл: Telegram-iOS/Swiftgram/SGLocalPremium/Sources/SGLocalPremium.swift

Полный код класса

import Foundation
import SwiftSignalKit

public class SGLocalPremium {
    public static let shared = SGLocalPremium()
    
    private var currentAccountId: String?
    public var currentAccountPeerId: (id: Int64, namespace: Int32)?
    
    private init() {}
    
    // MARK: - Account Configuration
    
    public func setAccountPeerId(_ peerId: Int64, namespace: Int32) {
        self.currentAccountId = "\(namespace)_\(peerId)"
        self.currentAccountPeerId = (id: peerId, namespace: namespace)
    }
    
    private func accountKey(_ key: String) -> String {
        guard let accountId = currentAccountId else {
            return key
        }
        return "\(key)_\(accountId)"
    }
    
    // MARK: - Main Setting (Per-Account)
    
    public var emulatePremium: Bool {
        get {
            return UserDefaults.standard.bool(forKey: accountKey("localPremiumEmulate"))
        }
        set {
            UserDefaults.standard.set(newValue, forKey: accountKey("localPremiumEmulate"))
            UserDefaults.standard.synchronize()
        }
    }
    
    // MARK: - Computed Properties
    
    public var showPremiumBadge: Bool { return emulatePremium }
    public var unlimitedPinnedChats: Bool { return emulatePremium }
    public var unlimitedFolders: Bool { return emulatePremium }
    public var unlimitedChatsPerFolder: Bool { return emulatePremium }
    public var unlimitedSavedMessageTags: Bool { return emulatePremium }
    public var allowFolderReordering: Bool { return emulatePremium }
    public var shouldDisableServerSync: Bool { return emulatePremium }
}

Ключевые особенности:

  • Singleton pattern: SGLocalPremium.shared для глобального доступа
  • Per-account настройки: Каждый аккаунт имеет свои настройки через accountKey()
  • Одна главная настройка: emulatePremium контролирует все функции
  • Computed properties: Все функции возвращают значение emulatePremium
  • currentAccountPeerId: Хранит ID текущего аккаунта для проверки в Peer.isPremium

🔗 Точки интеграции

1. Инициализация аккаунта

Файл: Telegram-iOS/submodules/TelegramUI/Sources/AccountContext.swift

// MARK: Swiftgram Local Premium - Set current account
SGLocalPremium.shared.setAccountPeerId(
    account.peerId.id._internalGetInt64Value(),
    namespace: account.peerId.namespace._internalGetInt32Value()
)

Назначение: Устанавливает текущий аккаунт для per-account настроек и для проверки в Peer.isPremium.


2. Premium Badge - Ключевая модификация

Файл: Telegram-iOS/submodules/TelegramCore/Sources/Utils/PeerUtils.swift

var isPremium: Bool {
    switch self {
    case let user as TelegramUser:
        // MARK: Swiftgram Local Premium - Override isPremium for current user
        if user.id.id._internalGetInt64Value() == SGLocalPremium.shared.currentAccountPeerId?.id && 
           user.id.namespace._internalGetInt32Value() == SGLocalPremium.shared.currentAccountPeerId?.namespace {
            return user.flags.contains(.isPremium) || SGLocalPremium.shared.showPremiumBadge
        }
        return user.flags.contains(.isPremium)
    default:
        return false
    }
}

Почему это критически важно:

  • Это единственное место, где нужно добавить проверку для Premium Badge
  • Все UI компоненты используют peer.isPremium для проверки
  • Badge автоматически отображается везде:
    • PeerInfoScreen - профиль пользователя
    • PeerInfoHeaderNode - заголовок профиля
    • ChatListItem - список чатов
    • ChatTitleView - заголовок чата
    • ChatTitleComponent - заголовок чата (компонент)
    • ItemListAvatarAndNameItem - элемент списка с аватаром
    • ContactsPeerItem - элемент контакта
    • CallListCallItem - элемент списка звонков
    • VoiceChatParticipantItem - участник голосового чата
    • ReactionListContextMenuContent - контекстное меню реакций
  • Badge не исчезает после обновлений с сервера (сервер возвращает isPremium = false, но проверка || SGLocalPremium.shared.showPremiumBadge сохраняет его)

3. Лимиты закрепленных чатов

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift

public var maxPinnedChatCount: Int32 {
    // MARK: Swiftgram Local Premium - Unlimited pinned chats
    return SGLocalPremium.shared.getMaxPinnedChatCount(
        self.isPremium ? self.defaultMaxPremiumPinnedChatCount : self.defaultMaxPinnedChatCount
    )
}

Метод в SGLocalPremium:

public func getMaxPinnedChatCount(_ original: Int32) -> Int32 {
    if unlimitedPinnedChats {
        return Int32.max // Практически безлимит
    }
    return original
}

Назначение: Возвращает Int32.max если emulatePremium = true, иначе оригинальный лимит (5 для обычных, 10 для Premium).


4. Лимиты папок

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift

public var maxFoldersCount: Int32 {
    // MARK: Swiftgram Local Premium - Unlimited folders
    return SGLocalPremium.shared.getMaxFoldersCount(
        self.isPremium ? self.defaultMaxPremiumFoldersCount : self.defaultMaxFoldersCount
    )
}

Назначение: Возвращает Int32.max если emulatePremium = true, иначе оригинальный лимит (10 для обычных, 20 для Premium).


5. Лимиты чатов в папке

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift

public var maxFolderChatsCount: Int32 {
    // MARK: Swiftgram Local Premium - Unlimited chats per folder
    return SGLocalPremium.shared.getMaxFolderChatsCount(
        self.isPremium ? self.defaultMaxPremiumFolderChatsCount : self.defaultMaxFolderChatsCount
    )
}

Назначение: Возвращает Int32.max если emulatePremium = true, иначе оригинальный лимит (100 для обычных, 200 для Premium).


6. Отключение синхронизации закрепленных чатов

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/ManagedSynchronizePinnedChatsOperations.swift

func synchronizePinnedChats(
    transaction: Transaction,
    accountPeerId: PeerId
) -> Signal<Void, NoError> {
    // MARK: Swiftgram Local Premium - Skip server sync if emulate premium is enabled
    if SGLocalPremium.shared.shouldDisableServerSync {
        return .complete()
    }
    
    // ... оригинальный код синхронизации
}

Назначение:

  • Предотвращает отправку закрепленных чатов на сервер
  • Сервер не будет откреплять чаты при превышении лимита
  • Локальные изменения остаются только на устройстве

Что это дает:

  • Можно закрепить больше 5 чатов (для обычных пользователей)
  • Чаты не будут автоматически откреплены сервером
  • Закрепленные чаты сохраняются между перезапусками

7. Отключение синхронизации папок

Файл: Telegram-iOS/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift

public func _internal_synchronizeChatListFilters(
    postbox: Postbox,
    network: Network,
    stateManager: AccountStateManager,
    ignoreRemoteUpdates: Bool = false
) -> Signal<Void, NoError> {
    // MARK: Swiftgram Local Premium - Skip server sync if emulate premium is enabled
    if SGLocalPremium.shared.shouldDisableServerSync {
        return .complete()
    }
    
    // ... оригинальный код синхронизации
}

Назначение:

  • Предотвращает отправку папок на сервер
  • Сервер не будет удалять папки при превышении лимита
  • Сервер не будет удалять чаты из папок при превышении лимита

Что это дает:

  • Можно создать больше 10 папок (для обычных пользователей)
  • Можно добавить больше 100 чатов в папку
  • Папки и чаты не будут автоматически удалены сервером

8. Отключение синхронизации порядка папок

Файл: Telegram-iOS/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift

func _internal_requestUpdateChatListFilterOrder(
    account: Account, 
    ids: [Int32]
) -> Signal<Never, RequestUpdateChatListFilterOrderError> {
    // MARK: Swiftgram Local Premium - Skip server sync if emulate premium is enabled
    if SGLocalPremium.shared.shouldDisableServerSync {
        return .complete()
    }
    
    return account.network.request(Api.functions.messages.updateDialogFiltersOrder(order: ids))
    |> mapError { _ -> RequestUpdateChatListFilterOrderError in
        return .generic
    }
    |> mapToSignal { _ -> Signal<Never, RequestUpdateChatListFilterOrderError> in
        return .complete()
    }
}

Назначение:

  • Предотвращает отправку порядка папок на сервер
  • Сервер не будет изменять порядок папок
  • Можно переместить любую папку на первую позицию (включая "Все чаты")

Что это дает:

  • Можно переместить любую папку на первую позицию
  • Папка "Все чаты" может быть не первой
  • Порядок папок сохраняется между перезапусками

9. Переупорядочивание папок - UI компонент

Файл: Telegram-iOS/submodules/TelegramUI/Components/HorizontalTabsComponent/Sources/HorizontalTabsComponent.swift

public final class HorizontalTabsComponent: Component {
    public let canReorderAllChats: Bool
    
    public init(
        // ... другие параметры
        canReorderAllChats: Bool = true
    ) {
        self.canReorderAllChats = canReorderAllChats
        // ...
    }
}

Проверка возможности переупорядочивания:

// MARK: Swiftgram Local Premium - Check if user can reorder all chats
if !self.canReorderAllChats, let reorderedItemIds = self.reorderedItemIds {
    if let firstReorderedId = reorderedItemIds.first,
       let firstOriginalTab = component.tabs.first,
       firstReorderedId != firstOriginalTab.id {
        self.reorderedItemIds = self.initialReorderedItemIds
    }
}

Файл: Telegram-iOS/submodules/ChatListUI/Sources/ChatListControllerNode.swift

let tabsComponent = HorizontalTabsComponent(
    // ... другие параметры
    canReorderAllChats: SGLocalPremium.shared.canReorderAllChats(isPremium: self.context.isPremium)
)

Метод в SGLocalPremium:

public func canReorderAllChats(isPremium: Bool) -> Bool {
    if isPremium {
        return true
    }
    return allowFolderReordering
}

🎨 UI компоненты

Контроллер настроек IAppsGram

Файл: Telegram-iOS/Swiftgram/IAppsGramSettings/Sources/IAppsGramSettingsController.swift

Секция Local Premium в UI

// MARK: - Local Premium Section
case localPremiumHeader(PresentationTheme, String)
case localPremiumEmulate(PresentationTheme, String, Bool)
case localPremiumInfo(PresentationTheme, String)

Генерация UI элементов

// Local Premium Section
entries.append(.localPremiumHeader(presentationData.theme, "LOCAL PREMIUM"))
entries.append(.localPremiumEmulate(
    presentationData.theme,
    "Emulate Premium",
    SGLocalPremium.shared.emulatePremium
))
entries.append(.localPremiumInfo(
    presentationData.theme,
    "Enables all Premium features locally:\n• Premium badge next to your name\n• Unlimited pinned chats\n• Unlimited folders\n• Unlimited chats per folder\n• Unlimited saved message tags\n• Folder reordering\n• Disables server sync validation\n\n⚠️ Warning: These features are client-side only and visible only to you. Server may reject some changes."
))

Обработчик переключателя

let arguments = IAppsGramSettingsControllerArguments(
    context: context,
    // ... другие обработчики
    toggleLocalPremiumEmulate: { value in
        SGLocalPremium.shared.emulatePremium = value
    }
)

Особенности UI:

  • Один переключатель для всех функций
  • Подробное описание всех включенных функций
  • Предупреждение о клиентской природе
  • Простой и понятный интерфейс
  • Настройки сохраняются автоматически в UserDefaults

🏷️ Saved Message Tags (Теги в Избранном)

Описание функции

Saved Message Tags — это функция, позволяющая добавлять теги (реакции) к сообщениям в "Избранном" для их организации и быстрого поиска. В оригинальном Telegram это Premium-функция.

Точки интеграции

1. UI Premium-проверки (4 файла)

Добавлена проверка !SGLocalPremium.shared.unlimitedSavedMessageTags во все места проверки Premium для тегов:

Файл Назначение
ChatControllerOpenMessageReactionContextMenu.swift Меню выбора тега (реакции)
ChatController.swift Основная Premium-проверка для тегов
ChatControllerOpenMessageContextMenu.swift Контекстное меню сообщения
ChatSearchTitleAccessoryPanelNode.swift Панель поиска по тегам

Пример изменения:

// Было:
if !hasPremium {
    showPremiumPaywall()
}

// Стало:
if !hasPremium && !SGLocalPremium.shared.unlimitedSavedMessageTags {
    showPremiumPaywall()
}

2. Локальное сохранение тегов

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/MessageReactions.swift

// MARK: Swiftgram - Skip server sync for tags in Saved Messages when Local Premium is active
if isTags && SGLocalPremium.shared.shouldDisableServerSync {
    return postbox.transaction { transaction -> Void in
        // 1. Отменяем pending action (не отправляем на сервер)
        transaction.setPendingMessageAction(type: .updateReaction, id: messageId, action: nil)
        
        // 2. Объединяем pending и существующие реакции
        let mergedReactions = mergedMessageReactions(attributes: currentMessage.attributes, isTags: true)
        
        // 3. Обновляем сообщение с постоянными ReactionsMessageAttribute
        transaction.updateMessage(messageId, update: { currentMessage in
            // ... обновление атрибутов сообщения
            return .update(StoreMessage(...))
        })
        
        // 4. Postbox автоматически индексирует customTags
        // 5. Обновляем SavedMessageTags для UI
    }
}

Ключевой момент: Postbox автоматически индексирует теги при вызове updateMessage.

3. Отключение серверной синхронизации тегов

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/SavedMessageTags.swift

// MARK: Swiftgram - Skip server sync for tags when Local Premium is active
if SGLocalPremium.shared.shouldDisableServerSync {
    return .complete()  // Не делаем polling с сервером
}

4. Bypass синхронизации при изменении тегов

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/ManagedConsumePersonalMessagesActions.swift

// MARK: Swiftgram - When Local Premium is active, skip server sync but mark as cached
if SGLocalPremium.shared.shouldDisableServerSync {
    return postbox.transaction { transaction -> Void in
        // Помечаем теги как закэшированные, чтобы UI их показывал
        transaction.setPreferencesEntry(
            key: PreferencesKeys.didCacheSavedMessageTags(threadId: threadId), 
            value: PreferencesEntry(data: Data())
        )
    }
    |> ignoreValues
}

5. Bypass заполнения "holes" для фильтрации (КЛЮЧЕВОЙ!)

Файл: Telegram-iOS/submodules/TelegramCore/Sources/State/Holes.swift

// MARK: Swiftgram - Skip server requests for customTag holes when Local Premium is active
if case .customTag = space {
    switch peerInput {
    case let .direct(peerId, _):
        if peerId == accountPeerId && SGLocalPremium.shared.shouldDisableServerSync {
            return postbox.transaction { transaction -> FetchMessageHistoryHoleResult? in
                // Помечаем hole как заполненный
                transaction.removeHole(peerId: peerId, threadId: nil, namespace: namespace, space: space, range: minMaxRange)
                
                // Возвращаем пустой результат - система использует локальные данные
                return FetchMessageHistoryHoleResult(
                    removedIndices: IndexSet(integersIn: Int(minMaxRange.lowerBound) ... Int(minMaxRange.upperBound)),
                    strictRemovedIndices: IndexSet(),
                    actualPeerId: peerId,
                    actualThreadId: nil,
                    ids: []
                )
            }
        }
    }
}

Почему это критически важно:

  • Без этого bypass система ожидает ответ от сервера на запрос messages.search с фильтром по тегу
  • Сервер либо не отвечает, либо возвращает ошибку Premium
  • Результат: бесконечная загрузка
  • С bypass: система сразу использует локально проиндексированные сообщения

📝 BUILD конфигурация

Добавление зависимости SGLocalPremium

Для каждого модуля, который использует SGLocalPremium, нужно добавить зависимость в BUILD файл:

deps = [
    "//Swiftgram/SGLocalPremium:SGLocalPremium",
    # ... другие зависимости
]

Список модулей с добавленной зависимостью

  1. TelegramCore - для PeerUtils.swift, UserLimitsConfiguration.swift, MessageReactions.swift, SavedMessageTags.swift, Holes.swift
  2. TelegramUI - для AccountContext.swift, ChatController.swift, ChatControllerLoadDisplayNode.swift, ChatControllerContentData.swift
  3. ChatTitleView - для ChatTitleComponent.swift
  4. PeerInfoScreen - для PeerInfoHeaderNode.swift, PeerInfoScreen.swift
  5. ItemListAvatarAndNameInfoItem - для ItemListAvatarAndNameItem.swift
  6. ContactsPeerItem - для ContactsPeerItem.swift
  7. CallListUI - для CallListCallItem.swift
  8. TelegramCallsUI - для VoiceChatParticipantItem.swift
  9. ReactionListContextMenuContent - для ReactionListContextMenuContent.swift
  10. ChatListUI - для ChatListItem.swift, ChatListControllerNode.swift
  11. HorizontalTabsComponent - для HorizontalTabsComponent.swift
  12. IAppsGramSettings - для IAppsGramSettingsController.swift

Импорт модуля

В каждом файле, использующем SGLocalPremium, добавлен импорт:

import SGLocalPremium

🔍 Критические детали реализации

1. Per-Account настройки

Настройки хранятся отдельно для каждого аккаунта:

// Установка текущего аккаунта
SGLocalPremium.shared.setAccountPeerId(peerId, namespace: namespace)

// Ключ в UserDefaults
"localPremiumEmulate_<namespace>_<peerId>"

Преимущества:

  • Настройки не сбрасываются при перезапуске
  • Каждый аккаунт имеет независимые настройки
  • Простое переключение между аккаунтами

2. Одна настройка для всех функций

Вместо отдельных переключателей используется одна настройка emulatePremium:

public var emulatePremium: Bool // Главная настройка

// Все функции - computed properties
public var showPremiumBadge: Bool { return emulatePremium }
public var unlimitedPinnedChats: Bool { return emulatePremium }
public var unlimitedFolders: Bool { return emulatePremium }
public var unlimitedChatsPerFolder: Bool { return emulatePremium }
public var unlimitedSavedMessageTags: Bool { return emulatePremium }
public var allowFolderReordering: Bool { return emulatePremium }

Преимущества:

  • Простой и понятный UI
  • Все функции включаются одновременно
  • Меньше путаницы для пользователей

3. Отключение серверной синхронизации

Ключевая особенность - отключение синхронизации с сервером:

public var shouldDisableServerSync: Bool {
    return emulatePremium
}

Что отключается:

  1. Синхронизация закрепленных чатов - сервер не откреплит чаты
  2. Синхронизация папок - сервер не удалит папки
  3. Синхронизация чатов в папках - сервер не удалит чаты из папок
  4. Синхронизация порядка папок - сервер не изменит порядок папок
  5. Синхронизация тегов - сервер не будет синхронизировать теги

Как это работает:

  • Функции синхронизации проверяют shouldDisableServerSync
  • Если true, функция возвращает .complete() без выполнения
  • Локальные изменения остаются только на устройстве

4. Переопределение лимитов

Лимиты переопределяются через методы в SGLocalPremium:

public func getMaxPinnedChatCount(_ original: Int32) -> Int32 {
    if unlimitedPinnedChats {
        return Int32.max // Безлимит
    }
    return original // Оригинальный лимит
}

Стратегия:

  • Если emulatePremium = true, возвращается Int32.max
  • Если emulatePremium = false, возвращается оригинальный лимит
  • Применяется ко всем типам лимитов

5. Premium Badge - Ключевое архитектурное решение

Premium значок работает через модификацию Peer.isPremium:

var isPremium: Bool {
    switch self {
    case let user as TelegramUser:
        // Проверяем, является ли это текущим пользователем
        if user.id.id._internalGetInt64Value() == SGLocalPremium.shared.currentAccountPeerId?.id && 
           user.id.namespace._internalGetInt32Value() == SGLocalPremium.shared.currentAccountPeerId?.namespace {
            // Возвращаем true если реальный Premium ИЛИ Local Premium включен
            return user.flags.contains(.isPremium) || SGLocalPremium.shared.showPremiumBadge
        }
        return user.flags.contains(.isPremium)
    default:
        return false
    }
}

Проверки:

  1. Является ли пользователь текущим аккаунтом?
  2. Есть ли реальный Premium (user.flags.contains(.isPremium))?
  3. Включен ли Local Premium (SGLocalPremium.shared.showPremiumBadge)?

Результат:

  • Значок показывается только рядом с вашим именем
  • Другие пользователи не видят значок
  • Значок виден только на вашем устройстве
  • Не исчезает после обновлений с сервера (сервер возвращает isPremium = false, но проверка || SGLocalPremium.shared.showPremiumBadge сохраняет его)

📊 Полный список измененных файлов

Основной модуль

  1. Telegram-iOS/Swiftgram/SGLocalPremium/Sources/SGLocalPremium.swift - Главный менеджер

Core изменения

  1. Telegram-iOS/submodules/TelegramCore/Sources/Utils/PeerUtils.swift - КЛЮЧЕВОЙ - Модификация Peer.isPremium
  2. Telegram-iOS/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift - Лимиты (3 места)
  3. Telegram-iOS/submodules/TelegramCore/Sources/State/ManagedSynchronizePinnedChatsOperations.swift - Bypass синхронизации закрепленных чатов
  4. Telegram-iOS/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChatListFiltering.swift - Bypass синхронизации папок (2 места)
  5. Telegram-iOS/submodules/TelegramCore/Sources/State/MessageReactions.swift - Локальное сохранение тегов
  6. Telegram-iOS/submodules/TelegramCore/Sources/State/SavedMessageTags.swift - Bypass синхронизации тегов (2 места)
  7. Telegram-iOS/submodules/TelegramCore/Sources/State/ManagedConsumePersonalMessagesActions.swift - Bypass с маркером кэширования
  8. Telegram-iOS/submodules/TelegramCore/Sources/State/Holes.swift - КЛЮЧЕВОЙ - Bypass заполнения holes для тегов

UI изменения

  1. Telegram-iOS/submodules/TelegramUI/Sources/AccountContext.swift - Инициализация аккаунта
  2. Telegram-iOS/submodules/TelegramUI/Sources/ChatController.swift - Premium-проверка для тегов
  3. Telegram-iOS/submodules/TelegramUI/Sources/ChatControllerLoadDisplayNode.swift - Bypass закрытия панели фильтрации
  4. Telegram-iOS/submodules/TelegramUI/Sources/ChatControllerContentData.swift - Bypass hasSearchTags (2 места)
  5. Telegram-iOS/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift - Premium-проверка
  6. Telegram-iOS/submodules/TelegramUI/Sources/ChatControllerOpenMessageContextMenu.swift - Premium-проверка
  7. Telegram-iOS/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift - Premium-проверка (4 места)

UI компоненты (продолжение)

  1. Telegram-iOS/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleComponent.swift - Premium Badge в заголовке чата
  2. Telegram-iOS/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift - Premium Badge в заголовке профиля
  3. Telegram-iOS/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift - Premium Badge в профиле
  4. Telegram-iOS/submodules/ItemListAvatarAndNameInfoItem/Sources/ItemListAvatarAndNameItem.swift - Premium Badge в элементе списка
  5. Telegram-iOS/submodules/ContactsPeerItem/Sources/ContactsPeerItem.swift - Premium Badge в контактах
  6. Telegram-iOS/submodules/CallListUI/Sources/CallListCallItem.swift - Premium Badge в списке звонков
  7. Telegram-iOS/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift - Premium Badge в голосовом чате
  8. Telegram-iOS/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift - Premium Badge в реакциях
  9. Telegram-iOS/submodules/ChatListUI/Sources/ChatListItem.swift - Premium Badge в списке чатов (2 места)
  10. Telegram-iOS/submodules/ChatListUI/Sources/ChatListControllerNode.swift - Передача canReorderAllChats
  11. Telegram-iOS/submodules/TelegramUI/Components/HorizontalTabsComponent/Sources/HorizontalTabsComponent.swift - Переупорядочивание папок

Настройки

  1. Telegram-iOS/Swiftgram/IAppsGramSettings/Sources/IAppsGramSettingsController.swift - UI настроек

BUILD файлы

29-40. BUILD файлы для всех модулей выше (добавлена зависимость //Swiftgram/SGLocalPremium:SGLocalPremium)

Итого: 40+ файлов изменено


⚠️ Важные предупреждения и ограничения

1. Клиентская природа функций

Все функции работают только на вашем устройстве:

  • Premium Badge виден только вам
  • Другие пользователи не видят ваш Premium статус
  • Сервер не знает о ваших локальных изменениях

2. Серверная валидация

Сервер может отклонить некоторые изменения:

  • При синхронизации с другими устройствами
  • При восстановлении из резервной копии
  • При переустановке приложения

Что защищено от серверной валидации:

  • Закрепленные чаты (синхронизация отключена)
  • Папки (синхронизация отключена)
  • Чаты в папках (синхронизация отключена)
  • Порядок папок (синхронизация отключена)
  • Теги в Избранном (синхронизация отключена)

3. Локальное хранение

Все данные хранятся локально:

  • Настройки в UserDefaults
  • Закрепленные чаты в Postbox
  • Папки в Postbox
  • Теги в Postbox

При удалении приложения:

  • Все локальные данные будут потеряны
  • Настройки Local Premium будут сброшены
  • Локальные теги будут удалены

4. Синхронизация между устройствами

Local Premium НЕ синхронизируется между устройствами:

  • Настройки нужно включать на каждом устройстве отдельно
  • Закрепленные чаты не синхронизируются (синхронизация отключена)
  • Папки не синхронизируются (синхронизация отключена)
  • Теги не синхронизируются (синхронизация отключена)

5. Совместимость с реальным Premium

Если у вас есть реальный Premium:

  • Local Premium не конфликтует с реальным Premium
  • Все функции работают как обычно
  • Можно включить Local Premium для дополнительных функций
  • Отключение серверной синхронизации работает независимо от реального Premium

🚀 Руководство по использованию

Включение Local Premium

  1. Откройте Settings → IAppsGram → Local Premium
  2. Включите переключатель "Emulate Premium"
  3. Все функции активированы!

Проверка работы Premium Badge

  1. Включите "Emulate Premium"
  2. Откройте свой профиль
  3. Проверьте наличие Premium значка рядом с именем
  4. Откройте любой чат - значок должен быть в заголовке
  5. Откройте список чатов - значок должен быть рядом с вашим именем

Тестирование безлимитных закрепленных чатов

  1. Включите "Emulate Premium"
  2. Закрепите 6+ чатов (больше стандартного лимита 5)
  3. Проверьте, что все чаты остаются закрепленными
  4. Перезапустите приложение
  5. Проверьте, что все чаты все еще закреплены

Тестирование безлимитных папок

  1. Включите "Emulate Premium"
  2. Создайте 11+ папок (больше стандартного лимита 10)
  3. Проверьте, что все папки созданы
  4. Перезапустите приложение
  5. Проверьте, что все папки все еще существуют

Тестирование тегов в Избранном

  1. Включите "Emulate Premium"
  2. Откройте "Saved Messages" (Избранное)
  3. Выберите любое сообщение
  4. Нажмите на кнопку реакции
  5. Выберите любую реакцию как тег
  6. Проверьте, что тег добавлен к сообщению
  7. Нажмите на тег в панели поиска
  8. Проверьте, что отображаются только сообщения с этим тегом

Тестирование переупорядочивания папок

  1. Включите "Emulate Premium"
  2. Создайте несколько папок
  3. Зажмите любую папку и перетащите её на первую позицию
  4. Проверьте, что папка переместилась
  5. Попробуйте переместить папку "Все чаты" на другую позицию
  6. Проверьте, что это работает
  7. Перезапустите приложение
  8. Проверьте, что порядок папок сохранился

🔧 Troubleshooting (Решение проблем)

Premium Badge не отображается

Проблема: Premium Badge не виден в профиле или чатах.

Решение:

  1. Проверьте, что "Emulate Premium" включен в настройках
  2. Перезапустите приложение
  3. Проверьте, что вы смотрите на свой профиль (не на профиль другого пользователя)
  4. Проверьте, что SGLocalPremium.shared.currentAccountPeerId установлен правильно

Закрепленные чаты откреплены после перезапуска

Проблема: Закрепленные чаты исчезают после перезапуска приложения.

Решение:

  1. Проверьте, что "Emulate Premium" включен
  2. Проверьте, что синхронизация отключена (shouldDisableServerSync = true)
  3. Проверьте логи на наличие ошибок синхронизации

Папки удалены после перезапуска

Проблема: Созданные папки исчезают после перезапуска.

Решение:

  1. Проверьте, что "Emulate Premium" включен
  2. Проверьте, что синхронизация отключена
  3. Проверьте, что bypass в ChatListFiltering.swift работает

Теги не сохраняются

Проблема: Добавленные теги исчезают или не отображаются.

Решение:

  1. Проверьте, что "Emulate Premium" включен
  2. Проверьте, что bypass в MessageReactions.swift работает
  3. Проверьте, что bypass в Holes.swift работает (критически важно!)
  4. Проверьте логи Postbox на наличие ошибок индексации

Бесконечная загрузка при фильтрации по тегу

Проблема: При нажатии на тег в панели поиска появляется бесконечная загрузка.

Решение:

  1. КРИТИЧЕСКИ ВАЖНО: Проверьте, что bypass в Holes.swift работает
  2. Этот bypass предотвращает запросы к серверу для заполнения "holes"
  3. Без него система ожидает ответ от сервера, который никогда не придет
  4. Проверьте, что case .customTag обрабатывается правильно

Настройки сбрасываются при переключении аккаунтов

Проблема: Настройки Local Premium сбрасываются при переключении между аккаунтами.

Решение:

  1. Это нормальное поведение - настройки per-account
  2. Каждый аккаунт имеет свои независимые настройки
  3. Включите "Emulate Premium" для каждого аккаунта отдельно

📚 Дополнительные ресурсы

Связанные документы

  • LOCAL_PREMIUM_GUIDE.md - Старая версия документации (для справки)
  • LOCAL_PREMIUM_IMPLEMENTATION_PROGRESS.md - История разработки

Ключевые файлы для изучения

  1. SGLocalPremium.swift - Главный менеджер, начните отсюда
  2. PeerUtils.swift - Ключевая модификация Peer.isPremium
  3. UserLimitsConfiguration.swift - Переопределение лимитов
  4. MessageReactions.swift - Локальное сохранение тегов
  5. Holes.swift - Критический bypass для фильтрации по тегам

Архитектурные решения

Почему модификация Peer.isPremium вместо проверок в UI?

  • Одно место изменения вместо 10+
  • Автоматически работает везде
  • Не исчезает после обновлений с сервера
  • Проще поддерживать
  • Меньше кода

Почему одна настройка вместо отдельных переключателей?

  • Проще для пользователей
  • Меньше путаницы
  • Все функции работают вместе
  • Проще тестировать

Почему отключение серверной синхронизации?

  • Предотвращает откат изменений сервером
  • Локальные данные остаются на устройстве
  • Не нужно бороться с серверной валидацией
  • Проще реализовать

🎓 Заключение

Local Premium - это комплексная функция, которая эмулирует Premium подписку Telegram локально на устройстве. Ключевые особенности реализации:

  1. Модификация Peer.isPremium - главное архитектурное решение для Premium Badge
  2. Отключение серверной синхронизации - защита от отката изменений
  3. Per-account настройки - независимые настройки для каждого аккаунта
  4. Одна настройка для всех функций - простой и понятный UI

Все функции работают только на стороне клиента и видны только вам. Сервер не знает о ваших локальных изменениях.