Skip to content

Commit

Permalink
feat: add header and change url
Browse files Browse the repository at this point in the history
  • Loading branch information
moonrailgun committed Mar 10, 2023
1 parent 953ebf3 commit 2b314d7
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 61 deletions.
8 changes: 4 additions & 4 deletions release/app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 16 additions & 1 deletion src/main/webviewManager.ts
Expand Up @@ -2,6 +2,7 @@ import { BrowserView, BrowserWindow, ipcMain, Rectangle } from 'electron';

interface WebviewInfo {
view: BrowserView;
url: string;
hidden: boolean;
}

Expand All @@ -21,6 +22,11 @@ function fixRect(rect: Rectangle): Rectangle {

export function initWebviewManager(win: BrowserWindow) {
ipcMain.on('mount-webview', (e, info) => {
if (!win) {
console.log('[mount-webview]', 'cannot get mainWindow');
return;
}

console.log('[mount-webview] info:', info);

const key = info.key;
Expand All @@ -33,6 +39,10 @@ export function initWebviewManager(win: BrowserWindow) {
const webview = webviewMap.get(key)!;
win.setTopBrowserView(webview.view);
webview.view.setBounds(fixRect(info.rect));
if (webview.url !== url) {
// url has been change.
webview.view.webContents.loadURL(url);
}
return;
}

Expand All @@ -44,7 +54,7 @@ export function initWebviewManager(win: BrowserWindow) {
win.addBrowserView(view);
view.setBounds(fixRect(info.rect));
view.webContents.loadURL(url);
webviewMap.set(key, { view, hidden: false });
webviewMap.set(key, { view, url, hidden: false });
});

ipcMain.on('update-webview-rect', (e, info) => {
Expand All @@ -64,6 +74,11 @@ export function initWebviewManager(win: BrowserWindow) {
});

ipcMain.on('clear-all-webview', (e) => {
if (!win) {
console.log('[clear-all-webview]', 'cannot get mainWindow');
return;
}

console.log('[clear-all-webview]');

win.getBrowserViews().forEach((view) => {
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/App.tsx
@@ -1,7 +1,7 @@
import { MemoryRouter as Router, Routes, Route } from 'react-router-dom';
import { Allotment } from 'allotment';
import { SideTree } from './components/SideTree';
import { WebContent } from './components/WebContent';
import { WebContent } from './components/main/WebContent';

function Main() {
return (
Expand Down
64 changes: 64 additions & 0 deletions src/renderer/components/main/WebContent.tsx
@@ -0,0 +1,64 @@
import { Input } from '@arco-design/web-react';
import React from 'react';
import styled from 'styled-components';
import { useTreeStore } from '../../store/tree';
import { useEditValue } from '../../utils/hooks/useEditValue';
import { WebPlaceholder } from './WebPlaceholder';
import { WebviewRender } from './WebviewRender';

const Root = styled.div`
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
> .title {
display: flex;
flex-direction: row;
}
> .main {
flex: 1;
}
`;

export const WebContent: React.FC = React.memo(() => {
const selectedNode = useTreeStore((state) => state.selectedNode);
const [title, setTitle, onTitleBlur] = useEditValue<string>(
selectedNode?.title ?? '',
(val) => useTreeStore.getState().patchSelectedNode('title', val ?? '')
);
const [url, setUrl, onUrlBlur] = useEditValue(
selectedNode?.url ?? '',
(val) => useTreeStore.getState().patchSelectedNode('url', val ?? '')
);

if (!selectedNode) {
return <WebPlaceholder />;
}

return (
<Root>
<div className="title">
<Input
placeholder="Title"
value={title}
onChange={setTitle}
onBlur={onTitleBlur}
onPressEnter={onTitleBlur}
/>
<Input
placeholder="Url"
value={url}
onChange={setUrl}
onBlur={onUrlBlur}
onPressEnter={onUrlBlur}
/>
</div>
<div className="main">
<WebviewRender node={selectedNode} />
</div>
</Root>
);
});
WebContent.displayName = 'WebContent';
41 changes: 41 additions & 0 deletions src/renderer/components/main/WebPlaceholder.tsx
@@ -0,0 +1,41 @@
import React from 'react';
import { useEffect } from 'react';
import styled from 'styled-components';
import webpageSvg from '../../assets/web-page.svg';
import { AddWebsiteBtn } from '../AddWebsiteBtn';

const WebPlaceholderRoot = styled.div`
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
flex-direction: column;
img {
width: 120px;
}
`;

export const WebPlaceholder: React.FC = React.memo(() => {
useEffect(() => {
window.electron.ipcRenderer.sendMessage('hide-all-webview');
}, []);

return (
<WebPlaceholderRoot>
<div>
<img src={webpageSvg} />
</div>
<div>Please Select Any Page on Left</div>
<div>
<small>OR</small>
</div>
<div>
<AddWebsiteBtn />
</div>
</WebPlaceholderRoot>
);
});
WebPlaceholder.displayName = 'WebPlaceholder';
@@ -1,10 +1,7 @@
import React, { useEffect, useRef } from 'react';
import styled from 'styled-components';
import { useTreeStore, WebsiteTreeNode } from '../store/tree';
import webpageSvg from '../assets/web-page.svg';
import { AddWebsiteBtn } from './AddWebsiteBtn';
import { WebsiteTreeNode } from '../../store/tree';

const WebviewRender: React.FC<{ node: WebsiteTreeNode }> = React.memo(
export const WebviewRender: React.FC<{ node: WebsiteTreeNode }> = React.memo(
(props) => {
const containerRef = useRef<HTMLDivElement>(null);
const node = props.node;
Expand All @@ -26,7 +23,7 @@ const WebviewRender: React.FC<{ node: WebsiteTreeNode }> = React.memo(
height: rect.height,
},
});
}, [node.key]);
}, [node.key, node.url]);

useEffect(() => {
if (!containerRef.current) {
Expand Down Expand Up @@ -66,50 +63,3 @@ const WebviewRender: React.FC<{ node: WebsiteTreeNode }> = React.memo(
}
);
WebviewRender.displayName = 'WebviewRender';

const WebPlaceholderRoot = styled.div`
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
flex-direction: column;
img {
width: 120px;
}
`;

const WebPlaceholder: React.FC = React.memo(() => {
useEffect(() => {
window.electron.ipcRenderer.sendMessage('hide-all-webview');
}, []);

return (
<WebPlaceholderRoot>
<div>
<img src={webpageSvg} />
</div>
<div>Please Select Any Page on Left</div>
<div>
<small>OR</small>
</div>
<div>
<AddWebsiteBtn />
</div>
</WebPlaceholderRoot>
);
});
WebPlaceholder.displayName = 'WebPlaceholder';

export const WebContent: React.FC = React.memo(() => {
const selectedNode = useTreeStore((state) => state.selectedNode);

if (!selectedNode) {
return <WebPlaceholder />;
}

return <WebviewRender node={selectedNode} />;
});
WebContent.displayName = 'WebContent';
28 changes: 26 additions & 2 deletions src/renderer/store/tree.ts
Expand Up @@ -6,7 +6,8 @@ import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';

export type WebsiteTreeNode = Pick<TreeDataType, 'title'> & {
export type WebsiteTreeNode = {
title: string;
key: string;
children?: WebsiteTreeNode[];
url: string;
Expand All @@ -26,6 +27,10 @@ interface TreeStoreState {
dropPosition: number
) => void;
deleteTreeNode: (key: string) => void;
patchSelectedNode: <T extends Exclude<keyof WebsiteTreeNode, 'key'>>(
key: T,
value: WebsiteTreeNode[T]
) => void;
}

const defaultTreeData = [
Expand Down Expand Up @@ -55,7 +60,6 @@ export const useTreeStore = create<TreeStoreState>()(
selectedNode,
});
},

setTreeData: (treeData: WebsiteTreeNode[]) => {
set({
treeData,
Expand Down Expand Up @@ -146,6 +150,26 @@ export const useTreeStore = create<TreeStoreState>()(
deleteTreeNode(state.treeData, key);
});
},
patchSelectedNode: (key, value) => {
set((state) => {
if (!state.selectedNode) {
return;
}

// Check is changed
if (state.selectedNode[key] === value) {
return;
}

const node = findTreeNode(state.treeData, state.selectedNode.key);
if (!node) {
return;
}

state.selectedNode[key] = value;
node[key] = value;
});
},
})),
{
name: 'webbox-tree',
Expand Down
15 changes: 15 additions & 0 deletions src/renderer/utils/hooks/useEditValue.ts
@@ -0,0 +1,15 @@
import { useCallback, useEffect, useLayoutEffect, useState } from 'react';

export function useEditValue<T>(value: T, onChange: (val: T) => void) {
const [inner, setInner] = useState(value);

useLayoutEffect(() => {
setInner(value);
}, [value]);

const onSave = useCallback(() => {
onChange(inner);
}, [inner, onChange]);

return [inner, setInner, onSave] as const;
}

0 comments on commit 2b314d7

Please sign in to comment.