Preview layout modes, default devices refined and minor UI polish

This commit is contained in:
Manoj Vivek 2022-12-02 13:14:08 +05:30
parent fc9e502a6a
commit 2510ac47d9
8 changed files with 93 additions and 12 deletions

View file

@ -42,7 +42,7 @@
}, },
"lint-staged": { "lint-staged": {
"*.{js,jsx,ts,tsx}": [ "*.{js,jsx,ts,tsx}": [
"cross-env NODE_ENV=development eslint --cache" "cross-env NODE_ENV=development eslint --cache --fix"
], ],
"*.json,.{eslintrc,prettierrc}": [ "*.json,.{eslintrc,prettierrc}": [
"prettier --ignore-path .eslintignore --parser json --write" "prettier --ignore-path .eslintignore --parser json --write"

View file

@ -5,3 +5,11 @@ export const DOCK_POSITION = {
RIGHT: 'RIGHT', RIGHT: 'RIGHT',
UNDOCKED: 'UNDOCKED', UNDOCKED: 'UNDOCKED',
} as const; } as const;
export const PREVIEW_LAYOUTS = {
COLUMN: 'COLUMN',
FLEX: 'FLEX',
} as const;
export type PreviewLayout =
typeof PREVIEW_LAYOUTS[keyof typeof PREVIEW_LAYOUTS];

View file

@ -606,7 +606,8 @@ const devices: Device[] = [
height: 1280, height: 1280,
dpi: 1, dpi: 1,
capabilities: ['touch'], capabilities: ['touch'],
userAgent: '', userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
type: 'notebook', type: 'notebook',
isTouchCapable: true, isTouchCapable: true,
isMobileCapable: false, isMobileCapable: false,
@ -617,7 +618,8 @@ const devices: Device[] = [
height: 1440, height: 1440,
dpi: 2, dpi: 2,
capabilities: [], capabilities: [],
userAgent: '', userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
type: 'notebook', type: 'notebook',
isTouchCapable: false, isTouchCapable: false,
isMobileCapable: false, isMobileCapable: false,
@ -628,7 +630,20 @@ const devices: Device[] = [
height: 1280, height: 1280,
dpi: 1, dpi: 1,
capabilities: [], capabilities: [],
userAgent: '', userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
type: 'notebook',
isTouchCapable: false,
isMobileCapable: false,
},
{
name: 'Macbook Pro',
width: 1440,
height: 900,
dpi: 2,
capabilities: [],
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 13_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
type: 'notebook', type: 'notebook',
isTouchCapable: false, isTouchCapable: false,
isMobileCapable: false, isMobileCapable: false,

View file

@ -1,11 +1,12 @@
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import cx from 'classnames'; import cx from 'classnames';
import { selectDevices } from 'renderer/store/features/device-manager'; import { selectDevices } from 'renderer/store/features/device-manager';
import { DOCK_POSITION } from 'common/constants'; import { DOCK_POSITION, PREVIEW_LAYOUTS } from 'common/constants';
import { import {
selectDockPosition, selectDockPosition,
selectIsDevtoolsOpen, selectIsDevtoolsOpen,
} from 'renderer/store/features/devtools'; } from 'renderer/store/features/devtools';
import { selectLayout } from 'renderer/store/features/renderer';
import Device from './Device'; import Device from './Device';
import DevtoolsResizer from './DevtoolsResizer'; import DevtoolsResizer from './DevtoolsResizer';
@ -13,6 +14,7 @@ const Previewer = () => {
const devices = useSelector(selectDevices); const devices = useSelector(selectDevices);
const dockPosition = useSelector(selectDockPosition); const dockPosition = useSelector(selectDockPosition);
const isDevtoolsOpen = useSelector(selectIsDevtoolsOpen); const isDevtoolsOpen = useSelector(selectIsDevtoolsOpen);
const layout = useSelector(selectLayout);
return ( return (
<div <div
@ -21,7 +23,11 @@ const Previewer = () => {
'flex-row': dockPosition === DOCK_POSITION.RIGHT, 'flex-row': dockPosition === DOCK_POSITION.RIGHT,
})} })}
> >
<div className="flex gap-4 overflow-auto p-4"> <div
className={cx('flex h-full gap-4 overflow-auto p-4', {
'flex-wrap': layout === PREVIEW_LAYOUTS.FLEX,
})}
>
{devices.map((device, idx) => { {devices.map((device, idx) => {
return ( return (
<Device key={device.name} device={device} isPrimary={idx === 0} /> <Device key={device.name} device={device} isPrimary={idx === 0} />

View file

@ -0,0 +1,32 @@
import { Icon } from '@iconify/react';
import { PREVIEW_LAYOUTS } from 'common/constants';
import { useDispatch, useSelector } from 'react-redux';
import Toggle from 'renderer/components/Toggle';
import { selectLayout, setLayout } from 'renderer/store/features/renderer';
const PreviewLayout = () => {
const layout = useSelector(selectLayout);
const dispatch = useDispatch();
return (
<div className="flex flex-row items-center justify-start px-4">
<span className="w-1/2">Preview Layout</span>
<div className="flex w-fit items-center gap-3 border-l px-5 dark:border-slate-400">
<Icon icon="radix-icons:layout" />
<Toggle
isOn={layout === PREVIEW_LAYOUTS.FLEX}
onChange={(e) => {
if (e.target.checked) {
dispatch(setLayout(PREVIEW_LAYOUTS.FLEX));
} else {
dispatch(setLayout(PREVIEW_LAYOUTS.COLUMN));
}
}}
/>
<Icon icon="lucide:layout-dashboard" />
</div>
</div>
);
};
export default PreviewLayout;

View file

@ -7,6 +7,7 @@ import UITheme from './UITheme';
import Zoom from './Zoom'; import Zoom from './Zoom';
import AllowInSecureSSL from './AllowInSecureSSL'; import AllowInSecureSSL from './AllowInSecureSSL';
import ClearHistory from './ClearHistory'; import ClearHistory from './ClearHistory';
import PreviewLayout from './PreviewLayout';
const MenuFlyout = () => { const MenuFlyout = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -14,6 +15,7 @@ const MenuFlyout = () => {
return ( return (
<div className="absolute top-[26px] right-[4px] z-50 flex w-80 flex-col gap-2 rounded bg-white p-2 text-sm shadow-lg ring-1 ring-slate-500 !ring-opacity-40 focus:outline-none dark:bg-slate-900 dark:ring-white dark:!ring-opacity-40"> <div className="absolute top-[26px] right-[4px] z-50 flex w-80 flex-col gap-2 rounded bg-white p-2 text-sm shadow-lg ring-1 ring-slate-500 !ring-opacity-40 focus:outline-none dark:bg-slate-900 dark:ring-white dark:!ring-opacity-40">
<Zoom /> <Zoom />
<PreviewLayout />
<UITheme /> <UITheme />
<Devtools /> <Devtools />
<AllowInSecureSSL /> <AllowInSecureSSL />

View file

@ -1,5 +1,6 @@
import { createSlice } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit';
import { PreviewLayout } from 'common/constants';
import type { RootState } from '../..'; import type { RootState } from '../..';
export interface RendererState { export interface RendererState {
@ -7,17 +8,19 @@ export interface RendererState {
zoomFactor: number; zoomFactor: number;
rotate: boolean; rotate: boolean;
isInspecting: boolean | undefined; isInspecting: boolean | undefined;
layout: PreviewLayout;
} }
const zoomSteps = [ const zoomSteps = [
0.25, 0.33, 0.5, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 0.25, 0.33, 0.5, 0.55, 0.67, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2,
]; ];
const initialState: RendererState = { const initialState: RendererState = {
address: window.electron.store.get('homepage'), address: window.electron.store.get('homepage'),
zoomFactor: zoomSteps[4], zoomFactor: zoomSteps[3],
rotate: false, rotate: false,
isInspecting: undefined, isInspecting: undefined,
layout: window.electron.store.get('ui.previewLayout'),
}; };
export const rendererSlice = createSlice({ export const rendererSlice = createSlice({
@ -47,17 +50,28 @@ export const rendererSlice = createSlice({
setIsInspecting: (state, action: PayloadAction<boolean>) => { setIsInspecting: (state, action: PayloadAction<boolean>) => {
state.isInspecting = action.payload; state.isInspecting = action.payload;
}, },
setLayout: (state, action: PayloadAction<PreviewLayout>) => {
state.layout = action.payload;
window.electron.store.set('ui.previewLayout', action.payload);
},
}, },
}); });
// Action creators are generated for each case reducer function // Action creators are generated for each case reducer function
export const { setAddress, zoomIn, zoomOut, setRotate, setIsInspecting } = export const {
rendererSlice.actions; setAddress,
zoomIn,
zoomOut,
setRotate,
setIsInspecting,
setLayout,
} = rendererSlice.actions;
export const selectZoomFactor = (state: RootState) => state.renderer.zoomFactor; export const selectZoomFactor = (state: RootState) => state.renderer.zoomFactor;
export const selectAddress = (state: RootState) => state.renderer.address; export const selectAddress = (state: RootState) => state.renderer.address;
export const selectRotate = (state: RootState) => state.renderer.rotate; export const selectRotate = (state: RootState) => state.renderer.rotate;
export const selectIsInspecting = (state: RootState) => export const selectIsInspecting = (state: RootState) =>
state.renderer.isInspecting; state.renderer.isInspecting;
export const selectLayout = (state: RootState) => state.renderer.layout;
export default rendererSlice.reducer; export default rendererSlice.reducer;

View file

@ -1,4 +1,4 @@
import { DOCK_POSITION } from '../common/constants'; import { DOCK_POSITION, PREVIEW_LAYOUTS } from '../common/constants';
const Store = require('electron-store'); const Store = require('electron-store');
@ -10,6 +10,10 @@ const schema = {
type: 'boolean', type: 'boolean',
default: true, default: true,
}, },
previewlayout: {
enum: Object.values(PREVIEW_LAYOUTS),
default: PREVIEW_LAYOUTS.FLEX,
},
}, },
}, },
devtools: { devtools: {
@ -30,7 +34,7 @@ const schema = {
items: { items: {
type: 'string', type: 'string',
}, },
default: ['iPhone SE', 'iPhone XR', 'iPhone 12 Pro'], default: ['iPhone 12 Pro', 'iPad', 'Macbook Pro'],
}, },
customDevices: { customDevices: {
type: 'array', type: 'array',