Client guide
Web & Mini Program development guide
A complete path through floo-web: choose a build, initialise and authenticate, manage contacts and groups, exchange every message type, receive events, and add voice & video.
Use lanying-im-web for desktop browsers, lanying-im-uniapp for H5 and multi-vendor Mini Programs, or lanying-im-miniprogram for a native WeChat Mini Program. These builds follow the same feature model, but transport and packaging settings differ.
Prerequisites and build selection
| Build | Targets | Configuration |
|---|---|---|
| lanying-im-web | Desktop browsers and traditional front-end applications | Set ws to false. |
| lanying-im-uniapp | H5 plus WeChat, Alipay, Baidu, ByteDance, QQ, DingTalk, and other uni-app targets | Set ws to true. |
| lanying-im-miniprogram | Native WeChat Mini Programs | Use the Mini Program package and platform network/storage adapters. |
- Create an application in the console and copy its App ID.
- Download the matching floo-web or floo-uniapp release.
- For voice & video, install the runtime dependencies used by the Web demo, including webrtc-adapter.
- Choose one application-wide SDK instance; do not create a separate instance per view.
Initialise the SDK
const config = {
//dnsServer: "https://dns.lanying.chat/v2/app_dns",
appid: "YOUR_APP_ID",
ws: false, // true for uni-app, false for web
autoLogin: true
};The module form is the preferred integration. The script form remains available for legacy pages, but the upstream demo documents an initialisation race that requires retry handling.
import flooim from 'floo-3.0.0';
const im = flooim(config);Register, sign in, restore, and sign out
im.userManage.asyncRegister(this.user).then(() => {
console.log("注册成功");
}).catch(ex => {
console.log(ex.message);
});im.login({
name, // User name
password,
});With autoLogin enabled, the SDK restores the previous session from local storage. In production, clear application-specific SDK state rather than unrelated origin storage, and coordinate sign-out with push-token unbinding on mobile containers.
const list = im.userManage.getConversationList();
console.log(list);Contacts and relationship requests
| Task | API |
|---|---|
| Send a contact request | rosterManage.asyncApply({ user_id, alias }) |
| Accept or decline | rosterManage.asyncAccept / asyncDecline |
| Delete a contact | rosterManage.asyncDeleteRoster({ user_id }) |
| Read cached contacts | rosterManage.getAllRosterDetail() |
| Track changes | onRosterListUpdate |
| Block and unblock | rosterManage block-list APIs |
im.rosterManage.asyncApply({ user_id, alias })
.then(() => {
console.log("请求已发送成功!");
});Groups and membership
Group work includes the group lifecycle, membership, roles, invitations, join requests, mute and block lists, announcements, shared files, and per-group notification settings. Load group details before rendering a chat so policy and permissions are current.
im.groupManage
.asyncCreate({
name,
type, // Whether the group is public: 0 or 1
avatar,
description,
user_list, // User IDs
})
.then(() => {
console.log("群创建成功");
});| Lifecycle | API |
|---|---|
| Join / leave | asyncApply({ group_id, reason }) / asyncLeave({ group_id }) |
| Destroy | asyncDestroy({ group_id }) |
| Joined groups | asyncGetJoinedGroups() |
| Group details | asyncGetGroupInfo(group_id) |
| Cached members | getGroupMembers(group_id) |
| Administration | groupManage announcement, role, mute, block-list, and shared-file APIs |
Build messages
| Content | Required fields |
|---|---|
| Text | content plus uid or gid |
| Image | type=image and attachment with dName, fLen, width, height, url |
| File | type=file and file attachment metadata |
| Location | type=location and attachment with lat, lon, addr |
| Voice & video signalling | type=rtc and config with action and callId |
| Custom | A documented custom content type plus extension payload |
const message = {
uid, // User ID; used only for direct chat
gid, // Group ID; used only for group chat
content, // Message text
priority, // Message distribution priority from 0 to 10. Regular chat-room users default to 5 and messages may be dropped; administrators default to 0 and messages are retained. Choose other values for your business needs.
}Send, forward, recall, and receive
im.sysManage.sendRosterMessage(message);
// or
im.sysManage.sendGroupMessage(message);im.on({
onRosterMessage: function(message) {
console.log(message);
}
});
im.on({
onGroupMessage: function(message) {
console.log(message);
}
});- Use onMessageStatusChanged to reconcile local pending messages with server state.
- Handle recall and deletion events by message ID and make each handler idempotent.
- Forward and recall through sysManage; enforce the server recall window in the UI.
- Persist message IDs and conversation IDs rather than relying on rendered-list indexes.
Mentions, typing, and search
im.sysManage.sendMentionMessage({
gid,
txt, // Mention text
mentionAll, // Whether to mention everyone
mentionList, // [id,id ...]
mentionedMessage, // Mention content
pushMessage, // Push notification
senderNickname // Sender nickname
});Typing state is ephemeral and should not be stored as a chat message. Search results are grouped by contact and group; debounce UI input and keep the original SDK result identifiers when navigating to a message.
Voice & video lifecycle
Caller starts the voice or video call
im.rtcManage.initRTCEngine(message);
// or the recipient accepts and joins the call
im.rtcManage.joinRoom(message);- Register onRosterRTCMessage before sending or accepting an invitation.
- Use sendRTCMessage for call signalling and the engine APIs for media state.
- Publish local tracks only after room join succeeds; subscribe after remote sources arrive.
- On every exit path, unpublish, unsubscribe, leave the room, destroy the engine, and remove listeners.
Web troubleshooting
| Symptom | Check |
|---|---|
| flooim export not found | For the documented Babel setup, use sourceType: unambiguous. |
| third/long is missing | Confirm dependency installation completed; the legacy guide notes fsevents-related installation failures. |
| No default export in Vite/Vue 3 | Use the CommonJS compatibility plugins documented by the upstream demo. |
| No voice or video | Use HTTPS or localhost, verify permissions, adapter dependencies, and console feature enablement. |
| Duplicate events | Register listeners once and remove the exact handler during teardown. |