mirror of
https://github.com/responsively-org/responsively-app
synced 2024-11-11 07:14:12 +00:00
Adding history to store and using it for addressbar suggestions
This commit is contained in:
parent
548afdef14
commit
b7da006442
8 changed files with 75 additions and 68 deletions
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
};
|
|
@ -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>
|
||||
|
|
|
@ -90,7 +90,7 @@ const AddressBar = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const onEnter = (url: string) => {
|
||||
const onEnter = (url?: string) => {
|
||||
dispatchAddress(url);
|
||||
inputRef.current?.blur();
|
||||
};
|
||||
|
|
|
@ -82,9 +82,6 @@ const schema = {
|
|||
title: {
|
||||
type: 'string',
|
||||
},
|
||||
favicon: {
|
||||
type: 'string',
|
||||
},
|
||||
lastVisited: {
|
||||
type: 'number',
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue