
Мова 🇺🇦 Українська
Документація
Початок роботи
Аутентифікація
Використання
Add Comments to Your iOS App
Це офіційна бібліотека iOS для FastComments.
Вбудовуйте віджети для живих коментарів, чату та відгуків у ваш iOS-застосунок.
Репозиторій
Функції 
- Деревовидні коментарі з вкладеними відповідями та пагінацією
- Соціальна стрічка зі створенням публікацій, реакціями та медіавкладеннями
- Режим живого чату з автопрокруткою та роздільниками за датою
- Оновлення в реальному часі через WebSocket (нові коментарі, голоси, присутність)
- Єдиний вхід (Simple SSO для тестування, Secure SSO для продакшену)
- Редагування з розширеним форматуванням: напівжирний, курсив, код та @згадування
- Голосування з налаштовуваними стилями (стрілки вгору/вниз або сердечка)
- Модераційні дії: позначити, закріпити, зачинити, заблокувати
- Розширене налаштування тем з пресетами та повною кастомізацією
- Користувацькі кнопки панелі інструментів для коментарів та створення публікацій у стрічці
- Завантаження зображень
- Підтримка регіону ЄС
- Присутність користувачів (індикатори онлайн/офлайн)
- Фільтрація стрічки за тегами
- Підтримка локалізації
Встановлення 
Додайте FastCommentsUI у свій проєкт, використовуючи Swift Package Manager.
У Xcode: File > Add Package Dependencies, потім введіть URL репозиторію.
Або додайте його до вашого Package.swift:
dependencies: [
.package(url: "https://github.com/fastcomments/fastcomments-ios.git", from: "1.0.0")
]
Потім додайте продукт до вашого target:
.target(
name: "YourApp",
dependencies: [
.product(name: "FastCommentsUI", package: "fastcomments-ios")
]
)
Імпортуйте обидва модулі там, де потрібно:
import FastCommentsUI
import FastCommentsSwift
Швидкий старт 
Мінімальні налаштування для відображення віджета коментарів:
import SwiftUI
import FastCommentsUI
struct ContentView: View {
@StateObject private var sdk = FastCommentsSDK(
config: FastCommentsWidgetConfig(
tenantId: "demo",
urlId: "my-page-1",
url: "https://example.com/page-1",
pageTitle: "My Page"
)
)
var body: some View {
FastCommentsView(sdk: sdk)
.task {
try? await sdk.load()
}
}
}
Замініть "demo" на свій ідентифікатор орендаря FastComments. Параметр urlId ідентифікує сторінку або тему, де зберігаються коментарі.
Аутентифікація (SSO) 
FastComments підтримує три режими автентифікації:
- Anonymous -- відсутній SSO-токен; користувачі отримують ідентичності на основі сесії
- Simple SSO -- токен на боці клієнта для демонстрацій та тестування (небезпечно)
- Secure SSO -- підписаний сервером токен для продакшн
Simple SSO
Підходить для демонстрацій та локального тестування. З Simple SSO будь-хто може видавати себе за будь-якого користувача, тому не використовуйте його в продакшн.
import FastCommentsSwift
let userData = SimpleSSOUserData(
username: "Jane Doe",
email: "jane@example.com",
avatar: "https://example.com/avatar.jpg"
)
let sso = FastCommentsSSO.createSimple(simpleSSOUserData: userData)
let token = try? sso.prepareToSend()
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page-1",
sso: token
)
let sdk = FastCommentsSDK(config: config)
SimpleSSOUserData також підтримує додаткові поля:
id-- ID користувача (за замовчуванням — email, якщо не вказано)displayName-- окреме відображуване ім'яdisplayLabel-- кастомна мітка, що показується поруч з ім'ям (наприклад, "VIP")websiteUrl-- посилання у імені користувачаlocale-- код локаліisProfileActivityPrivate-- приховати активність профілю (за замовчуванням — true)
Secure SSO
У продакшні ваш бекенд генерує підписаний SSO-токен, використовуючи ваш API secret. iOS-додаток отримує цей токен з вашого сервера і передає його в конфіг.
На вашому бекенді (з використанням FastComments Swift SDK або будь-якої мови):
let userData = SecureSSOUserData(
id: "user-123",
email: "user@example.com",
username: "Display Name",
avatar: "https://example.com/avatar.jpg"
)
let sso = try FastCommentsSSO.createSecure(apiKey: "YOUR_API_KEY", secureSSOUserData: userData)
let token = try sso.prepareToSend()
// Поверніть цей токен вашому iOS-додатку через ваш API
У вашому iOS-додатку:
struct MyView: View {
@StateObject private var sdk = FastCommentsSDK(
config: FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page-1"
)
)
@State private var isLoadingToken = true
var body: some View {
Group {
if isLoadingToken {
ProgressView("Loading...")
} else {
FastCommentsView(sdk: sdk)
}
}
.task {
// Отримайте токен з вашого бекенду
let token = try? await fetchSSOTokenFromYourBackend()
// Створіть нову конфігурацію з токеном, або встановіть його перед завантаженням
isLoadingToken = false
try? await sdk.load()
}
}
}
SecureSSOUserData підтримує додаткові поля:
optedInNotifications-- підписка на email-повідомленняdisplayLabel-- кастомна міткаdisplayName-- відображуване ім'яwebsiteUrl-- URL вебсайтуgroupIds-- членство в групахisAdmin-- привілеї адміністратораisModerator-- привілеї модератораisProfileActivityPrivate-- приватність активності профілю
Вкладені коментарі 
Базове використання
struct CommentsPage: View {
@StateObject private var sdk = FastCommentsSDK(
config: FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "article-42",
url: "https://example.com/article/42",
pageTitle: "Article Title"
)
)
var body: some View {
FastCommentsView(sdk: sdk)
.task {
try? await sdk.load()
}
}
}
Стилі голосування
За замовчуванням стиль голосування відображає стрілки вгору/вниз. Передайте ._1 для стилю з сердечком:
FastCommentsView(sdk: sdk, voteStyle: ._1)
| Style | Зовнішній вигляд |
|---|---|
._0 |
Кнопки зі стрілками вгору/вниз із загальним лічильником |
._1 |
Одна кнопка-сердечко з лічильником |
Обробники подій
Використовуйте колбеки у вигляді модифікаторів для обробки взаємодій користувача:
FastCommentsView(sdk: sdk)
.onCommentPosted { comment in
print("New comment: \(comment.commentHTML)")
}
.onReplyClick { renderableComment in
print("Replying to: \(renderableComment.comment.id)")
}
.onUserClick { context, userInfo, source in
// source — це .name або .avatar
print("Tapped \(userInfo.displayName)")
}
Застосування теми
Передайте тему через середовище SwiftUI:
FastCommentsView(sdk: sdk)
.fastCommentsTheme(myTheme)
.task { try? await sdk.load() }
Або встановіть її безпосередньо в SDK:
sdk.theme = FastCommentsTheme.modern
Напрям сортування
sdk.defaultSortDirection = .nf // Найновіші першими (за замовчуванням)
sdk.defaultSortDirection = .of // Найстаріші першими
sdk.defaultSortDirection = .mr // Найрелевантніші
Живий чат 
LiveChatView забезпечує чат у реальному часі з автопрокруткою, розділювачами дат та компактним макетом. Він автоматично конфігурує SDK для сортування від найстаріших і негайного відображення в реальному часі.
struct ChatView: View {
@StateObject private var sdk: FastCommentsSDK = {
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "chat-room-1",
sso: ssoToken // Рекомендовано SSO, щоб у користувачів були імена
)
return FastCommentsSDK(config: config)
}()
var body: some View {
LiveChatView(sdk: sdk)
.onCommentPosted { comment in
print("Sent: \(comment.commentHTML)")
}
.task {
try? await sdk.load()
}
}
}
LiveChatView підтримує ці зворотні виклики:
.onCommentPosted-- викликається, коли користувач надсилає повідомлення.onCommentDeleted-- викликається, коли повідомлення видаляється.onUserClick-- викликається, коли натискають на ім'я або аватар користувача
Соціальна стрічка 
Система стрічки — це окремий SDK (FastCommentsFeedSDK) зі своїм власним виглядом.
Завантаження та відображення стрічки
struct FeedPage: View {
@StateObject private var sdk: FastCommentsFeedSDK = {
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-feed",
sso: ssoToken
)
return FastCommentsFeedSDK(config: config)
}()
@State private var commentsPost: FeedPost?
var body: some View {
FastCommentsFeedView(sdk: sdk)
.onPostSelected { post in
commentsPost = post
}
.onCommentsRequested { post in
commentsPost = post
}
.onSharePost { post in
// Показати діалог спільного доступу
}
.onUserClick { context, userInfo, source in
// Перейти до профілю користувача
}
.onMediaClick { mediaItem, index in
// Показати переглядач зображення на весь екран
}
.task {
try? await sdk.load()
}
}
}
Вигляд стрічки автоматично підтримує потягування для оновлення та безкінечну прокрутку.
Створення дописів
Використовуйте FeedPostCreateView для відображення форми створення допису:
@State private var showCreatePost = false
// У тілі вашого вигляду:
.sheet(isPresented: $showCreatePost) {
FeedPostCreateView(
sdk: sdk,
onPostCreated: { post in
showCreatePost = false
Task { try? await sdk.refresh() }
},
onCancelled: {
showCreatePost = false
}
)
}
Реакції на дописи
SDK обробляє реакції з оптимістичними оновленнями:
try await sdk.reactPost(postId: post.id, reactionType: "l")
// Перевірити стан реакції
let hasLiked = sdk.hasUserReacted(postId: post.id, reactType: "l")
let likeCount = sdk.getLikeCount(postId: post.id)
Відкриття коментарів до допису
Використовуйте CommentsSheet для відображення коментарів до допису стрічки. Він створює екземпляр FastCommentsSDK всередині, використовуючи конфігурацію feed SDK:
.sheet(item: $commentsPost) { post in
CommentsSheet(post: post, feedSDK: sdk, onUserClick: { context, userInfo, source in
// Обробити натискання на користувача
})
}
Примітка: FeedPost має відповідати протоколу Identifiable для .sheet(item:). Додайте це розширення:
extension FeedPost: @retroactive Identifiable {}
Фільтрація стрічки за тегами
Реалізуйте протокол TagSupplier, щоб фільтрувати дописи стрічки за тегами:
struct TeamTagSupplier: TagSupplier {
func getTags(currentUser: UserSessionInfo?) -> [String]? {
guard let user = currentUser else { return nil }
return ["team:\(user.id ?? "")", "public"]
}
}
sdk.tagSupplier = TeamTagSupplier()
Поверніть nil для нефільтрованої глобальної стрічки.
Збереження та відновлення стану стрічки
Збережіть стан пагінації між подіями життєвого циклу вигляду:
let state = sdk.savePaginationState()
// Later...
sdk.restorePaginationState(state)
Видалення дописів
sdk.onPostDeleted = { postId in
print("Post \(postId) was deleted")
}
Теми оформлення 
Пресети тем
Доступні чотири вбудовані пресети:
// Системні налаштування за замовчуванням
sdk.theme = FastCommentsTheme.default
// Картки з тінями та великими заокругленими кутами
sdk.theme = FastCommentsTheme.modern
// Плоский, без тіней, невеликий радіус заокруглення, без ліній розгалуження
sdk.theme = FastCommentsTheme.minimal
// Встановити всі кольори дій в один фірмовий колір
sdk.theme = FastCommentsTheme.allPrimary(.indigo)
Стилі відображення коментарів
var theme = FastCommentsTheme()
theme.commentStyle = .flat // Плоский список з роздільниками (за замовчуванням)
theme.commentStyle = .card // Картки з заокругленими кутами та тінями
theme.commentStyle = .bubble // Стиль чат-бульбашок
Кольори
Усі властивості кольорів необов'язкові. Незадані значення використовують адекватні системні значення за замовчуванням.
var theme = FastCommentsTheme()
// Фірмові кольори
theme.primaryColor = .indigo
theme.primaryLightColor = .indigo.opacity(0.6)
theme.primaryDarkColor = Color(red: 0.2, green: 0.1, blue: 0.5)
// Фони
theme.commentBackgroundColor = Color(.secondarySystemGroupedBackground)
theme.containerBackgroundColor = Color(.systemGroupedBackground)
// Кнопки дій
theme.actionButtonColor = .indigo
theme.replyButtonColor = .indigo
theme.toggleRepliesButtonColor = .indigo.opacity(0.8)
theme.loadMoreButtonTextColor = .indigo
// Голоси
theme.voteActiveColor = .red
theme.voteCountColor = .primary
theme.voteCountZeroColor = .secondary
theme.voteDividerColor = Color(.separator)
// Посилання
theme.linkColor = .indigo
theme.linkColorPressed = .indigo.opacity(0.5)
// Діалоги
theme.dialogHeaderBackgroundColor = .indigo
theme.dialogHeaderTextColor = .white
// Панель вводу
theme.inputBarBackgroundColor = Color(.systemBackground)
theme.inputBarBorderColor = Color(.separator)
// Інше
theme.onlineIndicatorColor = .green
theme.separatorColor = Color(.separator)
theme.badgeBackgroundColor = .gray.opacity(0.2)
theme.threadLineColor = .indigo.opacity(0.15)
Типографіка
theme.commenterNameFont = .subheadline.weight(.bold)
theme.bodyFont = .body
theme.captionFont = .caption
theme.actionFont = .caption.weight(.medium)
Макет і відступи
theme.cornerRadius = .large // .none, .small, .medium, .large
theme.commentSpacing = 4 // Пункти між рядками коментарів
theme.nestingIndent = 20 // Відступ у пунктах на кожен рівень вкладення
theme.avatarSize = 36 // Діаметр аватара для кореневих коментарів
theme.replyAvatarSize = 28 // Діаметр аватара для вкладених відповідей
Візуальні ефекти
theme.showShadows = true // Легкі тіні на картках
theme.showThreadLine = true // Вертикальна лінія, що з'єднує вкладені відповіді
theme.animateVotes = true // Пружинна анімація при зміні голосів
Застосування тем
Два підходи:
// Через середовище SwiftUI (рекомендується для ієрархії представлень)
FastCommentsView(sdk: sdk)
.fastCommentsTheme(theme)
// Безпосередньо в SDK
sdk.theme = theme
Користувацькі кнопки панелі інструментів 
Кнопки панелі інструментів коментаря
Реалізуйте протокол CustomToolbarButton, щоб додати кнопки до панелі введення коментаря:
struct EmojiButton: CustomToolbarButton {
let id = "emoji"
let iconSystemName = "face.smiling" // назва SF Symbol
let contentDescription = "Add Emoji"
let badgeText: String? = nil // Необов'язковий лічильник значка
func onClick(text: Binding<String>) {
text.wrappedValue += "\u{1F44D}"
}
// Необов'язкові перевизначення (за замовчуванням true)
func isEnabled() -> Bool { true }
func isVisible() -> Bool { true }
}
Передайте власні кнопки при створенні представлення:
FastCommentsView(
sdk: sdk,
customToolbarButtons: [EmojiButton(), CodeBlockButton()]
)
Або додайте їх глобально в SDK (застосовується до всіх екземплярів):
sdk.addGlobalCustomToolbarButton(EmojiButton())
sdk.removeGlobalCustomToolbarButton(id: "emoji")
sdk.clearGlobalCustomToolbarButtons()
Кнопки панелі інструментів стрічки
Реалізуйте FeedCustomToolbarButton для форми створення допису:
struct HashtagButton: FeedCustomToolbarButton {
let id = "hashtag"
let iconSystemName = "number"
let contentDescription = "Add Hashtag"
func onClick(content: Binding<String>) {
content.wrappedValue += "#"
}
}
Передайте їх у представлення створення:
FeedPostCreateView(
sdk: sdk,
customToolbarButtons: [HashtagButton()],
onPostCreated: { _ in },
onCancelled: { }
)
Або встановіть їх глобально в SDK стрічки:
sdk.globalFeedToolbarButtons = [HashtagButton()]
Модерація 
Дії, доступні всім користувачам
- Поскаржитися/Зняти скаргу -- повідомити про коментар для перевірки
try await sdk.flagComment(commentId: commentId)
try await sdk.unflagComment(commentId: commentId)
- Заблокувати/Розблокувати -- приховати всі коментарі від користувача (для поточного переглядача)
try await sdk.blockUser(commentId: commentId)
try await sdk.unblockUser(commentId: commentId)
Дії лише для адміністраторів
- Закріпити/Відкріпити -- закріпити коментар у верхній частині теми
try await sdk.pinComment(commentId: commentId)
try await sdk.unpinComment(commentId: commentId)
- Заблокувати/Розблокувати -- заборонити нові відповіді на коментар
try await sdk.lockComment(commentId: commentId)
try await sdk.unlockComment(commentId: commentId)
Усі дії модерації також доступні через контекстне меню коментаря в інтерфейсі. Дії адміністратора з'являються лише коли поточний користувач є адміністратором сайту (встановлюється через SSO isAdmin flag or dashboard configuration).
Оновлення в реальному часі 
Після виклику sdk.load(), SDK автоматично підписується на події WebSocket для налаштованого urlId. Обробляються такі події:
- Нові коментарі, редагування та видалення
- Голоси (нові та видалені)
- Зміни станів: закріплення (pin), блокування (lock), позначення (flag) та блокування (block)
- Присутність користувачів (приєднання/вихід)
- Відкриття/закриття треду
- Нагородження значками
- Оновлення конфігурації сервера
Керування живим відображенням
За замовчуванням нові коментарі від інших користувачів з'являються негайно:
sdk.showLiveRightAway = true // За замовчуванням: показати негайно
Встановіть це в false, щоб буферизувати нові коментарі за кнопкою "N нових коментарів", дозволяючи користувачеві вибрати, коли їх показати:
sdk.showLiveRightAway = false
Присутність користувачів
Індикатори онлайн/офлайн автоматично відображаються на аватарах користувачів, коли сервер увімкне відстеження присутності. Додаткова конфігурація на клієнті не потрібна.
Пагінація 
Розмір сторінки
// Коментарі: за замовчуванням 30
sdk.pageSize = 50
// Стрічка: за замовчуванням 10
feedSDK.pageSize = 20
Завантаження додаткових коментарів
Інтерфейс автоматично відображає елементи керування пагінацією. Ви також можете ініціювати пагінацію програмно:
// Завантажити наступну сторінку
try await sdk.loadMore()
// Завантажити всі залишки (відключено, якщо >2000 коментарів для продуктивності)
try await sdk.loadAll()
// Перевірити стан
sdk.hasMore // Чи є ще сторінки
sdk.shouldShowLoadAll()
sdk.getCountRemainingToShow()
Пагінація дочірніх коментарів
Вкладені відповіді завантажуються відкладено. Коли користувач розгортає гілку, завантажуються перші 5 дочірніх коментарів. З'являється елемент керування "завантажити більше відповідей", якщо їх більше. Це обробляється автоматично інтерфейсом.
Стан і спостережуваність 
Обидва FastCommentsSDK та FastCommentsFeedSDK — це класи ObservableObject з властивостями @Published. Ви можете спостерігати за ними у ваших SwiftUI представленнях для реактивного оновлення інтерфейсу.
Опубліковані властивості FastCommentsSDK
| Властивість | Тип | Опис |
|---|---|---|
commentCountOnServer |
Int |
Загальна кількість коментарів на сервері |
newRootCommentCount |
Int |
Накопичені нові коментарі (коли showLiveRightAway встановлено в false) |
currentUser |
UserSessionInfo? |
Поточний автентифікований користувач |
isSiteAdmin |
Bool |
Чи є поточний користувач адміністратором сайту |
isClosed |
Bool |
Чи закрито тред коментарів |
hasBillingIssue |
Bool |
Чи існує проблема з білінгом |
isLoading |
Bool |
Чи виконується мережевий запит |
hasMore |
Bool |
Чи існують додаткові сторінки коментарів |
blockingErrorMessage |
String? |
Помилка, яка перешкоджає роботі інтерфейсу |
warningMessage |
String? |
Попереджувальне повідомлення, що не блокує |
isDemo |
Bool |
Чи працює у демонстраційному режимі |
commentsVisible |
Bool |
Перемикач видимості коментарів |
toolbarEnabled |
Bool |
Чи відображається панель форматування |
Опубліковані властивості FastCommentsFeedSDK
| Властивість | Тип | Опис |
|---|---|---|
feedPosts |
[FeedPost] |
Наразі завантажені пости стрічки |
hasMore |
Bool |
Чи існують додаткові сторінки |
currentUser |
UserSessionInfo? |
Поточний автентифікований користувач |
blockingErrorMessage |
String? |
Повідомлення про помилку, що блокує |
isLoading |
Bool |
Чи виконується мережевий запит |
newPostsCount |
Int |
Кількість нових дописів з моменту останнього завантаження |
Дерево коментарів
Дерево коментарів доступне через sdk.commentsTree:
// Плоский список видимих вузлів для відображення
sdk.commentsTree.visibleNodes
// Пошук коментаря за ID
sdk.commentsTree.commentsById["comment-id"]
Регіон ЄС 
Щоб використовувати європейський центр обробки даних, задайте поле region у вашій конфігурації:
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page",
region: "eu"
)
Це спрямовує всі запити API та з'єднання WebSocket до eu.fastcomments.com.
Очищення 
Коли ви завершили роботу з екземпляром SDK (наприклад, коли подання закривається), викличте cleanup() щоб закрити WebSocket-з'єднання та скасувати фонові задачі:
sdk.cleanup()
Для подань, якими керує SwiftUI через @StateObject, це зазвичай викликають у .onDisappear або коли подання звільняється з пам'яті.
Завантаження зображень 
Коментарі
let imageUrl = try await sdk.uploadImage(imageData: jpegData, filename: "photo.jpg")
Повертає рядок URL завантаженого зображення.
Публікації у стрічці
let mediaItem = try await feedSDK.uploadImage(imageData: jpegData, filename: "photo.jpg")
// Завантаження кількох зображень паралельно
let mediaItems = try await feedSDK.uploadImages(images: [
(jpegData1, "photo1.jpg"),
(jpegData2, "photo2.jpg")
])
Згадки користувачів 
Пошук користувачів для автодоповнення @mention:
let results = try await sdk.searchUsers(query: "jan")
// Повертає [UserSearchResult] з userId, username, avatar тощо.
Вбудований CommentInputBar автоматично обробляє автодоповнення @mention.
Редагування та видалення коментарів 
Редагувати
try await sdk.editComment(commentId: commentId, newText: "Updated text")
Сервер повторно рендерить HTML. Локальний коментар оновлюється автоматично.
Видалити
try await sdk.deleteComment(commentId: commentId)
Видалення коментаря також видаляє його нащадків у локальному дереві.
Обидві дії доступні через контекстне меню коментаря в інтерфейсі, коли поточний користувач є автором коментаря (або адміністратором сайту).
Обробка помилок 
Методи SDK викидають FastCommentsError, який відповідає протоколу LocalizedError:
do {
try await sdk.load()
} catch let error as FastCommentsError {
print(error.translatedError ?? error.reason ?? "Unknown error")
} catch {
print(error.localizedDescription)
}
FastCommentsError properties:
code-- код помилки з APIreason-- опис помилки англійською мовоюtranslatedError-- локалізоване повідомлення про помилку, надане сервером
Блокувальні помилки також автоматично надаються через sdk.blockingErrorMessage, і вбудовані перегляди відображають їх користувачеві.
Локалізація 
Передайте код локалі в конфігурацію, щоб локалізувати рядки, надані сервером:
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page",
locale: "fr_fr"
)
Рядки інтерфейсу на стороні клієнта використовують локалізацію на основі iOS bundle.
Приклад застосунку 
У репозиторії міститься повний приклад додатка в ExampleApp/ з демонстраціями:
- Вкладені (threaded) коментарі з SSO та власними темами
- Соціальна стрічка зі створенням публікацій та фільтрацією за тегами
- Живий чат
- Прості та безпечні потоки SSO
- Користувацькі кнопки панелі інструментів (коментарі та стрічка)
Потрібна допомога?
Якщо ви зіткнулися з будь-якими проблемами або маєте запитання щодо бібліотеки iOS, будь ласка:
Як зробити внесок
Внески вітаються! Будь ласка, відвідайте репозиторій на GitHub для отримання вказівок щодо внеску.