Skip to content

Commit 2301ecd

Browse files
authored
feat: desktop screensharing (#865)
* feat: screen sharing for desktops * feat: Add localizations * docs: Add documentation and custom example * feat: add melos command for gen-l10n * fix: remove delay for _getSources
1 parent 5fbad7a commit 2301ecd

24 files changed

+765
-2
lines changed

dogfooding/lib/app/app_content.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import 'package:firebase_core/firebase_core.dart';
55
import 'package:firebase_messaging/firebase_messaging.dart';
66
import 'package:flutter/foundation.dart';
77
import 'package:flutter/material.dart';
8+
import 'package:flutter_dogfooding/app/custom_video_localizations.dart';
89
import 'package:flutter_dogfooding/core/repos/token_service.dart';
910
import 'package:flutter_dogfooding/router/routes.dart';
1011
import 'package:flutter_dogfooding/theme/app_palette.dart';
1112
import 'package:google_fonts/google_fonts.dart';
1213
import 'package:rxdart/rxdart.dart';
1314
import 'package:stream_video_flutter/stream_video_flutter.dart';
15+
import 'package:stream_video_flutter/stream_video_flutter_l10n.dart';
1416

1517
import '../core/repos/app_preferences.dart';
1618
import '../di/injector.dart';
@@ -262,6 +264,11 @@ class _StreamDogFoodingAppContentState
262264
title: kAppName,
263265
routerConfig: _router,
264266
theme: _buildTheme(Brightness.dark),
267+
supportedLocales: const [Locale('en'), Locale('nl')],
268+
localizationsDelegates: [
269+
CustomVideoLocalizationsNL.delegate,
270+
...StreamVideoFlutterLocalizations.localizationsDelegates,
271+
],
265272
builder: (context, child) {
266273
return child!;
267274
},
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import 'package:flutter/widgets.dart';
2+
import 'package:stream_video_flutter/stream_video_flutter_l10n.dart';
3+
4+
class CustomVideoLocalizationsNL extends StreamVideoFlutterLocalizationsNl {
5+
static LocalizationsDelegate<StreamVideoFlutterLocalizations> get delegate =>
6+
CustomVideoLocalizationsDelegate('nl', CustomVideoLocalizationsNL());
7+
8+
@override
9+
String get desktopScreenShareEntireScreen => 'Scherm';
10+
}

dogfooding/lib/screens/call_screen.dart

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import '../app/user_auth_controller.dart';
2323
import '../di/injector.dart';
2424
import '../widgets/closed_captions_widget.dart';
2525

26+
const _useCustomDesktopScreenShareOption = false;
27+
2628
class CallScreen extends StatefulWidget {
2729
const CallScreen({
2830
super.key,
@@ -264,6 +266,10 @@ class _CallScreenState extends State<CallScreen> {
264266
enabledScreenShareBackgroundColor:
265267
AppColorPalette.primary,
266268
disabledScreenShareIcon: Icons.screen_share,
269+
desktopScreenSelectorBuilder:
270+
_useCustomDesktopScreenShareOption
271+
? _customDesktopScreenShareSelector
272+
: null,
267273
),
268274
ToggleMicrophoneOption(
269275
call: call,
@@ -330,3 +336,30 @@ class ChatBottomSheet extends StatelessWidget {
330336
);
331337
}
332338
}
339+
340+
// This is an example of a bottom sheet that only allows the selection of a screen.
341+
// After tapping a screen the bottom sheet is directly closed and the screen is shared.
342+
Future<DesktopCapturerSource?> _customDesktopScreenShareSelector(
343+
BuildContext context) {
344+
final ScreenSelectorStateNotifier stateNotifier =
345+
ScreenSelectorStateNotifier(sourceTypes: [SourceType.Screen]);
346+
347+
return showModalBottomSheet<DesktopCapturerSource?>(
348+
context: context,
349+
builder: (BuildContext context) {
350+
return ValueListenableBuilder(
351+
valueListenable: stateNotifier,
352+
builder:
353+
(BuildContext context, ScreenSelectorState value, Widget? child) =>
354+
Padding(
355+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
356+
child: ThumbnailGrid(
357+
sources: value.sources.values.toList(),
358+
selectedSource: value.selectedSource,
359+
onSelectSource: (source) => Navigator.pop(context, source),
360+
),
361+
),
362+
);
363+
},
364+
);
365+
}

melos.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ scripts:
9595
run: melos exec -c 1 --depends-on="build_runner" --flutter -- "flutter pub run build_runner build --delete-conflicting-outputs"
9696
description: Build all generated files for Flutter packages in this project.
9797

98+
gen-l10n: >
99+
melos exec -c 1 --fail-fast --depends-on=flutter_localizations -- \
100+
"flutter gen-l10n && dart format ."
101+
98102
test:all:
99103
run: melos run test:dart --no-select && melos run test:flutter --no-select
100104
description: Run all Dart & Flutter tests in this project.

packages/stream_video/lib/src/webrtc/rtc_track/rtc_local_track.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ extension RtcLocalScreenShareTrackExt on RtcLocalScreenShareTrack {
369369
}
370370

371371
return mediaConstraints.useiOSBroadcastExtension ==
372-
constraints.useiOSBroadcastExtension;
372+
constraints.useiOSBroadcastExtension &&
373+
mediaConstraints.deviceId == constraints.deviceId;
373374
}
374375
}

packages/stream_video/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ dependencies:
2323
sdk: flutter
2424
http: ^1.1.0
2525
internet_connection_checker_plus: ^2.5.2
26-
intl: ">=0.18.1 <=0.19.0"
26+
intl: ">=0.18.1 <=0.21.0"
2727
jose: ^0.3.4
2828
meta: ^1.9.1
2929
package_info_plus: ^8.2.1

packages/stream_video_flutter/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
ignoresPersistentStateOnLaunch = "NO"
4949
debugDocumentVersioning = "YES"
5050
debugServiceExtension = "internal"
51+
enableGPUValidationMode = "1"
5152
allowLocationSimulation = "YES">
5253
<BuildableProductRunnable
5354
runnableDebuggingMode = "0">
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
synthetic-package: false
2+
arb-dir: lib/src/l10n/arb
3+
output-dir: lib/src/l10n/localizations
4+
template-arb-file: stream_video_flutter_en.arb
5+
output-localization-file: stream_video_flutter_localizations.dart
6+
output-class: StreamVideoFlutterLocalizations

packages/stream_video_flutter/lib/src/call_controls/controls/toggle_screen_sharing_option.dart

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class ToggleScreenShareOption extends StatelessWidget {
1717
this.disabledScreenShareIconColor,
1818
this.enabledScreenShareBackgroundColor,
1919
this.disabledScreenShareBackgroundColor,
20+
this.desktopScreenSelectorBuilder,
2021
});
2122

2223
/// Represents a call.
@@ -48,9 +49,12 @@ class ToggleScreenShareOption extends StatelessWidget {
4849

4950
final NotificationOptionsBuilder? screenSharingNotificationOptionsBuilder;
5051

52+
final DesktopScreenSelectorBuilder? desktopScreenSelectorBuilder;
53+
5154
@override
5255
Widget build(BuildContext context) {
5356
final enabled = localParticipant.isScreenShareEnabled;
57+
var screenShareConstraints = this.screenShareConstraints;
5458

5559
return CallControlOption(
5660
icon: enabled
@@ -64,6 +68,19 @@ class ToggleScreenShareOption extends StatelessWidget {
6468
onPressed: () async {
6569
final toggledEnabled = !enabled;
6670

71+
if (CurrentPlatform.isDesktop && toggledEnabled) {
72+
final source = await (desktopScreenSelectorBuilder?.call(context) ??
73+
showDefaultScreenSelectionDialog(context));
74+
75+
if (source != null) {
76+
screenShareConstraints =
77+
(screenShareConstraints ?? const ScreenShareConstraints())
78+
.copyWith(deviceId: source.id);
79+
} else {
80+
return;
81+
}
82+
}
83+
6784
if (CurrentPlatform.isAndroid) {
6885
if (toggledEnabled) {
6986
if (!await call.requestScreenSharePermission()) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"desktopScreenShareChooseDialogTitle": "Choose what to share",
3+
"@desktopScreenShareChooseDialogTitle": {
4+
"description": "Title for dialog to choose for a window or screen to share"
5+
},
6+
"desktopScreenShareChooseDialogShare": "Share",
7+
"@desktopScreenShareChooseDialogShare": {
8+
"description": "Share action to start sharing"
9+
},
10+
"desktopScreenShareChooseDialogCancel": "Cancel",
11+
"@desktopScreenShareChooseDialogCancel": {
12+
"description": "Cancel action to go back without sharing"
13+
},
14+
"desktopScreenShareEntireScreen": "Entire Screen",
15+
"@desktopScreenShareEntireScreen": {
16+
"description": "Tab to select a screen to share"
17+
},
18+
"desktopScreenShareWindow": "Window",
19+
"@desktopScreenShareWindow": {
20+
"description": "Tab to select a single window to share"
21+
}
22+
}

0 commit comments

Comments
 (0)