@@ -3,6 +3,80 @@ import 'dart:async';
33import 'package:flutter/material.dart' ;
44import 'package:flutter_webrtc/flutter_webrtc.dart' ;
55
6+ class ThumbnailWidget extends StatefulWidget {
7+ const ThumbnailWidget (
8+ {Key ? key,
9+ required this .source,
10+ required this .selected,
11+ required this .onTap})
12+ : super (key: key);
13+ final DesktopCapturerSource source;
14+ final bool selected;
15+ final Function (DesktopCapturerSource ) onTap;
16+
17+ @override
18+ _ThumbnailWidgetState createState () => _ThumbnailWidgetState ();
19+ }
20+
21+ class _ThumbnailWidgetState extends State <ThumbnailWidget > {
22+ final List <StreamSubscription > _subscriptions = [];
23+
24+ @override
25+ void initState () {
26+ super .initState ();
27+ _subscriptions.add (widget.source.onThumbnailChanged.stream.listen ((event) {
28+ setState (() {});
29+ }));
30+ _subscriptions.add (widget.source.onNameChanged.stream.listen ((event) {
31+ setState (() {});
32+ }));
33+ }
34+
35+ @override
36+ void deactivate () {
37+ _subscriptions.forEach ((element) {
38+ element.cancel ();
39+ });
40+ super .deactivate ();
41+ }
42+
43+ @override
44+ Widget build (BuildContext context) {
45+ return Column (
46+ children: [
47+ Expanded (
48+ child: Container (
49+ decoration: widget.selected
50+ ? BoxDecoration (
51+ border: Border .all (width: 2 , color: Colors .blueAccent))
52+ : null ,
53+ child: InkWell (
54+ onTap: () {
55+ print ('Selected source id => ${widget .source .id }' );
56+ widget.onTap (widget.source);
57+ },
58+ child: widget.source.thumbnail != null
59+ ? Image .memory (
60+ widget.source.thumbnail! ,
61+ gaplessPlayback: true ,
62+ alignment: Alignment .center,
63+ )
64+ : Container (),
65+ ),
66+ )),
67+ Text (
68+ widget.source.name,
69+ style: TextStyle (
70+ fontSize: 12 ,
71+ color: Colors .black87,
72+ fontWeight:
73+ widget.selected ? FontWeight .bold : FontWeight .normal),
74+ ),
75+ ],
76+ );
77+ }
78+ }
79+
680// ignore: must_be_immutable
781class ScreenSelectDialog extends Dialog {
882 ScreenSelectDialog () {
@@ -19,14 +93,8 @@ class ScreenSelectDialog extends Dialog {
1993 _stateSetter? .call (() {});
2094 }));
2195
22- _subscriptions.add (desktopCapturer.onNameChanged.stream.listen ((source) {
23- _sources[source.id] = source;
24- _stateSetter? .call (() {});
25- }));
26-
2796 _subscriptions
2897 .add (desktopCapturer.onThumbnailChanged.stream.listen ((source) {
29- _sources[source.id] = source;
3098 _stateSetter? .call (() {});
3199 }));
32100 }
@@ -60,15 +128,15 @@ class ScreenSelectDialog extends Dialog {
60128 print (
61129 'name: ${element .name }, id: ${element .id }, type: ${element .type }' );
62130 });
63- _stateSetter? .call (() {
64- sources.forEach ((element) {
65- _sources[element.id] = element;
66- });
67- });
68131 _timer? .cancel ();
69132 _timer = Timer .periodic (Duration (seconds: 3 ), (timer) {
70133 desktopCapturer.updateSources (types: [_sourceType]);
71134 });
135+ _sources.clear ();
136+ sources.forEach ((element) {
137+ _sources[element.id] = element;
138+ });
139+ _stateSetter? .call (() {});
72140 return ;
73141 } catch (e) {
74142 print (e.toString ());
@@ -158,59 +226,16 @@ class ScreenSelectDialog extends Dialog {
158226 .where ((element) =>
159227 element.value.type ==
160228 SourceType .Screen )
161- .map ((e) => Column (
162- children: [
163- Expanded (
164- child: Container (
165- decoration: (_selected_source !=
166- null &&
167- _selected_source!
168- .id ==
169- e.value.id)
170- ? BoxDecoration (
171- border: Border .all (
172- width: 2 ,
173- color: Colors
174- .blueAccent))
175- : null ,
176- child: InkWell (
177- onTap: () {
178- print (
179- 'Selected screen id => ${e .value .id }' );
180- setState (() {
181- _selected_source =
182- e.value;
183- });
184- },
185- child:
186- e.value.thumbnail !=
187- null
188- ? Image .memory (
189- e.value
190- .thumbnail! ,
191- scale: 1.0 ,
192- repeat: ImageRepeat
193- .noRepeat,
194- )
195- : Container (),
196- ),
197- )),
198- Text (
199- e.value.name,
200- style: TextStyle (
201- fontSize: 12 ,
202- color: Colors .black87,
203- fontWeight: (_selected_source !=
204- null &&
205- _selected_source!
206- .id ==
207- e.value
208- .id)
209- ? FontWeight .bold
210- : FontWeight
211- .normal),
212- ),
213- ],
229+ .map ((e) => ThumbnailWidget (
230+ onTap: (source) {
231+ setState (() {
232+ _selected_source = source;
233+ });
234+ },
235+ source: e.value,
236+ selected:
237+ _selected_source? .id ==
238+ e.value.id,
214239 ))
215240 .toList (),
216241 ),
@@ -225,61 +250,16 @@ class ScreenSelectDialog extends Dialog {
225250 .where ((element) =>
226251 element.value.type ==
227252 SourceType .Window )
228- .map ((e) => Column (
229- children: [
230- Expanded (
231- child: Container (
232- decoration: (_selected_source !=
233- null &&
234- _selected_source!
235- .id ==
236- e.value.id)
237- ? BoxDecoration (
238- border: Border .all (
239- width: 2 ,
240- color: Colors
241- .blueAccent))
242- : null ,
243- child: InkWell (
244- onTap: () {
245- print (
246- 'Selected window id => ${e .value .id }' );
247- setState (() {
248- _selected_source =
249- e.value;
250- });
251- },
252- child: e
253- .value
254- .thumbnail!
255- .isNotEmpty
256- ? Image .memory (
257- e.value
258- .thumbnail! ,
259- scale: 1.0 ,
260- repeat:
261- ImageRepeat
262- .noRepeat,
263- )
264- : Container (),
265- ),
266- )),
267- Text (
268- e.value.name,
269- style: TextStyle (
270- fontSize: 12 ,
271- color: Colors .black87,
272- fontWeight: (_selected_source !=
273- null &&
274- _selected_source!
275- .id ==
276- e.value
277- .id)
278- ? FontWeight .bold
279- : FontWeight
280- .normal),
281- ),
282- ],
253+ .map ((e) => ThumbnailWidget (
254+ onTap: (source) {
255+ setState (() {
256+ _selected_source = source;
257+ });
258+ },
259+ source: e.value,
260+ selected:
261+ _selected_source? .id ==
262+ e.value.id,
283263 ))
284264 .toList (),
285265 ),
0 commit comments