jbilcke-hf HF Staff commited on
Commit
2f88b0d
Β·
1 Parent(s): c0047e4

share button

Browse files
build/web/flutter_bootstrap.js CHANGED
@@ -39,6 +39,6 @@ _flutter.buildConfig = {"engineRevision":"382be0028d370607f76215a9be322e5514b263
39
 
40
  _flutter.loader.load({
41
  serviceWorkerSettings: {
42
- serviceWorkerVersion: "3442266771"
43
  }
44
  });
 
39
 
40
  _flutter.loader.load({
41
  serviceWorkerSettings: {
42
+ serviceWorkerVersion: "1819633575"
43
  }
44
  });
build/web/flutter_service_worker.js CHANGED
@@ -3,11 +3,11 @@ const MANIFEST = 'flutter-app-manifest';
3
  const TEMP = 'flutter-temp-cache';
4
  const CACHE_NAME = 'flutter-app-cache';
5
 
6
- const RESOURCES = {"flutter_bootstrap.js": "c64b96cbce918c8ac7cc2c575969e0b9",
7
  "version.json": "b5eaae4fc120710a3c35125322173615",
8
  "index.html": "f34c56fffc6b38f62412a5db2315dec8",
9
  "/": "f34c56fffc6b38f62412a5db2315dec8",
10
- "main.dart.js": "bfae61d5987aa1b3031b3fe4ec0cb3e7",
11
  "flutter.js": "83d881c1dbb6d6bcd6b42e274605b69c",
12
  "aitube.svg": "26140ba0d153b213b122bc6ebcc17f6c",
13
  "favicon.png": "c8a183c516004e648a7bac7497c89b97",
 
3
  const TEMP = 'flutter-temp-cache';
4
  const CACHE_NAME = 'flutter-app-cache';
5
 
6
+ const RESOURCES = {"flutter_bootstrap.js": "f0b6c27a0f6bac054555f105232f0c00",
7
  "version.json": "b5eaae4fc120710a3c35125322173615",
8
  "index.html": "f34c56fffc6b38f62412a5db2315dec8",
9
  "/": "f34c56fffc6b38f62412a5db2315dec8",
10
+ "main.dart.js": "4e26b37ccf9ca902db38fe5292263609",
11
  "flutter.js": "83d881c1dbb6d6bcd6b42e274605b69c",
12
  "aitube.svg": "26140ba0d153b213b122bc6ebcc17f6c",
13
  "favicon.png": "c8a183c516004e648a7bac7497c89b97",
build/web/main.dart.js CHANGED
The diff for this file is too large to render. See raw diff
 
docs/for-bots/{flutter-fullscreen β†’ flutter/flutter-fullscreen}/fullscreen.md RENAMED
File without changes
docs/for-bots/flutter/flutter-share_plus/share_plus.md ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![](/static/hash-9gbn097u/img/ff-banner-desktop-2x.png)![](/static/hash-9gbn097u/img/ff-banner-desktop-dark-2x.png)![](/static/hash-9gbn097u/img/ff-banner-mobile-2x.png)![](/static/hash-9gbn097u/img/ff-banner-mobile-dark-2x.png)](https://flutter.dev/docs/development/packages-and-plugins/favorites "Package is a Flutter Favorite")
2
+
3
+ share\_plus 11.0.0 ![copy "share_plus: ^11.0.0" to clipboard](/static/hash-9gbn097u/img/content-copy-icon.svg "Copy "share_plus: ^11.0.0" to clipboard")
4
+
5
+ share\_plus: ^11.0.0 copied to clipboard
6
+
7
+
8
+ ====================================================================================================================================================================================================
9
+
10
+ Published 15 days ago β€’ [![verified publisher](/static/hash-9gbn097u/img/material-icon-verified.svg "Published by a pub.dev verified publisher")fluttercommunity.dev](/publishers/fluttercommunity.dev)Dart 3 compatible
11
+
12
+ SDK[Flutter](/packages?q=sdk%3Aflutter "Packages compatible with Flutter SDK")
13
+
14
+ Platform[Android](/packages?q=platform%3Aandroid "Packages compatible with Android platform")[iOS](/packages?q=platform%3Aios "Packages compatible with iOS platform")[Linux](/packages?q=platform%3Alinux "Packages compatible with Linux platform")[macOS](/packages?q=platform%3Amacos "Packages compatible with macOS platform")[web](/packages?q=platform%3Aweb "Packages compatible with Web platform")[Windows](/packages?q=platform%3Awindows "Packages compatible with Windows platform")
15
+
16
+ ![liked status: inactive](/static/hash-9gbn097u/img/like-inactive.svg)![liked status: active](/static/hash-9gbn097u/img/like-active.svg)3.6k
17
+
18
+ β†’
19
+
20
+ ### Metadata
21
+
22
+ Flutter plugin for sharing content via the platform share UI, using the ACTION\_SEND intent on Android and UIActivityViewController on iOS.
23
+
24
+ More...
25
+
26
+ * Readme
27
+ * [Changelog](/packages/share_plus/changelog)
28
+ * [Example](/packages/share_plus/example)
29
+ * [Installing](/packages/share_plus/install)
30
+ * [Versions](/packages/share_plus/versions)
31
+ * [Scores](/packages/share_plus/score)
32
+
33
+ share\_plus [#](#share_plus)
34
+ ============================
35
+
36
+ [![share_plus](https://github.com/fluttercommunity/plus_plugins/actions/workflows/share_plus.yaml/badge.svg)](https://github.com/fluttercommunity/plus_plugins/actions/workflows/share_plus.yaml) [![pub points](https://img.shields.io/pub/points/share_plus?color=2E8B57&label=pub%20points)](https://pub.dev/packages/share_plus/score) [![pub package](https://img.shields.io/pub/v/share_plus.svg)](https://pub.dev/packages/share_plus)
37
+
38
+ [![](https://github.com/fluttercommunity/plus_plugins/raw/main/assets/flutter-favorite-badge.png)](https://flutter.dev/docs/development/packages-and-plugins/favorites)
39
+
40
+ A Flutter plugin to share content from your Flutter app via the platform's share dialog.
41
+
42
+ Wraps the `ACTION_SEND` Intent on Android, `UIActivityViewController` on iOS, or equivalent platform content sharing methods.
43
+
44
+ Platform Support [#](#platform-support)
45
+ ---------------------------------------
46
+
47
+ Shared content
48
+
49
+ Android
50
+
51
+ iOS
52
+
53
+ MacOS
54
+
55
+ Web
56
+
57
+ Linux
58
+
59
+ Windows
60
+
61
+ Text
62
+
63
+ βœ…
64
+
65
+ βœ…
66
+
67
+ βœ…
68
+
69
+ βœ…
70
+
71
+ βœ…
72
+
73
+ βœ…
74
+
75
+ URI
76
+
77
+ βœ…
78
+
79
+ βœ…
80
+
81
+ βœ…
82
+
83
+ As text
84
+
85
+ As text
86
+
87
+ As text
88
+
89
+ Files
90
+
91
+ βœ…
92
+
93
+ βœ…
94
+
95
+ βœ…
96
+
97
+ βœ…
98
+
99
+ ❌
100
+
101
+ βœ…
102
+
103
+ Also compatible with Windows and Linux by using "mailto" to share text via Email.
104
+
105
+ Sharing files is not supported on Linux.
106
+
107
+ Requirements [#](#requirements)
108
+ -------------------------------
109
+
110
+ * Flutter >=3.22.0
111
+ * Dart >=3.4.0 <4.0.0
112
+ * iOS >=12.0
113
+ * MacOS >=10.14
114
+ * Android `compileSDK` 34
115
+ * Java 17
116
+ * Android Gradle Plugin >=8.3.0
117
+ * Gradle wrapper >=8.4
118
+
119
+ Usage [#](#usage)
120
+ -----------------
121
+
122
+ To use this plugin, add `share_plus` as a [dependency in your pubspec.yaml file](https://plus.fluttercommunity.dev/docs/overview).
123
+
124
+ Import the library.
125
+
126
+ import 'package:share_plus/share_plus.dart';
127
+
128
+
129
+ copied to clipboard
130
+
131
+ ### Share Text [#](#share-text)
132
+
133
+ Access the `SharePlus` instance via `SharePlus.instance`. Then, invoke the `share()` method anywhere in your Dart code.
134
+
135
+ SharePlus.instance.share(
136
+ ShareParams(text: 'check out my website https://example.com')
137
+ );
138
+
139
+
140
+ copied to clipboard
141
+
142
+ The `share()` method requires the `ShareParams` object, which contains the content to share.
143
+
144
+ These are some of the accepted parameters of the `ShareParams` class:
145
+
146
+ * `text`: text to share.
147
+ * `title`: content or share-sheet title (if supported).
148
+ * `subject`: email subject (if supported).
149
+
150
+ Check the class documentation for more details.
151
+
152
+ `share()` returns `status` object that allows to check the result of user action in the share sheet.
153
+
154
+ final result = await SharePlus.instance.share(params);
155
+
156
+ if (result.status == ShareResultStatus.success) {
157
+ print('Thank you for sharing my website!');
158
+ }
159
+
160
+
161
+ copied to clipboard
162
+
163
+ ### Share Files [#](#share-files)
164
+
165
+ To share one or multiple files, provide the `files` list in `ShareParams`. Optionally, you can pass `title`, `text` and `sharePositionOrigin`.
166
+
167
+ final params = ShareParams(
168
+ text: 'Great picture',
169
+ files: [XFile('${directory.path}/image.jpg')],
170
+ );
171
+
172
+ final result = await SharePlus.instance.share(params);
173
+
174
+ if (result.status == ShareResultStatus.success) {
175
+ print('Thank you for sharing the picture!');
176
+ }
177
+
178
+
179
+ copied to clipboard
180
+
181
+ final params = ShareParams(
182
+ files: [
183
+ XFile('${directory.path}/image1.jpg'),
184
+ XFile('${directory.path}/image2.jpg'),
185
+ ],
186
+ );
187
+
188
+ final result = await SharePlus.instance.share(params);
189
+
190
+ if (result.status == ShareResultStatus.dismissed) {
191
+ print('Did you not like the pictures?');
192
+ }
193
+
194
+
195
+ copied to clipboard
196
+
197
+ On web, this uses the [Web Share API](https://web.dev/web-share/) if it's available. Otherwise it falls back to downloading the shared files. See [Can I Use - Web Share API](https://caniuse.com/web-share) to understand which browsers are supported. This builds on the [`cross_file`](https://pub.dev/packages/cross_file) package.
198
+
199
+ File downloading fallback mechanism for web can be disabled by setting:
200
+
201
+ ShareParams(
202
+ // rest of params
203
+ downloadFallbackEnabled: false,
204
+ )
205
+
206
+
207
+ copied to clipboard
208
+
209
+ #### Share Data
210
+
211
+ You can also share files that you dynamically generate from its data using [`XFile.fromData`](https://pub.dev/documentation/share_plus/latest/share_plus/XFile/XFile.fromData.html).
212
+
213
+ To set the name of such files, use the `fileNameOverrides` parameter, otherwise the file name will be a random UUID string.
214
+
215
+ final params = ShareParams(
216
+ files: [XFile.fromData(utf8.encode(text), mimeType: 'text/plain')],
217
+ fileNameOverrides: ['myfile.txt']
218
+ );
219
+
220
+ SharePlus.instance.share(params);
221
+
222
+
223
+ copied to clipboard
224
+
225
+ Caution
226
+
227
+ The `name` parameter in the `XFile.fromData` method is ignored in most platforms. Use `fileNameOverrides` instead.
228
+
229
+ ### Share URI [#](#share-uri)
230
+
231
+ iOS supports fetching metadata from a URI when shared using `UIActivityViewController`. This special functionality is only properly supported on iOS. On other platforms, the URI will be shared as plain text.
232
+
233
+ final params = ShareParams(uri: uri);
234
+
235
+ SharePlus.instance.share(params);
236
+
237
+
238
+ copied to clipboard
239
+
240
+ ### Share Results [#](#share-results)
241
+
242
+ All three methods return a `ShareResult` object which contains the following information:
243
+
244
+ * `status`: a `ShareResultStatus`
245
+ * `raw`: a `String` describing the share result, e.g. the opening app ID.
246
+
247
+ Note: `status` will be `ShareResultStatus.unavailable` if the platform does not support identifying the user action.
248
+
249
+ Known Issues [#](#known-issues)
250
+ -------------------------------
251
+
252
+ ### Sharing data created with XFile.fromData [#](#sharing-data-created-with-xfilefromdata)
253
+
254
+ When sharing data created with `XFile.fromData`, the plugin will write a temporal file inside the cache directory of the app, so it can be shared.
255
+
256
+ Although the OS should take care of deleting those files, it is advised, that you clean up this data once in a while (e.g. on app start).
257
+
258
+ You can access this directory using [path\_provider](https://pub.dev/packages/path_provider) [getTemporaryDirectory](https://pub.dev/documentation/path_provider/latest/path_provider/getTemporaryDirectory.html).
259
+
260
+ Alternatively, don't use `XFile.fromData` and instead write the data down to a `File` with a path before sharing it, so you control when to delete it.
261
+
262
+ ### Mobile platforms (Android and iOS) [#](#mobile-platforms-android-and-ios)
263
+
264
+ #### Sharing images + text
265
+
266
+ When attempting to share images with text, some apps may fail to properly accept the share action with them.
267
+
268
+ For example, due to restrictions set up by Meta/Facebook this plugin isn't capable of sharing data reliably to Facebook related apps on Android and iOS. This includes eg. sharing text to the Facebook Messenger.
269
+
270
+ If you require this functionality please check the native Facebook Sharing SDK ([https://developers.facebook.com/docs/sharing](https://developers.facebook.com/docs/sharing)) or search for other Flutter plugins implementing this SDK. More information can be found in [this issue](https://github.com/fluttercommunity/plus_plugins/issues/413).
271
+
272
+ Other apps may also give problems when attempting to share content to them. This is because 3rd party app developers do not properly implement the logic to receive share actions.
273
+
274
+ We cannot warranty that a 3rd party app will properly implement the share functionality. Therefore, **all bugs reported regarding compatibility with a specific app will be closed.**
275
+
276
+ #### Localization in Apple platforms
277
+
278
+ It could happen that the Share sheet appears with a different language, [as reported here](https://github.com/fluttercommunity/plus_plugins/issues/2696).
279
+
280
+ To fix this issue, you will have to setup the keys `CFBundleAllowMixedLocalizations` and `CFBundleDevelopmentRegion` in your project's `info.plist`.
281
+
282
+ For more information check the [CoreFoundationKeys](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html) documentation.
283
+
284
+ #### iPad
285
+
286
+ `share_plus` requires iPad users to provide the `sharePositionOrigin` parameter.
287
+
288
+ Without it, `share_plus` will not work on iPads and may cause a crash or letting the UI not responding.
289
+
290
+ To avoid that problem, provide the `sharePositionOrigin`.
291
+
292
+ For example:
293
+
294
+ // Use Builder to get the widget context
295
+ Builder(
296
+ builder: (BuildContext context) {
297
+ return ElevatedButton(
298
+ onPressed: () => _onShare(context),
299
+ child: const Text('Share'),
300
+ );
301
+ },
302
+ ),
303
+
304
+ // _onShare method:
305
+ final box = context.findRenderObject() as RenderBox?;
306
+
307
+ await SharePlus.instance.share(
308
+ ShareParams(
309
+ text: text,
310
+ sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
311
+ )
312
+ );
313
+
314
+
315
+ copied to clipboard
316
+
317
+ See the `main.dart` in the `example` for a complete example.
318
+
319
+ Migrating from `Share.share()` to `SharePlus.instance.share()` [#](#migrating-from-shareshare-to-shareplusinstanceshare)
320
+ ------------------------------------------------------------------------------------------------------------------------
321
+
322
+ The static methods `Share.share()`, `Share.shareUri()` and `Share.shareXFiles()` have been deprecated in favor of the `SharePlus.instance.share(params)`.
323
+
324
+ To convert code using `Share.share()` to the new `SharePlus` class:
325
+
326
+ 1. Wrap the current parameters in a `ShareParams` object.
327
+ 2. Change the call to `SharePlus.instance.share()`.
328
+
329
+ e.g.
330
+
331
+ Share.share("Shared text");
332
+
333
+ Share.shareUri("http://example.com");
334
+
335
+ Share.shareXFiles(files);
336
+
337
+
338
+ copied to clipboard
339
+
340
+ Becomes:
341
+
342
+ SharePlus.instance.share(
343
+ ShareParams(text: "Shared text"),
344
+ );
345
+
346
+ SharePlus.instance.share(
347
+ ShareParams(uri: "http://example.com"),
348
+ );
349
+
350
+ SharePlus.instance.share(
351
+ ShareParams(files: files),
352
+ );
353
+
354
+
355
+ copied to clipboard
356
+
357
+ Learn more [#](#learn-more)
358
+ ---------------------------
359
+
360
+ * [API Documentation](https://pub.dev/documentation/share_plus/latest/share_plus/share_plus-library.html)
361
+
362
+ [
363
+
364
+ 3.69k
365
+
366
+ likes
367
+
368
+ 160
369
+
370
+ points
371
+
372
+ 1.48M
373
+
374
+ downloads
375
+
376
+
377
+
378
+ ](/packages/share_plus/score)
379
+
380
+ ### Publisher
381
+
382
+ [![verified publisher](/static/hash-9gbn097u/img/material-icon-verified.svg "Published by a pub.dev verified publisher")fluttercommunity.dev](/publishers/fluttercommunity.dev)
383
+
384
+ ### Weekly Downloads
385
+
386
+ 2024.06.09 - 2025.05.04
387
+
388
+ ### Metadata
389
+
390
+ Flutter plugin for sharing content via the platform share UI, using the ACTION\_SEND intent on Android and UIActivityViewController on iOS.
391
+
392
+ [Homepage](https://github.com/fluttercommunity/plus_plugins)
393
+ [Repository (GitHub)](https://github.com/fluttercommunity/plus_plugins/tree/main/packages/share_plus/share_plus)
394
+ [View/report issues](https://github.com/fluttercommunity/plus_plugins/labels/share_plus)
395
+
396
+ ### Topics
397
+
398
+ [#share](/packages?q=topic%3Ashare) [#utils](/packages?q=topic%3Autils)
399
+
400
+ ### Documentation
401
+
402
+ [API reference](/documentation/share_plus/latest/)
403
+
404
+ ### License
405
+
406
+ ![](/static/hash-9gbn097u/img/material-icon-balance.svg)BSD-3-Clause ([license](/packages/share_plus/license))
407
+
408
+ ### Dependencies
409
+
410
+ [cross\_file](/packages/cross_file "^0.3.4+2"), [ffi](/packages/ffi "^2.1.2"), [file](/packages/file ">=6.1.4 <8.0.0"), [flutter](https://api.flutter.dev/), [flutter\_web\_plugins](https://api.flutter.dev/flutter/flutter_web_plugins/flutter_web_plugins-library.html), [meta](/packages/meta "^1.8.0"), [mime](/packages/mime ">=1.0.4 <3.0.0"), [share\_plus\_platform\_interface](/packages/share_plus_platform_interface "^6.0.0"), [url\_launcher\_linux](/packages/url_launcher_linux "^3.1.1"), [url\_launcher\_platform\_interface](/packages/url_launcher_platform_interface "^2.3.2"), [url\_launcher\_web](/packages/url_launcher_web "^2.3.2"), [url\_launcher\_windows](/packages/url_launcher_windows "^3.1.2"), [web](/packages/web "^1.0.0"), [win32](/packages/win32 "^5.5.3")
411
+
412
+ ### More
413
+
414
+ [Packages that depend on share\_plus](/packages?q=dependency%3Ashare_plus)
415
+
416
+ {"@context":"http\\u003a\\u002f\\u002fschema.org","@type":"SoftwareSourceCode","name":"share\\u005fplus","version":"11.0.0","description":"share\\u005fplus - Flutter plugin for sharing content via the platform share UI, using the ACTION\\u005fSEND intent on Android and UIActivityViewController on iOS.","url":"https\\u003a\\u002f\\u002fpub.dev\\u002fpackages\\u002fshare\\u005fplus","dateCreated":"2020-04-20T18\\u003a02\\u003a15.748611Z","dateModified":"2025-04-22T05\\u003a19\\u003a26.240981Z","programmingLanguage":"Dart","image":"https\\u003a\\u002f\\u002fpub.dev\\u002fstatic\\u002fimg\\u002fpub-dev-icon-cover-image.png","license":"https\\u003a\\u002f\\u002fpub.dev\\u002fpackages\\u002fshare\\u005fplus\\u002flicense"}
docs/for-bots/{flutter-videos β†’ flutter/flutter-videos}/fvp.md RENAMED
File without changes
docs/for-bots/{flutter-videos β†’ flutter/flutter-videos}/fvp_usage_example__main.dart RENAMED
File without changes
docs/for-bots/{flutter-videos β†’ flutter/flutter-videos}/fvp_usage_example__multi_textures.dart RENAMED
File without changes
docs/for-bots/{flutter-videos β†’ flutter/flutter-videos}/video_player.md RENAMED
File without changes
lib/main.dart CHANGED
@@ -42,33 +42,47 @@ void main() async {
42
  homeWidget = HomeScreen(initialSearchQuery: searchQuery);
43
  }
44
  }
45
- // Handle view parameter (higher priority than search if both are present)
46
- else if (params.containsKey('view')) {
47
- final viewQuery = params['view'] ?? '';
48
- if (viewQuery.isNotEmpty) {
49
- // Create a loading widget that will transition to VideoScreen once search completes
50
- homeWidget = FutureBuilder<VideoResult>(
51
- future: wsService.search(viewQuery),
52
- builder: (context, snapshot) {
53
- if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
54
- // Navigate to VideoScreen once we have the result
55
- return VideoScreen(video: snapshot.data!);
56
- } else if (snapshot.hasError) {
57
- return Scaffold(
58
- body: Center(
59
- child: Text('Error loading video: ${snapshot.error}'),
60
- ),
61
- );
62
- } else {
63
- // Show loading indicator while waiting
64
- return const Scaffold(
65
- body: Center(
66
- child: CircularProgressIndicator(),
67
- ),
68
- );
69
- }
70
- },
71
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
  }
74
  }
 
42
  homeWidget = HomeScreen(initialSearchQuery: searchQuery);
43
  }
44
  }
45
+ // Handle title parameter
46
+ else if (params.containsKey('title')) {
47
+ final titleQuery = params['title'] ?? '';
48
+
49
+ if (titleQuery.isNotEmpty) {
50
+ // If both title and description are provided, create video directly
51
+ if (params.containsKey('description')) {
52
+ final description = params['description'] ?? '';
53
+ final videoResult = VideoResult(
54
+ id: DateTime.now().millisecondsSinceEpoch.toString(),
55
+ title: titleQuery,
56
+ description: description,
57
+ thumbnailUrl: '',
58
+ tags: [],
59
+ );
60
+ homeWidget = VideoScreen(video: videoResult);
61
+ } else {
62
+ // If only title is provided, use search like before (same as legacy 'view' parameter)
63
+ homeWidget = FutureBuilder<VideoResult>(
64
+ future: wsService.search(titleQuery),
65
+ builder: (context, snapshot) {
66
+ if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
67
+ // Navigate to VideoScreen once we have the result
68
+ return VideoScreen(video: snapshot.data!);
69
+ } else if (snapshot.hasError) {
70
+ return Scaffold(
71
+ body: Center(
72
+ child: Text('Error loading video: ${snapshot.error}'),
73
+ ),
74
+ );
75
+ } else {
76
+ // Show loading indicator while waiting
77
+ return const Scaffold(
78
+ body: Center(
79
+ child: CircularProgressIndicator(),
80
+ ),
81
+ );
82
+ }
83
+ },
84
+ );
85
+ }
86
  }
87
  }
88
  }
lib/screens/home_screen.dart CHANGED
@@ -468,9 +468,9 @@ class _HomeScreenState extends State<HomeScreen> {
468
 
469
  // Update URL parameter on web platform
470
  if (kIsWeb) {
471
- // Update view parameter and remove search parameter
472
- // Use description instead of title for the URL parameter
473
- updateUrlParameter('view', _results[index].description);
474
  removeUrlParameter('search');
475
  }
476
 
 
468
 
469
  // Update URL parameter on web platform
470
  if (kIsWeb) {
471
+ // Update title and description parameters and remove search parameter
472
+ updateUrlParameter('title', _results[index].title);
473
+ updateUrlParameter('description', _results[index].description);
474
  removeUrlParameter('search');
475
  }
476
 
lib/screens/video_screen.dart CHANGED
@@ -7,6 +7,8 @@ import 'package:aitube2/widgets/search_box.dart';
7
  import 'package:aitube2/widgets/web_utils.dart';
8
  import 'package:flutter/foundation.dart';
9
  import 'package:flutter/material.dart';
 
 
10
  import '../config/config.dart';
11
  import '../models/video_result.dart';
12
  import '../services/websocket_api_service.dart';
@@ -260,6 +262,50 @@ class _VideoScreenState extends State<VideoScreen> {
260
  }
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  // Reference to the current VideoPlayerWidget to force reset when needed
264
  Key _videoPlayerKey = UniqueKey();
265
 
@@ -275,8 +321,7 @@ class _VideoScreenState extends State<VideoScreen> {
275
 
276
  // Update URL parameter on web platform
277
  if (kIsWeb) {
278
- // Update view parameter with the description instead of the query
279
- // We'll get the actual description from the search result
280
  // removeUrlParameter('search') will happen after we get the result
281
  }
282
 
@@ -297,8 +342,9 @@ class _VideoScreenState extends State<VideoScreen> {
297
 
298
  // Now that we have the result, update the URL parameter on web platform
299
  if (kIsWeb) {
300
- // Update view parameter with the description
301
- updateUrlParameter('view', result.description);
 
302
  removeUrlParameter('search');
303
  }
304
  }
@@ -331,12 +377,11 @@ class _VideoScreenState extends State<VideoScreen> {
331
  onPressed: () {
332
  // Restore the search parameter in URL when navigating back
333
  if (kIsWeb) {
334
- // Remove the view parameter
335
- removeUrlParameter('view');
 
336
 
337
  // Get the search query from the video description
338
- // This matches what we stored in the view parameter when
339
- // navigating to this screen
340
  final searchQuery = _videoData.description.trim();
341
  if (searchQuery.isNotEmpty) {
342
  // Update URL to show search parameter again
@@ -446,12 +491,23 @@ class _VideoScreenState extends State<VideoScreen> {
446
  return ExpansionTile(
447
  initiallyExpanded: false,
448
  tilePadding: EdgeInsets.zero,
449
- title: Text(
450
- _videoData.title,
451
- style: Theme.of(context).textTheme.headlineSmall?.copyWith(
452
- color: AiTubeColors.onBackground,
453
- fontWeight: FontWeight.bold,
454
- ),
 
 
 
 
 
 
 
 
 
 
 
455
  ),
456
  iconColor: AiTubeColors.primary,
457
  collapsedIconColor: AiTubeColors.primary,
 
7
  import 'package:aitube2/widgets/web_utils.dart';
8
  import 'package:flutter/foundation.dart';
9
  import 'package:flutter/material.dart';
10
+ import 'package:flutter/services.dart';
11
+ import 'package:universal_html/html.dart' if (dart.library.io) 'package:aitube2/services/html_stub.dart' as html;
12
  import '../config/config.dart';
13
  import '../models/video_result.dart';
14
  import '../services/websocket_api_service.dart';
 
262
  }
263
  }
264
 
265
+ void _shareVideo() async {
266
+
267
+ // For non-web platforms
268
+ final uri = Uri.parse("https://aitube.at");
269
+ final params = Map<String, String>.from(uri.queryParameters);
270
+
271
+ // Ensure title and description are in the URL parameters
272
+ params['title'] = _videoData.title;
273
+ params['description'] = _videoData.description;
274
+
275
+ // Create a new URL with updated parameters
276
+ final shareUri = uri.replace(queryParameters: params);
277
+ final shareUrl = shareUri.toString();
278
+
279
+
280
+ try {
281
+ // this is a text to share on social media
282
+ // final textToCopy = 'Messing around with #aitube2 πŸ‘€ $shareUrl';
283
+
284
+ // but for now let's just use the url
285
+ final textToCopy = shareUrl;
286
+
287
+ // Copy to clipboard
288
+ await Clipboard.setData(ClipboardData(text: textToCopy));
289
+
290
+ // Show a temporary "Copied!" message
291
+ if (mounted) {
292
+ ScaffoldMessenger.of(context).showSnackBar(
293
+ const SnackBar(
294
+ content: Text('Copied to clipboard!'),
295
+ backgroundColor: Colors.green,
296
+ duration: Duration(seconds: 3),
297
+ ),
298
+ );
299
+ }
300
+ } catch (e) {
301
+ if (mounted) {
302
+ ScaffoldMessenger.of(context).showSnackBar(
303
+ SnackBar(content: Text('Error copying to clipboard: $e')),
304
+ );
305
+ }
306
+ }
307
+ }
308
+
309
  // Reference to the current VideoPlayerWidget to force reset when needed
310
  Key _videoPlayerKey = UniqueKey();
311
 
 
321
 
322
  // Update URL parameter on web platform
323
  if (kIsWeb) {
324
+ // We'll update title and description parameters after we get the search result
 
325
  // removeUrlParameter('search') will happen after we get the result
326
  }
327
 
 
342
 
343
  // Now that we have the result, update the URL parameter on web platform
344
  if (kIsWeb) {
345
+ // Update title and description parameters
346
+ updateUrlParameter('title', result.title);
347
+ updateUrlParameter('description', result.description);
348
  removeUrlParameter('search');
349
  }
350
  }
 
377
  onPressed: () {
378
  // Restore the search parameter in URL when navigating back
379
  if (kIsWeb) {
380
+ // Remove the title and description parameters
381
+ removeUrlParameter('title');
382
+ removeUrlParameter('description');
383
 
384
  // Get the search query from the video description
 
 
385
  final searchQuery = _videoData.description.trim();
386
  if (searchQuery.isNotEmpty) {
387
  // Update URL to show search parameter again
 
491
  return ExpansionTile(
492
  initiallyExpanded: false,
493
  tilePadding: EdgeInsets.zero,
494
+ title: Row(
495
+ children: [
496
+ Expanded(
497
+ child: Text(
498
+ _videoData.title,
499
+ style: Theme.of(context).textTheme.headlineSmall?.copyWith(
500
+ color: AiTubeColors.onBackground,
501
+ fontWeight: FontWeight.bold,
502
+ ),
503
+ ),
504
+ ),
505
+ IconButton(
506
+ icon: const Icon(Icons.share, color: AiTubeColors.primary),
507
+ onPressed: _shareVideo,
508
+ tooltip: 'Share video',
509
+ ),
510
+ ],
511
  ),
512
  iconColor: AiTubeColors.primary,
513
  collapsedIconColor: AiTubeColors.primary,
lib/widgets/video_player/ui_components.dart CHANGED
@@ -73,7 +73,7 @@ Widget buildBufferStatus({
73
 
74
  return Positioned(
75
  right: 16,
76
- bottom: 16,
77
  child: Container(
78
  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
79
  decoration: BoxDecoration(
 
73
 
74
  return Positioned(
75
  right: 16,
76
+ top: 16,
77
  child: Container(
78
  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
79
  decoration: BoxDecoration(