From 6e8198fd61df2677768dc6f93b16e3beb65e59da Mon Sep 17 00:00:00 2001 From: tarikpo Date: Mon, 2 Dec 2024 20:45:26 +0100 Subject: [PATCH 1/6] added logs --- .../android/.project | 28 ++++++++++++++++ .../ExternalDisplayHelper.java | 18 +++++++++++ .../RNExternalDisplayPackage.java | 9 ++++++ .../RNExternalDisplayView.java | 32 +++++++++++++++++++ .../RNExternalDisplayManager.java | 21 ++++++++++++ .../RNExternalDisplayModule.java | 4 +++ 6 files changed, 112 insertions(+) create mode 100644 packages/react-native-external-display/android/.project diff --git a/packages/react-native-external-display/android/.project b/packages/react-native-external-display/android/.project new file mode 100644 index 00000000..c55ce2f6 --- /dev/null +++ b/packages/react-native-external-display/android/.project @@ -0,0 +1,28 @@ + + + react-native-external-display + Project react-native-external-display created by Buildship. + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.buildship.core.gradleprojectnature + + + + 1733156198568 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java index 6ec288af..a52cf98b 100644 --- a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java +++ b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.HashMap; +import android.util.Log; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; @@ -25,17 +26,24 @@ class ExternalDisplayScreen extends Presentation { ExternalDisplayScreen(Context ctx, Display display) { super(ctx, display); + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen init"); + } @Override protected void onCreate(Bundle savedInstanceState) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onCreate"); + super.onCreate(savedInstanceState); } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) class ExternalDisplayHelper implements DisplayManager.DisplayListener { + public static Map getScreenInfo(Display[] displays) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getScreenInfo"); + HashMap info = new HashMap(); for (Display display : displays) { int displayId = display.getDisplayId(); @@ -74,25 +82,35 @@ public ExternalDisplayHelper(Context context, Listener listener) { } public Display getDisplay(int displayId) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getDisplay"); + return dm.getDisplay(displayId); } public Display[] getDisplays() { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getDisplays"); + return dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); } @Override public void onDisplayAdded(int displayId) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayAdded"); + listener.onDisplayAdded(getDisplays(), displayId); } @Override public void onDisplayChanged(int displayId) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayChanged"); + listener.onDisplayChanged(getDisplays(), displayId); } @Override public void onDisplayRemoved(int displayId) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayRemoved"); + listener.onDisplayRemoved(getDisplays(), displayId); } } diff --git a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java index 93a92e7f..94c19eb8 100644 --- a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java +++ b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java @@ -7,6 +7,7 @@ import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.TurboReactPackage; import com.facebook.react.uimanager.ViewManager; +import android.util.Log; import java.util.ArrayList; import java.util.Collections; @@ -15,11 +16,15 @@ import java.util.Map; import android.util.Log; +import com.externaldisplay.RNExternalDisplayManager; +import com.externaldisplay.RNExternalDisplayModule; public class RNExternalDisplayPackage extends TurboReactPackage { @Override public List createViewManagers(ReactApplicationContext reactContext) { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage createViewManagers"); + List viewManagers = new ArrayList<>(); viewManagers.add(new RNExternalDisplayManager(reactContext)); return viewManagers; @@ -28,6 +33,8 @@ public List createViewManagers(ReactApplicationContext reactContext @Nullable @Override public NativeModule getModule(String name, ReactApplicationContext reactContext) { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage getModule"); + if (name.equals(RNExternalDisplayModule.REACT_CLASS)) { return new com.externaldisplay.RNExternalDisplayModule(reactContext); } else { @@ -37,6 +44,8 @@ public NativeModule getModule(String name, ReactApplicationContext reactContext) @Override public ReactModuleInfoProvider getReactModuleInfoProvider() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage getReactModuleInfoProvider"); + return () -> { final Map moduleInfos = new HashMap<>(); boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; diff --git a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java index f2ae98fc..c411774f 100644 --- a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java +++ b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java @@ -9,6 +9,7 @@ import android.widget.LinearLayout; import com.facebook.common.logging.FLog; import com.facebook.react.common.ReactConstants; +import android.util.Log; import android.view.Display; import android.util.DisplayMetrics; @@ -30,11 +31,15 @@ public RNExternalDisplayView(Context context, ExternalDisplayHelper helper) { ((ReactContext) context).addLifecycleEventListener(this); this.context = context; this.helper = helper; + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView init"); + } @Override public void addView(View child, int index) { subviews.add(index, child); + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView addView"); + updateScreen(); } @@ -44,22 +49,30 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { @Override public int getChildCount() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView getChildCount"); + return subviews.size(); } @Override public View getChildAt(int index) { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView getChildAt"); + return subviews.get(index); } @Override public void removeView(View view) { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView removeView"); + super.removeView(view); } @Override public void removeViewAt(int index) { View child = getChildAt(index); + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView removeViewAt"); + super.removeView(child); subviews.remove(index); if (wrap != null) { @@ -72,6 +85,8 @@ public void removeViewAt(int index) { } public void onDropInstance() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onDropInstance"); + ((ReactContext) getContext()).removeLifecycleEventListener(this); if (wrap != null && wrap.getChildCount() > 0) { for (int i = 0; i < wrap.getChildCount(); i++) { @@ -89,6 +104,8 @@ public void addChildrenForAccessibility(ArrayList outChildren) { @Override public void onHostResume() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onHostResume"); + if (displayScreen == null && !pausedWithDisplayScreen) { return; } @@ -98,6 +115,8 @@ public void onHostResume() { @Override public void onHostPause() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onHostPause"); + if (displayScreen == null) { return; } @@ -112,11 +131,16 @@ public void onHostPause() { @Override public void onHostDestroy() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onHostDestroy"); + onDropInstance(); } public void updateScreen() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView updateScreen"); + if (getChildCount() == 0) return; + if (screen > 0) { Display display = helper.getDisplay(screen); if (display != null) { @@ -159,6 +183,8 @@ public void updateScreen() { } private void destroyScreen() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView destroyScreen"); + if (displayScreen != null) { displayScreen.hide(); displayScreen.dismiss(); @@ -168,6 +194,8 @@ private void destroyScreen() { } public void setScreen(String screen) { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView setScreen"); + if (getChildCount() > 0 && wrap != null && wrap.getChildCount() > 0) { for (int i = 0; i < wrap.getChildCount(); i++) { wrap.removeViewAt(i); @@ -191,10 +219,14 @@ public void setScreen(String screen) { } public int getScreen() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView getScreen"); + return this.screen; } public void setFallbackInMainScreen(boolean value) { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayView setFallbackInMainScreen"); + this.fallbackInMainScreen = value; } } diff --git a/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java b/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java index 787a5447..5ed4479c 100644 --- a/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java +++ b/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java @@ -15,6 +15,7 @@ import android.util.DisplayMetrics; import android.view.Display; import android.graphics.Rect; +import android.util.Log; import javax.annotation.Nullable; import java.util.Map; @@ -29,6 +30,8 @@ public class RNExternalDisplayManager extends ViewGroupManager getConstants() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayModule getConstants"); + HashMap map = new HashMap(); map.put("SCREEN_INFO", ExternalDisplayHelper.getScreenInfo(dm.getDisplays())); return map; From a97159070d5af3cbd113c336536dae4cc87e8a43 Mon Sep 17 00:00:00 2001 From: tarikpo Date: Tue, 3 Dec 2024 10:03:37 +0100 Subject: [PATCH 2/6] decoupled the event logic from component logic. Events when a screen is connected/disconnected will be received even if the external view component is not rendered --- .../ExternalDisplayHelper.java | 171 ++++---- .../RNExternalDisplayPackage.java | 101 +++-- .../RNExternalDisplayView.java | 370 +++++++++--------- .../RNExternalDisplayManager.java | 158 +++----- .../RNExternalDisplayModule.java | 108 +++-- 5 files changed, 475 insertions(+), 433 deletions(-) diff --git a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java index a52cf98b..6943d4e1 100644 --- a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java +++ b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/ExternalDisplayHelper.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.HashMap; + import android.util.Log; import com.facebook.react.bridge.LifecycleEventListener; @@ -24,93 +25,119 @@ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) class ExternalDisplayScreen extends Presentation { - ExternalDisplayScreen(Context ctx, Display display) { - super(ctx, display); - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen init"); + ExternalDisplayScreen(Context ctx, Display display) { + super(ctx, display); + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen init"); - } + } - @Override - protected void onCreate(Bundle savedInstanceState) { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onCreate"); + @Override + protected void onCreate(Bundle savedInstanceState) { + Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onCreate"); - super.onCreate(savedInstanceState); - } + super.onCreate(savedInstanceState); + } } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) class ExternalDisplayHelper implements DisplayManager.DisplayListener { - - public static Map getScreenInfo(Display[] displays) { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getScreenInfo"); - - HashMap info = new HashMap(); - for (Display display : displays) { - int displayId = display.getDisplayId(); - if ( - display.getDisplayId() == Display.DEFAULT_DISPLAY || - (display.getFlags() & Display.FLAG_PRESENTATION) == 0 - ) { - continue; - } - HashMap data = new HashMap(); - DisplayMetrics displayMetrics = new DisplayMetrics(); - display.getMetrics(displayMetrics); - data.put("id", displayId); - data.put("width", displayMetrics.widthPixels); - data.put("height", displayMetrics.heightPixels); - info.put(String.valueOf(display.getDisplayId()), data); + private static final String TAG = "RNExternalDisplayEvent"; + private static ExternalDisplayHelper instance = null; + private DisplayManager dm = null; + private Listener listener = null; + private Display displays = null; + + // Private constructor to prevent direct instantiation + private ExternalDisplayHelper(Context context, Listener listener) { + this.listener = listener; + dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); + if (dm != null) { + dm.registerDisplayListener(this, null); + } else { + } } - return info; - } - - public interface Listener { - void onDisplayAdded(Display[] displays, int displayId); - void onDisplayChanged(Display[] displays, int displayId); - void onDisplayRemoved(Display[] displays, int displayId); - } - - private Listener listener = null; - private DisplayManager dm = null; - private Display displays = null; - public ExternalDisplayHelper(Context context, Listener listener) { - this.listener = listener; - - dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); - dm.registerDisplayListener(this, null); - } - - public Display getDisplay(int displayId) { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getDisplay"); - - return dm.getDisplay(displayId); - } + // Method to initialize the singleton instance + public static synchronized void initialize(Context context, Listener listener) { + if (instance == null) { + instance = new ExternalDisplayHelper(context.getApplicationContext(), listener); + } + } - public Display[] getDisplays() { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen getDisplays"); + // Method to get the singleton instance + public static synchronized ExternalDisplayHelper getInstance() { + if (instance == null) { + throw new IllegalStateException("ExternalDisplayHelper is not initialized. Call initialize() first."); + } + return instance; + } - return dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); - } + // Method to clean up the singleton instance + public static synchronized void destroy() { + if (instance != null && instance.dm != null) { + instance.dm.unregisterDisplayListener(instance); + instance = null; + } + } + public static Map getScreenInfo(Display[] displays) { + HashMap info = new HashMap<>(); + for (Display display : displays) { + int displayId = display.getDisplayId(); + if ( + display.getDisplayId() == Display.DEFAULT_DISPLAY || + (display.getFlags() & Display.FLAG_PRESENTATION) == 0 + ) { + continue; + } + HashMap data = new HashMap<>(); + DisplayMetrics displayMetrics = new DisplayMetrics(); + display.getMetrics(displayMetrics); + data.put("id", displayId); + data.put("width", displayMetrics.widthPixels); + data.put("height", displayMetrics.heightPixels); + info.put(String.valueOf(display.getDisplayId()), data); + } + return info; + } - @Override - public void onDisplayAdded(int displayId) { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayAdded"); + @Override + public void onDisplayAdded(int displayId) { + if (listener != null) { + listener.onDisplayAdded(getDisplays(), displayId); + } + } - listener.onDisplayAdded(getDisplays(), displayId); - } + @Override + public void onDisplayChanged(int displayId) { + if (listener != null) { + listener.onDisplayChanged(getDisplays(), displayId); + } + } - @Override - public void onDisplayChanged(int displayId) { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayChanged"); + @Override + public void onDisplayRemoved(int displayId) { + if (listener != null) { + listener.onDisplayRemoved(getDisplays(), displayId); + } + } - listener.onDisplayChanged(getDisplays(), displayId); - } + public Display getDisplay(int displayId) { + if (dm != null) { + return dm.getDisplay(displayId); + } + return null; + } - @Override - public void onDisplayRemoved(int displayId) { - Log.d("RNExternalDisplayEvent", "ExternalDisplayScreen onDisplayRemoved"); + public Display[] getDisplays() { + if (dm != null) { + return dm.getDisplays(DisplayManager.DISPLAY_CATEGORY_PRESENTATION); + } + return new Display[0]; + } - listener.onDisplayRemoved(getDisplays(), displayId); - } + public interface Listener { + void onDisplayAdded(Display[] displays, int displayId); + void onDisplayChanged(Display[] displays, int displayId); + void onDisplayRemoved(Display[] displays, int displayId); + } } diff --git a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java index 94c19eb8..32589536 100644 --- a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java +++ b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayPackage.java @@ -1,12 +1,14 @@ package com.externaldisplay; import androidx.annotation.Nullable; + import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.react.module.model.ReactModuleInfoProvider; import com.facebook.react.TurboReactPackage; import com.facebook.react.uimanager.ViewManager; + import android.util.Log; import java.util.ArrayList; @@ -16,64 +18,61 @@ import java.util.Map; import android.util.Log; + import com.externaldisplay.RNExternalDisplayManager; import com.externaldisplay.RNExternalDisplayModule; public class RNExternalDisplayPackage extends TurboReactPackage { + private static final String TAG = "RNExternalDisplayEvent"; - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage createViewManagers"); - - List viewManagers = new ArrayList<>(); - viewManagers.add(new RNExternalDisplayManager(reactContext)); - return viewManagers; - } - @Nullable - @Override - public NativeModule getModule(String name, ReactApplicationContext reactContext) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage getModule"); - - if (name.equals(RNExternalDisplayModule.REACT_CLASS)) { - return new com.externaldisplay.RNExternalDisplayModule(reactContext); - } else { - return null; + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + List viewManagers = new ArrayList<>(); + viewManagers.add(new RNExternalDisplayManager(reactContext)); + return viewManagers; } - } - @Override - public ReactModuleInfoProvider getReactModuleInfoProvider() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayPackage getReactModuleInfoProvider"); + @Nullable + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(RNExternalDisplayModule.REACT_CLASS)) { + return new RNExternalDisplayModule(reactContext); + } else { + return null; + } + } - return () -> { - final Map moduleInfos = new HashMap<>(); - boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - moduleInfos.put( - RNExternalDisplayModule.REACT_CLASS, - new ReactModuleInfo( - RNExternalDisplayModule.REACT_CLASS, - RNExternalDisplayModule.REACT_CLASS, - false, // canOverrideExistingModule - false, // needsEagerInit - true, // hasConstants - false, // isCxxModule - isTurboModule // isTurboModule - ) - ); - moduleInfos.put( - RNExternalDisplayManager.REACT_CLASS, - new ReactModuleInfo( - RNExternalDisplayManager.REACT_CLASS, - RNExternalDisplayManager.REACT_CLASS, - false, // canOverrideExistingModule - false, // needsEagerInit - true, // hasConstants - false, // isCxxModule - isTurboModule // isTurboModule - ) - ); - return moduleInfos; - }; - } + @Override + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return () -> { + final Map moduleInfos = new HashMap<>(); + boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + moduleInfos.put( + RNExternalDisplayModule.REACT_CLASS, + new ReactModuleInfo( + RNExternalDisplayModule.REACT_CLASS, + RNExternalDisplayModule.REACT_CLASS, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + ) + ); + moduleInfos.put( + RNExternalDisplayManager.REACT_CLASS, + new ReactModuleInfo( + RNExternalDisplayManager.REACT_CLASS, + RNExternalDisplayManager.REACT_CLASS, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + ) + ); + return moduleInfos; + }; + } } diff --git a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java index c411774f..107e85e7 100644 --- a/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java +++ b/packages/react-native-external-display/android/src/main/java/com/externaldisplay/RNExternalDisplayView.java @@ -3,12 +3,16 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; + import com.facebook.react.ReactRootView; import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactContext; + import android.widget.LinearLayout; + import com.facebook.common.logging.FLog; import com.facebook.react.common.ReactConstants; + import android.util.Log; import android.view.Display; @@ -17,216 +21,214 @@ import java.util.ArrayList; public class RNExternalDisplayView extends ReactRootView implements LifecycleEventListener { - Context context; - private boolean fallbackInMainScreen = false; - private ExternalDisplayHelper helper; - private ExternalDisplayScreen displayScreen; - private int screen = -1; - private ArrayList subviews = new ArrayList(); - private ReactRootView wrap; - private boolean pausedWithDisplayScreen = false; - - public RNExternalDisplayView(Context context, ExternalDisplayHelper helper) { - super(context); - ((ReactContext) context).addLifecycleEventListener(this); - this.context = context; - this.helper = helper; - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView init"); - - } - - @Override - public void addView(View child, int index) { - subviews.add(index, child); - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView addView"); - - updateScreen(); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - } - - @Override - public int getChildCount() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView getChildCount"); - - return subviews.size(); - } - - @Override - public View getChildAt(int index) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView getChildAt"); - - return subviews.get(index); - } - - @Override - public void removeView(View view) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView removeView"); - - super.removeView(view); - } - - @Override - public void removeViewAt(int index) { - View child = getChildAt(index); - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView removeViewAt"); - - super.removeView(child); - subviews.remove(index); - if (wrap != null) { - for (int i = 0; i < wrap.getChildCount(); i++) { - if (i == index) { - wrap.removeViewAt(i); + private static final String TAG = "RNExternalDisplayEvent"; + private boolean fallbackInMainScreen = false; + private ExternalDisplayHelper helper; + private ExternalDisplayScreen displayScreen; + private int screen = -1; + private ArrayList subviews = new ArrayList(); + private ReactRootView wrap; + private boolean pausedWithDisplayScreen = false; + Context context; + + + public RNExternalDisplayView(Context context, ExternalDisplayHelper helper) { + super(context); + ((ReactContext) context).addLifecycleEventListener(this); + if (helper != null) { + this.helper = helper; + } else { + this.helper = null; } - } } - } - - public void onDropInstance() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onDropInstance"); - - ((ReactContext) getContext()).removeLifecycleEventListener(this); - if (wrap != null && wrap.getChildCount() > 0) { - for (int i = 0; i < wrap.getChildCount(); i++) { - wrap.removeViewAt(i); - } + /** + * Retrieves the singleton ExternalDisplayHelper instance. + * If not available, returns null. + * + * @param context The context. + * @return ExternalDisplayHelper instance or null. + */ + private ExternalDisplayHelper getDefaultHelper(Context context) { + try { + return ExternalDisplayHelper.getInstance(); + } catch (IllegalStateException e) { + return null; + } } - destroyScreen(); - } - @Override - public void addChildrenForAccessibility(ArrayList outChildren) { - // This solves an accessibility bug originally addressed in RN - // Reference: https://github.com/mybigday/react-native-external-display/issues/211 - } + @Override + public void addView(View child, int index) { + subviews.add(index, child); + updateScreen(); + } - @Override - public void onHostResume() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onHostResume"); + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + } - if (displayScreen == null && !pausedWithDisplayScreen) { - return; + @Override + public int getChildCount() { + return subviews.size(); } - pausedWithDisplayScreen = false; - updateScreen(); - } - @Override - public void onHostPause() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onHostPause"); + @Override + public View getChildAt(int index) { + return subviews.get(index); + } - if (displayScreen == null) { - return; + @Override + public void removeView(View view) { + super.removeView(view); } - pausedWithDisplayScreen = true; - if (wrap != null) { - for (int i = 0; i < wrap.getChildCount(); i++) { - wrap.removeViewAt(i); - } + + @Override + public void removeViewAt(int index) { + View child = getChildAt(index); + super.removeView(child); + subviews.remove(index); + if (wrap != null) { + for (int i = 0; i < wrap.getChildCount(); i++) { + if (i == index) { + wrap.removeViewAt(i); + } + } + } } - destroyScreen(); - } - @Override - public void onHostDestroy() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView onHostDestroy"); + public void onDropInstance() { + ((ReactContext) getContext()).removeLifecycleEventListener(this); + if (wrap != null && wrap.getChildCount() > 0) { + for (int i = 0; i < wrap.getChildCount(); i++) { + wrap.removeViewAt(i); + } + } + destroyScreen(); + } - onDropInstance(); - } + @Override + public void addChildrenForAccessibility(ArrayList outChildren) { + // This solves an accessibility bug originally addressed in RN + // Reference: https://github.com/mybigday/react-native-external-display/issues/211 + } - public void updateScreen() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView updateScreen"); + @Override + public void onHostResume() { + if (displayScreen == null && !pausedWithDisplayScreen) { + return; + } + pausedWithDisplayScreen = false; + updateScreen(); + } - if (getChildCount() == 0) return; - - if (screen > 0) { - Display display = helper.getDisplay(screen); - if (display != null) { + @Override + public void onHostPause() { if (displayScreen == null) { - displayScreen = new ExternalDisplayScreen(context, display); - wrap = new ReactRootView(context); - } else if (wrap.getChildCount() > 0) { - for (int i = 0; i < wrap.getChildCount(); i++) { - wrap.removeViewAt(i); - } - } - for (int i = 0; i < subviews.size(); i++) { - View subview = subviews.get(i); - if (subview.getParent() != null) { - // Make sure removed from parent - ((ViewGroup) subview.getParent()).removeView(subview); - } - wrap.addView(subview, i); + return; } - displayScreen.setContentView(wrap); - displayScreen.show(); - return; - } - } - if (fallbackInMainScreen == true) { - if (wrap != null) { - for (int i = 0; i < wrap.getChildCount(); i++) { - wrap.removeViewAt(i); + pausedWithDisplayScreen = true; + if (wrap != null) { + for (int i = 0; i < wrap.getChildCount(); i++) { + wrap.removeViewAt(i); + } } - } - for (int i = 0; i < subviews.size(); i++) { - View subview = subviews.get(i); - if (subview.getParent() != null) { - // Make sure removed from parent - ((ViewGroup) subview.getParent()).removeView(subview); - } - super.addView(subview, i); - } + destroyScreen(); } - } - private void destroyScreen() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView destroyScreen"); - - if (displayScreen != null) { - displayScreen.hide(); - displayScreen.dismiss(); - displayScreen = null; - wrap = null; + @Override + public void onHostDestroy() { + onDropInstance(); } - } - public void setScreen(String screen) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView setScreen"); + public void updateScreen() { + if (getChildCount() == 0) return; + + if (screen > 0 && helper != null) { + Display display = helper.getDisplay(screen); + if (display != null) { + if (displayScreen == null) { + displayScreen = new ExternalDisplayScreen(getContext(), display); + wrap = new ReactRootView(getContext()); + } else if (wrap.getChildCount() > 0) { + for (int i = 0; i < wrap.getChildCount(); i++) { + wrap.removeViewAt(i); + } + } + for (int i = 0; i < subviews.size(); i++) { + View subview = subviews.get(i); + if (subview.getParent() != null) { + // Make sure removed from parent + ((ViewGroup) subview.getParent()).removeView(subview); + } + wrap.addView(subview, i); + } + try { + displayScreen.setContentView(wrap); + displayScreen.show(); + } catch (Exception e) { + } + return; + }else { + Log.e(TAG, "Display with ID " + screen + " not found."); + } + } - if (getChildCount() > 0 && wrap != null && wrap.getChildCount() > 0) { - for (int i = 0; i < wrap.getChildCount(); i++) { - wrap.removeViewAt(i); - } - } else { - for (View subview : subviews) { - removeView(subview); - } - } - try { - int nextScreen = Integer.parseInt(screen); - if (nextScreen != this.screen) { - destroyScreen(); - } - this.screen = nextScreen; - } catch (NumberFormatException e) { - destroyScreen(); - this.screen = -1; + if (fallbackInMainScreen) { + if (wrap != null) { + for (int i = 0; i < wrap.getChildCount(); i++) { + wrap.removeViewAt(i); + } + } + for (int i = 0; i < subviews.size(); i++) { + View subview = subviews.get(i); + if (subview.getParent() != null) { + // Make sure removed from parent + ((ViewGroup) subview.getParent()).removeView(subview); + } + super.addView(subview, i); + } + } } - updateScreen(); - } - public int getScreen() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView getScreen"); + private void destroyScreen() { + if (displayScreen != null) { + try { + displayScreen.hide(); + displayScreen.dismiss(); + } catch (Exception e) { + } + displayScreen = null; + wrap = null; + } + } - return this.screen; - } + public void setScreen(String screen) { + if (getChildCount() > 0 && wrap != null && wrap.getChildCount() > 0) { + for (int i = 0; i < wrap.getChildCount(); i++) { + wrap.removeViewAt(i); + } + } else { + for (View subview : subviews) { + removeView(subview); + } + } + try { + int nextScreen = Integer.parseInt(screen); + if (nextScreen != this.screen) { + destroyScreen(); + } + this.screen = nextScreen; + } catch (NumberFormatException e) { + destroyScreen(); + this.screen = -1; + } + updateScreen(); + } - public void setFallbackInMainScreen(boolean value) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayView setFallbackInMainScreen"); + public int getScreen() { + return this.screen; + } - this.fallbackInMainScreen = value; - } + public void setFallbackInMainScreen(boolean value) { + this.fallbackInMainScreen = value; + } } diff --git a/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java b/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java index 5ed4479c..98149dd0 100644 --- a/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java +++ b/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayManager.java @@ -16,117 +16,75 @@ import android.view.Display; import android.graphics.Rect; import android.util.Log; - +import com.externaldisplay.RNExternalDisplayModule; import javax.annotation.Nullable; + import java.util.Map; import java.util.HashMap; -public class RNExternalDisplayManager extends ViewGroupManager implements ExternalDisplayHelper.Listener { - public static final String REACT_CLASS = "RNExternalDisplay"; - private ExternalDisplayHelper helper; - private ReactApplicationContext reactContext; - private Map views = new HashMap(); - - public RNExternalDisplayManager(ReactApplicationContext reactContext) { - super(); - this.reactContext = reactContext; - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager init"); - - } - - @Override - public String getName() { - return REACT_CLASS; - } +public class RNExternalDisplayManager extends ViewGroupManager { + public static final String REACT_CLASS = "RNExternalDisplay"; + private static final String TAG = "RNExternalDisplayEvent"; + private ReactApplicationContext reactContext; + //private Map views = new HashMap(); - @Override - public RNExternalDisplayView createViewInstance(ThemedReactContext context) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager createViewInstance"); - - if (this.helper == null) { - this.helper = new ExternalDisplayHelper(reactContext, this); + public RNExternalDisplayManager(ReactApplicationContext reactContext) { + super(); + this.reactContext = reactContext; } - RNExternalDisplayView view = new RNExternalDisplayView(context, this.helper); - views.put(view, view); - return view; - } - - @Override - public void onDropViewInstance(RNExternalDisplayView view) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager onDropViewInstance"); - - views.remove(view); - super.onDropViewInstance(view); - view.onDropInstance(); - } - private void checkScreen() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager checkScreen"); - - int screenId = -1; - for (RNExternalDisplayView view : views.values()) { - int viewScreenId = view.getScreen(); - if (viewScreenId > 0 && screenId == viewScreenId) { - // TODO: Log to console - FLog.e(ReactConstants.TAG, "Detected two or more RNExternalDisplayView to register the same screen id: " + screenId); - } - if (viewScreenId > 0) { - screenId = viewScreenId; - } + @Override + public String getName() { + return REACT_CLASS; } - } - - @ReactProp(name = "screen") - public void setScreen(RNExternalDisplayView view, @Nullable String screen) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager setScreen"); - view.setScreen(screen); - checkScreen(); - } - - @ReactProp(name = "fallbackInMainScreen", defaultBoolean = false) - public void setFallbackInMainScreen(RNExternalDisplayView view, boolean fallbackInMainScreen) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager setFallbackInMainScreen"); - - view.setFallbackInMainScreen(fallbackInMainScreen); - } - - private void sendEvent(String eventName, @Nullable WritableMap params) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager sendEvent:"+eventName); - - reactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } + @Override + public RNExternalDisplayView createViewInstance(ThemedReactContext context) { + // Retrieve the module to access the helper + RNExternalDisplayModule module = context.getNativeModule(RNExternalDisplayModule.class); + ExternalDisplayHelper helper = null; + if (module != null) { + helper = module.getExternalDisplayHelper(); + } else { + } + + RNExternalDisplayView view = new RNExternalDisplayView(context, helper); + return view; + } - public void onDisplayAdded(Display[] displays, int displayId) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager onDisplayAdded:"+displayId); + @Override + public void onDropViewInstance(RNExternalDisplayView view) { + //views.remove(view); + super.onDropViewInstance(view); + view.onDropInstance(); + } +/* + private void checkScreen() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager checkScreen"); + + int screenId = -1; + for (RNExternalDisplayView view : views.values()) { + int viewScreenId = view.getScreen(); + if (viewScreenId > 0 && screenId == viewScreenId) { + // TODO: Log to console + FLog.e(ReactConstants.TAG, "Detected two or more RNExternalDisplayView to register the same screen id: " + screenId); + } + if (viewScreenId > 0) { + screenId = viewScreenId; + } + } + } - sendEvent( - "@RNExternalDisplay_screenDidConnect", - Arguments.makeNativeMap( - ExternalDisplayHelper.getScreenInfo(displays) - ) - ); - } - public void onDisplayChanged(Display[] displays, int displayId) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager onDisplayChanged:"+displayId); + */ - sendEvent( - "@RNExternalDisplay_screenDidChange", - Arguments.makeNativeMap( - ExternalDisplayHelper.getScreenInfo(displays) - ) - ); - } - public void onDisplayRemoved(Display[] displays, int displayId) { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager onDisplayRemoved:"+displayId); + @ReactProp(name = "screen") + public void setScreen(RNExternalDisplayView view, String screen) { + view.setScreen(screen); + //checkScreen(); + } - sendEvent( - "@RNExternalDisplay_screenDidDisconnect", - Arguments.makeNativeMap( - ExternalDisplayHelper.getScreenInfo(displays) - ) - ); - } + @ReactProp(name = "fallbackInMainScreen", defaultBoolean = false) + public void setFallbackInMainScreen(RNExternalDisplayView view, boolean fallbackInMainScreen) { + view.setFallbackInMainScreen(fallbackInMainScreen); + } } diff --git a/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayModule.java b/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayModule.java index 28c368a7..2029f7d0 100644 --- a/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayModule.java +++ b/packages/react-native-external-display/android/src/oldarch/java/com/externaldisplay/RNExternalDisplayModule.java @@ -1,6 +1,7 @@ package com.externaldisplay; import android.content.Context; + import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; @@ -12,29 +13,84 @@ import java.util.Map; import java.util.HashMap; -public class RNExternalDisplayModule extends ReactContextBaseJavaModule { - public static final String REACT_CLASS = "RNExternalDisplayEvent"; - private ReactApplicationContext reactContext = null; - private DisplayManager dm = null; - - public RNExternalDisplayModule(ReactApplicationContext context) { - super(context); - Log.d("RNExternalDisplayEvent", "RNExternalDisplayModule init"); - reactContext = context; - dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); - } - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - public Map getConstants() { - Log.d("RNExternalDisplayEvent", "RNExternalDisplayModule getConstants"); - - HashMap map = new HashMap(); - map.put("SCREEN_INFO", ExternalDisplayHelper.getScreenInfo(dm.getDisplays())); - return map; - } -} \ No newline at end of file +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import com.facebook.react.bridge.Arguments; + +@ReactModule(name = RNExternalDisplayModule.REACT_CLASS) // Added Annotation +public class RNExternalDisplayModule extends ReactContextBaseJavaModule implements ExternalDisplayHelper.Listener { + public static final String REACT_CLASS = "RNExternalDisplayEvent"; + private static final String TAG = "RNExternalDisplayEvent"; + + private ReactApplicationContext reactContext = null; + + public RNExternalDisplayModule(ReactApplicationContext context) { + super(context); + this.reactContext = context; + // Initialize ExternalDisplayHelper singleton + ExternalDisplayHelper.initialize(context, this); + } + + @Override + public String getName() { + return REACT_CLASS; + } + + @Override + public Map getConstants() { + HashMap map = new HashMap<>(); + try { + map.put("SCREEN_INFO", ExternalDisplayHelper.getScreenInfo(ExternalDisplayHelper.getInstance().getDisplays())); + } catch (IllegalStateException e) { + map.put("SCREEN_INFO", new HashMap()); + } + return map; + } + + private void sendEvent(String eventName, WritableMap params) { + reactContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(eventName, params); + } + + @Override + public void onDisplayAdded(Display[] displays, int displayId) { + sendEvent( + "@RNExternalDisplay_screenDidConnect", + Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(displays)) + ); + } + + @Override + public void onDisplayChanged(Display[] displays, int displayId) { + sendEvent( + "@RNExternalDisplay_screenDidChange", + Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(displays)) + ); + } + + @Override + public void onDisplayRemoved(Display[] displays, int displayId) { + sendEvent( + "@RNExternalDisplay_screenDidDisconnect", + Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(displays)) + ); + } + + @Override + public void onCatalystInstanceDestroy() { + super.onCatalystInstanceDestroy(); + // Clean up the ExternalDisplayHelper singleton + ExternalDisplayHelper.destroy(); + } + + // Optional: Provide a getter for ExternalDisplayHelper + public ExternalDisplayHelper getExternalDisplayHelper() { + try { + return ExternalDisplayHelper.getInstance(); + } catch (IllegalStateException e) { + return null; + } + } +} From 7ee214717dc7c8ad2efa810e7a02dbb3161f1dda Mon Sep 17 00:00:00 2001 From: Dmitriy Grachev Date: Thu, 15 May 2025 12:40:19 +0300 Subject: [PATCH 3/6] fix `Can't add "react-native-external-display": invalid package version undefined.` --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 12ad5324..7ec7b009 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "workspaces": [ "packages/*" ], + "version": "0.6.6", "packageManager": "yarn@1.22.22", "scripts": { "lint": "eslint .", From 1ceddfeffcc4673d31217aade85f60d8ef117c23 Mon Sep 17 00:00:00 2001 From: Dmitriy Grachev Date: Thu, 15 May 2025 15:12:42 +0300 Subject: [PATCH 4/6] copied config files from the root dir --- .../.eslintignore | 1 + .../.eslintrc.js | 26 ++++++++ .../.gitattributes | 3 + .../react-native-external-display/.gitignore | 60 +++++++++++++++++++ .../react-native-external-display/.prettierrc | 7 +++ 5 files changed, 97 insertions(+) create mode 100644 packages/react-native-external-display/.eslintignore create mode 100644 packages/react-native-external-display/.eslintrc.js create mode 100644 packages/react-native-external-display/.gitattributes create mode 100644 packages/react-native-external-display/.gitignore create mode 100644 packages/react-native-external-display/.prettierrc diff --git a/packages/react-native-external-display/.eslintignore b/packages/react-native-external-display/.eslintignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/packages/react-native-external-display/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/packages/react-native-external-display/.eslintrc.js b/packages/react-native-external-display/.eslintrc.js new file mode 100644 index 00000000..22d1753f --- /dev/null +++ b/packages/react-native-external-display/.eslintrc.js @@ -0,0 +1,26 @@ +module.exports = { + root: true, + extends: [ + '@fugood/eslint-config-react', + // 'plugin:ft-flow/recommended', + ], + parser: 'hermes-eslint', + plugins: [ + 'ft-flow' + ], + env: { + node: true, + browser: true, + jest: true, + }, + rules: { + 'import/order': 0, + }, + settings: { + 'import/resolver': { + node: { + extensions: ['.js', '.jsx', '.json', '.native.js', '.ios.js', '.android.js'], + }, + }, + }, +} diff --git a/packages/react-native-external-display/.gitattributes b/packages/react-native-external-display/.gitattributes new file mode 100644 index 00000000..e27f70fa --- /dev/null +++ b/packages/react-native-external-display/.gitattributes @@ -0,0 +1,3 @@ +*.pbxproj -text +# specific for windows script files +*.bat text eol=crlf diff --git a/packages/react-native-external-display/.gitignore b/packages/react-native-external-display/.gitignore new file mode 100644 index 00000000..cc53454e --- /dev/null +++ b/packages/react-native-external-display/.gitignore @@ -0,0 +1,60 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +*.keystore +!debug.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +*/fastlane/report.xml +*/fastlane/Preview.html +*/fastlane/screenshots + +# Bundle artifact +*.jsbundle + +# CocoaPods +/ios/Pods/ diff --git a/packages/react-native-external-display/.prettierrc b/packages/react-native-external-display/.prettierrc new file mode 100644 index 00000000..30661acc --- /dev/null +++ b/packages/react-native-external-display/.prettierrc @@ -0,0 +1,7 @@ +{ + "trailingComma": "all", + "tabWidth": 2, + "semi": false, + "singleQuote": true, + "printWidth": 80 +} From b7ecd1dff15a48856d98a08ede7b245ec1a147f6 Mon Sep 17 00:00:00 2001 From: Dmitriy Grachev Date: Thu, 2 Oct 2025 14:56:00 +0300 Subject: [PATCH 5/6] remove ignored Android project configuration file for react-native-external-display --- .../android/.project | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 packages/react-native-external-display/android/.project diff --git a/packages/react-native-external-display/android/.project b/packages/react-native-external-display/android/.project deleted file mode 100644 index c55ce2f6..00000000 --- a/packages/react-native-external-display/android/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - react-native-external-display - Project react-native-external-display created by Buildship. - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.buildship.core.gradleprojectnature - - - - 1733156198568 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - From a49ade10785375ba46db87afe6e9503a52ed6a49 Mon Sep 17 00:00:00 2001 From: Dmitriy Grachev Date: Thu, 2 Oct 2025 14:57:23 +0300 Subject: [PATCH 6/6] Updated RNExternalDisplayModule to initialize ExternalDisplayHelper and handle display events --- .../RNExternalDisplayManager.java | 61 ++++++----------- .../RNExternalDisplayModule.java | 67 +++++++++++++++++-- 2 files changed, 80 insertions(+), 48 deletions(-) diff --git a/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayManager.java b/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayManager.java index 4d7538c3..970d5079 100644 --- a/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayManager.java +++ b/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayManager.java @@ -27,11 +27,11 @@ import java.util.HashMap; public class RNExternalDisplayManager extends ViewGroupManager - implements ExternalDisplayHelper.Listener, RNExternalDisplayManagerInterface { + implements RNExternalDisplayManagerInterface { public static final String REACT_CLASS = "RNExternalDisplay"; - private ExternalDisplayHelper helper; + private static final String TAG = "RNExternalDisplayEvent"; private ReactApplicationContext reactContext; - private Map views = new HashMap(); + //private Map views = new HashMap(); private final ViewManagerDelegate mDelegate; @@ -54,22 +54,28 @@ public String getName() { @Override public RNExternalDisplayView createViewInstance(ThemedReactContext context) { - if (this.helper == null) { - this.helper = new ExternalDisplayHelper(reactContext, this); + // Retrieve the module to access the helper + RNExternalDisplayModule module = context.getNativeModule(RNExternalDisplayModule.class); + ExternalDisplayHelper helper = null; + if (module != null) { + helper = module.getExternalDisplayHelper(); + } else { } - RNExternalDisplayView view = new RNExternalDisplayView(context, this.helper); - views.put(view, view); + + RNExternalDisplayView view = new RNExternalDisplayView(context, helper); return view; } @Override public void onDropViewInstance(RNExternalDisplayView view) { - views.remove(view); + //views.remove(view); super.onDropViewInstance(view); view.onDropInstance(); } - +/* private void checkScreen() { + Log.d("RNExternalDisplayEvent", "RNExternalDisplayManager checkScreen"); + int screenId = -1; for (RNExternalDisplayView view : views.values()) { int viewScreenId = view.getScreen(); @@ -83,45 +89,16 @@ private void checkScreen() { } } + */ + @ReactProp(name = "screen") - public void setScreen(RNExternalDisplayView view, @Nullable String screen) { + public void setScreen(RNExternalDisplayView view, String screen) { view.setScreen(screen); - checkScreen(); + //checkScreen(); } @ReactProp(name = "fallbackInMainScreen", defaultBoolean = false) public void setFallbackInMainScreen(RNExternalDisplayView view, boolean fallbackInMainScreen) { view.setFallbackInMainScreen(fallbackInMainScreen); } - - private void sendEvent(String eventName, @Nullable WritableMap params) { - reactContext - .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) - .emit(eventName, params); - } - - public void onDisplayAdded(Display[] displays, int displayId) { - sendEvent( - "@RNExternalDisplay_screenDidConnect", - Arguments.makeNativeMap( - ExternalDisplayHelper.getScreenInfo(displays) - ) - ); - } - public void onDisplayChanged(Display[] displays, int displayId) { - sendEvent( - "@RNExternalDisplay_screenDidChange", - Arguments.makeNativeMap( - ExternalDisplayHelper.getScreenInfo(displays) - ) - ); - } - public void onDisplayRemoved(Display[] displays, int displayId) { - sendEvent( - "@RNExternalDisplay_screenDidDisconnect", - Arguments.makeNativeMap( - ExternalDisplayHelper.getScreenInfo(displays) - ) - ); - } } diff --git a/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayModule.java b/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayModule.java index 9bda6bc1..1ca67910 100644 --- a/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayModule.java +++ b/packages/react-native-external-display/android/src/newarch/java/com/externaldisplay/RNExternalDisplayModule.java @@ -9,19 +9,24 @@ import android.view.Display; import android.hardware.display.DisplayManager; +import android.util.Log; import java.util.Map; import java.util.HashMap; -public class RNExternalDisplayModule extends NativeRNExternalDisplayEventSpec { +import com.facebook.react.modules.core.DeviceEventManagerModule; + +public class RNExternalDisplayModule extends NativeRNExternalDisplayEventSpec implements ExternalDisplayHelper.Listener { public static final String REACT_CLASS = "RNExternalDisplayEvent"; + private static final String TAG = "RNExternalDisplayEvent"; + private ReactApplicationContext reactContext = null; - private DisplayManager dm = null; - + public RNExternalDisplayModule(ReactApplicationContext context) { super(context); - reactContext = context; - dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE); + this.reactContext = context; + // Initialize ExternalDisplayHelper singleton + ExternalDisplayHelper.initialize(context, this); } @Override @@ -32,7 +37,11 @@ public String getName() { @Override public WritableMap getInitialScreens() { WritableMap map = Arguments.createMap(); - map.putMap("SCREEN_INFO", Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(dm.getDisplays()))); + try { + map.putMap("SCREEN_INFO", Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(ExternalDisplayHelper.getInstance().getDisplays()))); + } catch (IllegalStateException e) { + map.putMap("SCREEN_INFO", Arguments.createMap()); + } return map; } @@ -52,4 +61,50 @@ public void init() {} @Override public boolean resumeMainScene() { return false; } + + private void sendEvent(String eventName, WritableMap params) { + reactContext + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(eventName, params); + } + + @Override + public void onDisplayAdded(Display[] displays, int displayId) { + sendEvent( + "@RNExternalDisplay_screenDidConnect", + Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(displays)) + ); + } + + @Override + public void onDisplayChanged(Display[] displays, int displayId) { + sendEvent( + "@RNExternalDisplay_screenDidChange", + Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(displays)) + ); + } + + @Override + public void onDisplayRemoved(Display[] displays, int displayId) { + sendEvent( + "@RNExternalDisplay_screenDidDisconnect", + Arguments.makeNativeMap(ExternalDisplayHelper.getScreenInfo(displays)) + ); + } + + @Override + public void onCatalystInstanceDestroy() { + super.onCatalystInstanceDestroy(); + // Clean up the ExternalDisplayHelper singleton + ExternalDisplayHelper.destroy(); + } + + // Optional: Provide a getter for ExternalDisplayHelper + public ExternalDisplayHelper getExternalDisplayHelper() { + try { + return ExternalDisplayHelper.getInstance(); + } catch (IllegalStateException e) { + return null; + } + } } \ No newline at end of file