Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 0 additions & 65 deletions src/features/browser/screens/BrowserScreen/WebViewComponent.tsx

This file was deleted.

122 changes: 122 additions & 0 deletions src/features/browser/screens/BrowserScreen/WebViewContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { useScripts } from "@/src/features/scripts/hooks/useScripts";
import { useCallback, useRef } from "react";
import { StyleSheet, View, ViewProps } from "react-native";
import {
WebView,
WebViewMessageEvent,
WebViewNavigation,
} from "react-native-webview";
import { useBrowser } from "../../hooks/useBrowser";
import { normalizeUrl } from "../../utils/urlUtils";

const SCROLL_DIRECTION_THRESHOLD = 8;

function getInjectionScripts(
url: string,
runAt: "document-start" | "document-ready" | "document-end",
getScriptsByRunAt: any
) {
return getScriptsByRunAt(url, runAt)
.map((script: any) => script.code)
.join("\n");
}

type WebViewContainerProps = {
bottomPadding?: number;
onScrollDirectionChange?: (direction: "up" | "down") => void;
} & ViewProps;

export default function WebViewContainer({
bottomPadding = 0,
style,
onScrollDirectionChange,
...props
}: WebViewContainerProps) {
const { activeTab, updateTabById } = useBrowser();
const { getScriptsByRunAt, logExecution } = useScripts();

Check warning on line 36 in src/features/browser/screens/BrowserScreen/WebViewContainer.tsx

View workflow job for this annotation

GitHub Actions / test

'logExecution' is assigned a value but never used
const webviewRef = useRef<WebView>(null);

// Prepare URL
const url = activeTab?.url ? normalizeUrl(activeTab.url) : "about:blank";

// Inject scripts at different lifecycle points
const injectedJavaScriptBeforeContentLoaded = activeTab?.url
? getInjectionScripts(url, "document-start", getScriptsByRunAt)
: "";
const injectedJavaScript = activeTab?.url
? getInjectionScripts(url, "document-ready", getScriptsByRunAt)
: "";

// Handle navigation events
const onNavigationStateChange = useCallback(
(navState: WebViewNavigation) => {
if (!activeTab) return;
updateTabById(activeTab.id, {
url: navState.url,
title: navState.title ?? "",
canGoBack: navState.canGoBack,
canGoForward: navState.canGoForward,
isLoading: navState.loading,
});
},
[activeTab, updateTabById]
);

// Handle JS execution results
const onMessage = useCallback((event: WebViewMessageEvent) => {
// TODO: Log execution results
}, []);

// Inject CSS to add bottom padding to the body
const injectedCSS = `

Check warning on line 71 in src/features/browser/screens/BrowserScreen/WebViewContainer.tsx

View workflow job for this annotation

GitHub Actions / test

'injectedCSS' is assigned a value but never used
const style = document.createElement('style');
style.innerHTML = 'body { padding-bottom: ${bottomPadding}px !important; box-sizing: border-box; }';
document.head.appendChild(style);
`;

const lastScrollY = useRef(0);
const lastDirection = useRef<"up" | "down" | null>(null); // pixels
const handleScroll = (event: any) => {
const currentY = event.nativeEvent.contentOffset?.y ?? 0;
const diff = currentY - lastScrollY.current;

if (Math.abs(diff) > SCROLL_DIRECTION_THRESHOLD) {
const newDirection = diff > 0 ? "down" : "up";
if (newDirection !== lastDirection.current) {
onScrollDirectionChange?.(newDirection);
lastDirection.current = newDirection;
}
}
lastScrollY.current = currentY;
};

return (
<View style={[styles.container, style]} {...props}>
<WebView
ref={webviewRef}
source={{ uri: url }}
injectedJavaScriptBeforeContentLoaded={
injectedJavaScriptBeforeContentLoaded
}
injectedJavaScript={injectedJavaScript}
onNavigationStateChange={onNavigationStateChange}
onMessage={onMessage}
startInLoadingState={true}
allowsInlineMediaPlayback
javaScriptEnabled
domStorageEnabled
setSupportMultipleWindows={false}
allowsBackForwardNavigationGestures
originWhitelist={["*"]}
onScroll={handleScroll}
/>
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#ecf0f1",
},
});
60 changes: 27 additions & 33 deletions src/features/browser/screens/BrowserScreen/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import AddressBar from "./AddressBar";
import AddressBarDisplay from "./AddressBarDisplay";
import Toolbar from "./Toolbar";
import WebViewComponent from "./WebViewComponent";
import WebViewContainer from "./WebViewContainer";

const KEYBOARD_OPENED_HEIGHT = 102;
const KEYBOARD_CLOSED_HEIGHT = 0;

export default function BrowserScreen() {
const theme = useTheme();
const { showTabs } = useBrowser();

Check warning on line 20 in src/features/browser/screens/BrowserScreen/index.tsx

View workflow job for this annotation

GitHub Actions / test

'showTabs' is assigned a value but never used
const { height, progress } = useKeyboardAnimation();

const [isAddressBarFocused, setAddressBarFocused] = useState(false);
Expand Down Expand Up @@ -55,30 +55,33 @@
outputRange: [KEYBOARD_CLOSED_HEIGHT, KEYBOARD_OPENED_HEIGHT],
});

const addressBarStyle = useMemo(
const bottomContainerY = useMemo(() => new Animated.Value(0), []);

useEffect(() => {
Animated.timing(bottomContainerY, {
toValue: showBottomContainer ? 0 : 200,
duration: 400,
useNativeDriver: true,
}).start();
}, [showBottomContainer, bottomContainerY]);

const bottomContainerStyle = useMemo(
() => [
{
transform: [
{
translateY: Animated.add(height, offset),
},
{
translateY: bottomContainerY,
},
],
},
{ backgroundColor: "white" },
],
[height, offset]
[height, offset, bottomContainerY]
);

const bottomContainerY = useMemo(() => new Animated.Value(0), []);

useEffect(() => {
Animated.timing(bottomContainerY, {
toValue: showBottomContainer ? 0 : 200,
duration: 400,
useNativeDriver: true,
}).start();
}, [showBottomContainer, bottomContainerY]);

return (
<View style={{ flex: 1 }}>
<SafeAreaView
Expand All @@ -89,32 +92,18 @@
edges={["top"]}
>
<View style={styles.webViewContainer}>
<WebViewComponent
<WebViewContainer
bottomPadding={isKeyboardVisible ? 16 : 0}
onScrollDirectionChange={setScrollDirection}
/>
</View>
</SafeAreaView>

<Animated.View
style={[
styles.bottomContainer,
{
backgroundColor: "white",
transform: [{ translateY: bottomContainerY }],
position: "absolute",
left: 0,
right: 0,
bottom: 0,
},
]}
>
<Animated.View style={addressBarStyle}>
{showAddressBar && (
<AddressBar onFocusChange={onAddressBarFocusChange} />
)}
{!showAddressBar && <AddressBarDisplay />}
</Animated.View>
<Animated.View style={[styles.bottomContainer, bottomContainerStyle]}>
{showAddressBar && (
<AddressBar onFocusChange={onAddressBarFocusChange} />
)}
{!showAddressBar && <AddressBarDisplay />}
{/* Toolbar contains the SafeAreaView */}
<Toolbar />
</Animated.View>
Expand All @@ -132,5 +121,10 @@
},
bottomContainer: {
width: "100%",
backgroundColor: "white",
position: "absolute",
left: 0,
right: 0,
bottom: 0,
},
});
Loading