qriib_meet 0.1.0 copy "qriib_meet: ^0.1.0" to clipboard
qriib_meet: ^0.1.0 copied to clipboard

Flutter APIs for creating Qriib rooms and embedding secure, customizable audio and video meeting experiences.

qriib_meet #

Flutter room and meeting APIs for Qriib applications.

Getting started #

Add the package to your Flutter application, create a single client from trusted credentials, create or join a room, then open the fresh final_link returned by Qriib. The SDK owns request signing and the embedded meeting experience; your application owns its navigation, identity, and secure credential delivery.

QriibMeetClient keeps room REST calls and the meeting experience together:

The identifiers and room settings below are application-owned values. Obtain them from authenticated application state or your backend; do not copy user data, credentials, or environment-specific values into source code.

Use the built-in newClientRoomId() for every create-room request. It creates a cryptographically random UUID-style string and contains no user data, credentials, or room metadata.

final qriib = QriibMeetClient.withProjectCredentials(
  apiKey: const String.fromEnvironment('QRIIB_API_KEY'),
  secretKey: const String.fromEnvironment('QRIIB_SECRET_KEY'),
  enableNetworkLogging: false,
);

final response = await qriib.rooms.createQuickVideoRoom(
  projectId: projectId,
  moderatorId: moderatorId,
  name: participantName,
  maxParticipants: roomCapacity,
  emptyTimeout: emptyRoomTimeoutSeconds,
  clientRoomId: newClientRoomId(),
  metadata: QriibRoomMetadata(
    roomTitle: roomTitle,
    welcomeMessage: welcomeMessage,
  ),
);

final payload = response['data'] is Map
    ? Map<String, dynamic>.from(response['data'] as Map)
    : response;
final finalLink = payload['final_link'] as String;

await qriib.meetings.join(
  context: context,
  finalLink: finalLink,
  userName: participantName,
  configuration: meetingConfiguration,
);

Use the built-in openMeetingFromResponse to extract the response’s fresh final_link and open the meeting. It throws QriibMeetException when the link is absent and automatically disables video when audioOnly is true:

await openMeetingFromResponse(
  context: context,
  qriib: qriib,
  response: response,
  userName: participantName,
  audioOnly: isAudioRoom,
  configuration: meetingConfiguration,
);

For a room created with createQuickAudioRoom (or a scheduled audio room), join with videoEnabled: false:

await qriib.meetings.join(
  context: context,
  finalLink: finalLink,
  videoEnabled: false,
);

This requests microphone permission only and never starts the camera. The default video-off control remains visible but disabled, with an accessibility label and tooltip explaining that video is unavailable in an audio-only room.

QriibMeetingConfiguration is optional. Without it, the package displays its premium default meeting view. The supplied builders receive Qriib session and participant types only; consumers do not need to import the media engine.

Always obtain a fresh final_link before joining. Do not store or log it.

Meeting UI configuration #

Pass a QriibMeetingConfiguration to join or openMeetingFromResponse to style the built-in meeting surface or replace individual regions. All options are optional; omit a builder to retain that part of the premium default UI.

final meetingConfiguration = QriibMeetingConfiguration(
  title: meetingTitle,
  theme: QriibMeetingTheme(
    backgroundColor: meetingBackgroundColor,
    surfaceColor: meetingSurfaceColor,
    primaryColor: brandColor,
    dangerColor: leaveButtonColor,
    tileColor: participantTileColor,
    participantNameStyle: participantNameTextStyle,
    topBarTextStyle: topBarTextStyle,
    cameraOnIcon: cameraOnIcon,
    cameraOffIcon: cameraOffIcon,
    microphoneOnIcon: microphoneOnIcon,
    microphoneOffIcon: microphoneOffIcon,
    leaveIcon: leaveIcon,
  ),
  showTopBar: showTopBar,
  showParticipantNames: showParticipantNames,
  showCameraControl: showCameraControl,
  showMicrophoneControl: showMicrophoneControl,
  showLeaveControl: showLeaveControl,
  videoAvailable: roomAllowsVideo,
  onCameraChanged: (session, enabled) {
    // Update app-owned UI or analytics without recording sensitive media data.
  },
  onMicrophoneChanged: (session, enabled) {
    // Update app-owned UI or analytics without recording sensitive media data.
  },
  onLeaveRequested: (session) async {
    // Return false to keep the participant in the meeting.
    return await confirmLeaveWithUser();
  },
);

Visibility and audio-only behavior #

showTopBar, showParticipantNames, showCameraControl, showMicrophoneControl, and showLeaveControl hide default elements. videoAvailable controls whether video is permitted. For audio-only rooms, join with videoEnabled: false and keep videoAvailable: false: the package renders a visible, disabled camera-off control with an accessible explanation, instead of starting a camera or hiding the reason it is unavailable.

Replace individual regions #

The three builders receive neutral Qriib types and a QriibMeetingSession:

final meetingConfiguration = QriibMeetingConfiguration(
  participantBuilder: (context, participant, video, session) {
    // `video` is the SDK-provided renderer. Do not retain it when local video
    // is disabled; listen to the neutral session state instead.
    return ValueListenableBuilder<QriibMeetingState>(
      valueListenable: session.state,
      builder: (context, state, child) {
        final localCameraOff = participant.isLocal && !state.cameraEnabled;
        if (!localCameraOff) return video;
        final initial = participant.label.isEmpty
            ? fallbackInitial
            : participant.label.characters.first.toUpperCase();
        return ColoredBox(
          color: participantTileColor,
          child: Center(child: CircleAvatar(child: Text(initial))),
        );
      },
    );
  },
  topBarBuilder: (context, state, session) => MeetingHeader(
    title: meetingTitle,
    participantCount: state.participants.length,
  ),
  controlsBuilder: (context, state, session) => MeetingControls(
    cameraEnabled: state.cameraEnabled,
    microphoneEnabled: state.microphoneEnabled,
    onCameraPressed: () => session.setCameraEnabled(!state.cameraEnabled),
    onMicrophonePressed: () =>
        session.setMicrophoneEnabled(!state.microphoneEnabled),
    onLeavePressed: session.leave,
  ),
);

When replacing controls, provide the same accessible labels, focus behavior, disabled video indication for audio-only rooms, and a way to leave. When replacing participant tiles, do not render a camera frame when the relevant camera state is off; show an initial/avatar on a fixed background instead.

Host permissions #

Add these declarations to the host app's android/app/src/main/AndroidManifest.xml, directly under <manifest>:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

On iOS, add purpose strings to the host application's ios/Runner/Info.plist:

<key>NSCameraUsageDescription</key>
<string>Use the camera to share video in a meeting.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Use the microphone to share audio in a meeting.</string>

permission_handler_apple also requires the iOS host's Podfile to enable the camera and microphone permission macros. Add these definitions to every Pods build configuration in the post_install hook:

config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
  '$(inherited)',
  'PERMISSION_CAMERA=1',
  'PERMISSION_MICROPHONE=1',
]

The example app is a generated Android/iOS smoke host. It reads QRIIB_API_KEY, QRIIB_SECRET_KEY, and a fresh QRIIB_FINAL_LINK from compile-time environment definitions; it contains no credential or link values. Supply them through your development or CI secret store when running the example on a trusted device.

Transport and credentials #

qriib_meet owns the signed Qriib V4 transport. Applications do not create a second HTTP client, manually set key or hash-signature, or depend on a separate V.cloud package. Keep project API credentials and fresh final_link values out of source control and application logs.

Room workflows #

The integration examples use a single QriibMeetClient for the lifetime of the host widget, then call close() from dispose().

Quick rooms #

Supply a unique clientRoomId for each create request. Quick video rooms can be opened immediately from the response:

final response = await qriib.rooms.createQuickVideoRoom(
  projectId: projectId,
  clientRoomId: clientRoomId,
  moderatorId: moderatorId,
  name: participantName,
  maxParticipants: roomCapacity,
  emptyTimeout: emptyRoomTimeoutSeconds,
  metadata: QriibRoomMetadata(
    roomTitle: roomTitle,
    welcomeMessage: welcomeMessage,
  ),
);

final payload = response['data'] is Map
    ? Map<String, dynamic>.from(response['data'] as Map)
    : response;
final finalLink = payload['final_link'] as String;

Use createQuickAudioRoom for an audio-only room, then join it with videoEnabled: false as shown above.

Scheduled rooms #

Use createScheduledVideoRoom or createScheduledAudioRoom with the same room fields plus an ISO-8601 startAt value. When it is time to open the room, call:

final response = await qriib.rooms.startScheduledRoom(
  roomId,
  name: participantName,
);

Extract the fresh final_link from that response before joining. Set videoEnabled: false only when starting an audio room.

Join and manage rooms #

await qriib.rooms.joinRoom(
  roomId: roomId,
  userInfo: const QriibUserInfo(
    name: participantName,
    role: 'attendee',
    isAdmin: false,
    isHidden: false,
  ),
);

The client also provides createInvitationLink, endRoom, getRoomStatus, getActiveRoomInfo, getActiveRoomsInfo, and fetchPastRooms. Catch QriibApiException and QriibMeetException to show their user-safe message values.

Complete Rooms API map #

The bundled example implements every operation below. Inputs marked “room ID” must refer to the room returned by a previous create response.

Operation Method and required inputs Result / next step
Quick video createQuickVideoRoom(projectId, clientRoomId, metadata, name, moderatorId, maxParticipants, emptyTimeout) Extract final_link, then join with video enabled.
Quick audio createQuickAudioRoom(...) with the same fields Extract final_link, then join with videoEnabled: false.
Scheduled video createScheduledVideoRoom(projectId, clientRoomId, startAt, metadata, maxParticipants, emptyTimeout) Store the returned room ID and start it later.
Scheduled audio createScheduledAudioRoom(...) with the same scheduled fields Start later, then join with videoEnabled: false.
Start scheduled startScheduledRoom(roomId, name: participantName) Extract its fresh final_link; select audio/video to match the room type.
Join joinRoom(roomId: roomId, userInfo: QriibUserInfo(...)) Extract its fresh final_link and open the meeting.
Invitation createInvitationLink(roomId: roomId, role: QriibInvitationRole.attendee) Share the returned HTTP(S) link only with the intended participant.
Inspect active room getActiveRoomInfo(roomId) Displays current active-room details.
Inspect all active rooms getActiveRoomsInfo() Displays the active-room collection.
Status getRoomStatus(roomId) Displays the current lifecycle status.
Past rooms fetchPastRooms(projectId: projectId, from: offset, limit: pageSize, orderBy: QriibPastRoomsOrder.desc) Displays a paged, newest-first history.
End endRoom(roomId) Ends an active room; confirm this action with the user before invoking it in production.

final_link is short-lived meeting access data. Read it from either response['data']['final_link'] or response['final_link'], use it immediately, and do not persist it.

Run the complete example #

The example application is a full Rooms API playground. It covers quick and scheduled audio/video rooms, joining, invitation links, active and past room lookups, status, and ending rooms. It has no embedded secrets.

Run it on a trusted device with values supplied only at build time:

cd example
flutter run \
  --dart-define=QRIIB_API_KEY=your-project-api-key \
  --dart-define=QRIIB_SECRET_KEY=your-project-secret \
  --dart-define=QRIIB_PROJECT_ID=your-project-id

The example displays API responses in an in-app dialog and automatically opens the meeting when a create, join, or start response contains a final_link. Treat all credentials and final links as sensitive: do not commit, log, or send them through analytics.

1
likes
0
points
168
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter APIs for creating Qriib rooms and embedding secure, customizable audio and video meeting experiences.

Homepage

License

unknown (license)

Dependencies

async, collection, connectivity_plus, crypto, dart_jsonwebtoken, dart_webrtc, device_info_plus, dio, fixnum, flutter, flutter_webrtc, http, json_annotation, logging, meta, mime_type, path, permission_handler, pretty_dio_logger, protobuf, sdp_transform, synchronized, uuid, web

More

Packages that depend on qriib_meet

Packages that implement qriib_meet