placeholder widget for video support
This commit is contained in:
parent
211c088df9
commit
1a4ef800c6
12 changed files with 265 additions and 54 deletions
12
flake.lock
generated
12
flake.lock
generated
|
|
@ -5,11 +5,11 @@
|
|||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1777988971,
|
||||
"narHash": "sha256-qIoWPDs+0/8JecyYgE3gpKQxW/4bLW/gp45vow9ioCQ=",
|
||||
"lastModified": 1778716662,
|
||||
"narHash": "sha256-m1Yf0wZ8j1OHjTc2UwHwyQRSnNeSgLJOd7q5Y45hzi4=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "0678d8986be1661af6bb555f3489f2fdfc31f6ff",
|
||||
"rev": "f7c1a2d347e4c52d5fb8d10cb4d94b5884e546fb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -88,11 +88,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1777954456,
|
||||
"narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=",
|
||||
"lastModified": 1778869304,
|
||||
"narHash": "sha256-30sZNZoA1cqF5JNO9fVX+wgiQYjB7HJqqJ4ztCDeBZE=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1",
|
||||
"rev": "d233902339c02a9c334e7e593de68855ad26c4cb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import "dart:io";
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:media_kit/media_kit.dart";
|
||||
import "package:nexus/controllers/client_controller.dart";
|
||||
import "package:nexus/controllers/client_state_controller.dart";
|
||||
import "package:nexus/controllers/header_controller.dart";
|
||||
|
|
@ -56,6 +57,7 @@ void showError(Object error, [StackTrace? stackTrace]) {
|
|||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
MediaKit.ensureInitialized();
|
||||
|
||||
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
|
||||
await windowManager.ensureInitialized();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import "package:nexus/models/info/audio.dart";
|
|||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/info/file.dart";
|
||||
import "package:nexus/models/info/image.dart";
|
||||
import "package:nexus/models/info/video.dart";
|
||||
part "message.freezed.dart";
|
||||
part "message.g.dart";
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ abstract class MessageContent extends Content with _$MessageContent {
|
|||
String? formattedBody,
|
||||
// EncryptedFile? file
|
||||
String? filename,
|
||||
AudioInfo? info,
|
||||
VideoInfo? info,
|
||||
Uri? url,
|
||||
}) = VideoMessageContent;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import "package:nexus/widgets/chat_page/lazy_loading/message_avatar.dart";
|
|||
import "package:nexus/widgets/chat_page/lazy_loading/message_displayname.dart";
|
||||
import "package:nexus/widgets/link_preview.dart";
|
||||
import "package:nexus/widgets/loading.dart";
|
||||
import "package:nexus/widgets/players/video.dart";
|
||||
import "package:timeago/timeago.dart";
|
||||
import "package:flutter_linkify/flutter_linkify.dart";
|
||||
|
||||
|
|
@ -153,6 +154,21 @@ class RenderEvent extends ConsumerWidget {
|
|||
:final body,
|
||||
:final formattedBody,
|
||||
:final format,
|
||||
) ||
|
||||
VideoMessageContent(
|
||||
:final body,
|
||||
:final formattedBody,
|
||||
:final format,
|
||||
) ||
|
||||
AudioMessageContent(
|
||||
:final body,
|
||||
:final formattedBody,
|
||||
:final format,
|
||||
) ||
|
||||
FileMessageContent(
|
||||
:final body,
|
||||
:final formattedBody,
|
||||
:final format,
|
||||
) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -199,9 +215,11 @@ class RenderEvent extends ConsumerWidget {
|
|||
if (!textOnly)
|
||||
if (event.content
|
||||
case ImageMessageContent(
|
||||
:final url,
|
||||
:final info,
|
||||
))
|
||||
:final url,
|
||||
) ||
|
||||
FileMessageContent(:final url) ||
|
||||
VideoMessageContent(:final url) ||
|
||||
AudioMessageContent(:final url))
|
||||
switch (url?.mxcToHttps(
|
||||
ref.watch(
|
||||
ClientStateController.provider
|
||||
|
|
@ -215,32 +233,37 @@ class RenderEvent extends ConsumerWidget {
|
|||
constraints: BoxConstraints.loose(
|
||||
Size.fromWidth(500),
|
||||
),
|
||||
child: ExpandableImage(
|
||||
url.toString(),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(8),
|
||||
),
|
||||
child: Image(
|
||||
image: CachedNetworkImage(
|
||||
url.toString(),
|
||||
ref.watch(
|
||||
CrossCacheController
|
||||
.provider,
|
||||
child: switch (event.content) {
|
||||
VideoMessageContent(
|
||||
:final info,
|
||||
) =>
|
||||
VideoPlayer(url, info),
|
||||
ImageMessageContent(:final info) => ExpandableImage(
|
||||
url.toString(),
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.all(
|
||||
Radius.circular(8),
|
||||
),
|
||||
child: Image(
|
||||
image: CachedNetworkImage(
|
||||
url.toString(),
|
||||
ref.watch(
|
||||
CrossCacheController
|
||||
.provider,
|
||||
),
|
||||
headers: ref.headers,
|
||||
),
|
||||
headers: ref.headers,
|
||||
),
|
||||
width: info?.width,
|
||||
loadingBuilder:
|
||||
(
|
||||
_,
|
||||
child,
|
||||
loadingProgress,
|
||||
) => loadingProgress == null
|
||||
? child
|
||||
: switch (info?.blurHash) {
|
||||
final blurHash? =>
|
||||
SizedBox(
|
||||
width: info?.width,
|
||||
loadingBuilder:
|
||||
(
|
||||
_,
|
||||
child,
|
||||
loadingProgress,
|
||||
) => loadingProgress == null
|
||||
? child
|
||||
: switch (info?.blurHash) {
|
||||
final blurHash? => SizedBox(
|
||||
width:
|
||||
info?.width ??
|
||||
info?.height ??
|
||||
|
|
@ -253,26 +276,28 @@ class RenderEvent extends ConsumerWidget {
|
|||
hash: blurHash,
|
||||
),
|
||||
),
|
||||
_ => Loading(),
|
||||
},
|
||||
errorBuilder:
|
||||
(
|
||||
context,
|
||||
error,
|
||||
stackTrace,
|
||||
) => Center(
|
||||
child: Text(
|
||||
"Image Failed to Load",
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.error,
|
||||
_ => Loading(),
|
||||
},
|
||||
errorBuilder:
|
||||
(
|
||||
context,
|
||||
error,
|
||||
stackTrace,
|
||||
) => Center(
|
||||
child: Text(
|
||||
"Image Failed to Load",
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
_ => SizedBox.shrink(),
|
||||
},
|
||||
),
|
||||
_ => Text(
|
||||
"Nexus currently cannot handle encrypted media",
|
||||
|
|
|
|||
27
lib/widgets/players/video.dart
Normal file
27
lib/widgets/players/video.dart
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:nexus/models/info/video.dart";
|
||||
// import "package:flutter_hooks/flutter_hooks.dart";
|
||||
// import "package:media_kit/media_kit.dart";
|
||||
// import "package:media_kit_video/media_kit_video.dart";
|
||||
// import "package:nexus/helpers/extensions/get_headers.dart";
|
||||
|
||||
class VideoPlayer extends HookConsumerWidget {
|
||||
final VideoInfo? info;
|
||||
final Uri url;
|
||||
const VideoPlayer(this.url, this.info, {super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
// final player = useMemoized(Player.new);
|
||||
// final controller = useMemoized(() => VideoController(player), [player]);
|
||||
|
||||
// useEffect(() {
|
||||
// player.open(Media(url.toString(), httpHeaders: ref.headers), play: false);
|
||||
|
||||
// return player.dispose;
|
||||
// }, []);
|
||||
|
||||
return Placeholder();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <dynamic_system_colors/dynamic_color_plugin.h>
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||
#include <media_kit_video/media_kit_video_plugin.h>
|
||||
#include <screen_retriever_linux/screen_retriever_linux_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
|
@ -19,6 +21,12 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
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) screen_retriever_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverLinuxPlugin");
|
||||
screen_retriever_linux_plugin_register_with_registrar(screen_retriever_linux_registrar);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
dynamic_system_colors
|
||||
file_selector_linux
|
||||
media_kit_libs_linux
|
||||
media_kit_video
|
||||
screen_retriever_linux
|
||||
url_launcher_linux
|
||||
window_manager
|
||||
|
|
|
|||
|
|
@ -22,7 +22,14 @@ pkgs.mkShell {
|
|||
go
|
||||
git
|
||||
jdk17
|
||||
flutter
|
||||
libGL
|
||||
wayland
|
||||
(flutter.override {
|
||||
extraPkgConfigPackages = [
|
||||
mpv-unwrapped
|
||||
libass
|
||||
];
|
||||
})
|
||||
android.platform-tools
|
||||
];
|
||||
|
||||
|
|
|
|||
130
pubspec.lock
130
pubspec.lock
|
|
@ -760,6 +760,70 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.0"
|
||||
media_kit:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: media_kit
|
||||
sha256: ae9e79597500c7ad6083a3c7b7b7544ddabfceacce7ae5c9709b0ec16a5d6643
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.6"
|
||||
media_kit_libs_android_video:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: media_kit_libs_android_video
|
||||
sha256: "3f6274e5ab2de512c286a25c327288601ee445ed8ac319e0ef0b66148bd8f76c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.8"
|
||||
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: "2b473399a49ec94452c4d4ae51cfc0f6585074398d74216092bf3d54aac37ecf"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
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: "2b235b5dac79c6020e01eef5022c6cc85fedc0df1738aadc6ea489daa12a92a9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.7"
|
||||
media_kit_libs_windows_video:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: media_kit_libs_windows_video
|
||||
sha256: dff76da2778729ab650229e6b4ec6ec111eb5151431002cbd7ea304ff1f112ab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.11"
|
||||
media_kit_video:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: media_kit_video
|
||||
sha256: afaa509e7b7e0bf247557a3a740cde903a52c34ace9810f94500e127bd7b043d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -808,6 +872,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.0.1"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -976,6 +1056,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.28.0"
|
||||
safe_local_storage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: safe_local_storage
|
||||
sha256: "287ea1f667c0b93cdc127dccc707158e2d81ee59fba0459c31a0c7da4d09c755"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
screen_retriever:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1277,6 +1365,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
universal_platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: universal_platform
|
||||
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
uri_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uri_parser
|
||||
sha256: "051c62e5f693de98ca9f130ee707f8916e2266945565926be3ff20659f7853ce"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1341,6 +1445,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.5"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: "1fef9e8e11e2991bb773070d4656b7bd5d850967a2456cfc83cf47925ba79489"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.3"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1381,6 +1493,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "15.2.0"
|
||||
wakelock_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: ddf3db70eaa10c37558ff817519b85d527dbd21034fd5d8e1c2e85f31588f1c1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.2"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: b13f99e992e7ae6a152e16c5559d3c07ff445b13330192662494e614ca3e7d7b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1470,5 +1598,5 @@ packages:
|
|||
source: hosted
|
||||
version: "2.2.4"
|
||||
sdks:
|
||||
dart: "3.11.4"
|
||||
dart: "3.11.5"
|
||||
flutter: ">=3.38.4"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ flutter:
|
|||
uses-material-design: true
|
||||
|
||||
environment:
|
||||
sdk: "3.11.4"
|
||||
sdk: "3.11.5"
|
||||
|
||||
dependency_overrides:
|
||||
linkify:
|
||||
|
|
@ -60,6 +60,9 @@ dependencies:
|
|||
url: https://github.com/Henry-Hiles/emoji_text_field
|
||||
flutter_blurhash: 0.9.1
|
||||
super_sliver_list: 0.4.1
|
||||
media_kit: 1.2.6
|
||||
media_kit_video: 2.0.1
|
||||
media_kit_libs_video: 1.0.7
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: 2.15.0
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <dynamic_system_colors/dynamic_color_plugin_c_api.h>
|
||||
#include <file_selector_windows/file_selector_windows.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_retriever_windows/screen_retriever_windows_plugin_c_api.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
#include <window_manager/window_manager_plugin.h>
|
||||
|
|
@ -17,6 +19,10 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||
registry->GetRegistrarForPlugin("DynamicColorPluginCApi"));
|
||||
FileSelectorWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
|
||||
MediaKitVideoPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("MediaKitVideoPluginCApi"));
|
||||
ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
dynamic_system_colors
|
||||
file_selector_windows
|
||||
media_kit_libs_windows_video
|
||||
media_kit_video
|
||||
screen_retriever_windows
|
||||
url_launcher_windows
|
||||
window_manager
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue