
Језик 🇲🇪 Српски (Црна Гора)
Документација
Почетак рада
Аутентификација
Коришћење
Add Comments to Your iOS App
Ово је званична iOS библиотека за FastComments.
Уградите коментаре уживо, ћаскање и видгете за рецензије у вашу iOS апликацију.
Репозиторијум
Функције 
- Нити коментара са уграђеним одговорима и пагинацијом
- Друштвени фид са креирањем објава, реакцијама и прилозима медија
- Режим живог ћаскања са аутоматским скроловањем и раздвајачима по датуму
- Ажурирања у реалном времену преко WebSocket-а (нови коментари, гласови, присутност)
- Једнократно пријављивање (Simple SSO за тестирање, Secure SSO за продукцију)
- Уређивање богатог текста са подебљаним, курзивом, кодом и @поменама
- Гласање са прилагодљивим стиловима (стрелице горе/доле или срца)
- Модерацијске радње: пријављивање, причвршћивање, закључавање, блокирање
- Свеобухватно прилагођавање тема са предефинисаним подешавањима и потпуном прилагодбом
- Прилагођена дугмад на алатној траци за коментаре и креирање објава у фиду
- Отпремање слика
- Подршка за ЕУ регион
- Присуство корисника (индикатори онлајн/офлајн)
- Филтрирање фида по таговима
- Подршка за локализацију
Инсталација 
Dodajte FastCommentsUI u svoj projekat koristeći Swift Package Manager.
U Xcode-u: File > Add Package Dependencies, zatim unesite URL repozitorijuma.
Ili ga dodajte u vaš Package.swift:
dependencies: [
.package(url: "https://github.com/fastcomments/fastcomments-ios.git", from: "1.0.0")
]
Zatim dodajte product u svoj target:
.target(
name: "YourApp",
dependencies: [
.product(name: "FastCommentsUI", package: "fastcomments-ios")
]
)
Uvezite oba modula gde je potrebno:
import FastCommentsUI
import FastCommentsSwift
Брзи почетак 
Минимална подешавања за приказ widget-а за коментаре:
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()
}
}
}
Zамијените "demo" вашим FastComments tenant ID-јем. urlId идентификује страницу или нит на којој су коментари смештени.
Аутентификација (SSO) 
FastComments подржава три режима аутентификације:
- Анонимно -- без SSO токена; корисници добијају идентитете засноване на сесији
- Једноставан SSO -- клијентски токен за демое и тестирање (није безбедно)
- Безбедан SSO -- серверски потписан токен за продукцију
Једноставан SSO
Корисно за демое и локално тестирање. Било ко може се претварати као било који корисник уз Једноставан 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)
Безбедан SSO
У продукцији, ваш бекенд генерише потписани SSO токен користећи ваш API тајни кључ. 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()
// Return this token to your iOS app via your 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-- опција пријаве за примање обавештења путем е-поште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 | Appearance |
|---|---|
._0 |
Up/down arrow buttons with net count |
._1 |
Single heart button with count |
Повратни позиви догађаја
Користите повратне позиве у облику модификатора за обраду корисничких интеракција:
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
// извор је .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-- активира се када се кликне на име корисника или аватар
Друштвени фид 
Feed систем је посебан 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")
// Check reaction state
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 симбола
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 ознаке или конфигурације контролне табле).
Ажурирања у реалном времену 
Након позива sdk.load(), SDK аутоматски претплаћује се на WebSocket догађаје за конфигурисани urlId. Следећи догађаји се обрађују:
- Нови коментари, измјене и брисања
- Гласови (нови и уклоњени)
- Промјене стања: закачење (pin), закључавање, пријављивање (flag) и блокирање
- Присуство корисника (приступ/напуштање)
- Отварање/затварање нити
- Додијељивања значки
- Ажурирања конфигурације сервера
Контрола живог приказа
Подразумјевано, нови коментари од других корисника се појављују одмах:
sdk.showLiveRightAway = true // Подразумјевано: прикажи одмах
Поставите ово на false да бисте кеширали нове коментаре иза дугмета "N нових коментара", омогућавајући кориснику да одабере када ће их открити:
sdk.showLiveRightAway = false
Присуство корисника
Онлајн/офлајн индикатори се аутоматски појављују на аватарима корисника када сервер омогући праћење присуства. На клијенту није потребна додатна конфигурација.
Пагинација 
Величина странице
// Коментари: подразумевано 30
sdk.pageSize = 50
// Фид: подразумевано 10
feedSDK.pageSize = 20
Учитавање више коментара
UI аутоматски приказује контроле пагинације. Такође можете покренути пагинацију програмски:
// Учитај следећу страницу
try await sdk.loadMore()
// Учитај све преостало (онемогућено ако има више од 2000 коментара због перформанси)
try await sdk.loadAll()
// Провери стање
sdk.hasMore // Да ли постоје још странице
sdk.shouldShowLoadAll()
sdk.getCountRemainingToShow()
Пагинација дечијих коментара
Угнеждени одговори се учитавају по захтеву. Када корисник прошири нит, првих 5 подкоментара се учитава. Контрола "учитај још одговора" појављује се ако их има још. Ово се аутоматски обрађује у UI-у.
Стање и опсервабилност 
Обa 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 у вашем config:
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")
])
Помене корисника 
Pretražite korisnike radi automatskog dovršavanja @mention:
let results = try await sdk.searchUsers(query: "jan")
// Vraća [UserSearchResult] sa userId, username, avatar, itd.
Ugrađeni CommentInputBar automatski podržava dovršavanje @mention.
Уређивање и брисање коментара 
Измјени
try await sdk.editComment(commentId: commentId, newText: "Updated text")
Сервер поново рендерује HTML. Локални коментар се аутоматски ажурира.
Обриши
try await sdk.deleteComment(commentId: commentId)
Брисање коментара такође уклања његове потомке из локалног стабла.
Обе радње су доступне преко контекстног менија коментара у корисничком интерфејсу када је тренутни корисник аутор коментара (или администратор сајта).
Обрада грешака 
SDK metode bacaju FastCommentsError, koji implementira 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-- kod greške iz API-jareason-- opis greške na engleskom jezikutranslatedError-- lokalizovana poruka o grešci koju pruža server
Blocking errors are also surfaced automatically via sdk.blockingErrorMessage, which the built-in views display to the user.
Локализација 
Proslijedite kod lokaliteta u konfiguraciju da biste lokalizovali stringove koje server pruža:
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page",
locale: "fr_fr"
)
Stringovi korisničkog interfejsa na klijentskoj strani koriste lokalizaciju zasnovanu na iOS bundle-u.
Пример апликације 
Repozitorijum sadrži kompletan primjer aplikacije u ExampleApp/ sa demonstracijama:
- Ugnježdeni komentari sa SSO i prilagođenim temama
- Društveni feed sa kreiranjem objava i filtriranjem po oznakama
- Razgovor uživo
- Jednostavni i sigurni SSO tokovi
- Prilagođena dugmad na alatnoj traci (komentari i feed)
Потребна помоћ?
Ако наиђете на било какве проблеме или имате питања у вези iOS библиотеке, молимо вас:
Доприноси
Доприноси су добродошли! Посетите GitHub репозиторијум за смернице о доприносу.