blob: 42202fc546b24f5a0197c2d7b5ccf3c7a85c8beb [file] [log] [blame]
Andres Olivares6490c002020-12-02 16:03:351// Copyright 2020 The Chromium Authors. All rights reserved.
Andres Olivares0e3a9e82020-12-01 14:03:202// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tim van der Lippeaa61faf2021-04-07 15:32:075import * as Common from '../../core/common/common.js';
Douglas Chiang5f52fb62023-04-05 08:43:106import * as i18n from '../../core/i18n/i18n.js';
Benedikt Meurere0b4b922024-01-15 13:33:537import * as Platform from '../../core/platform/platform.js';
Tim van der Lippeaa61faf2021-04-07 15:32:078import * as Root from '../../core/root/root.js';
Andres Olivares0e3a9e82020-12-01 14:03:209
10import {Context} from './Context.js';
11
Douglas Chiang5f52fb62023-04-05 08:43:1012const UIStrings = {
13 /**
14 *@description Title of the keybind category 'Elements' in Settings' Shortcuts pannel.
15 */
16 elements: 'Elements',
17 /**
18 *@description Title of the keybind category 'Screenshot' in Settings' Shortcuts pannel.
19 */
20 screenshot: 'Screenshot',
21 /**
22 *@description Title of the keybind category 'Network' in Settings' Shortcuts pannel.
23 */
24 network: 'Network',
25 /**
26 *@description Title of the keybind category 'Memory' in Settings' Shortcuts pannel.
27 */
28 memory: 'Memory',
29 /**
30 *@description Title of the keybind category 'JavaScript Profiler' in Settings' Shortcuts pannel.
31 */
32 javascript_profiler: 'JavaScript Profiler',
33 /**
34 *@description Title of the keybind category 'Console' in Settings' Shortcuts pannel.
35 */
36 console: 'Console',
37 /**
38 *@description Title of the keybind category 'Performance' in Settings' Shortcuts pannel.
39 */
40 performance: 'Performance',
41 /**
42 *@description Title of the keybind category 'Mobile' in Settings' Shortcuts pannel.
43 */
44 mobile: 'Mobile',
45 /**
46 *@description Title of the keybind category 'Help' in Settings' Shortcuts pannel.
47 */
48 help: 'Help',
49 /**
50 *@description Title of the keybind category 'Layers' in Settings' Shortcuts pannel.
51 */
52 layers: 'Layers',
53 /**
54 *@description Title of the keybind category 'Navigation' in Settings' Shortcuts pannel.
55 */
56 navigation: 'Navigation',
57 /**
58 *@description Title of the keybind category 'Drawer' in Settings' Shortcuts pannel.
59 */
60 drawer: 'Drawer',
61 /**
62 *@description Title of the keybind category 'Global' in Settings' Shortcuts pannel.
63 */
64 global: 'Global',
65 /**
66 *@description Title of the keybind category 'Resources' in Settings' Shortcuts pannel.
67 */
68 resources: 'Resources',
69 /**
70 *@description Title of the keybind category 'Background Services' in Settings' Shortcuts pannel.
71 */
72 background_services: 'Background Services',
73 /**
74 *@description Title of the keybind category 'Settings' in Settings' Shortcuts pannel.
75 */
76 settings: 'Settings',
77 /**
78 *@description Title of the keybind category 'Debugger' in Settings' Shortcuts pannel.
79 */
80 debugger: 'Debugger',
81 /**
82 *@description Title of the keybind category 'Sources' in Settings' Shortcuts pannel.
83 */
84 sources: 'Sources',
85 /**
86 *@description Title of the keybind category 'Rendering' in Settings' Shortcuts pannel.
87 */
88 rendering: 'Rendering',
Nikolay Vitkov8f7bda52023-11-10 16:46:1389 /**
90 *@description Title of the keybind category 'Recorder' in Settings' Shortcuts pannel.
91 */
92 recorder: 'Recorder',
Benedikt Meurer01fabc62023-11-16 10:24:1693 /**
94 *@description Title of the keybind category 'Changes' in Settings' Shortcuts pannel.
95 */
96 changes: 'Changes',
Ergun Erdogmus5efc7e92025-02-21 11:36:5097} as const;
Douglas Chiang5f52fb62023-04-05 08:43:1098const str_ = i18n.i18n.registerUIStrings('ui/legacy/ActionRegistration.ts', UIStrings);
99const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
100
Andres Olivares0e3a9e82020-12-01 14:03:20101export interface ActionDelegate {
Nikolay Vitkovb31abae2024-05-28 15:52:27102 handleAction(context: Context, actionId: string): boolean;
Andres Olivares0e3a9e82020-12-01 14:03:20103}
104
Kateryna Prokopenkoa72448b2021-08-31 14:16:16105export class Action extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
Jan Scheffler01eab3c2021-08-16 17:18:07106 private enabledInternal = true;
107 private toggledInternal = false;
Jack Franklin01d09b02020-12-02 15:15:20108 private actionRegistration: ActionRegistration;
Andres Olivares0e3a9e82020-12-01 14:03:20109 constructor(actionRegistration: ActionRegistration) {
110 super();
Jack Franklin01d09b02020-12-02 15:15:20111 this.actionRegistration = actionRegistration;
Andres Olivares0e3a9e82020-12-01 14:03:20112 }
113
114 id(): string {
Jack Franklin01d09b02020-12-02 15:15:20115 return this.actionRegistration.actionId;
Andres Olivares0e3a9e82020-12-01 14:03:20116 }
117
118 async execute(): Promise<boolean> {
Jack Franklin01d09b02020-12-02 15:15:20119 if (!this.actionRegistration.loadActionDelegate) {
Andres Olivares0e3a9e82020-12-01 14:03:20120 return false;
121 }
Jack Franklin01d09b02020-12-02 15:15:20122 const delegate = await this.actionRegistration.loadActionDelegate();
Andres Olivares0e3a9e82020-12-01 14:03:20123 const actionId = this.id();
124 return delegate.handleAction(Context.instance(), actionId);
125 }
126
127 icon(): string|undefined {
Jack Franklin01d09b02020-12-02 15:15:20128 return this.actionRegistration.iconClass;
Andres Olivares0e3a9e82020-12-01 14:03:20129 }
130
131 toggledIcon(): string|undefined {
Jack Franklin01d09b02020-12-02 15:15:20132 return this.actionRegistration.toggledIconClass;
Andres Olivares0e3a9e82020-12-01 14:03:20133 }
134
135 toggleWithRedColor(): boolean {
Tim van der Lippeba0e6452021-01-07 13:46:34136 return Boolean(this.actionRegistration.toggleWithRedColor);
Andres Olivares0e3a9e82020-12-01 14:03:20137 }
138
Tim van der Lipped946df02020-12-14 14:35:49139 setEnabled(enabled: boolean): void {
Jan Scheffler01eab3c2021-08-16 17:18:07140 if (this.enabledInternal === enabled) {
Andres Olivares0e3a9e82020-12-01 14:03:20141 return;
142 }
143
Jan Scheffler01eab3c2021-08-16 17:18:07144 this.enabledInternal = enabled;
Benedikt Meurerf08ab4a2024-09-03 09:37:35145 this.dispatchEventToListeners(Events.ENABLED, enabled);
Andres Olivares0e3a9e82020-12-01 14:03:20146 }
147
148 enabled(): boolean {
Jan Scheffler01eab3c2021-08-16 17:18:07149 return this.enabledInternal;
Andres Olivares0e3a9e82020-12-01 14:03:20150 }
151
Douglas Chiang5f52fb62023-04-05 08:43:10152 category(): ActionCategory {
Jack Franklin01d09b02020-12-02 15:15:20153 return this.actionRegistration.category;
Andres Olivares0e3a9e82020-12-01 14:03:20154 }
155
Andres Olivares344120f2020-12-07 17:43:28156 tags(): string|void {
157 if (this.actionRegistration.tags) {
158 // Get localized keys and separate by null character to prevent fuzzy matching from matching across them.
Andres Olivares4ce36a52021-01-18 18:35:05159 return this.actionRegistration.tags.map(tag => tag()).join('\0');
Andres Olivares344120f2020-12-07 17:43:28160 }
Andres Olivares0e3a9e82020-12-01 14:03:20161 }
162
163 toggleable(): boolean {
Tim van der Lippeba0e6452021-01-07 13:46:34164 return Boolean(this.actionRegistration.toggleable);
Andres Olivares0e3a9e82020-12-01 14:03:20165 }
166
Simon ZĂĽnd6eb94e32023-04-11 05:28:22167 title(): Common.UIString.LocalizedString {
168 let title = this.actionRegistration.title ? this.actionRegistration.title() : i18n.i18n.lockedString('');
Jack Franklin01d09b02020-12-02 15:15:20169 const options = this.actionRegistration.options;
Andres Olivares0e3a9e82020-12-01 14:03:20170 if (options) {
171 // Actions with an 'options' property don't have a title field. Instead, the displayed
172 // title is taken from the 'title' property of the option that is not active. Only one of the
173 // two options can be active at a given moment and the 'toggled' property of the action along
174 // with the 'value' of the options are used to determine which one it is.
175
176 for (const pair of options) {
Jan Scheffler01eab3c2021-08-16 17:18:07177 if (pair.value !== this.toggledInternal) {
Andres Olivares4ce36a52021-01-18 18:35:05178 title = pair.title();
Andres Olivares0e3a9e82020-12-01 14:03:20179 }
180 }
181 }
182 return title;
183 }
184
185 toggled(): boolean {
Jan Scheffler01eab3c2021-08-16 17:18:07186 return this.toggledInternal;
Andres Olivares0e3a9e82020-12-01 14:03:20187 }
188
Tim van der Lipped946df02020-12-14 14:35:49189 setToggled(toggled: boolean): void {
Andres Olivares0e3a9e82020-12-01 14:03:20190 console.assert(this.toggleable(), 'Shouldn\'t be toggling an untoggleable action', this.id());
Jan Scheffler01eab3c2021-08-16 17:18:07191 if (this.toggledInternal === toggled) {
Andres Olivares0e3a9e82020-12-01 14:03:20192 return;
193 }
194
Jan Scheffler01eab3c2021-08-16 17:18:07195 this.toggledInternal = toggled;
Benedikt Meurerf08ab4a2024-09-03 09:37:35196 this.dispatchEventToListeners(Events.TOGGLED, toggled);
Andres Olivares0e3a9e82020-12-01 14:03:20197 }
198
Benedikt Meurer84b0fcc2025-02-12 13:57:23199 options(): undefined|ExtensionOption[] {
Jack Franklin01d09b02020-12-02 15:15:20200 return this.actionRegistration.options;
Andres Olivares0e3a9e82020-12-01 14:03:20201 }
202
Nikolay Vitkovb30f3b22025-03-04 13:38:33203 contextTypes(): undefined|Array<Platform.Constructor.Constructor<unknown>> {
Jack Franklin01d09b02020-12-02 15:15:20204 if (this.actionRegistration.contextTypes) {
205 return this.actionRegistration.contextTypes();
Andres Olivares0e3a9e82020-12-01 14:03:20206 }
207 return undefined;
208 }
209
210 canInstantiate(): boolean {
Tim van der Lippeba0e6452021-01-07 13:46:34211 return Boolean(this.actionRegistration.loadActionDelegate);
Andres Olivares0e3a9e82020-12-01 14:03:20212 }
213
Benedikt Meurer84b0fcc2025-02-12 13:57:23214 bindings(): Binding[]|undefined {
Jack Franklin01d09b02020-12-02 15:15:20215 return this.actionRegistration.bindings;
Andres Olivares0e3a9e82020-12-01 14:03:20216 }
217
218 experiment(): string|undefined {
Jack Franklin01d09b02020-12-02 15:15:20219 return this.actionRegistration.experiment;
Andres Olivares0e3a9e82020-12-01 14:03:20220 }
221
Alex Rudenko43ebf022024-01-31 18:43:40222 setting(): string|undefined {
223 return this.actionRegistration.setting;
224 }
225
Alex Rudenko6329ebd2024-02-08 14:39:59226 condition(): Root.Runtime.Condition|undefined {
Jack Franklin01d09b02020-12-02 15:15:20227 return this.actionRegistration.condition;
Andres Olivares0e3a9e82020-12-01 14:03:20228 }
Andres Olivares4dba1302021-01-28 23:17:32229
230 order(): number|undefined {
231 return this.actionRegistration.order;
232 }
Andres Olivares0e3a9e82020-12-01 14:03:20233}
234
Benedikt Meurerc9fb2be2024-01-15 09:06:42235const registeredActions = new Map<string, Action>();
Andres Olivares0e3a9e82020-12-01 14:03:20236
Tim van der Lipped946df02020-12-14 14:35:49237export function registerActionExtension(registration: ActionRegistration): void {
Andres Olivares0e3a9e82020-12-01 14:03:20238 const actionId = registration.actionId;
Benedikt Meurerc9fb2be2024-01-15 09:06:42239 if (registeredActions.has(actionId)) {
Benedikt Meurere0b4b922024-01-15 13:33:53240 throw new Error(`Duplicate action ID '${actionId}'`);
241 }
242 if (!Platform.StringUtilities.isExtendedKebabCase(actionId)) {
243 throw new Error(`Invalid action ID '${actionId}'`);
Andres Olivares0e3a9e82020-12-01 14:03:20244 }
Benedikt Meurerc9fb2be2024-01-15 09:06:42245 registeredActions.set(actionId, new Action(registration));
Andres Olivares0e3a9e82020-12-01 14:03:20246}
247
Andrés Olivaresb0fcd182023-02-21 10:13:28248export function reset(): void {
Benedikt Meurerc9fb2be2024-01-15 09:06:42249 registeredActions.clear();
Andrés Olivaresb0fcd182023-02-21 10:13:28250}
251
Benedikt Meurer84b0fcc2025-02-12 13:57:23252export function getRegisteredActionExtensions(): Action[] {
Benedikt Meurerc9fb2be2024-01-15 09:06:42253 return Array.from(registeredActions.values())
Alex Rudenko43ebf022024-01-31 18:43:40254 .filter(action => {
255 const settingName = action.setting();
Alex Rudenko3c5b6b32024-02-09 09:59:25256 try {
257 if (settingName && !Common.Settings.moduleSetting(settingName).get()) {
258 return false;
259 }
260 } catch (err) {
261 if (err.message.startsWith('No setting registered')) {
262 return false;
263 }
Alex Rudenko43ebf022024-01-31 18:43:40264 }
265
Benedikt Meurerea9d2862025-02-12 12:06:16266 return Root.Runtime.Runtime.isDescriptorEnabled({
267 experiment: action.experiment(),
268 condition: action.condition(),
269 });
Alex Rudenko43ebf022024-01-31 18:43:40270 })
Andres Olivares4dba1302021-01-28 23:17:32271 .sort((firstAction, secondAction) => {
272 const order1 = firstAction.order() || 0;
273 const order2 = secondAction.order() || 0;
274 return order1 - order2;
275 });
Andres Olivares0e3a9e82020-12-01 14:03:20276}
277
Andres Olivares975c3022021-03-29 13:45:24278export function maybeRemoveActionExtension(actionId: string): boolean {
Benedikt Meurerc9fb2be2024-01-15 09:06:42279 return registeredActions.delete(actionId);
Andres Olivares975c3022021-03-29 13:45:24280}
281
Andres Olivares4ce36a52021-01-18 18:35:05282export const enum Platforms {
Benedikt Meurerf08ab4a2024-09-03 09:37:35283 ALL = 'All platforms',
284 MAC = 'mac',
285 WINDOWS_LINUX = 'windows,linux',
286 ANDROID = 'Android',
287 WINDOWS = 'windows',
Andres Olivares0e3a9e82020-12-01 14:03:20288}
289
Kateryna Prokopenkoa72448b2021-08-31 14:16:16290export const enum Events {
Benedikt Meurerf08ab4a2024-09-03 09:37:35291 ENABLED = 'Enabled',
292 TOGGLED = 'Toggled',
Kateryna Prokopenkoa72448b2021-08-31 14:16:16293}
294
Nikolay Vitkov44e30062025-01-07 14:33:04295export interface EventTypes {
296 [Events.ENABLED]: boolean;
297 [Events.TOGGLED]: boolean;
298}
Andres Olivares0e3a9e82020-12-01 14:03:20299
Benedikt Meurer624312d2024-01-22 09:24:09300export const enum ActionCategory {
Douglas Chiang5f52fb62023-04-05 08:43:10301 NONE = '', // `NONE` must be a falsy value. Legacy code uses if-checks for the category.
302 ELEMENTS = 'ELEMENTS',
303 SCREENSHOT = 'SCREENSHOT',
304 NETWORK = 'NETWORK',
305 MEMORY = 'MEMORY',
306 JAVASCRIPT_PROFILER = 'JAVASCRIPT_PROFILER',
307 CONSOLE = 'CONSOLE',
308 PERFORMANCE = 'PERFORMANCE',
309 MOBILE = 'MOBILE',
310 HELP = 'HELP',
311 LAYERS = 'LAYERS',
312 NAVIGATION = 'NAVIGATION',
313 DRAWER = 'DRAWER',
314 GLOBAL = 'GLOBAL',
315 RESOURCES = 'RESOURCES',
316 BACKGROUND_SERVICES = 'BACKGROUND_SERVICES',
317 SETTINGS = 'SETTINGS',
318 DEBUGGER = 'DEBUGGER',
319 SOURCES = 'SOURCES',
320 RENDERING = 'RENDERING',
Nikolay Vitkov8f7bda52023-11-10 16:46:13321 RECORDER = 'RECORDER',
Benedikt Meurer01fabc62023-11-16 10:24:16322 CHANGES = 'CHANGES',
Douglas Chiang5f52fb62023-04-05 08:43:10323}
Andres Olivares0e3a9e82020-12-01 14:03:20324
Douglas Chiang5f52fb62023-04-05 08:43:10325export function getLocalizedActionCategory(category: ActionCategory): Platform.UIString.LocalizedString {
326 switch (category) {
327 case ActionCategory.ELEMENTS:
328 return i18nString(UIStrings.elements);
329 case ActionCategory.SCREENSHOT:
330 return i18nString(UIStrings.screenshot);
331 case ActionCategory.NETWORK:
332 return i18nString(UIStrings.network);
333 case ActionCategory.MEMORY:
334 return i18nString(UIStrings.memory);
335 case ActionCategory.JAVASCRIPT_PROFILER:
336 return i18nString(UIStrings.javascript_profiler);
337 case ActionCategory.CONSOLE:
338 return i18nString(UIStrings.console);
339 case ActionCategory.PERFORMANCE:
340 return i18nString(UIStrings.performance);
341 case ActionCategory.MOBILE:
342 return i18nString(UIStrings.mobile);
343 case ActionCategory.HELP:
344 return i18nString(UIStrings.help);
345 case ActionCategory.LAYERS:
346 return i18nString(UIStrings.layers);
347 case ActionCategory.NAVIGATION:
348 return i18nString(UIStrings.navigation);
349 case ActionCategory.DRAWER:
350 return i18nString(UIStrings.drawer);
351 case ActionCategory.GLOBAL:
352 return i18nString(UIStrings.global);
353 case ActionCategory.RESOURCES:
354 return i18nString(UIStrings.resources);
355 case ActionCategory.BACKGROUND_SERVICES:
356 return i18nString(UIStrings.background_services);
357 case ActionCategory.SETTINGS:
358 return i18nString(UIStrings.settings);
359 case ActionCategory.DEBUGGER:
360 return i18nString(UIStrings.debugger);
361 case ActionCategory.SOURCES:
362 return i18nString(UIStrings.sources);
363 case ActionCategory.RENDERING:
364 return i18nString(UIStrings.rendering);
Nikolay Vitkov8f7bda52023-11-10 16:46:13365 case ActionCategory.RECORDER:
366 return i18nString(UIStrings.recorder);
Benedikt Meurer01fabc62023-11-16 10:24:16367 case ActionCategory.CHANGES:
368 return i18nString(UIStrings.changes);
Douglas Chiang5f52fb62023-04-05 08:43:10369 case ActionCategory.NONE:
370 return i18n.i18n.lockedString('');
371 }
Simon ZĂĽndd2132fb2023-04-05 11:39:15372 // Not all categories are cleanly typed yet. Return the category as-is in this case.
373 return i18n.i18n.lockedString(category);
Douglas Chiang5f52fb62023-04-05 08:43:10374}
Andres Olivares0e3a9e82020-12-01 14:03:20375
376export const enum IconClass {
Kateryna Prokopenko910cb532023-03-28 09:36:46377 LARGEICON_NODE_SEARCH = 'select-element',
Kateryna Prokopenko75da9712023-03-31 11:56:38378 START_RECORDING = 'record-start',
379 STOP_RECORDING = 'record-stop',
Kateryna Prokopenko551f9c82023-04-04 14:34:21380 REFRESH = 'refresh',
Kateryna Prokopenko05ade9a2023-03-31 10:57:05381 CLEAR = 'clear',
382 EYE = 'eye',
Kateryna Prokopenko910cb532023-03-28 09:36:46383 LARGEICON_PHONE = 'devices',
Benedikt Meurer58fea3a2023-04-13 05:48:47384 PLAY = 'play',
Benedikt Meurerc4ad9d92023-04-11 07:25:02385 DOWNLOAD = 'download',
Benedikt Meurer4878f6a2023-03-29 12:01:44386 LARGEICON_PAUSE = 'pause',
387 LARGEICON_RESUME = 'resume',
Muhammad Mahad88237102023-12-10 10:24:03388 MOP = 'mop',
Benedikt Meurer178c0c32023-03-31 04:50:06389 BIN = 'bin',
Kateryna Prokopenko910cb532023-03-28 09:36:46390 LARGEICON_SETTINGS_GEAR = 'gear',
Benedikt Meurer4878f6a2023-03-29 12:01:44391 LARGEICON_STEP_OVER = 'step-over',
392 LARGE_ICON_STEP_INTO = 'step-into',
393 LARGE_ICON_STEP = 'step',
394 LARGE_ICON_STEP_OUT = 'step-out',
Benedikt Meurer32c2a1b2023-03-30 07:09:59395 BREAKPOINT_CROSSED_FILLED = 'breakpoint-crossed-filled',
396 BREAKPOINT_CROSSED = 'breakpoint-crossed',
Benedikt Meurer7d5cc372023-04-12 12:20:41397 PLUS = 'plus',
Benedikt Meurer01fabc62023-11-16 10:24:16398 UNDO = 'undo',
399 COPY = 'copy',
Benedikt Meurer92795632023-11-30 14:00:57400 IMPORT = 'import',
Andres Olivares0e3a9e82020-12-01 14:03:20401}
402
403export const enum KeybindSet {
404 DEVTOOLS_DEFAULT = 'devToolsDefault',
405 VS_CODE = 'vsCode',
406}
407
408export interface ExtensionOption {
409 value: boolean;
Andres Olivares4ce36a52021-01-18 18:35:05410 title: () => Platform.UIString.LocalizedString;
Andres Olivares0e3a9e82020-12-01 14:03:20411 text?: string;
412}
413
414export interface Binding {
Andres Olivares4ce36a52021-01-18 18:35:05415 platform?: Platforms;
Andres Olivares0e3a9e82020-12-01 14:03:20416 shortcut: string;
Benedikt Meurer84b0fcc2025-02-12 13:57:23417 keybindSets?: KeybindSet[];
Andres Olivares0e3a9e82020-12-01 14:03:20418}
419
Andres Olivares3f49f132020-12-03 13:10:27420/**
421 * The representation of an action extension to be registered.
422 */
Andres Olivares0e3a9e82020-12-01 14:03:20423export interface ActionRegistration {
Andres Olivares3f49f132020-12-03 13:10:27424 /**
425 * The unique id of an Action extension.
426 */
Andres Olivares0e3a9e82020-12-01 14:03:20427 actionId: string;
Andres Olivares3f49f132020-12-03 13:10:27428 /**
429 * The category with which the action is displayed in the UI.
430 */
Andres Olivares0e3a9e82020-12-01 14:03:20431 category: ActionCategory;
Andres Olivares3f49f132020-12-03 13:10:27432 /**
433 * The title with which the action is displayed in the UI.
434 */
Andres Olivares4ce36a52021-01-18 18:35:05435 title?: () => Platform.UIString.LocalizedString;
Andres Olivares3f49f132020-12-03 13:10:27436 /**
437 * The type of the icon used to trigger the action.
438 */
Andres Olivares844c58d2021-01-26 13:09:07439 iconClass?: IconClass;
Andres Olivares3f49f132020-12-03 13:10:27440 /**
441 * Whether the style of the icon toggles on interaction.
442 */
Andres Olivares844c58d2021-01-26 13:09:07443 toggledIconClass?: IconClass;
Andres Olivares3f49f132020-12-03 13:10:27444 /**
445 * Whether the class 'toolbar-toggle-with-red-color' is toggled on the icon on interaction.
446 */
Andres Olivares0e3a9e82020-12-01 14:03:20447 toggleWithRedColor?: boolean;
Andres Olivares3f49f132020-12-03 13:10:27448 /**
449 * Words used to find an action in the Command Menu.
450 */
Andres Olivares4ce36a52021-01-18 18:35:05451 tags?: Array<() => Platform.UIString.LocalizedString>;
Andres Olivares3f49f132020-12-03 13:10:27452 /**
453 * Whether the action is toggleable.
454 */
Andres Olivares0e3a9e82020-12-01 14:03:20455 toggleable?: boolean;
Andres Olivares3f49f132020-12-03 13:10:27456 /**
Andres Olivaresa0cdb382021-01-21 15:44:33457 * Loads the class that handles the action when it is triggered. The common pattern for implementing
458 * this function relies on having the module that contains the action’s handler lazily loaded. For example:
459 * ```js
460 * let loadedElementsModule;
461 *
462 * async function loadElementsModule() {
463 *
464 * if (!loadedElementsModule) {
465 * loadedElementsModule = await import('./elements.js');
466 * }
467 * return loadedElementsModule;
468 * }
469 * UI.ActionRegistration.registerActionExtension({
470 * <...>
471 * async loadActionDelegate() {
472 * const Elements = await loadElementsModule();
Benedikt Meurer64d1fec2023-11-24 10:32:08473 * return new Elements.ElementsPanel.ElementsActionDelegate();
Andres Olivaresa0cdb382021-01-21 15:44:33474 * },
475 * <...>
476 * });
477 * ```
Andres Olivares3f49f132020-12-03 13:10:27478 */
Andres Olivares0e3a9e82020-12-01 14:03:20479 loadActionDelegate?: () => Promise<ActionDelegate>;
Andres Olivares3f49f132020-12-03 13:10:27480 /**
481 * Returns the classes that represent the 'context flavors' under which the action is available for triggering.
482 * The context of the application is described in 'flavors' that are usually views added and removed to the context
483 * as the user interacts with the application (e.g when the user moves across views). (See UI.Context)
484 * When the action is supposed to be available globally, that is, it does not depend on the application to have
485 * a specific context, the value of this property should be undefined.
486 *
487 * Because the method is synchronous, context types should be already loaded when the method is invoked.
488 * In the case that an action has context types it depends on, and they haven't been loaded yet, the function should
489 * return an empty array. Once the context types have been loaded, the function should return an array with all types
490 * that it depends on.
491 *
492 * The common pattern for implementing this function is relying on having the module with the corresponding context
493 * types loaded and stored when the related 'view' extension is loaded asynchronously. As an example:
494 *
495 * ```js
496 * let loadedElementsModule;
497 *
498 * async function loadElementsModule() {
499 *
500 * if (!loadedElementsModule) {
501 * loadedElementsModule = await import('./elements.js');
502 * }
503 * return loadedElementsModule;
504 * }
505 * function maybeRetrieveContextTypes(getClassCallBack: (elementsModule: typeof Elements) => unknown[]): unknown[] {
506 *
507 * if (loadedElementsModule === undefined) {
508 * return [];
509 * }
510 * return getClassCallBack(loadedElementsModule);
511 * }
512 * UI.ActionRegistration.registerActionExtension({
513 *
514 * contextTypes() {
515 * return maybeRetrieveContextTypes(Elements => [Elements.ElementsPanel.ElementsPanel]);
516 * }
517 * <...>
518 * });
519 * ```
520 */
Nikolay Vitkovb30f3b22025-03-04 13:38:33521 contextTypes?: () => Array<Platform.Constructor.Constructor<unknown>>;
Andres Olivares3f49f132020-12-03 13:10:27522 /**
Andres Olivaresa0cdb382021-01-21 15:44:33523 * The descriptions for each of the two states in which a toggleable action can be.
Andres Olivares3f49f132020-12-03 13:10:27524 */
Benedikt Meurer84b0fcc2025-02-12 13:57:23525 options?: ExtensionOption[];
Andres Olivares3f49f132020-12-03 13:10:27526 /**
527 * The description of the variables (e.g. platform, keys and keybind sets) under which a keyboard shortcut triggers the action.
528 * If a keybind must be available on all platforms, its 'platform' property must be undefined. The same applies to keybind sets
529 * and the keybindSet property.
530 *
531 * Keybinds also depend on the context types of their corresponding action, and so they will only be available when such context types
532 * are flavors of the current appliaction context.
533 */
Benedikt Meurer84b0fcc2025-02-12 13:57:23534 bindings?: Binding[];
Andres Olivares3f49f132020-12-03 13:10:27535 /**
Andres Olivaresa0cdb382021-01-21 15:44:33536 * The name of the experiment an action is associated with. Enabling and disabling the declared
537 * experiment will enable and disable the action respectively.
Andres Olivares3f49f132020-12-03 13:10:27538 */
Andres Olivares0e3a9e82020-12-01 14:03:20539 experiment?: Root.Runtime.ExperimentName;
Andres Olivares3f49f132020-12-03 13:10:27540 /**
Alex Rudenko43ebf022024-01-31 18:43:40541 * The name of the setting an action is associated with. Enabling and
542 * disabling the declared setting will enable and disable the action
543 * respectively. Note that changing the setting requires a reload for it to
544 * apply to action registration.
545 */
546 setting?: string;
547 /**
Alex Rudenko6329ebd2024-02-08 14:39:59548 * A condition is a function that will make the action available if it
549 * returns true, and not available, otherwise. Make sure that objects you
550 * access from inside the condition function are ready at the time when the
551 * setting conditions are checked.
Andres Olivares3f49f132020-12-03 13:10:27552 */
Alex Rudenko6329ebd2024-02-08 14:39:59553 condition?: Root.Runtime.Condition;
Andres Olivares4dba1302021-01-28 23:17:32554 /**
555 * Used to sort actions when all registered actions are queried.
556 */
557 order?: number;
Andres Olivares0e3a9e82020-12-01 14:03:20558}