Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/browser/layoutPolicy.ts
13389 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Disposable } from '../../base/common/lifecycle.js';
7
import { observableValue, derived, IObservable } from '../../base/common/observable.js';
8
import { isIOS, isMobile } from '../../base/common/platform.js';
9
import { isAndroid } from '../../base/browser/browser.js';
10
import { Gesture } from '../../base/browser/touch.js';
11
12
/** Viewport classification based on container width. */
13
export type ViewportClass = 'phone' | 'tablet' | 'desktop';
14
15
/** Default visibility for each workbench part. */
16
export interface IPartVisibilityDefaults {
17
readonly sidebar: boolean;
18
readonly auxiliaryBar: boolean;
19
readonly panel: boolean;
20
readonly chatBar: boolean;
21
readonly editor: boolean;
22
}
23
24
/** Default sizes (in pixels) for each workbench part. */
25
export interface IPartSizeDefaults {
26
readonly sideBarSize: number;
27
readonly auxiliaryBarSize: number;
28
readonly panelSize: number;
29
readonly chatBarWidth: number;
30
}
31
32
const PHONE_MAX_WIDTH = 640;
33
const TABLET_MAX_WIDTH = 1024;
34
35
/**
36
* Whether the current platform is a phone/tablet OS. The phone layout is
37
* only applied on actual mobile devices so that resizing a desktop window
38
* below 640px does not switch the agents workbench into phone mode.
39
*/
40
const isMobilePlatform = isMobile;
41
42
/**
43
* Classifies the viewport into one of three classes based on width.
44
* Phone and tablet classifications are gated on a mobile OS; desktop
45
* browsers and Electron always report `desktop` regardless of width.
46
*/
47
function classifyViewport(width: number): ViewportClass {
48
if (!isMobilePlatform) {
49
return 'desktop';
50
}
51
if (width < PHONE_MAX_WIDTH) {
52
return 'phone';
53
}
54
if (width < TABLET_MAX_WIDTH) {
55
return 'tablet';
56
}
57
return 'desktop';
58
}
59
60
/**
61
* Observable-based viewport classification and layout policy for
62
* the Sessions workbench. Consumed by `SessionsWorkbench` to drive
63
* part visibility, sizing, and behavior based on viewport dimensions
64
* and platform.
65
*/
66
export class SessionsLayoutPolicy extends Disposable {
67
68
// --- Platform flags (static, read once) ---
69
70
/** Whether the current platform is iOS. */
71
readonly isIOS: boolean;
72
73
/** Whether the current platform is Android. */
74
readonly isAndroid: boolean;
75
76
/** Whether the current device supports touch input. */
77
readonly isTouchDevice: boolean;
78
79
// --- Observables ---
80
81
private readonly _viewportClass = observableValue<ViewportClass>(this, 'desktop');
82
83
/** Current viewport class derived from the most recent `update()` call. */
84
readonly viewportClass: IObservable<ViewportClass> = this._viewportClass;
85
86
/** `true` when the viewport class is `phone`. */
87
readonly isPhoneLayout: IObservable<boolean> = derived(this, reader => {
88
return this._viewportClass.read(reader) === 'phone';
89
});
90
91
constructor() {
92
super();
93
94
this.isIOS = isIOS;
95
this.isAndroid = isAndroid;
96
this.isTouchDevice = Gesture.isTouchDevice();
97
}
98
99
/**
100
* Update the viewport classification. Call this from the workbench
101
* `layout()` method whenever the container dimensions change.
102
*
103
* @param width Container width in pixels.
104
* @param height Container height in pixels (reserved for future use).
105
*/
106
update(width: number, _height: number): void {
107
const next = classifyViewport(width);
108
if (this._viewportClass.get() !== next) {
109
this._viewportClass.set(next, undefined);
110
}
111
}
112
113
/**
114
* Returns the default part visibility for the given viewport class.
115
* If no class is supplied the current observed class is used.
116
*/
117
getPartVisibilityDefaults(viewportClass?: ViewportClass): IPartVisibilityDefaults {
118
const vc = viewportClass ?? this._viewportClass.get();
119
switch (vc) {
120
case 'phone':
121
return { sidebar: false, auxiliaryBar: false, panel: false, chatBar: true, editor: false };
122
case 'tablet':
123
case 'desktop':
124
// Tablet and desktop share the standard multi-part workbench defaults.
125
// A dedicated tablet layout has not been designed yet.
126
return { sidebar: true, auxiliaryBar: true, panel: false, chatBar: true, editor: false };
127
}
128
}
129
130
/**
131
* Returns the default part sizes for the given viewport dimensions.
132
* If no viewport class is supplied the current observed class is used.
133
*
134
* @param width Container width in pixels.
135
* @param height Container height in pixels (reserved for future use).
136
* @param viewportClass Optional explicit viewport class override.
137
*/
138
getPartSizes(width: number, _height: number, viewportClass?: ViewportClass): IPartSizeDefaults {
139
const vc = viewportClass ?? this._viewportClass.get();
140
switch (vc) {
141
case 'phone':
142
return {
143
sideBarSize: 0,
144
auxiliaryBarSize: 0,
145
panelSize: 0,
146
chatBarWidth: width,
147
};
148
case 'tablet':
149
case 'desktop':
150
// Tablet currently falls back to desktop sizing.
151
return {
152
sideBarSize: 300,
153
auxiliaryBarSize: 340,
154
panelSize: 300,
155
chatBarWidth: width - 300,
156
};
157
}
158
}
159
}
160
161