Add YouTube video embedding

This commit is contained in:
John Wesley 2023-12-27 21:48:49 -05:00
parent 51dac891a7
commit b9f83ad1d6
11 changed files with 428 additions and 12 deletions

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:media_kit/media_kit.dart';
import 'src/app.dart';
import 'src/screens/settings/settings_controller.dart';
@ -6,6 +7,8 @@ import 'src/screens/settings/settings_controller.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
MediaKit.ensureInitialized();
// Load user settings
final settingsController = SettingsController();
await settingsController.loadSettings();

View File

@ -9,6 +9,7 @@ import 'package:interstellar/src/widgets/action_bar.dart';
import 'package:interstellar/src/widgets/display_name.dart';
import 'package:interstellar/src/widgets/markdown.dart';
import 'package:interstellar/src/widgets/open_webpage.dart';
import 'package:interstellar/src/widgets/video.dart';
import 'package:provider/provider.dart';
class EntryItem extends StatelessWidget {
@ -53,20 +54,30 @@ class EntryItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
final isVideo = item.url != null && isSupportedVideo(item.url!);
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (item.image?.storageUrl != null)
if (!isPreview && isVideo) VideoPlayer(Uri.parse(item.url!)),
if (item.image?.storageUrl != null && !(!isPreview && isVideo))
isPreview
? InkWell(
onTap: () => _onImageClick(context),
child: Image.network(
item.image!.storageUrl,
height: 160,
width: double.infinity,
fit: BoxFit.cover,
),
)
? (isVideo
? Image.network(
item.image!.storageUrl,
height: 160,
width: double.infinity,
fit: BoxFit.cover,
)
: InkWell(
onTap: () => _onImageClick(context),
child: Image.network(
item.image!.storageUrl,
height: 160,
width: double.infinity,
fit: BoxFit.cover,
),
))
: Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height / 2,
@ -82,7 +93,7 @@ class EntryItem extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
item.type == 'link' && item.url != null
item.url != null
? InkWell(
child: Text(
item.title,

View File

@ -0,0 +1,51 @@
import 'package:flutter/widgets.dart';
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
import 'package:youtube_explode_dart/youtube_explode_dart.dart'
as youtube_explode_dart;
bool isSupportedVideo(String link) {
return ['www.youtube.com', 'youtube.com', 'youtu.be']
.contains(Uri.parse(link).host);
}
Future<Uri> getVideoStreamUri(Uri link) async {
var yt = youtube_explode_dart.YoutubeExplode();
var manifest = await yt.videos.streamsClient.getManifest(link);
return manifest.muxed.withHighestBitrate().url;
}
class VideoPlayer extends StatefulWidget {
final Uri uri;
const VideoPlayer(this.uri, {super.key});
@override
State<VideoPlayer> createState() => _VideoPlayerState();
}
class _VideoPlayerState extends State<VideoPlayer> {
late final player = Player();
late final controller = VideoController(player);
Future<void> _initController() async {
player.open(Media((await getVideoStreamUri(widget.uri)).toString()));
}
@override
void initState() {
_initController();
super.initState();
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.width * 9.0 / 16.0,
child: Video(controller: controller),
);
}
}

View File

@ -73,6 +73,7 @@ apply_standard_settings(${BINARY_NAME})
# Add dependency libraries. Add any application-specific dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
target_link_libraries(${BINARY_NAME} PRIVATE ${MIMALLOC_LIB})
# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)

View File

@ -6,9 +6,17 @@
#include "generated_plugin_registrant.h"
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
#include <media_kit_video/media_kit_video_plugin.h>
#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
g_autoptr(FlPluginRegistrar) media_kit_video_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitVideoPlugin");
media_kit_video_plugin_register_with_registrar(media_kit_video_registrar);
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);

View File

@ -3,10 +3,13 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
media_kit_libs_linux
media_kit_video
url_launcher_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
media_kit_native_event_loop
)
set(PLUGIN_BUNDLED_LIBRARIES)

View File

@ -5,10 +5,20 @@
import FlutterMacOS
import Foundation
import media_kit_libs_macos_video
import media_kit_video
import package_info_plus
import screen_brightness_macos
import shared_preferences_foundation
import url_launcher_macos
import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
}

View File

@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
archive:
dependency: transitive
description:
name: archive
sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b"
url: "https://pub.dev"
source: hosted
version: "3.4.9"
args:
dependency: transitive
description:
@ -49,6 +57,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.18.0"
convert:
dependency: transitive
description:
name: convert
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
url: "https://pub.dev"
source: hosted
version: "3.1.1"
crypto:
dependency: transitive
description:
@ -57,6 +73,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
csslib:
dependency: transitive
description:
name: csslib
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
dbus:
dependency: transitive
description:
name: dbus
sha256: "365c771ac3b0e58845f39ec6deebc76e3276aa9922b0cc60840712094d9047ac"
url: "https://pub.dev"
source: hosted
version: "0.7.10"
fake_async:
dependency: transitive
description:
@ -125,6 +157,22 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
freezed_annotation:
dependency: transitive
description:
name: freezed_annotation
sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d
url: "https://pub.dev"
source: hosted
version: "2.4.1"
html:
dependency: transitive
description:
name: html
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
url: "https://pub.dev"
source: hosted
version: "0.15.4"
http:
dependency: "direct main"
description:
@ -141,6 +189,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
image:
dependency: transitive
description:
name: image
sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271"
url: "https://pub.dev"
source: hosted
version: "4.1.3"
infinite_scroll_pagination:
dependency: "direct main"
description:
@ -157,6 +213,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.18.1"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
url: "https://pub.dev"
source: hosted
version: "4.8.1"
lints:
dependency: transitive
description:
@ -189,6 +261,78 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.5.0"
media_kit:
dependency: "direct main"
description:
name: media_kit
sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a"
url: "https://pub.dev"
source: hosted
version: "1.1.10+1"
media_kit_libs_android_video:
dependency: transitive
description:
name: media_kit_libs_android_video
sha256: "9dd8012572e4aff47516e55f2597998f0a378e3d588d0fad0ca1f11a53ae090c"
url: "https://pub.dev"
source: hosted
version: "1.3.6"
media_kit_libs_ios_video:
dependency: transitive
description:
name: media_kit_libs_ios_video
sha256: b5382994eb37a4564c368386c154ad70ba0cc78dacdd3fb0cd9f30db6d837991
url: "https://pub.dev"
source: hosted
version: "1.1.4"
media_kit_libs_linux:
dependency: transitive
description:
name: media_kit_libs_linux
sha256: e186891c31daa6bedab4d74dcdb4e8adfccc7d786bfed6ad81fe24a3b3010310
url: "https://pub.dev"
source: hosted
version: "1.1.3"
media_kit_libs_macos_video:
dependency: transitive
description:
name: media_kit_libs_macos_video
sha256: f26aa1452b665df288e360393758f84b911f70ffb3878032e1aabba23aa1032d
url: "https://pub.dev"
source: hosted
version: "1.1.4"
media_kit_libs_video:
dependency: "direct main"
description:
name: media_kit_libs_video
sha256: "3688e0c31482074578652bf038ce6301a5d21e1eda6b54fc3117ffeb4bdba067"
url: "https://pub.dev"
source: hosted
version: "1.0.4"
media_kit_libs_windows_video:
dependency: transitive
description:
name: media_kit_libs_windows_video
sha256: "7bace5f35d9afcc7f9b5cdadb7541d2191a66bb3fc71bfa11c1395b3360f6122"
url: "https://pub.dev"
source: hosted
version: "1.0.9"
media_kit_native_event_loop:
dependency: transitive
description:
name: media_kit_native_event_loop
sha256: a605cf185499d14d58935b8784955a92a4bf0ff4e19a23de3d17a9106303930e
url: "https://pub.dev"
source: hosted
version: "1.0.8"
media_kit_video:
dependency: "direct main"
description:
name: media_kit_video
sha256: c048d11a19e379aebbe810647636e3fc6d18374637e2ae12def4ff8a4b99a882
url: "https://pub.dev"
source: hosted
version: "1.2.4"
meta:
dependency: transitive
description:
@ -213,6 +357,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_info_plus:
dependency: transitive
description:
name: package_info_plus
sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
url: "https://pub.dev"
source: hosted
version: "5.0.1"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
path:
dependency: transitive
description:
@ -245,6 +405,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.1"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform:
dependency: transitive
description:
@ -261,6 +429,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.7"
pointycastle:
dependency: transitive
description:
name: pointycastle
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
url: "https://pub.dev"
source: hosted
version: "3.7.3"
provider:
dependency: "direct main"
description:
@ -269,6 +445,62 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.1"
safe_local_storage:
dependency: transitive
description:
name: safe_local_storage
sha256: ede4eb6cb7d88a116b3d3bf1df70790b9e2038bc37cb19112e381217c74d9440
url: "https://pub.dev"
source: hosted
version: "1.0.2"
screen_brightness:
dependency: transitive
description:
name: screen_brightness
sha256: ed8da4a4511e79422fc1aa88138e920e4008cd312b72cdaa15ccb426c0faaedd
url: "https://pub.dev"
source: hosted
version: "0.2.2+1"
screen_brightness_android:
dependency: transitive
description:
name: screen_brightness_android
sha256: "3df10961e3a9e968a5e076fe27e7f4741fa8a1d3950bdeb48cf121ed529d0caf"
url: "https://pub.dev"
source: hosted
version: "0.1.0+2"
screen_brightness_ios:
dependency: transitive
description:
name: screen_brightness_ios
sha256: "99adc3ca5490b8294284aad5fcc87f061ad685050e03cf45d3d018fe398fd9a2"
url: "https://pub.dev"
source: hosted
version: "0.1.0"
screen_brightness_macos:
dependency: transitive
description:
name: screen_brightness_macos
sha256: "64b34e7e3f4900d7687c8e8fb514246845a73ecec05ab53483ed025bd4a899fd"
url: "https://pub.dev"
source: hosted
version: "0.1.0+1"
screen_brightness_platform_interface:
dependency: transitive
description:
name: screen_brightness_platform_interface
sha256: b211d07f0c96637a15fb06f6168617e18030d5d74ad03795dd8547a52717c171
url: "https://pub.dev"
source: hosted
version: "0.1.0"
screen_brightness_windows:
dependency: transitive
description:
name: screen_brightness_windows
sha256: "9261bf33d0fc2707d8cf16339ce25768100a65e70af0fcabaf032fc12408ba86"
url: "https://pub.dev"
source: hosted
version: "0.1.3"
shared_preferences:
dependency: "direct main"
description:
@ -346,6 +578,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.10.0"
sprintf:
dependency: transitive
description:
name: sprintf
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
url: "https://pub.dev"
source: hosted
version: "7.0.0"
stack_trace:
dependency: transitive
description:
@ -370,6 +610,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558"
url: "https://pub.dev"
source: hosted
version: "3.1.0+1"
term_glyph:
dependency: transitive
description:
@ -394,6 +642,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.2"
universal_platform:
dependency: transitive
description:
name: universal_platform
sha256: d315be0f6641898b280ffa34e2ddb14f3d12b1a37882557869646e0cc363d0cc
url: "https://pub.dev"
source: hosted
version: "1.0.0+1"
uri_parser:
dependency: transitive
description:
name: uri_parser
sha256: "6543c9fd86d2862fac55d800a43e67c0dcd1a41677cb69c2f8edfe73bbcf1835"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
url_launcher:
dependency: "direct main"
description:
@ -458,6 +722,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.0"
uuid:
dependency: transitive
description:
name: uuid
sha256: "22c94e5ad1e75f9934b766b53c742572ee2677c56bc871d850a57dad0f82127f"
url: "https://pub.dev"
source: hosted
version: "4.2.2"
vector_math:
dependency: transitive
description:
@ -466,6 +738,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
volume_controller:
dependency: transitive
description:
name: volume_controller
sha256: "189bdc7a554f476b412e4c8b2f474562b09d74bc458c23667356bce3ca1d48c9"
url: "https://pub.dev"
source: hosted
version: "2.0.7"
wakelock_plus:
dependency: transitive
description:
name: wakelock_plus
sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d
url: "https://pub.dev"
source: hosted
version: "1.1.4"
wakelock_plus_platform_interface:
dependency: transitive
description:
name: wakelock_plus_platform_interface
sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web:
dependency: transitive
description:
@ -522,6 +818,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.3"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
youtube_explode_dart:
dependency: "direct main"
description:
name: youtube_explode_dart
sha256: "89aff5ac7de139c492ecea4bfc9189d33791632fa57e7e438e598873b040b077"
url: "https://pub.dev"
source: hosted
version: "2.0.4"
sdks:
dart: ">=3.2.0 <4.0.0"
flutter: ">=3.13.0"

View File

@ -3,7 +3,7 @@ name: interstellar
# Prevent accidental publishing to pub.dev.
publish_to: 'none'
version: 0.2.1
version: 0.2.2
environment:
sdk: '>=3.1.0 <4.0.0'
@ -17,11 +17,15 @@ dependencies:
http: ^1.1.2
infinite_scroll_pagination: ^4.0.0
intl: ^0.18.1
media_kit: ^1.1.10
media_kit_video: ^1.2.4
media_kit_libs_video: ^1.0.4
oauth2: ^2.0.2
provider: ^6.1.1
shared_preferences: ^2.2.2
url_launcher: ^6.2.2
webview_flutter: ^4.4.2
youtube_explode_dart: ^2.0.4
dev_dependencies:
flutter_test:

View File

@ -6,9 +6,18 @@
#include "generated_plugin_registrant.h"
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
#include <media_kit_video/media_kit_video_plugin_c_api.h>
#include <screen_brightness_windows/screen_brightness_windows_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
MediaKitVideoPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("MediaKitVideoPluginCApi"));
ScreenBrightnessWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenBrightnessWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}

View File

@ -3,10 +3,14 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
media_kit_libs_windows_video
media_kit_video
screen_brightness_windows
url_launcher_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
media_kit_native_event_loop
)
set(PLUGIN_BUNDLED_LIBRARIES)