mirror of
https://github.com/responsively-org/responsively-app
synced 2024-11-10 06:44:13 +00:00
Removes icon.
This commit is contained in:
parent
cf515334ca
commit
e2dd9b8399
14 changed files with 2693 additions and 2143 deletions
5
.idea/.gitignore
vendored
Normal file
5
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
|
@ -107,6 +107,7 @@
|
|||
"@headlessui/react": "^1.7.4",
|
||||
"@iconify/react": "^3.2.2",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"@scena/react-guides": "^0.28.2",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"bluebird": "^3.7.2",
|
||||
"browser-sync": "^2.27.10",
|
||||
|
|
|
@ -15,6 +15,22 @@ const documentBodyInit = () => {
|
|||
contextMenuMeta: { x: e.x, y: e.y },
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('wheel', (e) => {
|
||||
ipcRenderer.sendToHost('pass-scroll-data', {
|
||||
coordinates: { x: e.deltaX, y: e.deltaY },
|
||||
innerHeight: document.body.scrollHeight,
|
||||
innerWidth: window.innerWidth,
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('dom-ready', () => {
|
||||
ipcRenderer.sendToHost('pass-scroll-data', {
|
||||
coordinates: { x: 0, y: 0 },
|
||||
innerHeight: document.body.scrollHeight,
|
||||
innerWidth: window.innerWidth,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ipcRenderer.on('context-menu-command', (_, command) => {
|
||||
|
@ -23,6 +39,7 @@ ipcRenderer.on('context-menu-command', (_, command) => {
|
|||
|
||||
const documentBodyWaitHandle = setInterval(() => {
|
||||
window.onerror = function (errorMsg, url, lineNumber) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Unhandled error: ${errorMsg} ${url} ${lineNumber}`);
|
||||
// Code to run when an error has occurred on the page
|
||||
};
|
||||
|
@ -32,10 +49,12 @@ const documentBodyWaitHandle = setInterval(() => {
|
|||
try {
|
||||
documentBodyInit();
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Error in documentBodyInit:', err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('document.body not ready');
|
||||
}, 300);
|
||||
|
|
14
desktop-app/src/main/ruler/index.ts
Normal file
14
desktop-app/src/main/ruler/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
// import { ipcMain } from 'electron';
|
||||
// // import { Coordinates } from '../../renderer/store/features/ruler';
|
||||
// //
|
||||
export const MOUSE_EVENTS = {
|
||||
SCROLL: 'scroll',
|
||||
};
|
||||
// //
|
||||
// export const initWebviewWheelEvent = () => {
|
||||
// ipcMain.on('show-context-menu', (event, ...args) => {
|
||||
// // const coordinates: Coordinates = args[0];
|
||||
// // console.log({ coordinates });
|
||||
// // // await webViewPubSub.publish(MOUSE_EVENTS.SCROLL, coordinates);
|
||||
// });
|
||||
// };
|
|
@ -1,5 +1,7 @@
|
|||
import { BrowserWindow, ipcMain, Menu } from 'electron';
|
||||
import { CONTEXT_MENUS } from './common';
|
||||
// import { webViewPubSub } from '../../renderer/lib/pubsub';
|
||||
// import { MOUSE_EVENTS } from '../ruler';
|
||||
|
||||
export const initWebviewContextMenu = () => {
|
||||
ipcMain.removeAllListeners('show-context-menu');
|
||||
|
@ -22,6 +24,10 @@ export const initWebviewContextMenu = () => {
|
|||
BrowserWindow.fromWebContents(event.sender) as Electron.PopupOptions
|
||||
);
|
||||
});
|
||||
// ipcMain.on('pass-scroll-data', (event, ...args) => {
|
||||
// console.log(args[0].coordinates);
|
||||
// webViewPubSub.publish(MOUSE_EVENTS.SCROLL, [args[0].coordinates]);
|
||||
// });
|
||||
};
|
||||
|
||||
export default initWebviewContextMenu;
|
||||
|
|
|
@ -15,6 +15,7 @@ import {
|
|||
selectCss,
|
||||
setCss,
|
||||
} from '../../../store/features/renderer';
|
||||
import { a11ycss, guides, layout } from './assets';
|
||||
|
||||
interface Props {
|
||||
webview: Electron.WebviewTag | null;
|
||||
|
@ -45,6 +46,13 @@ const Toolbar = ({
|
|||
useState<boolean>(false);
|
||||
const [rotated, setRotated] = useState<boolean>(false);
|
||||
|
||||
const debuggers = ['Layout', 'A11yCss'];
|
||||
|
||||
const debugStylesheet: { [key: string]: string } = {
|
||||
layout,
|
||||
a11ycss,
|
||||
};
|
||||
|
||||
const redgreen = [
|
||||
'Deuteranopia',
|
||||
'Deuteranomaly',
|
||||
|
@ -300,6 +308,63 @@ function handleMouseMove(){
|
|||
setFullScreenshotLoading(false);
|
||||
};
|
||||
|
||||
const layoutDebug = async (cssPath: string) => {
|
||||
if (webview === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const css = debugStylesheet[cssPath];
|
||||
|
||||
if (cssSelector !== undefined) {
|
||||
if (cssSelector.css === css) {
|
||||
await webview.removeInsertedCSS(cssSelector.key);
|
||||
dispatch(setCss(undefined));
|
||||
return;
|
||||
}
|
||||
await webview.removeInsertedCSS(cssSelector.key);
|
||||
dispatch(setCss(undefined));
|
||||
}
|
||||
|
||||
try {
|
||||
const key = await webview.insertCSS(css);
|
||||
dispatch(setCss({ key, css, name: cssPath }));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error inserting css', error);
|
||||
dispatch(setCss(undefined));
|
||||
}
|
||||
};
|
||||
|
||||
const showRulers = async () => {
|
||||
if (webview === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const css = guides;
|
||||
|
||||
if (cssSelector !== undefined) {
|
||||
if (cssSelector.css === css) {
|
||||
webview.reload();
|
||||
dispatch(setCss(undefined));
|
||||
return;
|
||||
}
|
||||
webview.reload();
|
||||
dispatch(setCss(undefined));
|
||||
}
|
||||
|
||||
try {
|
||||
const key = await webview.executeJavaScript(guides);
|
||||
// await webview.executeJavaScript(
|
||||
// `const guides=new Guides(document.body,{type:"horizontal"}).on("changeGuides",e=>{console.log(e.guides)});let scrollX=0,scrollY=0;window.addEventListener("resize",()=>{guides.resize()}),window.addEventListener("wheel",e=>{scrollX+=e.deltaX,scrollY+=e.deltaY,guides.scrollGuides(scrollY),guides.scroll(scrollX)});`
|
||||
// );
|
||||
dispatch(setCss({ key, css, name: 'guides' }));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error inserting js', error);
|
||||
dispatch(setCss(undefined));
|
||||
}
|
||||
};
|
||||
|
||||
const rotate = async () => {
|
||||
setRotated(!rotated);
|
||||
onRotate(!rotated);
|
||||
|
@ -354,7 +419,9 @@ function handleMouseMove(){
|
|||
}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<Button onClick={showRulers} title="Show rulers">
|
||||
<Icon icon="tdesign:measurement-1" />
|
||||
</Button>
|
||||
<DropDown
|
||||
className="text-xs"
|
||||
label={<Icon icon="codicon:debug-line-by-line" fontSize={18} />}
|
||||
|
@ -362,7 +429,35 @@ function handleMouseMove(){
|
|||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-12 whitespace-nowrap">
|
||||
<span className="font-bold">A11y Tools</span>
|
||||
<span className="font-bold">Debug</span>
|
||||
</div>
|
||||
),
|
||||
onClick: null,
|
||||
},
|
||||
...debuggers.map((x: string) => {
|
||||
return {
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-12 whitespace-nowrap">
|
||||
<span
|
||||
className={`ml-2 ${
|
||||
cssSelector?.name === x.toLowerCase()
|
||||
? 'font-semibold text-black'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{x}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
onClick: () => {
|
||||
layoutDebug(x.toLowerCase());
|
||||
},
|
||||
};
|
||||
}),
|
||||
{
|
||||
label: (
|
||||
<div className="flex w-full flex-shrink-0 items-center justify-between gap-12 whitespace-nowrap">
|
||||
<span className="font-bold">Accessibility Tools</span>
|
||||
</div>
|
||||
),
|
||||
onClick: null,
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -43,6 +43,8 @@ import { PREVIEW_LAYOUTS } from 'common/constants';
|
|||
import { NAVIGATION_EVENTS } from '../../ToolBar/NavigationControls';
|
||||
import Toolbar from './Toolbar';
|
||||
import { appendHistory } from './utils';
|
||||
import { Coordinates } from '../../../store/features/ruler';
|
||||
import GuideGrid from '../Guides';
|
||||
|
||||
interface Props {
|
||||
device: IDevice;
|
||||
|
@ -83,6 +85,13 @@ const Device = ({ isPrimary, device, setIndividualDevice }: Props) => {
|
|||
height = temp;
|
||||
}
|
||||
|
||||
const [coordinates, setCoordinates] = useState<Coordinates>({
|
||||
deltaX: 0,
|
||||
deltaY: 0,
|
||||
innerWidth: width * 2,
|
||||
innerHeight: height * 2,
|
||||
});
|
||||
|
||||
const registerNavigationHandlers = useCallback(() => {
|
||||
webViewPubSub.subscribe(NAVIGATION_EVENTS.RELOAD, () => {
|
||||
if (ref.current) {
|
||||
|
@ -223,7 +232,16 @@ const Device = ({ isPrimary, device, setIndividualDevice }: Props) => {
|
|||
webview.removeEventListener('did-navigate', didNavigateHandler);
|
||||
});
|
||||
|
||||
const ipc̨MessageHandler = (e: Electron.IpcMessageEvent) => {
|
||||
const ipcMessageHandler = (e: Electron.IpcMessageEvent) => {
|
||||
if (e.channel === 'pass-scroll-data') {
|
||||
console.log('ipcMessageHandler', e.args[0].innerHeight);
|
||||
setCoordinates({
|
||||
deltaX: e.args[0].coordinates.x,
|
||||
deltaY: e.args[0].coordinates.y,
|
||||
innerHeight: e.args[0].innerHeight,
|
||||
innerWidth: e.args[0].innerWidth,
|
||||
});
|
||||
}
|
||||
if (e.channel === 'context-menu-command') {
|
||||
const { command, arg } = e.args[0];
|
||||
switch (command) {
|
||||
|
@ -242,9 +260,9 @@ const Device = ({ isPrimary, device, setIndividualDevice }: Props) => {
|
|||
}
|
||||
}
|
||||
};
|
||||
webview.addEventListener('ipc-message', ipc̨MessageHandler);
|
||||
webview.addEventListener('ipc-message', ipcMessageHandler);
|
||||
handlerRemovers.push(() => {
|
||||
webview.removeEventListener('ipc-message', ipc̨MessageHandler);
|
||||
webview.removeEventListener('ipc-message', ipcMessageHandler);
|
||||
});
|
||||
|
||||
const didStartLoadingHandler = () => {
|
||||
|
@ -453,25 +471,31 @@ const Device = ({ isPrimary, device, setIndividualDevice }: Props) => {
|
|||
style={{ height: scaledHeight, width: scaledWidth }}
|
||||
className="relative origin-top-left bg-white"
|
||||
>
|
||||
<webview
|
||||
id={device.name}
|
||||
src={address}
|
||||
style={{
|
||||
height,
|
||||
width,
|
||||
display: 'inline-flex',
|
||||
transform: `scale(${zoomfactor})`,
|
||||
}}
|
||||
ref={ref}
|
||||
className="origin-top-left"
|
||||
/* eslint-disable-next-line react/no-unknown-property */
|
||||
preload={`file://${window.responsively.webviewPreloadPath}`}
|
||||
data-scale-factor={zoomfactor}
|
||||
/* eslint-disable-next-line react/no-unknown-property */
|
||||
allowpopups={isPrimary ? ('true' as any) : undefined}
|
||||
/* eslint-disable-next-line react/no-unknown-property */
|
||||
useragent={device.userAgent}
|
||||
/>
|
||||
<GuideGrid
|
||||
height={scaledHeight}
|
||||
width={scaledWidth}
|
||||
coordinates={coordinates}
|
||||
>
|
||||
<webview
|
||||
id={device.name}
|
||||
src={address}
|
||||
style={{
|
||||
height,
|
||||
width,
|
||||
display: 'inline-flex',
|
||||
transform: `scale(${zoomfactor})`,
|
||||
}}
|
||||
ref={ref}
|
||||
className="origin-top-left"
|
||||
/* eslint-disable-next-line react/no-unknown-property */
|
||||
preload={`file://${window.responsively.webviewPreloadPath}`}
|
||||
data-scale-factor={zoomfactor}
|
||||
/* eslint-disable-next-line react/no-unknown-property */
|
||||
allowpopups={isPrimary ? ('true' as any) : undefined}
|
||||
/* eslint-disable-next-line react/no-unknown-property */
|
||||
useragent={device.userAgent}
|
||||
/>
|
||||
</GuideGrid>
|
||||
{screenshotInProgress ? (
|
||||
<div
|
||||
className="absolute top-0 left-0 flex h-full w-full items-center justify-center bg-slate-600 bg-opacity-95"
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
.box {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: #444;
|
||||
box-sizing: border-box;
|
||||
z-index: 21;
|
||||
}
|
||||
.box:before,
|
||||
.box:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
background: #777;
|
||||
}
|
||||
.box:before {
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
left: 100%;
|
||||
}
|
||||
.box:after {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
top: 100%;
|
||||
}
|
105
desktop-app/src/renderer/components/Previewer/Guides/index.tsx
Normal file
105
desktop-app/src/renderer/components/Previewer/Guides/index.tsx
Normal file
|
@ -0,0 +1,105 @@
|
|||
import * as React from 'react';
|
||||
import Guides from '@scena/react-guides';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Coordinates } from '../../../store/features/ruler';
|
||||
import './guide.css';
|
||||
|
||||
interface Props {
|
||||
children: JSX.Element;
|
||||
height: number;
|
||||
width: number;
|
||||
coordinates: Coordinates;
|
||||
}
|
||||
|
||||
const GuideGrid = ({ children, height, width, coordinates }: Props) => {
|
||||
const horizonalGuidesRef: unknown = useRef();
|
||||
const verticalGuidesRef: unknown = useRef();
|
||||
|
||||
// let scrollX = useRef(0);
|
||||
// let scrollY = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (horizonalGuidesRef !== undefined && verticalGuidesRef !== undefined) {
|
||||
const scrollX =
|
||||
horizonalGuidesRef?.current?.getRulerScrollPos() + coordinates.deltaX;
|
||||
const scrollY =
|
||||
verticalGuidesRef?.current?.getRulerScrollPos() + coordinates.deltaY;
|
||||
let scrollPosY: any;
|
||||
if (Number(scrollY) > 0) {
|
||||
scrollPosY =
|
||||
Number(scrollY) > coordinates.innerHeight
|
||||
? coordinates.innerHeight
|
||||
: scrollY;
|
||||
} else {
|
||||
scrollPosY = 0;
|
||||
}
|
||||
let scrollPosX: any;
|
||||
if (Number(scrollX) > 0) {
|
||||
scrollPosX =
|
||||
Number(scrollX) > coordinates.innerWidth
|
||||
? coordinates.innerWidth
|
||||
: scrollX;
|
||||
} else {
|
||||
scrollPosX = 0;
|
||||
}
|
||||
horizonalGuidesRef?.current?.scrollGuides(scrollY);
|
||||
verticalGuidesRef?.current?.scrollGuides(scrollX);
|
||||
|
||||
horizonalGuidesRef?.current?.scroll(scrollPosX);
|
||||
verticalGuidesRef?.current?.scroll(scrollPosY);
|
||||
console.log('scrollY', scrollPosY);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
pointerEvents: 'none',
|
||||
width: `${width + 30}px`,
|
||||
height: `${height + 30}px`,
|
||||
zIndex: 1,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<div className="box bg-slate-200 dark:bg-slate-800" />
|
||||
<Guides
|
||||
ref={horizonalGuidesRef}
|
||||
type="horizontal"
|
||||
backgroundColor="rgb(30, 41, 59)"
|
||||
style={{
|
||||
height: '30px',
|
||||
left: '30px',
|
||||
width: width * 2,
|
||||
pointerEvents: 'auto',
|
||||
}}
|
||||
displayDragPos
|
||||
displayGuidePos
|
||||
useResizeObserver
|
||||
/>
|
||||
<Guides
|
||||
ref={verticalGuidesRef}
|
||||
type="vertical"
|
||||
backgroundColor="rgb(30, 41, 59)"
|
||||
style={{
|
||||
width: '30px',
|
||||
top: '0px',
|
||||
height: '10000px',
|
||||
pointerEvents: 'auto',
|
||||
}}
|
||||
displayDragPos
|
||||
displayGuidePos
|
||||
useResizeObserver
|
||||
/>
|
||||
</div>
|
||||
<div style={{ paddingLeft: '30px', paddingRight: '30px' }}>
|
||||
{children}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GuideGrid;
|
51
desktop-app/src/renderer/store/features/ruler/index.ts
Normal file
51
desktop-app/src/renderer/store/features/ruler/index.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import type { RootState } from '../..';
|
||||
|
||||
export interface Coordinates {
|
||||
deltaX: number;
|
||||
deltaY: number;
|
||||
innerHeight: number;
|
||||
innerWidth: number;
|
||||
}
|
||||
|
||||
export interface RulersState {
|
||||
isRulerEnabled: boolean;
|
||||
rulerCoordinates: Coordinates;
|
||||
webViewId: number;
|
||||
}
|
||||
|
||||
const initialState: RulersState = {
|
||||
isRulerEnabled: false,
|
||||
rulerCoordinates: { deltaX: 0, deltaY: 0, innerHeight: 0, innerWidth: 0 },
|
||||
webViewId: -1,
|
||||
};
|
||||
|
||||
export const rulerSlice = createSlice({
|
||||
name: 'rulers',
|
||||
initialState,
|
||||
reducers: {
|
||||
setRulersEnabled: (state, action: PayloadAction<RulersState>) => {
|
||||
state.isRulerEnabled = true;
|
||||
state.webViewId = action.payload.webViewId;
|
||||
},
|
||||
setRulerCoordinates: (state, action: PayloadAction<Coordinates>) => {
|
||||
state.rulerCoordinates = action.payload;
|
||||
},
|
||||
setRulersDisabled: (state, action: PayloadAction<RulersState>) => {
|
||||
state.isRulerEnabled = false;
|
||||
state.webViewId = action.payload.webViewId;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { setRulersEnabled, setRulersDisabled, setRulerCoordinates } =
|
||||
rulerSlice.actions;
|
||||
|
||||
export const selectRulerCoordinates = (state: RootState) =>
|
||||
state.rulers.rulerCoordinates;
|
||||
|
||||
export const selectRulerWebviewId = (state: RootState) =>
|
||||
state.rulers.webViewId;
|
||||
|
||||
export default rulerSlice.reducer;
|
|
@ -3,6 +3,7 @@ import { configureStore } from '@reduxjs/toolkit';
|
|||
import deviceManagerReducer from './features/device-manager';
|
||||
import devtoolsReducer from './features/devtools';
|
||||
import rendererReducer from './features/renderer';
|
||||
import rulersReducer from './features/ruler';
|
||||
import uiReducer from './features/ui';
|
||||
import bookmarkReducer from './features/bookmarks';
|
||||
|
||||
|
@ -13,6 +14,7 @@ export const store = configureStore({
|
|||
deviceManager: deviceManagerReducer,
|
||||
devtools: devtoolsReducer,
|
||||
bookmarks: bookmarkReducer,
|
||||
rulers: rulersReducer,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ const schema = {
|
|||
},
|
||||
homepage: {
|
||||
type: 'string',
|
||||
default: 'https://www.google.com/',
|
||||
default: 'https://www.example.org/',
|
||||
},
|
||||
seenReleaseNotes: {
|
||||
type: 'array',
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue