diff --git a/android/app/src/main/java/com/rajarsheechatterjee/LNReader/MainApplication.java b/android/app/src/main/java/com/rajarsheechatterjee/LNReader/MainApplication.java index 1cca556d..73229602 100644 --- a/android/app/src/main/java/com/rajarsheechatterjee/LNReader/MainApplication.java +++ b/android/app/src/main/java/com/rajarsheechatterjee/LNReader/MainApplication.java @@ -13,7 +13,6 @@ import com.facebook.react.defaults.DefaultReactNativeHost; import com.facebook.soloader.SoLoader; import com.rajarsheechatterjee.EpubUtil.EpubUtilPackage; -import com.rajarsheechatterjee.NavigationBarColor.NavigationBarColorPackage; import com.rajarsheechatterjee.TextFile.TextFilePackage; import com.rajarsheechatterjee.VolumeButtonListener.VolumeButtonListenerPackage; import com.rajarsheechatterjee.ZipArchive.ZipArchivePackage; @@ -35,7 +34,6 @@ public class MainApplication extends Application implements ReactApplication { @Override protected List getPackages() { List packages = new PackageList(this).getPackages(); - packages.add(new NavigationBarColorPackage()); packages.add(new VolumeButtonListenerPackage()); packages.add(new ZipArchivePackage()); packages.add(new TextFilePackage()); diff --git a/android/app/src/main/java/com/rajarsheechatterjee/NavigationBarColor/NavigationBarColorModule.java b/android/app/src/main/java/com/rajarsheechatterjee/NavigationBarColor/NavigationBarColorModule.java deleted file mode 100644 index a66d7e9d..00000000 --- a/android/app/src/main/java/com/rajarsheechatterjee/NavigationBarColor/NavigationBarColorModule.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.rajarsheechatterjee.NavigationBarColor; - -import android.animation.ArgbEvaluator; -import android.animation.ValueAnimator; -import android.graphics.Color; -import android.os.Build; -import android.app.Activity; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Promise; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.WritableMap; -import java.util.HashMap; -import java.util.Map; -import com.facebook.react.uimanager.IllegalViewOperationException; -import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread; - -public class NavigationBarColorModule extends ReactContextBaseJavaModule { - public static final String REACT_CLASS = "NavigationBarColor"; - private static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY"; - private static final String ERROR_NO_ACTIVITY_MESSAGE = "Tried to change the navigation bar while not attached to an Activity"; - private static final int UI_FLAG_HIDE_NAV_BAR = View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar - | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; - - public NavigationBarColorModule(ReactApplicationContext context) { - super(context); - } - - public void setNavigationBarTheme(Activity activity, Boolean light) { - if (activity != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - Window window = activity.getWindow(); - int flags = window.getDecorView().getSystemUiVisibility(); - if (light) { - flags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; - } else { - flags &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; - } - window.getDecorView().setSystemUiVisibility(flags); - } - } - - - @Override - public String getName() { - return REACT_CLASS; - } - - @Override - public Map getConstants() { - final Map constants = new HashMap<>(); - constants.put("EXAMPLE_CONSTANT", "example"); - - return constants; - } - - @ReactMethod - public void changeNavigationBarColor(final String color, final Boolean light, final Boolean animated, final Promise promise) { - final WritableMap map = Arguments.createMap(); - if (getCurrentActivity() != null) { - try { - final Window window = getCurrentActivity().getWindow(); - runOnUiThread(new Runnable() { - @Override - public void run() { - if (color.equals("transparent") || color.equals("translucent")) { - window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - if (color.equals("transparent")) { - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - } else { - window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - } - setNavigationBarTheme(getCurrentActivity(), light); - map.putBoolean("success", true); - promise.resolve(map); - return; - } else { - window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); - } - if (animated) { - Integer colorFrom = window.getNavigationBarColor(); - Integer colorTo = Color.parseColor(color); - //window.setNavigationBarColor(colorTo); - ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); - colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animator) { - window.setNavigationBarColor((Integer) animator.getAnimatedValue()); - } - }); - colorAnimation.start(); - } else { - window.setNavigationBarColor(Color.parseColor(color)); - } - setNavigationBarTheme(getCurrentActivity(), light); - WritableMap map = Arguments.createMap(); - map.putBoolean("success", true); - promise.resolve(map); - } - }); - } catch (IllegalViewOperationException e) { - map.putBoolean("success", false); - promise.reject("error", e); - } - - } else { - promise.reject(ERROR_NO_ACTIVITY, new Throwable(ERROR_NO_ACTIVITY_MESSAGE)); - } - } - - @ReactMethod - public void hideNavigationBar(Promise promise) { - try { - runOnUiThread(new Runnable() { - @Override - public void run() { - if (getCurrentActivity() != null) { - View decorView = getCurrentActivity().getWindow().getDecorView(); - decorView.setSystemUiVisibility(UI_FLAG_HIDE_NAV_BAR); - } - } - }); - } catch (IllegalViewOperationException e) { - WritableMap map = Arguments.createMap(); - map.putBoolean("success", false); - promise.reject("error", e); - } - } - - @ReactMethod - public void showNavigationBar(Promise promise) { - try { - runOnUiThread(new Runnable() { - @Override - public void run() { - if (getCurrentActivity() != null) { - Window w = getCurrentActivity().getWindow(); - w.setStatusBarColor(Color.TRANSPARENT); - w.setNavigationBarColor(Color.TRANSPARENT); - View decorView = w.getDecorView(); - decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - } - }); - } catch (IllegalViewOperationException e) { - WritableMap map = Arguments.createMap(); - map.putBoolean("success", false); - promise.reject("error", e); - } - } -} diff --git a/android/app/src/main/java/com/rajarsheechatterjee/NavigationBarColor/NavigationBarColorPackage.java b/android/app/src/main/java/com/rajarsheechatterjee/NavigationBarColor/NavigationBarColorPackage.java deleted file mode 100644 index ff4738f9..00000000 --- a/android/app/src/main/java/com/rajarsheechatterjee/NavigationBarColor/NavigationBarColorPackage.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.rajarsheechatterjee.NavigationBarColor; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class NavigationBarColorPackage implements ReactPackage { - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } - - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - List modules = new ArrayList<>(); - - modules.add(new NavigationBarColorModule(reactContext)); - - return modules; - } -} diff --git a/package-lock.json b/package-lock.json index 08371437..ecf0f5a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "expo-linear-gradient": "~12.3.0", "expo-linking": "~5.0.2", "expo-localization": "~14.3.0", + "expo-navigation-bar": "^2.8.1", "expo-notifications": "~0.20.1", "expo-speech": "~11.3.0", "expo-sqlite": "~11.3.3", @@ -10001,6 +10002,18 @@ "invariant": "^2.2.4" } }, + "node_modules/expo-navigation-bar": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/expo-navigation-bar/-/expo-navigation-bar-2.8.1.tgz", + "integrity": "sha512-aT5G+7SUsXDVPsRwp8fF940ycka1ABb4g3QKvTZN3YP6kMWvsiYEmRqMIJVy0zUr/i6bxBG1ZergkXimWrFt3w==", + "dependencies": { + "@react-native/normalize-color": "^2.0.0", + "debug": "^4.3.2" + }, + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-notifications": { "version": "0.20.1", "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-0.20.1.tgz", @@ -15722,6 +15735,18 @@ "@babel/runtime": "^7.20.6" } }, + "node_modules/react-native-dotenv/node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/react-native-drawer-layout": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/react-native-drawer-layout/-/react-native-drawer-layout-3.2.2.tgz", diff --git a/package.json b/package.json index b568d065..d8779a18 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "expo-linear-gradient": "~12.3.0", "expo-linking": "~5.0.2", "expo-localization": "~14.3.0", + "expo-navigation-bar": "^2.8.1", "expo-notifications": "~0.20.1", "expo-speech": "~11.3.0", "expo-sqlite": "~11.3.3", diff --git a/src/hooks/common/useFullscreenMode.ts b/src/hooks/common/useFullscreenMode.ts index b86d2c3e..9e210a1f 100644 --- a/src/hooks/common/useFullscreenMode.ts +++ b/src/hooks/common/useFullscreenMode.ts @@ -1,18 +1,17 @@ import { useCallback, useEffect } from 'react'; import { StatusBar } from 'react-native'; import { useNavigation } from '@react-navigation/native'; -import color from 'color'; -import { - changeNavigationBarColor, - hideNavigationBar, - showNavigationBar, -} from '../../native/NavigationBarColor'; import { useChapterGeneralSettings, useChapterReaderSettings, useTheme, } from '../persisted'; import Color from 'color'; +import * as NavigationBar from 'expo-navigation-bar'; +import { + changeNavigationBarColor, + setStatusBarColor, +} from '@theme/utils/setBarColor'; const useFullscreenMode = () => { const { addListener } = useNavigation(); @@ -23,21 +22,37 @@ const useFullscreenMode = () => { const setImmersiveMode = useCallback(() => { if (fullScreenMode) { StatusBar.setHidden(true); - hideNavigationBar(); + NavigationBar.setVisibilityAsync('hidden'); } else { - StatusBar.setBarStyle( - color(backgroundColor).isDark() ? 'light-content' : 'dark-content', + setStatusBarColor(Color(backgroundColor)); + changeNavigationBarColor( + backgroundColor, + Color(backgroundColor).isDark(), ); - StatusBar.setBackgroundColor(backgroundColor); - changeNavigationBarColor(backgroundColor); } }, [backgroundColor, fullScreenMode]); const showStatusAndNavBar = useCallback(() => { StatusBar.setHidden(false); - showNavigationBar(); - changeNavigationBarColor(Color(theme.surface).hex(), !theme.isDark); - }, []); + NavigationBar.setVisibilityAsync('visible'); + + if (fullScreenMode) { + /** + * This is overlay of reader footer and should be transparent. + * But in hexa, ##xxxxxx00 could be another color + */ + changeNavigationBarColor( + Color(theme.surface).alpha(0.05).hexa(), + theme.isDark, + ); + setStatusBarColor(theme); + } else { + changeNavigationBarColor( + backgroundColor, + Color(backgroundColor).isDark(), + ); + } + }, [backgroundColor, fullScreenMode]); useEffect(() => { setImmersiveMode(); @@ -45,13 +60,10 @@ const useFullscreenMode = () => { useEffect(() => { const unsubscribe = addListener('beforeRemove', () => { - showStatusAndNavBar(); - StatusBar.setBarStyle(theme.isDark ? 'light-content' : 'dark-content'); - changeNavigationBarColor( - Color(theme.surface2).hex(), - !theme.isDark, - true, - ); + StatusBar.setHidden(false); + NavigationBar.setVisibilityAsync('visible'); + setStatusBarColor(theme); + changeNavigationBarColor(Color(theme.surface2).hex(), !theme.isDark); }); return unsubscribe; diff --git a/src/native/NavigationBarColor.ts b/src/native/NavigationBarColor.ts deleted file mode 100644 index 1a45d5f5..00000000 --- a/src/native/NavigationBarColor.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NativeModules, Platform } from 'react-native'; - -const { NavigationBarColor } = NativeModules; - -const changeNavigationBarColor = ( - color = '', - light = false, - animated = true, -) => { - if (Platform.OS === 'android') { - const LightNav = light ? true : false; - NavigationBarColor.changeNavigationBarColor(color, LightNav, animated); - } -}; - -const hideNavigationBar = () => { - if (Platform.OS === 'android') { - NavigationBarColor.hideNavigationBar(); - } else { - return false; - } -}; - -const showNavigationBar = () => { - if (Platform.OS === 'android') { - NavigationBarColor.showNavigationBar(); - } else { - return false; - } -}; - -export { changeNavigationBarColor, hideNavigationBar, showNavigationBar }; diff --git a/src/navigators/Main.tsx b/src/navigators/Main.tsx index 8d785e8e..fceac2c3 100644 --- a/src/navigators/Main.tsx +++ b/src/navigators/Main.tsx @@ -3,7 +3,10 @@ import React, { useEffect } from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; -import { setBarColor } from '@theme/utils/setBarColor'; +import { + changeNavigationBarColor, + setStatusBarColor, +} from '@theme/utils/setBarColor'; import { useAppSettings, usePlugins, useTheme } from '@hooks/persisted'; import { useGithubUpdateChecker } from '@hooks/common/githubUpdateChecker'; @@ -31,7 +34,6 @@ import BrowseSettings from '../screens/browse/BrowseSettings'; import { updateLibrary } from '@services/updates'; import WebviewScreen from '@screens/WebviewScreen/WebviewScreen'; import { RootStackParamList } from './types'; -import { changeNavigationBarColor } from '@native/NavigationBarColor'; import Color from 'color'; const Stack = createStackNavigator(); @@ -43,12 +45,8 @@ const MainNavigator = () => { useEffect(() => { const timer = setTimeout(async () => { - setBarColor(theme); - changeNavigationBarColor( - Color(theme.surface2).hex(), - !theme.isDark, - true, - ); + setStatusBarColor(theme); + changeNavigationBarColor(Color(theme.surface2).hex(), theme.isDark); }, 500); return () => { diff --git a/src/screens/reader/components/ReaderFooter.tsx b/src/screens/reader/components/ReaderFooter.tsx index 50f84d8a..1e1a3a14 100644 --- a/src/screens/reader/components/ReaderFooter.tsx +++ b/src/screens/reader/components/ReaderFooter.tsx @@ -7,6 +7,7 @@ import { ThemeColors } from '@theme/types'; import { ChapterInfo, NovelInfo } from '@database/types'; import { BottomSheetModalMethods } from '@gorhom/bottom-sheet/lib/typescript/types'; import { ChapterScreenProps } from '@navigators/types'; +import { useDeviceOrientation } from '@hooks/index'; interface ChapterFooterProps { theme: ThemeColors; @@ -38,14 +39,17 @@ const ChapterFooter = ({ borderless: true, radius: 50, }; - + const orientation = useDeviceOrientation(); return ( @@ -142,7 +146,6 @@ const styles = StyleSheet.create({ zIndex: 1, bottom: 0, width: '100%', - paddingBottom: 16, }, buttonsContainer: { flexDirection: 'row', diff --git a/src/theme/utils/setBarColor.ts b/src/theme/utils/setBarColor.ts index b1543af8..3985da45 100644 --- a/src/theme/utils/setBarColor.ts +++ b/src/theme/utils/setBarColor.ts @@ -1,11 +1,21 @@ import { StatusBar } from 'react-native'; import { ThemeColors } from '@theme/types'; +import * as NavigationBar from 'expo-navigation-bar'; +import Color from 'color'; -/** - * Sets status and navigation bar color. - * - * @param theme - */ +export const setStatusBarColor = (color: ThemeColors | Color) => { + if (color instanceof Color) { + // fullscreen reader mode + StatusBar.setBarStyle(color.isDark() ? 'light-content' : 'dark-content'); + StatusBar.setBackgroundColor(color.hexa()); + } else { + StatusBar.setTranslucent(true); + StatusBar.setBackgroundColor('transparent'); + StatusBar.setBarStyle(color.isDark ? 'light-content' : 'dark-content'); + } +}; -export const setBarColor = (theme: ThemeColors) => - StatusBar.setBarStyle(theme.isDark ? 'light-content' : 'dark-content'); +export const changeNavigationBarColor = (color: string, isDark = false) => { + NavigationBar.setBackgroundColorAsync(color); + NavigationBar.setButtonStyleAsync(isDark ? 'light' : 'dark'); +};