Быстрый старт
Скопируйте пример целиком и адаптируйте под ваш бренд.
Минимальный пример
Самый быстрый способ применить фирменный цвет:
let colors = ChatColors()
colors.link = UIColor(named: "BrandColor") ?? .systemBlue
chatCenterSDK.theme = ChatTheme(colors: colors)
Полный пример с брендингом
Шаг 1 — Цвета
let colors = ChatColors()
// Основной текст и фон
colors.main = UIColor(named: "TextPrimary") ?? .label
colors.secondary = UIColor(named: "TextSecondary") ?? .secondaryLabel
colors.background = UIColor(named: "BackgroundPrimary") ?? .systemBackground
// Акцентный (фирменный) цвет
colors.link = UIColor(named: "BrandColor") ?? .systemBlue
colors.positive = UIColor(named: "BrandColor") ?? .systemBlue
// Ошибки и предупреждения (оставьте по умолчанию или задайте)
// colors.error = .systemRed
// colors.warning = .systemOrange
Шаг 2 — Шрифты
let typography = ChatTypography()
// Текст в пузырях сообщений — самый важный токен
typography.message = .systemFont(ofSize: 15, weight: .regular)
// Или кастомный шрифт (если зарегистрирован в приложении)
// typography.message = UIFont(name: "YourFont-Regular", size: 15) ?? .systemFont(ofSize: 15)
// Заголовок навигационной панели
typography.title = .systemFont(ofSize: 17, weight: .semibold)
Шаг 3 — Создать тему
let theme = ChatTheme(colors: colors, typography: typography)
Шаг 4 — Применить
Тему необходимо установить до открытия чата. После вызова getChat() изменения темы могут не применяться.
// Верный порядок
chatCenterSDK.theme = theme
let chatController = try chatCenterSDK.getChat()
navigationController?.pushViewController(chatController, animated: true)
// Неверно — тема установлена после открытия
let chatController = try chatCenterSDK.getChat()
chatCenterSDK.theme = theme // может не применяться
Шаг 5 — Тёмная тема (опционально)
let darkColors = ChatColors()
darkColors.main = .white
darkColors.secondary = UIColor(white: 0.7, alpha: 1)
darkColors.background = UIColor(named: "BackgroundDark") ?? .black
darkColors.link = UIColor(named: "BrandColorDark") ?? .systemBlue
let darkTheme = ChatTheme(colors: darkColors, typography: typography)
chatCenterSDK.darkTheme = darkTheme
Если darkTheme не задан — SDK использует светлую тему в обоих режимах.
Независимые светлая и тёмная темы
При создании двух тем убедитесь, что они не разделяют один экземпляр ChatComponents. Если передать один объект компонентов в обе темы, изменение в одной теме затронет другую:
// Неверно — одни компоненты на две темы
let components = ChatComponents()
let lightTheme = ChatTheme(components: components)
let darkTheme = ChatTheme(components: components) // тот же объект!
lightTheme.flows.chatFlow.incomeMessages.bubbleTintColor = .blue
// изменение затронет ОБЕ темы, т.к. components — общий объект
// Верно — каждая тема создаётся из своих цветов
let lightTheme = ChatTheme(colors: lightColors, typography: typography)
let darkTheme = ChatTheme(colors: darkColors, typography: typography)
// ChatTheme(colors:typography:) создаёт новый ChatComponents внутри
Если нужна детальная настройка компонентов для каждой темы — создавайте отдельные ChatComponents():
let lightComponents = ChatComponents(colors: lightColors, typography: typography)
lightComponents.navigationBarStyle.backgroundColor = .white
let darkComponents = ChatComponents(colors: darkColors, typography: typography)
darkComponents.navigationBarStyle.backgroundColor = UIColor(white: 0.15, alpha: 1)
chatCenterSDK.theme = ChatTheme(components: lightComponents)
chatCenterSDK.darkTheme = ChatTheme(components: darkComponents)
Полный код одним блоком
import ChatCenterUI
func configureChatTheme() {
// MARK: - Светлая тема
let colors = ChatColors()
colors.main = UIColor(named: "TextPrimary") ?? .label
colors.secondary = UIColor(named: "TextSecondary") ?? .secondaryLabel
colors.background = UIColor(named: "BackgroundPrimary") ?? .systemBackground
colors.link = UIColor(named: "BrandColor") ?? .systemBlue
colors.positive = UIColor(named: "BrandColor") ?? .systemBlue
let typography = ChatTypography()
typography.message = .systemFont(ofSize: 15, weight: .regular)
typography.title = .systemFont(ofSize: 17, weight: .semibold)
let theme = ChatTheme(colors: colors, typography: typography)
// MARK: - Тёмная тема
let darkColors = ChatColors()
darkColors.main = UIColor(named: "TextPrimaryDark") ?? .white
darkColors.secondary = UIColor(named: "TextSecondaryDark") ?? .lightGray
darkColors.background = UIColor(named: "BackgroundDark") ?? UIColor(white: 0.1, alpha: 1)
darkColors.link = UIColor(named: "BrandColorDark") ?? .systemBlue
let darkTheme = ChatTheme(colors: darkColors, typography: typography)
// MARK: - Применение
chatCenterSDK.theme = theme
chatCenterSDK.darkTheme = darkTheme
}
Вызовите configureChatTheme() при инициализации SDK — до открытия чата.
Место вызова в приложении
Тема должна быть задана один раз при инициализации SDK, до первого открытия чата. Типичный паттерн:
// AppDelegate.swift или SceneDelegate.swift
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: ...) -> Bool {
// 1. Создаём экземпляр SDK
let sdk = ChatCenterUISDK(providerUid: "...", appMarker: "...", ...)
// 2. Сразу задаём тему — ДО любого открытия чата
sdk.theme = createLightTheme()
sdk.darkTheme = createDarkTheme()
// 3. Сохраняем для дальнейшего использования
self.chatCenterSDK = sdk
return true
}
В ViewController тема уже задана — просто открываем чат:
// ChatViewController.swift
func openChat() {
// Тема задана в AppDelegate — здесь только открытие чата
let chatController = try chatCenterSDK.getChat()
navigationController?.pushViewController(chatController, animated: true)
}
Как передать SDK из AppDelegate в ViewController
Рекомендуемый паттерн — хранить chatCenterSDK в AppDelegate и получать через UIApplication.shared:
// AppDelegate.swift
var chatCenterSDK: ChatCenterUISDK!
func application(_ application: UIApplication, ...) -> Bool {
chatCenterSDK = ChatCenterUISDK(...)
chatCenterSDK.theme = createTheme()
return true
}
// Любой ViewController
private var chatCenterSDK: ChatCenterUISDK {
(UIApplication.shared.delegate as! AppDelegate).chatCenterSDK
}
func openChatButtonTapped() {
let chatController = try chatCenterSDK.getChat()
navigationController?.pushViewController(chatController, animated: true)
}
Альтернатива — передавать SDK через dependency injection (init или property) при создании ViewController.
Создание нового ChatTheme с другими параметрами перед каждым вызовом getChat() может приводить к визуальным артефактам. Создайте тему один раз и переиспользуйте её.
Дополнительные настройки
Скопируйте нужные строки и добавьте перед созданием ChatTheme:
let images = ChatImages()
// Заменить иконку отправки
images.sendButtonImage = ChatImage(system: "paperplane.fill", tintColor: .white)
// Заменить иконку прикрепления
images.attachButtonImage = ChatImage(system: "plus.circle.fill", tintColor: .white)
// Заменить иконку записи голосового
images.voiceButtonImage = ChatImage(system: "waveform", tintColor: .white)
let theme = ChatTheme(colors: colors, images: images, typography: typography)
// Скрыть аватар у исходящих сообщений
theme.flows.chatFlow.outcomeMessages.showAvatar = false
// Изменить цвет пузыря входящих сообщений
theme.flows.chatFlow.incomeMessages.bubbleTintColor = UIColor(named: "BubbleIncoming")
// Скрыть навигационную панель (если она встроена в приложение)
theme.flows.chatFlow.navigationBarStyle.hidden = true
// Экран поиска: фирменный цвет выделения совпадений
theme.flows.searchFlow.searchMessageStyle.matchTextStyle.color = UIColor(named: "BrandColor") ?? .systemOrange
Как проверить изменения
- Запустите приложение на симуляторе
- Откройте экран чата
- Для тёмной темы: Settings → Developer → Dark Appearance или
⌘ + Shift + Aв симуляторе
Актуальный рабочий пример со всеми параметрами: демо-приложение → MainViewController+Custom.swift
Что дальше
| Задача | Раздел |
|---|---|
| Все доступные токены цветов | Цветовая схема |
| Все токены шрифтов и Figma-маппинг | Типографика |
| Замена иконок | Изображения |
| Детальная настройка кнопок, панелей | Компоненты |
| Точечная настройка одного экрана | Сценарии |
| Что-то не работает | Troubleshooting |
| Не понятны термины | Глоссарий |