FastComments.com

iOSアプリにコメントを追加する

これは FastComments の公式 iOS ライブラリです。

iOS アプリにライブコメント、チャット、レビューのウィジェットを埋め込むことができます。

リポジトリ

GitHubで見る


機能 Internal Link

  • ネストされた返信とページネーションを備えたスレッド形式のコメントツリー
  • 投稿作成、リアクション、メディア添付を備えたソーシャルフィード
  • 自動スクロールと日付区切りを備えたライブチャットモード
  • WebSocket を介したリアルタイム更新(新しいコメント、投票、プレゼンス)
  • シングルサインオン(テスト用の簡易 SSO、運用向けのセキュア SSO)
  • 太字、斜体、コード、@メンションを含むリッチテキスト編集
  • 設定可能なスタイル(上/下の矢印またはハート)を持つ投票機能
  • モデレーション操作:フラグ、ピン、ロック、ブロック
  • プリセットとフルカスタマイズを備えた包括的なテーマ
  • コメントとフィード投稿作成のためのカスタムツールバーボタン
  • 画像アップロード
  • EUリージョンのサポート
  • ユーザーのプレゼンス(オンライン/オフライン表示)
  • タグベースのフィードフィルタリング
  • ローカリゼーションのサポート

要件 Internal Link


  • iOS 16+ または macOS 14+
  • Swift 5.9+
  • SwiftUI

インストール Internal Link


Swift Package Managerを使用してFastCommentsUIをプロジェクトに追加します。

Xcodeで: File > Add Package Dependencies を選択し、リポジトリのURLを入力します。

または、Package.swift に追加します:

dependencies: [
    .package(url: "https://github.com/fastcomments/fastcomments-ios.git", from: "1.0.0")
]

次に、ターゲットに製品を追加します:

.target(
    name: "YourApp",
    dependencies: [
        .product(name: "FastCommentsUI", package: "fastcomments-ios")
    ]
)

必要な箇所で両方のモジュールをインポートします:

import FastCommentsUI
import FastCommentsSwift

クイックスタート Internal Link

コメントウィジェットを表示するための最小限のセットアップ:

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 テナント ID に置き換えてください。urlId はコメントが保存されるページまたはスレッドを識別します。



認証(SSO) Internal Link


FastComments は 3 つの認証モードをサポートしています:

  1. Anonymous -- SSO トークンなし; ユーザーはセッションベースの識別を取得します
  2. Simple SSO -- デモやテスト用のクライアント側トークン(安全ではありません)
  3. 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

本番環境では、バックエンドが API シークレットを使って署名付き SSO トークンを生成します。iOS アプリはサーバーからこのトークンを取得し、config に渡します。

バックエンド側(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()
// このトークンを API 経由で iOS アプリに返します

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()
            // トークンで新しい config を作成するか、ロード前に設定する
            isLoadingToken = false
            try? await sdk.load()
        }
    }
}

SecureSSOUserData は追加のフィールドをサポートします:

  • optedInNotifications -- メール通知のオプトイン
  • displayLabel -- カスタムラベル
  • displayName -- 表示名
  • websiteUrl -- ウェブサイトの URL
  • groupIds -- グループ所属
  • isAdmin -- 管理者権限
  • isModerator -- モデレーター権限
  • isProfileActivityPrivate -- プロフィールの非公開設定


スレッドコメント Internal Link

基本的な使用法

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外観
._0Up/down arrow buttons with net count
._1Single 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
        // 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  // 最も関連性の高い


ライブチャット Internal Link

LiveChatViewは自動スクロール、日付区切り、コンパクトなレイアウトを備えたリアルタイムチャット体験を提供します。SDKを古い順(oldest-first)のソートと即時ライブ表示用に自動的に構成します。

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 -- ユーザーの名前やアバターがタップされたときに呼び出されます


ソーシャルフィード Internal Link

フィードシステムは独立した 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.loadIfNeeded()
            }
    }
}

フィードビューにはプル・トゥ・リフレッシュと無限スクロールが自動的に含まれます。 画面のライフサイクルに戻る場合は loadIfNeeded() を使用してください。既存または復元されたフィードがページ1にリセットされるのを防ぎます。

投稿の作成

投稿作成フォームを表示するには FeedPostCreateView を使用します:

@State private var showCreatePost = false

// In your view body:
.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 を使用します。これはフィードSDKの設定を使用して内部で FastCommentsSDK インスタンスを作成します:

.sheet(item: $commentsPost) { post in
    CommentsSheet(post: post, feedSDK: sdk, onUserClick: { context, userInfo, source in
        // ユーザークリックを処理する
    })
}

注意: .sheet(item:) には FeedPostIdentifiable に準拠している必要があります。この拡張を追加してください:

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)
try? await sdk.loadIfNeeded()

画面が一時的に非表示になる場合、フィードビューはライブ更新を自動的に一時停止し、再表示時に読み込んだ投稿をクリアせずに再開します。SDKインスタンスを本当に使い終わったときだけ sdk.cleanup() を呼び出してください。

投稿の削除

sdk.onPostDeleted = { postId in
    print("Post \(postId) was deleted")
}

テーマ Internal Link

テーマプリセット

4つの組み込みプリセットが利用可能です:

// システムのデフォルト
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         // 投票変更時のスプリングアニメーション

テーマの適用

2つの方法:

// SwiftUI の環境経由(ビュー階層には推奨)
FastCommentsView(sdk: sdk)
    .fastCommentsTheme(theme)

// SDK に直接設定
sdk.theme = theme

カスタムツールバーのボタン Internal Link

コメント入力ツールバーのボタン

コメント入力ツールバーにボタンを追加するには、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()]


モデレーション Internal Link

すべてのユーザーが利用できる操作

  • フラグ/フラグ解除 -- コメントを審査のために報告する
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)

すべてのモデレーション操作は、UI のコメントコンテキストメニューからも利用できます。管理者向けの操作は、現在のユーザーがサイト管理者である場合にのみ表示されます(SSO の isAdmin フラグまたはダッシュボードの設定で指定)。



リアルタイム更新 Internal Link

sdk.load() を呼び出した後、SDK は構成された urlId の WebSocket イベントに自動的に購読します。次のイベントが処理されます:

  • 新しいコメント、編集、削除
  • 投票(追加および削除)
  • ピン、ロック、フラグ、ブロックの状態変更
  • ユーザーのプレゼンス(参加/退出)
  • スレッドの開閉
  • バッジ付与
  • サーバー構成の更新

ライブ表示の制御

デフォルトでは、他のユーザーからの新しいコメントは即座に表示されます:

sdk.showLiveRightAway = true   // デフォルト: 即座に表示

これを false に設定すると、新しいコメントが「N件の新しいコメント」ボタンの背後にバッファされ、ユーザーが表示タイミングを選べるようになります:

sdk.showLiveRightAway = false

ユーザーのプレゼンス

サーバーがプレゼンス追跡を有効にすると、ユーザーのアバター上にオンライン/オフラインのインジケーターが自動的に表示されます。クライアント側での追加設定は不要です。



ページネーション Internal Link

ページサイズ

// コメント:デフォルトは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によって自動的に処理されます。



状態と可観測性 Internal Link

FastCommentsSDKFastCommentsFeedSDK はどちらも ObservableObject クラスで、@Published プロパティを持ちます。これらは SwiftUI のビューで監視してリアクティブな UI 更新に利用できます。

FastCommentsSDK の @Published プロパティ

プロパティ説明
commentCountOnServerIntサーバー上のコメントの総数
newRootCommentCountIntバッファされた新しいコメント(showLiveRightAway が false のとき)
currentUserUserSessionInfo?現在認証されているユーザー
isSiteAdminBool現在のユーザーがサイト管理者かどうか
isClosedBoolコメントスレッドが閉じられているかどうか
hasBillingIssueBool課金に問題があるかどうか
isLoadingBoolネットワークリクエストが進行中かどうか
hasMoreBoolさらにページが存在するかどうか
blockingErrorMessageString?UI の動作を妨げるエラー
warningMessageString?ブロッキングしない警告メッセージ
isDemoBoolデモモードで実行されているかどうか
commentsVisibleBoolコメント表示の切り替え
toolbarEnabledBool書式ツールバーが表示されているかどうか

FastCommentsFeedSDK の @Published プロパティ

プロパティ説明
feedPosts[FeedPost]現在読み込まれているフィード投稿
hasMoreBoolさらにページが存在するかどうか
currentUserUserSessionInfo?現在認証されているユーザー
blockingErrorMessageString?ブロッキングエラーのメッセージ
isLoadingBoolネットワークリクエストが進行中かどうか
newPostsCountInt前回の読み込み以降の新しい投稿数

コメントツリー

コメントツリーは sdk.commentsTree でアクセスできます:

// レンダリング用の表示されているノードのフラットな一覧
sdk.commentsTree.visibleNodes

// IDでコメントを検索
sdk.commentsTree.commentsById["comment-id"]


EUリージョン Internal Link


EU データセンターを使用するには、設定の region フィールドを設定してください:

let config = FastCommentsWidgetConfig(
    tenantId: "YOUR_TENANT_ID",
    urlId: "my-page",
    region: "eu"
)

これにより、すべての API リクエストと WebSocket 接続が eu.fastcomments.com にルーティングされます。



クリーンアップ Internal Link


SDKインスタンスの使用が終わったら(例: ビューが閉じられるとき)、WebSocket接続を閉じ、バックグラウンドタスクをキャンセルするためにcleanup()を呼び出してください:

sdk.cleanup()

SwiftUI の @StateObject によって管理されているビューでは、通常これは .onDisappear 内、またはビューが解放されるときに呼び出されます。



画像アップロード Internal Link

コメント

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")
])


ユーザーメンション Internal Link


@メンションのオートコンプリートをサポートするユーザーを検索:

let results = try await sdk.searchUsers(query: "jan")
// [UserSearchResult] を返します(userId、username、avatar など)

組み込みの CommentInputBar は @メンションのオートコンプリートを自動的に処理します。



コメントの編集と削除 Internal Link

編集

try await sdk.editComment(commentId: commentId, newText: "Updated text")

サーバーがHTMLを再レンダリングします。ローカルのコメントは自動的に更新されます。

削除

try await sdk.deleteComment(commentId: commentId)

コメントを削除すると、その子孫もローカルツリーから削除されます。

これらの操作は、現在のユーザーがコメントの作成者(またはサイト管理者)の場合、UIのコメントコンテキストメニューから利用できます。



エラー処理 Internal Link

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 のプロパティ:

  • code -- API からのエラーコード
  • reason -- 英語のエラー説明
  • translatedError -- サーバーから提供されるローカライズされたエラーメッセージ

ブロッキングエラーは sdk.blockingErrorMessage を通じて自動的に通知され、組み込みのビューがユーザーに表示します。



ローカリゼーション Internal Link


サーバー提供の文字列をローカライズするには、config にロケールコードを渡します:

let config = FastCommentsWidgetConfig(
    tenantId: "YOUR_TENANT_ID",
    urlId: "my-page",
    locale: "fr_fr"
)

クライアント側の UI 文字列は iOS のバンドルベースのローカリゼーションを使用します。



サンプルアプリ Internal Link

このリポジトリには、ExampleApp/ に完全なサンプルアプリが含まれており、以下のデモを示しています:

  • スレッド化されたコメント(SSOおよびカスタムテーマ対応)
  • 投稿作成とタグフィルタリングを備えたソーシャルフィード
  • ライブチャット
  • シンプルかつ安全なSSOフロー
  • カスタムツールバーボタン(コメントおよびフィード)

ヘルプが必要ですか?

iOS Library に関して問題が発生した場合や質問がある場合は、次のいずれかを行ってください:

貢献

貢献を歓迎します!コントリビューションのガイドラインについては、GitHub リポジトリをご覧ください。