Language: English | 简体中文
Flutter chat client / example app built on Tim2Tox
- What toxee is: a runnable Flutter chat app that uses Tencent Cloud Chat UIKit for UI and tox as the backend over the Tox P2P network.
- What Tim2Tox is: the compatibility layer / framework that bridges UIKit-style APIs to tox (located in
third_party/tim2tox, upstream repo: anonymoussoft/tim2tox); it is not the chat application itself. - One-line architecture summary: toxee integrates Tim2Tox with a hybrid approach of "binary replacement + Platform", where most SDK calls still go through
NativeLibraryManager -> Dart*, while history, polling, calling, and some stateful flows are implemented throughTim2ToxSdkPlatform -> FfiChatService. - Shortest path to run it: clone ->
dart run tool/bootstrap_deps.dart->flutter pub get->./build_all.sh --platform macos --mode debugor./run_toxee.sh.
For deeper implementation details and role-based reading paths, see doc/README.en.md.
toxee is a Flutter chat client / example app built on tox. It shows how to integrate tox with Tencent Cloud Chat UIKit to build a decentralized P2P chat experience: account flows, conversations, messages, contacts, groups, Bootstrap, optional calling, and extension points are all implemented or wired up in this repository.
Clearly defined:
- It is: a runnable Flutter application for developers who want to get something working quickly, and for maintainers who want to understand the relationship between a client app and Tim2Tox. It also serves as a reference implementation for integrating Tim2Tox.
- It is not: the low-level protocol library (protocol behavior and V2TIM mapping live in Tim2Tox).
- It is not: a general-purpose SDK (UI, account flows, Bootstrap configuration, calling bridge, and app-level wiring are toxee-specific and must be adapted for other clients).
- For users of the codebase: it provides a ready-to-run Tox chat client with UIKit-based screens and interactions, so you do not need to build the UI from scratch.
- For integrators: it demonstrates dependency bootstrap (submodules, SDK fetch + patching,
pubspec_overrides), Tim2Tox interface injection (preferences, logger, Bootstrap, and related adapters), and the startup sequence ofinit -> login -> startPolling -> Platform. - For maintainers: it explains why the current hybrid architecture exists, what binary replacement and Platform each own, and where to inspect call chains and logs when debugging or extending the app.
| Dimension | Tim2Tox | toxee |
|---|---|---|
| Role | Compatibility layer / framework: provides the C++ core, C FFI, Dart wrappers, and SDK Platform implementation that any Flutter client can integrate with. | Client app / example app: consumes Tim2Tox and implements account flows, UI, Bootstrap, history, calling bridge, and app-specific wiring. |
| Location | third_party/tim2tox (git submodule, upstream: anonymoussoft/tim2tox). |
Repository root. |
| Dependency direction | Tim2Tox does not depend on toxee; it receives capabilities such as preferences, logging, and Bootstrap through interfaces. | toxee depends on tim2tox_dart, implements the interfaces Tim2Tox expects, constructs FfiChatService, and configures the Platform path. |
Call relationship (simplified):
toxee (UI / account / Bootstrap / adapters)
|
|-- setNativeLibraryName('tim2tox_ffi') -> SDK loads libtim2tox_ffi
|-- FfiChatService(prefs, logger, bootstrap, ...) -> Tim2Tox service layer
|-- Tim2ToxSdkPlatform(ffiService) -> Platform path entry
'-- FakeUIKit / FakeMessageManager / ... -> adapt Tim2Tox data into UIKit models
|
v
Tim2Tox (dart / ffi / C++)
|
v
c-toxcore (Tox P2P)
The app currently uses a hybrid architecture: it keeps binary replacement (the SDK still reaches Tim2Tox through NativeLibraryManager -> Dart*) and also enables Tim2ToxSdkPlatform (history, some callbacks, calling, and stateful flows go through FfiChatService).
Why hybrid instead of pure binary replacement or pure Platform?
- Pure binary replacement keeps business code changes minimal, but history messages,
clearHistoryMessage,groupQuitNotification, Bootstrap configuration, polling, and calling all need Dart-side state and persistence. Those flows are incomplete if implemented only with C++ callbacks; UIKit APIs such asgetHistoryMessageListwould fail or behave inconsistently. - Pure Platform would route all SDK calls through Platform APIs, which means implementing many more methods and tracking SDK version changes closely. It is costly to migrate and maintain, and some SDK behavior still assumes the native library is loaded even when
isCustomPlatformis enabled. - Hybrid keeps the "swap the library, keep the call surface" benefits for most SDK usage, while moving the parts that must remain in Dart (history, polling, Bootstrap, calling bridge, and selected callbacks) into
Platform + FfiChatService. That gives a better balance between compatibility and completeness. See doc/architecture/HYBRID_ARCHITECTURE.en.md.
Call chain (ASCII):
UIKit / app logic
|
+-----------------+-----------------+
| |
TIMManager.instance getHistoryMessageList / ...
| |
NativeLibraryManager Tim2ToxSdkPlatform
bindings.DartXXX() |
| |
+-----------------+-----------------+
|
libtim2tox_ffi (dart_compat_* / tim2tox_ffi_*)
|
FfiChatService (polling, history, login state)
|
V2TIM*Manager / ToxManager -> c-toxcore
| Path | Responsibility |
|---|---|
lib/ |
App Dart code: UI, startup flow, adapters, utilities. |
lib/bootstrap/ |
Earliest startup work: logging, paths, setNativeLibraryName('tim2tox_ffi'), native log file setup. |
lib/adapters/ |
Tim2Tox interface implementations: preferences, logger, Bootstrap, event bus, conversation manager, and related adapters injected into FfiChatService. |
lib/sdk_fake/ |
Data adaptation layer that converts Tim2Tox / FfiChatService data into the fake UIKit models/providers expected by Tencent Cloud Chat UIKit. |
lib/ui/ |
Pages and widgets: login, home, conversations, settings, Bootstrap, and related UI. Mostly UIKit-based with a small number of custom pages. |
lib/util/ |
Shared helpers such as AppLogger, preferences, Bootstrap node lists, theme, and language utilities. |
lib/startup/ |
Startup orchestration: account restore, Bootstrap decisions, init -> login -> startPolling, plus timeout and error handling. |
lib/call/ |
Calling UI and effects, including TUICallKit integration and incoming-call overlay behavior. |
tool/ |
Dependency bootstrap tooling, especially bootstrap_deps.dart for submodules, SDK fetch, patching, and pubspec_overrides. |
third_party/ |
Vendored dependencies: Tim2Tox, Tencent Cloud Chat SDK, chat-uikit-flutter, and related assets fetched by scripts or submodules. |
doc/ |
Architecture, build, troubleshooting, integration, and maintainer documentation. |
Shortest path from a fresh clone (run in the repository root):
# 1. Clone the repo (if you have not already)
git clone <repo-url> toxee && cd toxee
# 2. Bootstrap dependencies: submodules, SDK fetch + patching,
# and pubspec_overrides generation
dart run tool/bootstrap_deps.dart
# 3. Fetch Dart / Flutter dependencies
flutter pub get
# 4. Build and run (this also builds the tim2tox FFI library)
./build_all.sh --platform macos --mode debug
# Or use the convenience runner (build + launch + optional log tail)
./run_toxee.shIf you hit a package_config.json parse error, run dart tool/bootstrap_deps.dart first (without run), then run flutter pub get. Full setup steps and common issues are documented in doc/getting-started.en.md and doc/operations/DEPENDENCY_BOOTSTRAP.en.md.
- Unified build:
./build_all.sh --platform <macos|ios|android|...> --mode <debug|release> - Run only:
./run_toxee.sh(other platform helpers includerun_toxee_ios.sh,run_toxee_android.sh, and related scripts) - For detailed platform steps, dependency layout, and deployment notes, see doc/operations/BUILD_AND_DEPLOY.en.md, doc/operations/DEPENDENCY_BOOTSTRAP.en.md, and doc/operations/DEPENDENCY_LAYOUT.en.md. For debugging issues, see doc/TROUBLESHOOTING.en.md.
The repository now includes .github/workflows/build-packages.yml, which runs on push, pull request, tag push, and manual dispatch. It builds and uploads artifacts for:
- Windows
- Linux
- macOS
- Android
- iOS
Each job uploads the contents of dist/<platform>/ as a GitHub Actions artifact. Desktop jobs build the host Tim2Tox FFI library and bundle it into the packaged app output. Android builds both app-release.apk and app-release.aab; if the secrets ANDROID_KEYSTORE_BASE64, ANDROID_KEYSTORE_PASSWORD, ANDROID_KEY_ALIAS, and ANDROID_KEY_PASSWORD are present, the workflow uses them for release signing, otherwise it falls back to the project's existing debug-key release signing.
iOS now has two modes:
- With
IOS_CERTIFICATE_P12_BASE64,IOS_CERTIFICATE_PASSWORD, andIOS_PROVISIONING_PROFILE_BASE64configured, the workflow performs a signedflutter build ios --releaseand packages a real.ipa. - Without those secrets, the iOS job still runs as an unsigned validation build, but it does not publish an installable package. Instead,
dist/ios/NOTES.txtexplains that signing was not configured.
Mobile jobs also write dist/<platform>/NOTES.txt when Tim2Tox mobile native artifacts were not available in the workspace, so CI keeps that remaining native-injection gap explicit instead of silently pretending the package is complete.
Publishing to GitHub Releases is built into the same workflow:
- Push a tag like
v1.2.3to build all platforms and publish a GitHub Release automatically. - Or run
workflow_dispatch, setpublish_release=true, and providerelease_tag(optionallyprerelease=true). - The publish job downloads the artifacts from the current run, uploads the packaged installables to the Release, and adds a generated
SHA256SUMS.txt. - Release notes use GitHub's
--generate-notesflow, while platform-specific packaging caveats are merged into the uploaded build-note assets.
For the full documentation index and role-based reading paths (new users / integrators / maintainers), start with doc/README.en.md.
Common entry points:
Good fits:
- You want to quickly run a Flutter chat app on top of Tox.
- You want a reference for integrating Tim2Tox into a client, including dependency bootstrap, interface injection, startup order, and the hybrid architecture split.
- You plan to extend or customize toxee itself (UI, Bootstrap, calling, plugins, or related features).
Non-goals:
- You only need the Tox protocol library or a general-purpose IM SDK. In that case, use Tim2Tox or c-toxcore instead of toxee.
- You need interoperability with Tencent Cloud IM server-side services. toxee uses Tox P2P as its backend and does not connect to Tencent Cloud IM.
- Platform focus: day-to-day build and development are primarily centered on macOS. iOS and Android require platform-specific setup and script validation.
- History and callback ownership: message history lives on the Dart side (
FfiChatService/MessageHistoryPersistence). In the hybrid architecture, binary replacement and Platform paths must not both write history or emit duplicate callbacks; that split is enforced by conventions such asBinaryReplacementHistoryHook. - Multiple instances: toxee uses Tim2Tox's default singleton-style flow. Multi-instance support mainly exists for Tim2Tox auto tests and is not part of the default client workflow.
- Dependencies: the project depends on submodules plus SDK/UIKit content fetched by scripts. After a fresh clone or dependency changes, you must run
dart run tool/bootstrap_deps.dartbeforeflutter pub get.
- Follow the quick start once on your own machine and verify you can log in, send a message, and see the conversation list.
- Read this README's "Understand this project in 5 minutes", "Relationship with Tim2Tox", and "Current architecture at a glance" sections, then follow the role-based reading path in doc/README.en.md.
- If you are touching startup, logging, or dependency bootstrap, start with
lib/main.dart,lib/bootstrap/logging_bootstrap.dart, andtool/bootstrap_deps.dart. - If you are touching messages, conversations, or history, start with
lib/sdk_fake/and doc/architecture/HYBRID_ARCHITECTURE.en.md. - If you need to change Tim2Tox itself, work in
third_party/tim2tox(upstream: anonymoussoft/tim2tox) and use third_party/tim2tox/doc/README.en.md as the local documentation entry point.
See LICENSE.