Skip to content

Commit f166585

Browse files
committed
AppLive customisations
1 parent d74c9b9 commit f166585

File tree

16 files changed

+265
-32
lines changed

16 files changed

+265
-32
lines changed

app/common/renderer/actions/Inspector.js

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import _ from 'lodash';
22

33
import {SAVED_FRAMEWORK, SET_SAVED_GESTURES} from '../../shared/setting-defs';
4+
import { INSTRUMENTATION_WINDOW_MESSAGE_EVENT, WINDOW_MESSAGE_TARGET_ORIGIN } from '../constants/common';
45
import {POINTER_TYPES} from '../constants/gestures';
5-
import {APP_MODE, NATIVE_APP} from '../constants/session-inspector';
6+
import {APP_MODE, INSPECTOR_TABS, NATIVE_APP} from '../constants/session-inspector';
67
import i18n from '../i18next';
78
import AppiumClient from '../lib/appium-client';
89
import frameworks from '../lib/client-frameworks';
@@ -117,6 +118,10 @@ export const TOGGLE_REFRESHING_STATE = 'TOGGLE_REFRESHING_STATE';
117118

118119
export const SET_GESTURE_UPLOAD_ERROR = 'SET_GESTURE_UPLOAD_ERROR';
119120

121+
122+
export const ENABLE_AUTO_RELOAD = 'ENABLE_AUTO_RELOAD';
123+
export const DISABLE_AUTO_RELOAD = 'DISABLE_AUTO_RELOAD';
124+
120125
const KEEP_ALIVE_PING_INTERVAL = 20 * 1000;
121126
const NO_NEW_COMMAND_LIMIT = 24 * 60 * 60 * 1000; // Set timeout to 24 hours
122127

@@ -436,6 +441,11 @@ export function storeSessionSettings(updatedSessionSettings = null) {
436441
export function showLocatorTestModal() {
437442
return (dispatch) => {
438443
dispatch({type: SHOW_LOCATOR_TEST_MODAL});
444+
window.parent.postMessage({
445+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
446+
action: 'element-search-tool-clicked',
447+
sessionId: window.AppLiveSessionId
448+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
439449
};
440450
}
441451

@@ -777,6 +787,20 @@ export function clearCoordAction() {
777787
export function selectInspectorTab(interaction) {
778788
return (dispatch) => {
779789
dispatch({type: SELECT_INSPECTOR_TAB, interaction});
790+
let action = '';
791+
switch (interaction) {
792+
case INSPECTOR_TABS.SOURCE: action = 'source-tab-clicked'; break;
793+
case INSPECTOR_TABS.COMMANDS: action = 'commands-tab-clicked'; break;
794+
case INSPECTOR_TABS.GESTURES: action = 'gestures-tab-clicked'; break;
795+
case INSPECTOR_TABS.RECORDER: action = 'recorder-tab-clicked'; break;
796+
case INSPECTOR_TABS.SESSION_INFO: action = 'session-info-tab-clicked'; break;
797+
default: action = '';
798+
}
799+
window.parent.postMessage({
800+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
801+
action,
802+
sessionId: window.AppLiveSessionId
803+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
780804
};
781805
}
782806

@@ -1079,3 +1103,11 @@ export function toggleShowAttributes() {
10791103
dispatch({type: TOGGLE_SHOW_ATTRIBUTES});
10801104
};
10811105
}
1106+
1107+
export function toggleAutoReload() {
1108+
return (dispatch, getState) => {
1109+
const {isAutoReloadEnabled} = getState().inspector;
1110+
const type = isAutoReloadEnabled ? DISABLE_AUTO_RELOAD : ENABLE_AUTO_RELOAD;
1111+
dispatch({type});
1112+
};
1113+
}

app/common/renderer/actions/Session.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,8 @@ export function getRunningSessions() {
944944
dispatch({type: SET_ATTACH_SESS_ID, attachSessId: null});
945945
}
946946
}
947+
// return the sessions to outer function. So, that automatic session start can be done
948+
return sessions;
947949
};
948950
}
949951

app/common/renderer/assets/stylesheets/main.less

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
// Global styles
2424
body {
2525
min-height: 610px;
26-
min-width: 870px;
26+
// min-width can be reduce from 870px to 770px without breaking UI
27+
min-width: 770px;
2728
color: #222 !important;
2829
box-sizing: border-box;
2930
}

app/common/renderer/components/Inspector/HeaderButtons.jsx

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {
22
AppstoreOutlined,
3+
CheckCircleOutlined,
4+
CloseCircleOutlined,
35
CloseOutlined,
46
ExclamationCircleOutlined,
57
GlobalOutlined,
@@ -10,13 +12,14 @@ import {
1012
SearchOutlined,
1113
VideoCameraOutlined,
1214
} from '@ant-design/icons';
13-
import {Button, Select, Space, Tooltip} from 'antd';
15+
import {Button, Select, Space, Switch, Tooltip} from 'antd';
16+
import {useCallback, useEffect, useRef} from 'react';
1417
import {BiCircle, BiSquare} from 'react-icons/bi';
1518
import {HiOutlineHome, HiOutlineMicrophone} from 'react-icons/hi';
1619
import {IoChevronBackOutline} from 'react-icons/io5';
1720

1821
import {BUTTON} from '../../constants/antd-types';
19-
import {LINKS} from '../../constants/common';
22+
import {INSTRUMENTATION_WINDOW_MESSAGE_EVENT, LINKS, NORMAL_WINDOW_MESSAGE_EVENT, WINDOW_MESSAGE_TARGET_ORIGIN} from '../../constants/common';
2023
import {APP_MODE} from '../../constants/session-inspector';
2124
import {openLink} from '../../polyfills';
2225
import InspectorStyles from './Inspector.module.css';
@@ -40,7 +43,53 @@ const HeaderButtons = (props) => {
4043
currentContext,
4144
setContext,
4245
t,
46+
isAutoReloadEnabled,
47+
toggleAutoReload
4348
} = props;
49+
const isAutoReloadEnabledRef = useRef(isAutoReloadEnabled);
50+
51+
const handleReloadClicked = () => {
52+
applyClientMethod({methodName: 'getPageSource'});
53+
window.parent.postMessage({
54+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
55+
action: 'manual-refresh',
56+
sessionId: window.AppLiveSessionId
57+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
58+
};
59+
60+
const handleToggleAutoReloadClicked = useCallback((event) => {
61+
isAutoReloadEnabledRef.current = !isAutoReloadEnabled;
62+
toggleAutoReload(event);
63+
applyClientMethod({methodName: 'getPageSource'});
64+
window.parent.postMessage({
65+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
66+
action: isAutoReloadEnabled ? 'disabled-auto-refresh' : 'enabled-auto-refresh',
67+
sessionId: window.AppLiveSessionId
68+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
69+
}, [isAutoReloadEnabled]);
70+
71+
const handleHomeButtonClicked = () => {
72+
window.parent.postMessage({
73+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
74+
action: 'home-cta-clicked',
75+
sessionId: window.AppLiveSessionId
76+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
77+
};
78+
79+
const windowMessageCallback = useCallback((event) => {
80+
if (event.data.type === NORMAL_WINDOW_MESSAGE_EVENT) {
81+
if (event.data.data === 'triggerAutoRefresh' && isAutoReloadEnabledRef.current) {
82+
applyClientMethod({methodName: 'getPageSource'});
83+
}
84+
}
85+
}, []);
86+
87+
useEffect(() => {
88+
window.addEventListener('message', windowMessageCallback);
89+
return () => {
90+
window.removeEventListener('message', windowMessageCallback);
91+
};
92+
}, []);
4493

4594
const deviceControls = (
4695
<Button.Group>
@@ -50,12 +99,13 @@ const HeaderButtons = (props) => {
5099
<Button
51100
id="btnPressHomeButton"
52101
icon={<HiOutlineHome className={InspectorStyles['custom-button-icon']} />}
53-
onClick={() =>
102+
onClick={() => {
54103
applyClientMethod({
55104
methodName: 'executeScript',
56105
args: ['mobile:pressButton', [{name: 'home'}]],
57-
})
58-
}
106+
});
107+
handleHomeButtonClicked();
108+
}}
59109
/>
60110
</Tooltip>
61111
<Tooltip title={t('Execute Siri Command')}>
@@ -80,7 +130,10 @@ const HeaderButtons = (props) => {
80130
<Button
81131
id="btnPressHomeButton"
82132
icon={<BiCircle className={InspectorStyles['custom-button-icon']} />}
83-
onClick={() => applyClientMethod({methodName: 'pressKeyCode', args: [3]})}
133+
onClick={() => {
134+
applyClientMethod({methodName: 'pressKeyCode', args: [3]});
135+
handleHomeButtonClicked();
136+
}}
84137
/>
85138
</Tooltip>
86139
<Tooltip title={t('Press App Switch Button')}>
@@ -162,6 +215,29 @@ const HeaderButtons = (props) => {
162215
</Button.Group>
163216
);
164217

218+
const refreshControls = (
219+
<Button.Group className='refresh-button-group'>
220+
<Tooltip title='Refresh Source & Screenshot'>
221+
<Button
222+
id="btnReload"
223+
icon={<ReloadOutlined />}
224+
onClick={handleReloadClicked}
225+
/>
226+
</Tooltip>
227+
<Tooltip
228+
title={isAutoReloadEnabled ? 'Disable Auto-Refresh' : 'Enable Auto-Refresh'}
229+
>
230+
<Switch
231+
id="btnAutoReload"
232+
defaultChecked={isAutoReloadEnabled}
233+
onChange={handleToggleAutoReloadClicked}
234+
checkedChildren={<CheckCircleOutlined />}
235+
unCheckedChildren={<CloseCircleOutlined />}
236+
/>
237+
</Tooltip>
238+
</Button.Group>
239+
);
240+
165241
const generalControls = (
166242
<Button.Group>
167243
{mjpegScreenshotUrl && !isSourceRefreshOn && (
@@ -182,13 +258,6 @@ const HeaderButtons = (props) => {
182258
/>
183259
</Tooltip>
184260
)}
185-
<Tooltip title={t('refreshSource')}>
186-
<Button
187-
id="btnReload"
188-
icon={<ReloadOutlined />}
189-
onClick={() => applyClientMethod({methodName: 'getPageSource'})}
190-
/>
191-
</Tooltip>
192261
<Tooltip title={t('Search for element')}>
193262
<Button id="searchForElement" icon={<SearchOutlined />} onClick={showLocatorTestModal} />
194263
</Tooltip>
@@ -221,6 +290,7 @@ const HeaderButtons = (props) => {
221290
<Space size="middle">
222291
{deviceControls}
223292
{appModeControls}
293+
{refreshControls}
224294
{generalControls}
225295
{quitSessionButton}
226296
</Space>

app/common/renderer/components/Inspector/Inspector.jsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {useEffect, useRef, useState} from 'react';
1818
import {useNavigate} from 'react-router';
1919

2020
import {BUTTON} from '../../constants/antd-types';
21-
import {WINDOW_DIMENSIONS} from '../../constants/common';
21+
import {INSTRUMENTATION_WINDOW_MESSAGE_EVENT, NORMAL_WINDOW_MESSAGE_EVENT, WINDOW_DIMENSIONS, WINDOW_MESSAGE_TARGET_ORIGIN} from '../../constants/common';
2222
import {SCREENSHOT_INTERACTION_MODE} from '../../constants/screenshot';
2323
import {
2424
INSPECTOR_TABS,
@@ -152,6 +152,16 @@ const Inspector = (props) => {
152152
};
153153

154154
const quitCurrentSession = async (reason, killedByUser = true) => {
155+
window.parent.postMessage({
156+
type: NORMAL_WINDOW_MESSAGE_EVENT,
157+
data: 'quitSession',
158+
sessionId: window.AppLiveSessionId
159+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
160+
window.parent.postMessage({
161+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
162+
action: 'disabled',
163+
sessionId: window.AppLiveSessionId
164+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
155165
await quitSession(reason, killedByUser);
156166
navigate('/session', {replace: true});
157167
};
@@ -289,8 +299,9 @@ const Inspector = (props) => {
289299
key: INSPECTOR_TABS.SOURCE,
290300
disabled: !showScreenshot,
291301
children: (
292-
<div className="action-row">
293-
<div className="action-col">
302+
// show the two sections side by side
303+
<div className="applive-row">
304+
<div className="applive-col">
294305
<Card
295306
title={
296307
<span>
@@ -331,7 +342,8 @@ const Inspector = (props) => {
331342
</div>
332343
<div
333344
id="selectedElementContainer"
334-
className={`${InspectorStyles['interaction-tab-container']} ${InspectorStyles['element-detail-container']} action-col`}
345+
// for showing the sections side by side with proper margins
346+
className={`${InspectorStyles['interaction-tab-container']} ${InspectorStyles['element-detail-container']} selectedElementContainer applive-col`}
335347
>
336348
<Card
337349
title={

app/common/renderer/components/Inspector/Inspector.module.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,30 @@
119119
height: 100%;
120120
}
121121

122+
/* for showing the two sections side by side with proper paddings */
123+
.inspector-main .interaction-tab-container :global(.applive-row) {
124+
display: flex;
125+
flex-direction: column;
126+
gap: 1em;
127+
width: 100%;
128+
height: 100%;
129+
}
130+
131+
.inspector-main .interaction-tab-container :global(.applive-col) {
132+
min-height: calc(50% - 0.5em);
133+
max-height: calc(50% - 0.5em);
134+
width: 100%;
135+
}
136+
137+
.inspector-main .interaction-tab-container :global(.selectedElementContainer) {
138+
padding-left: 0;
139+
}
140+
141+
:global(.refresh-button-group) {
142+
align-items: center;
143+
gap: 8px
144+
}
145+
122146
.inspector-main .tree-container {
123147
height: 100%;
124148
overflow: auto;

app/common/renderer/components/Inspector/Screenshot.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Spin} from 'antd';
22
import {Fragment, useRef, useState} from 'react';
33

4+
import {INSTRUMENTATION_WINDOW_MESSAGE_EVENT, WINDOW_MESSAGE_TARGET_ORIGIN} from '../../constants/common';
45
import {GESTURE_ITEM_STYLES, POINTER_TYPES} from '../../constants/gestures';
56
import {DEFAULT_SWIPE, DEFAULT_TAP, SCREENSHOT_INTERACTION_MODE} from '../../constants/screenshot';
67
import {INSPECTOR_TABS} from '../../constants/session-inspector';
@@ -38,6 +39,11 @@ const Screenshot = (props) => {
3839
if (selectedTick) {
3940
await tapTickCoordinates(x, y);
4041
}
42+
window.parent.postMessage({
43+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
44+
action: 'clicked-on-appium-device-view',
45+
sessionId: window.AppLiveSessionId
46+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
4147
};
4248

4349
const handleScreenshotDown = async () => {

app/common/renderer/components/Inspector/Source.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {Spin, Tree} from 'antd';
22

3+
import {INSTRUMENTATION_WINDOW_MESSAGE_EVENT, WINDOW_MESSAGE_TARGET_ORIGIN} from '../../constants/common';
34
import {IMPORTANT_SOURCE_ATTRS} from '../../constants/source';
45
import InspectorStyles from './Inspector.module.css';
56
import LocatorTestModal from './LocatorTestModal.jsx';
@@ -57,6 +58,11 @@ const Source = (props) => {
5758
} else {
5859
selectElement(path);
5960
}
61+
window.parent.postMessage({
62+
type: INSTRUMENTATION_WINDOW_MESSAGE_EVENT,
63+
action: 'app-source-hierarchy-interacted',
64+
sessionId: window.AppLiveSessionId
65+
}, WINDOW_MESSAGE_TARGET_ORIGIN);
6066
};
6167

6268
// Recursives through the source and renders a TreeNode for an element

0 commit comments

Comments
 (0)