mirror of
https://github.com/responsively-org/responsively-app
synced 2024-11-10 14:54:12 +00:00
Preview layout modes, default devices refined and minor UI polish
This commit is contained in:
parent
fc9e502a6a
commit
2510ac47d9
8 changed files with 93 additions and 12 deletions
|
@ -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"
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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} />
|
||||||
|
|
|
@ -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;
|
|
@ -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 />
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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',
|
||||||
|
|
Loading…
Reference in a new issue