Skip to content

Commit ed95a40

Browse files
authored
Optimize interface for mobile (#709)
1 parent 297bf35 commit ed95a40

File tree

6 files changed

+56
-12
lines changed

6 files changed

+56
-12
lines changed

src/main/frontend/pipeline-console-view/pipeline-console/main/PipelineConsole.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export default function PipelineConsole() {
3939
<Dropdown
4040
items={[
4141
<StagesCustomization key="visibility-select" />,
42-
"separator",
4342
{
4443
text: "View as plain text",
4544
icon: DOCUMENT,

src/main/frontend/pipeline-console-view/pipeline-console/main/StageNodeLink.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default function StageNodeLink({ agent }: StageNodeLinkProps) {
1414
}
1515

1616
return (
17-
<li>
17+
<li className={"jenkins-mobile-hide"}>
1818
<a
1919
href={href}
2020
className={"jenkins-button jenkins-button--tertiary"}

src/main/frontend/pipeline-console-view/pipeline-console/main/components/stages-customization.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ export default function StagesCustomization() {
1414
setMainViewVisibility,
1515
stageViewPosition,
1616
setStageViewPosition,
17+
isMobile,
1718
} = useLayoutPreferences();
1819

20+
if (isMobile) {
21+
return null;
22+
}
23+
1924
const handleViewChange = (e: ChangeEvent<HTMLSelectElement>) => {
2025
setMainViewVisibility(e.target.value as MainViewVisibility);
2126
};
@@ -121,6 +126,7 @@ export default function StagesCustomization() {
121126
<option value={StageViewPosition.LEFT}>Left</option>
122127
</select>
123128
</label>
129+
<div className="jenkins-dropdown__separator" />
124130
</>
125131
);
126132
}

src/main/frontend/pipeline-console-view/pipeline-console/main/providers/user-preference-provider.tsx

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ interface LayoutPreferences {
3030
setTreeViewWidth: (width: number) => void;
3131
setStageViewWidth: (width: number) => void;
3232
setStageViewHeight: (height: number) => void;
33+
/**
34+
* Returns true if the current window width is less than the mobile breakpoint.
35+
* Used for disabling customization options in favor of a mobile-friendly layout.
36+
*/
37+
isMobile: boolean;
3338
}
3439

3540
// CONTEXT
@@ -65,20 +70,27 @@ const loadFromLocalStorage = <T,>(key: string, fallback: T): T => {
6570
return fallback;
6671
};
6772

73+
const MOBILE_BREAKPOINT = 700;
74+
6875
// PROVIDER
6976
export const LayoutPreferencesProvider = ({
7077
children,
7178
}: {
7279
children: ReactNode;
7380
}) => {
74-
const [stageViewPosition, setStageViewPositionState] =
81+
const [windowWidth, setWindowWidth] = useState<number>(
82+
typeof window !== "undefined" ? window.innerWidth : 1000,
83+
);
84+
85+
const [persistedStageViewPosition, setStageViewPositionState] =
7586
useState<StageViewPosition>(
7687
loadFromLocalStorage(LS_KEYS.stageViewPosition, StageViewPosition.TOP),
7788
);
78-
const [mainViewVisibility, setMainViewVisibilityState] =
89+
const [persistedMainViewVisibility, setMainViewVisibilityState] =
7990
useState<MainViewVisibility>(
8091
loadFromLocalStorage(LS_KEYS.mainViewVisibility, MainViewVisibility.BOTH),
8192
);
93+
8294
const [treeViewWidth, setTreeViewWidthState] = useState<number>(
8395
loadFromLocalStorage(LS_KEYS.treeViewWidth, 300),
8496
);
@@ -89,14 +101,33 @@ export const LayoutPreferencesProvider = ({
89101
loadFromLocalStorage(LS_KEYS.stageViewHeight, 250),
90102
);
91103

92-
// Save to localStorage
104+
// Handle responsive override
105+
const isMobile = windowWidth < MOBILE_BREAKPOINT;
106+
const stageViewPosition = isMobile
107+
? StageViewPosition.TOP
108+
: persistedStageViewPosition;
109+
const mainViewVisibility = isMobile
110+
? MainViewVisibility.GRAPH_ONLY
111+
: persistedMainViewVisibility;
112+
113+
// Save to localStorage only when not in mobile mode
93114
useEffect(() => {
94-
window.localStorage.setItem(LS_KEYS.stageViewPosition, stageViewPosition);
95-
}, [stageViewPosition]);
115+
if (!isMobile) {
116+
window.localStorage.setItem(
117+
LS_KEYS.stageViewPosition,
118+
persistedStageViewPosition,
119+
);
120+
}
121+
}, [persistedStageViewPosition, isMobile]);
96122

97123
useEffect(() => {
98-
window.localStorage.setItem(LS_KEYS.mainViewVisibility, mainViewVisibility);
99-
}, [mainViewVisibility]);
124+
if (!isMobile) {
125+
window.localStorage.setItem(
126+
LS_KEYS.mainViewVisibility,
127+
persistedMainViewVisibility,
128+
);
129+
}
130+
}, [persistedMainViewVisibility, isMobile]);
100131

101132
useEffect(() => {
102133
window.localStorage.setItem(
@@ -119,7 +150,13 @@ export const LayoutPreferencesProvider = ({
119150
);
120151
}, [stageViewHeight]);
121152

122-
// Setter wrappers
153+
// Update window width on resize
154+
useEffect(() => {
155+
const handleResize = () => setWindowWidth(window.innerWidth);
156+
window.addEventListener("resize", handleResize);
157+
return () => window.removeEventListener("resize", handleResize);
158+
}, []);
159+
123160
const setStageViewPosition = (position: StageViewPosition) =>
124161
setStageViewPositionState(position);
125162
const setMainViewVisibility = (visibility: MainViewVisibility) =>
@@ -142,6 +179,7 @@ export const LayoutPreferencesProvider = ({
142179
setTreeViewWidth,
143180
setStageViewWidth,
144181
setStageViewHeight,
182+
isMobile,
145183
}}
146184
>
147185
{children}

src/main/frontend/pipeline-console-view/pipeline-console/main/split-view.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
display: grid;
44
gap: var(--section-padding);
55
animation: fade-in 0.1s ease-in-out both;
6+
align-items: start;
67
}
78

89
@keyframes fade-in {
@@ -12,7 +13,7 @@
1213
}
1314

1415
.pgv-split-view__side-panel {
15-
position: relative;
16+
display: contents;
1617
}
1718

1819
.pgv-split-view__divider {

src/main/frontend/pipeline-console-view/pipeline-console/main/stage-details.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export default function StageDetails({ stage }: StageDetailsProps) {
8080
</Tooltip>
8181
</li>
8282
{stage.pauseDurationMillis !== 0 && (
83-
<li>
83+
<li className={"jenkins-mobile-hide"}>
8484
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
8585
<path
8686
d="M145.61 464h220.78c19.8 0 35.55-16.29 33.42-35.06C386.06 308 304 310 304 256s83.11-51 95.8-172.94c2-18.78-13.61-35.06-33.41-35.06H145.61c-19.8 0-35.37 16.28-33.41 35.06C124.89 205 208 201 208 256s-82.06 52-95.8 172.94c-2.14 18.77 13.61 35.06 33.41 35.06z"

0 commit comments

Comments
 (0)