deewan

Deewan video meetings for Flutter — end-to-end encrypted, in Arabic and English. Two ways in:

Embed Your own interface
You build One widget The whole UI
From your server A join link A media token
Features All of Deewan's, ready-made Everything a participant can do, as methods and streams
Strict encrypted rooms Yes Yes
flutter pub add deewan

Embed Deewan's meeting

Your server creates a join link (POST /rooms/{id}/join-links) for the signed-in person and returns its url.

import 'package:deewan/deewan.dart';

DeewanMeetingView(
  joinUrl: url,
  onExit: (_) => Navigator.of(context).pop(),
  onError: (message) => showError(message),
);

The view only loads https links on deewan.io, grants the camera and microphone only to the meeting, and never navigates away from Deewan: when the person leaves or the meeting ends, onExit is called instead.

Your own interface

Your server calls POST /rooms/{id}/tokens and returns the response.

import 'package:deewan/custom.dart';

final meeting = await DeewanMeeting.join(
  MeetingCredentials.fromJson(response),
  microphone: true,
  camera: true,
);

// meeting.room is a ChangeNotifier: rebuild with ListenableBuilder.
for (final person in meeting.participants) {
  final video = meeting.videoTrack(person.id);
  if (video != null) VideoTrackRenderer(video);
}

Everything a participant can do

You want to… Call Listen to
Camera and microphone setCamera(on) · setMicrophone(on) meeting.room (ChangeNotifier)
Chat and reactions sendMessage(text) · sendReaction(emoji) messages · reactions
Raise a hand raiseHand(true) / raiseHand(false) handRaised, handRaisedAt
Answer a poll polls() · vote(pollId, optionIds) pollChanges
Live captions for yourself setCaptions(true) captions
Webinar Q&A ask(text) · voteQuestion(id) · hosts: markQuestion(id, answered: true) questionChanges
Recording indicator meeting.recording recordingChanges
Breakout announcements — announcements
Strict encryption exchangeKey() before the token securityChanges: the code to compare
Leave leave() left (why it ended)

Each DeewanParticipant has id, name, isSelf, isHost, isCohost, isGuest, micOn, camOn, isScreenSharing, isSpeaking, handRaised, handRaisedAt, captionsOn, onStage and isAudience. Participant actions throw DeewanException with the API's status and code. Host powers stay on your server, through the REST API.

Strict end-to-end encryption

final key = exchangeKey(); // the private half never leaves the device
// Your server: POST /rooms/{id}/tokens with { "name": …, "exchange_key": key }
final meeting = await DeewanMeeting.join(MeetingCredentials.fromJson(response));
meeting.securityChanges.listen((s) => setState(() => code = s.code));

The code matches every other screen in the meeting, including Deewan's own web and mobile apps.

Permissions

iOS: NSCameraUsageDescription and NSMicrophoneUsageDescription in Info.plist. Android: CAMERA, RECORD_AUDIO, MODIFY_AUDIO_SETTINGS and INTERNET.

Security

  • Never put an API key in an app: your server issues the join link or token for the signed-in person and returns only that.
  • Media, chat and reactions are encrypted on the device before they are sent; in strict rooms only the people in the meeting hold the key.
  • Tokens are only sent over HTTPS/WSS (plain http is refused except to localhost).

MIT © Deewan

Libraries

custom
Join a Deewan meeting from Flutter and draw your own interface, end-to-end encrypted.
deewan
Deewan video meetings for Flutter.