Adding history to store and using it for addressbar suggestions

This commit is contained in:
Manoj Vivek 2022-11-18 16:01:33 +05:30
parent 548afdef14
commit b7da006442
8 changed files with 75 additions and 68 deletions

View file

@ -21,7 +21,7 @@ import { initScreenshotHandlers } from './screenshot';
import { initDevtoolsHandlers } from './devtools';
import { initWebviewStorageManagerHandlers } from './webview-storage-manager';
import { initNativeFunctionHandlers } from './native-functions';
import { initWebPermissionHandlers } from './web-permissions';
import { WebPermissionHandlers } from './web-permissions';
export default class AppUpdater {
constructor() {
@ -112,6 +112,7 @@ const createWindow = async () => {
},
});
initDevtoolsHandlers(mainWindow);
const webPermissionHandlers = WebPermissionHandlers(mainWindow);
mainWindow.loadURL(resolveHtmlPath('index.html'));
@ -120,7 +121,7 @@ const createWindow = async () => {
if (!mainWindow) {
throw new Error('"mainWindow" is not defined');
}
await initWebPermissionHandlers(mainWindow);
webPermissionHandlers.init();
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {

View file

@ -85,24 +85,24 @@ class PermissionsManager {
constructor(mainWindow: BrowserWindow) {
this.mainWindow = mainWindow;
this.permissions = loadPermissions();
ipcMain.removeAllListeners('permission-response');
ipcMain.handle(
'permission-response',
(_event, arg: PermissionResponseArg) => {
this.setPermissionState(
arg.permissionRequest.requestingOrigin,
arg.permissionRequest.permission,
arg.allow ? PERMISSION_STATE.GRANTED : PERMISSION_STATE.DENIED
);
const key = `${arg.permissionRequest.requestingOrigin}-${arg.permissionRequest.permission}`;
const callbacks = this.callbacks[key];
const handler = (_event, arg: PermissionResponseArg) => {
this.setPermissionState(
arg.permissionRequest.requestingOrigin,
arg.permissionRequest.permission,
arg.allow ? PERMISSION_STATE.GRANTED : PERMISSION_STATE.DENIED
);
const key = `${arg.permissionRequest.requestingOrigin}-${arg.permissionRequest.permission}`;
const callbacks = this.callbacks[key];
if (callbacks) {
callbacks.forEach((callback) => callback(arg.allow));
this.callbacks[key] = [];
}
if (callbacks) {
callbacks.forEach((callback) => callback(arg.allow));
this.callbacks[key] = [];
}
);
};
const PERMISSION_RESPONSE_CHANNEL = 'permission-response';
if (ipcMain.listeners(PERMISSION_RESPONSE_CHANNEL).length === 0) {
ipcMain.handle(PERMISSION_RESPONSE_CHANNEL, handler);
}
}
getPermissionState(origin: string, type: string): PermissionState {

View file

@ -2,25 +2,29 @@ import { BrowserWindow, session } from 'electron';
import PermissionsManager, { PERMISSION_STATE } from './PermissionsManager';
// eslint-disable-next-line import/prefer-default-export
export const initWebPermissionHandlers = (mainWindow: BrowserWindow) => {
export const WebPermissionHandlers = (mainWindow: BrowserWindow) => {
const permissionsManager = new PermissionsManager(mainWindow);
session.defaultSession.setPermissionRequestHandler(
(webContents, permission, callback) => {
permissionsManager.requestPermission(
new URL(webContents.getURL()).origin,
permission,
callback
return {
init: () => {
session.defaultSession.setPermissionRequestHandler(
(webContents, permission, callback) => {
permissionsManager.requestPermission(
new URL(webContents.getURL()).origin,
permission,
callback
);
}
);
}
);
session.defaultSession.setPermissionCheckHandler(
(_webContents, permission, requestingOrigin) => {
const status = permissionsManager.getPermissionState(
requestingOrigin,
permission
session.defaultSession.setPermissionCheckHandler(
(_webContents, permission, requestingOrigin) => {
const status = permissionsManager.getPermissionState(
requestingOrigin,
permission
);
return status === PERMISSION_STATE.GRANTED;
}
);
return status === PERMISSION_STATE.GRANTED;
}
);
},
};
};

View file

@ -38,6 +38,7 @@ import {
} from 'renderer/store/features/renderer';
import { NAVIGATION_EVENTS } from '../../ToolBar/NavigationControls';
import Toolbar from './Toolbar';
import { appendHistory } from './utils';
interface Props {
device: IDevice;
@ -157,6 +158,9 @@ const Device = ({ isPrimary, device }: Props) => {
const webview = ref.current as Electron.WebviewTag;
webview.addEventListener('did-navigate', (e) => {
dispatch(setAddress(e.url));
if (isPrimary) {
appendHistory(webview.getURL(), webview.getTitle());
}
});
webview.addEventListener('ipc-message', (e) => {

View file

@ -0,0 +1,16 @@
import { HistoryItem } from 'renderer/components/ToolBar/AddressBar/SuggestionList';
// eslint-disable-next-line import/prefer-default-export
export const appendHistory = (url: string, title: string) => {
if (url === `${title}/`) {
return;
}
const history: HistoryItem[] = window.electron.store.get('history');
window.electron.store.set(
'history',
[
{ url, title, lastVisited: new Date().getTime() },
...history.filter(({ url: _url }) => url !== _url),
].slice(0, 100)
);
};

View file

@ -3,45 +3,22 @@ import { useDispatch } from 'react-redux';
import cx from 'classnames';
import { setAddress } from 'renderer/store/features/renderer';
interface HistoryItem {
export interface HistoryItem {
title: string;
url: string;
favicon: string;
lastVisited: number;
}
interface Props {
match: string;
onEnter: (url: string) => void;
onEnter: (url?: string) => void;
}
const SuggestionList = ({ match, onEnter }: Props) => {
const dispatch = useDispatch();
const [activeIndex, setActiveIndex] = useState<number>(0);
const [history] = useState<HistoryItem[]>(
window.electron.store.get('history').length === 0
? [
{
url: 'https://google.com',
title: 'Google',
favicon: 'https://www.google.com/favicon.ico',
lastVisited: Date.now(),
},
{
url: 'https://expo.dev',
title: 'Expo',
favicon: 'https://static.expo.dev/static/brand/square-228x228.png',
lastVisited: Date.now(),
},
{
url: 'https://responsively.app',
title: 'Responsively App',
favicon:
'https://responsively.app/assets/img/favicons/apple-icon-60x60.png',
lastVisited: Date.now(),
},
]
: window.electron.store.get('history.items')
window.electron.store.get('history')
);
const suggestions = useMemo(() => {
@ -57,7 +34,11 @@ const SuggestionList = ({ match, onEnter }: Props) => {
const keyDownHandler = useCallback(
(e: KeyboardEvent) => {
if (e.key === 'Enter') {
onEnter(suggestions[activeIndex].url);
onEnter(
suggestions[activeIndex] != null
? suggestions[activeIndex].url
: undefined
);
return;
}
if (e.key === 'ArrowUp') {
@ -85,7 +66,7 @@ const SuggestionList = ({ match, onEnter }: Props) => {
return (
<div className="absolute z-10 flex w-full flex-col items-start rounded-b-lg bg-white pb-2 shadow-lg dark:bg-slate-900">
{suggestions.map(({ title, url, favicon }, idx) => (
{suggestions.map(({ title, url }, idx) => (
<div
onClick={() => dispatch(setAddress(url))}
className={cx(
@ -95,7 +76,11 @@ const SuggestionList = ({ match, onEnter }: Props) => {
key={url}
>
<span>
<img src={favicon} className="w-4 rounded-md" alt="favicon" />
<img
src={`https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=${url}&size=64`}
className="w-4 rounded-md"
alt="favicon"
/>
</span>
{title} - <span className="text-blue-500">{url}</span>
</div>

View file

@ -90,7 +90,7 @@ const AddressBar = () => {
}
};
const onEnter = (url: string) => {
const onEnter = (url?: string) => {
dispatchAddress(url);
inputRef.current?.blur();
};

View file

@ -82,9 +82,6 @@ const schema = {
title: {
type: 'string',
},
favicon: {
type: 'string',
},
lastVisited: {
type: 'number',
},