diff --git a/app/(auth)/(tabs)/(home)/index.tsx b/app/(auth)/(tabs)/(home)/index.tsx
index 98bfc01e..31bff9b1 100644
--- a/app/(auth)/(tabs)/(home)/index.tsx
+++ b/app/(auth)/(tabs)/(home)/index.tsx
@@ -6,7 +6,7 @@ import { Loader } from "@/components/Loader";
import { MediaListSection } from "@/components/medialists/MediaListSection";
import { Colors } from "@/constants/Colors";
import { TAB_HEIGHT } from "@/constants/Values";
-import { hello } from "@/modules/vlc-player";
+import { hello, VlcPlayerView } from "@/modules/vlc-player";
import { useDownload } from "@/providers/DownloadProvider";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
@@ -383,9 +383,27 @@ export default function index() {
);
return (
-
- {hello()}
-
+
+ }
+ key={"home"}
+ contentContainerStyle={{
+ paddingLeft: insets.left,
+ paddingRight: insets.right,
+ paddingBottom: 16,
+ }}
+ style={{
+ marginBottom: TAB_HEIGHT,
+ }}
+ >
+
+ {hello()}
+
+
+
);
}
diff --git a/modules/vlc-player/index.ts b/modules/vlc-player/index.ts
index 3d17dbea..30bf6931 100644
--- a/modules/vlc-player/index.ts
+++ b/modules/vlc-player/index.ts
@@ -1,10 +1,14 @@
-import { NativeModulesProxy, EventEmitter, Subscription } from 'expo-modules-core';
+import {
+ NativeModulesProxy,
+ EventEmitter,
+ Subscription,
+} from "expo-modules-core";
// Import the native module. On web, it will be resolved to VlcPlayer.web.ts
// and on native platforms to VlcPlayer.ts
-import VlcPlayerModule from './src/VlcPlayerModule';
-import VlcPlayerView from './src/VlcPlayerView';
-import { ChangeEventPayload, VlcPlayerViewProps } from './src/VlcPlayer.types';
+import VlcPlayerModule from "./src/VlcPlayerModule";
+import VlcPlayerView from "./src/VlcPlayerView";
+import { ChangeEventPayload, VlcPlayerViewProps } from "./src/VlcPlayer.types";
// Get the native constant value.
export const PI = VlcPlayerModule.PI;
@@ -17,10 +21,14 @@ export async function setValueAsync(value: string) {
return await VlcPlayerModule.setValueAsync(value);
}
-const emitter = new EventEmitter(VlcPlayerModule ?? NativeModulesProxy.VlcPlayer);
+const emitter = new EventEmitter(
+ VlcPlayerModule ?? NativeModulesProxy.VlcPlayer
+);
-export function addChangeListener(listener: (event: ChangeEventPayload) => void): Subscription {
- return emitter.addListener('onChange', listener);
+export function addChangeListener(
+ listener: (event: ChangeEventPayload) => void
+): Subscription {
+ return emitter.addListener("onChange", listener);
}
export { VlcPlayerView, VlcPlayerViewProps, ChangeEventPayload };
diff --git a/modules/vlc-player/ios/VlcPlayerModule.swift b/modules/vlc-player/ios/VlcPlayerModule.swift
index 4097921d..756aea11 100644
--- a/modules/vlc-player/ios/VlcPlayerModule.swift
+++ b/modules/vlc-player/ios/VlcPlayerModule.swift
@@ -9,36 +9,14 @@ public class VlcPlayerModule: Module {
// Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
// The module will be accessible from `requireNativeModule('VlcPlayer')` in JavaScript.
Name("VlcPlayer")
-
- // Sets constant properties on the module. Can take a dictionary or a closure that returns a dictionary.
- Constants([
- "PI": Double.pi
- ])
-
- // Defines event names that the module can send to JavaScript.
- Events("onChange")
-
- // Defines a JavaScript synchronous function that runs the native code on the JavaScript thread.
- Function("hello") {
- return "Hello world! 👋"
- }
-
- // Defines a JavaScript function that always returns a Promise and whose native code
- // is by default dispatched on the different thread than the JavaScript runtime runs on.
- AsyncFunction("setValueAsync") { (value: String) in
- // Send an event to JavaScript.
- self.sendEvent("onChange", [
- "value": value
- ])
- }
-
- // Enables the module to be used as a native view. Definition components that are accepted as part of the
- // view definition: Prop, Events.
View(VlcPlayerView.self) {
- // Defines a setter for the `name` prop.
- Prop("name") { (view: VlcPlayerView, prop: String) in
- print(prop)
+ Prop("source") { (view: VlcPlayerView, source: String) in
+ view.setSource(source)
}
}
+
+ Function("hello") {
+ return "hello from native ios"
+ }
}
}
diff --git a/modules/vlc-player/ios/VlcPlayerView.swift b/modules/vlc-player/ios/VlcPlayerView.swift
index 70c17d44..90ccf3ee 100644
--- a/modules/vlc-player/ios/VlcPlayerView.swift
+++ b/modules/vlc-player/ios/VlcPlayerView.swift
@@ -1,7 +1,77 @@
import ExpoModulesCore
+import UIKit
+import MobileVLCKit
-// This view will be used as a native component. Make sure to inherit from `ExpoView`
-// to apply the proper styling (e.g. border radius and shadows).
-class VlcPlayerView: ExpoView {
-
-}
+class VlcPlayerView: ExpoView, VLCMediaPlayerDelegate {
+ private var mediaPlayer: VLCMediaPlayer?
+ private var movieView: UIView?
+
+ required init(appContext: AppContext? = nil) {
+ super.init(appContext: appContext)
+ DispatchQueue.main.async {
+ self.setupView()
+ self.backgroundColor = UIColor.black // Set background color to black
+ }
+ }
+
+ private func setupView() {
+ DispatchQueue.main.async {
+ self.movieView = UIView()
+ self.movieView?.translatesAutoresizingMaskIntoConstraints = false
+
+ if let movieView = self.movieView {
+ self.addSubview(movieView)
+ NSLayoutConstraint.activate([
+ movieView.leadingAnchor.constraint(equalTo: self.leadingAnchor),
+ movieView.trailingAnchor.constraint(equalTo: self.trailingAnchor),
+ movieView.topAnchor.constraint(equalTo: self.topAnchor),
+ movieView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
+ ])
+ }
+
+ self.setupMediaPlayer()
+ }
+ }
+
+ private func setupMediaPlayer() {
+ DispatchQueue.main.async {
+ self.mediaPlayer = VLCMediaPlayer()
+ self.mediaPlayer?.delegate = self
+ self.mediaPlayer?.drawable = self.movieView
+ print("Media player setup on main thread: \(Thread.isMainThread)")
+ }
+ }
+
+ @objc func setSource(_ source: String) {
+ DispatchQueue.main.async {
+ print("Setting media source on main thread: \(Thread.isMainThread)")
+ if let url = URL(string: source) {
+ self.mediaPlayer?.media = VLCMedia(url: url)
+ print("Media set, now playing...")
+ self.mediaPlayer?.play()
+ } else {
+ print("Invalid URL.")
+ }
+ }
+ }
+
+ @objc func handlePlayPause() {
+ DispatchQueue.main.async {
+ print("Handling play/pause on main thread: \(Thread.isMainThread)")
+ if self.mediaPlayer?.isPlaying == true {
+ self.mediaPlayer?.pause()
+ } else {
+ self.mediaPlayer?.play()
+ }
+ }
+ }
+
+ func mediaPlayerStateChanged(_ aNotification: Notification!) {
+ DispatchQueue.main.async {
+ print("Media player state changed on main thread: \(Thread.isMainThread)")
+ if self.mediaPlayer?.state == .stopped {
+ print("Media player stopped")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/vlc-player/src/VlcPlayer.types.ts b/modules/vlc-player/src/VlcPlayer.types.ts
index 6a86dd3f..0a1dd94d 100644
--- a/modules/vlc-player/src/VlcPlayer.types.ts
+++ b/modules/vlc-player/src/VlcPlayer.types.ts
@@ -3,5 +3,5 @@ export type ChangeEventPayload = {
};
export type VlcPlayerViewProps = {
- name: string;
+ source: string;
};
diff --git a/modules/vlc-player/src/VlcPlayerView.tsx b/modules/vlc-player/src/VlcPlayerView.tsx
index 50a7547a..5f245d91 100644
--- a/modules/vlc-player/src/VlcPlayerView.tsx
+++ b/modules/vlc-player/src/VlcPlayerView.tsx
@@ -1,10 +1,10 @@
-import { requireNativeViewManager } from 'expo-modules-core';
-import * as React from 'react';
+import { requireNativeViewManager } from "expo-modules-core";
+import * as React from "react";
-import { VlcPlayerViewProps } from './VlcPlayer.types';
+import { VlcPlayerViewProps } from "./VlcPlayer.types";
const NativeView: React.ComponentType =
- requireNativeViewManager('VlcPlayer');
+ requireNativeViewManager("VlcPlayer");
export default function VlcPlayerView(props: VlcPlayerViewProps) {
return ;