chore: replace all cn comments of fe to en version by volc api (#320)

This commit is contained in:
tecvan
2025-07-31 10:32:15 +08:00
committed by GitHub
parent 716ec0cba8
commit 71f6245a01
2960 changed files with 15545 additions and 15545 deletions

View File

@@ -37,9 +37,9 @@ interface ActivityBarProps {
}
/**
* activitybar 有两种状态
* - 选中态 select 同时高亮和左侧有蓝色竖线
* - 激活态 active 仅高亮
* Activitybar has two states
* - Select state with both highlight and blue vertical bar on the left
* - active only highlighted
*/
export const ActivityBar: React.FC<ActivityBarProps> = ({
list,

View File

@@ -117,7 +117,7 @@ export default function (i) {
function mousewheelHandler(e) {
const [deltaX, deltaY] = getDeltaFromEvent(e);
// FIXME: mousewheel 滚动的时候有问题
// FIXME: There is a problem with the mousewheel rolling
if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
return;
}

View File

@@ -16,11 +16,11 @@
export const CUSTOM_TAB_BAR_CONTAINER = 'custom-tabBar-container';
// 前边的 action
// Previous actions
export const PRE_TAB_BAR_ACTION_CONTAINER = 'pre-flow-tabBar-action-container';
// 后边的 action
// The action behind
export const TAB_BAR_ACTION_CONTAINER = 'flow-tabBar-action-container';
// tab bar 滚动区域
// Tab bar scrolling area
export const TAB_BAR_SCROLL_CONTAINER = 'flow-tabBar-scroll-container';
// toolbar
@@ -28,5 +28,5 @@ export const TAB_BAR_TOOLBAR = 'flow-toolbar-container';
export const TAB_BAR_TOOLBAR_ITEM = 'flow-toolbar-item';
export const DISABLE_HANDLE_EVENT = 'disable-handle-event';
/** DebugBar 可拖拽区域 classname */
/** DebugBar Draggable classname */
export const DEBUG_BAR_DRAGGABLE = 'flow-debug-bar-draggable';

View File

@@ -26,13 +26,13 @@ import { Menu, MenuFactory } from './menu';
export type CanHandle = string | ((command?: string) => boolean);
/**
* 全局 contextmenu 监听
* Global contextmenu listening
*/
@injectable()
export class ContextMenu {
@inject(MenuFactory) menuFactory: MenuFactory;
// 全局主菜单
// Global Main Menu
menu: Menu;
@postConstruct()
@@ -41,15 +41,15 @@ export class ContextMenu {
}
/**
* 删除项
* delete item
*/
deleteItem(canHandle: CanHandle) {
if (typeof canHandle === 'string') {
// 精确删除
// precise deletion
const item = this._items.find(i => i.command === canHandle);
ArrayExt.removeFirstOf(this._items, item);
} else {
// 模糊删除
// blur delete
this._items.forEach(i => {
if (canHandle(i.command)) {
ArrayExt.removeFirstOf(this._items, i);
@@ -59,7 +59,7 @@ export class ContextMenu {
}
/**
* 添加项
* add item
*/
addItem(options: ContextMenu.IItemOptions): Disposable {
const item = Private.createItem(options, this._idTick++);
@@ -72,14 +72,14 @@ export class ContextMenu {
}
/**
* 手动关闭 menu
* Manually close the menu
*/
close() {
this.menu.close();
}
/**
* 打开事件
* open event
*/
open(event: React.MouseEvent, args?: any): boolean {
Menu.saveWindowData();
@@ -141,8 +141,8 @@ export namespace ContextMenu {
/**
* The CSS selector for the context menu item.
*
* 只有当当前元素冒泡途径 selector 元素,才会触发这个 contextmenu 事件。
* 底层通过 querySelector 获取,需要加上 commas
* The contextmenu event is triggered only when the current element is bubbling through the selector element.
* The bottom layer is obtained through querySelector, and commas need to be added.
*/
selector: string;

View File

@@ -25,7 +25,7 @@ import { type CanHandle, ContextMenu } from './context-menu';
export const MenuService = Symbol('MenuService');
/**
* menu service 注册
* Menu service registration
*/
export interface MenuService {
addMenuItem: (options: ContextMenu.IItemOptions) => void;

View File

@@ -1022,19 +1022,19 @@ export namespace Menu {
/**
* custom shortcut
* 专门为第三方快捷键预留
* Specially reserved for third-party shortcuts
*/
customShortcut?: string;
/**
* 回显 tooltip 文案
* Echo tooltip copy
*/
tooltip?: string | ((props: { disabled?: boolean }) => string);
/**
* 返回为 true 的才会被保留在 menu 回显。
* 默认不传,满足 selector 条件一定会被回显在菜单内。
* disabled 通过 command isEnabled 控制
* Only those that return true will be retained in the menu echo.
* The default is not passed, and the selector condition will definitely be echoed in the menu.
* Disabled Control via command isEnabled
*/
filter?: (args: any) => boolean;
}
@@ -1071,7 +1071,7 @@ export namespace Menu {
*/
readonly label: string;
/** 不建议使用,极端场景兼容。custom shortcut string, without ShortcutService */
/** Not recommended, compatible with extreme scenes. custom shortcut string, without ShortcutService */
readonly customShortcut?: string;
/**
@@ -1124,7 +1124,7 @@ export namespace Menu {
*/
readonly keyBinding: null;
/** tooltip 内容 */
/** Tooltip content */
readonly tooltip?: string | ((props: { disabled?: boolean }) => string);
}

View File

@@ -314,7 +314,7 @@ export class ViewCommonContribution
},
{
execute: () => {
// 没有 focus 内容的时候默认打开 problem
// Open the problem by default when there is no focus content
if (!this.shell.bottomPanel?.currentTitle) {
this.commandService.executeCommand(Command.Default.VIEW_PROBLEMS);
}
@@ -364,51 +364,51 @@ export class ViewCommonContribution
}
registerShortcuts(registry: ShortcutsRegistry): void {
// 关闭当前所有 tab
// Close all current tabs
registry.registerHandlers({
keybinding: 'alt shift w',
commandId: Command.Default.VIEW_CLOSE_ALL_WIDGET,
});
// 打开下一个 tab
// Open next tab
registry.registerHandlers({
keybinding: 'alt shift rightarrow',
commandId: Command.Default.VIEW_OPEN_NEXT_TAB,
preventDefault: true,
});
// 打开上一个 tab
// Open previous tab
registry.registerHandlers({
keybinding: 'alt shift leftarrow',
commandId: Command.Default.VIEW_OEPN_LAST_TAB,
preventDefault: true,
});
// 关闭当前 tab
// Close the current tab
registry.registerHandlers({
keybinding: 'alt w',
commandId: Command.Default.VIEW_CLOSE_CURRENT_WIDGET,
});
// 打开刚刚关闭当前 tab
// Open Just closed the current tab
registry.registerHandlers({
keybinding: 'alt shift t',
commandId: Command.Default.VIEW_REOPEN_LAST_WIDGET,
});
// 关闭除了当前打开的 tab 以外的所有 tab
// Close all tabs except the currently open tab
registry.registerHandlers({
keybinding: 'meta alt t',
commandId: Command.Default.VIEW_CLOSE_OTHER_WIDGET,
});
// 关闭除了当前打开的 tab 以外的所有 tab
// Close all tabs except the currently open tab
registry.registerHandlers({
keybinding: 'meta j',
commandId: Command.Default.VIEW_CLOSE_BOTTOM_PANEL,
});
// 全屏模式
// Full screen mode
registry.registerHandlers({
keybinding: 'alt f',
commandId: Command.Default.VIEW_FULL_SCREEN,

View File

@@ -81,7 +81,7 @@ import { MAIN_PANEL_ID } from './constants';
const DefaultFallbackRender = () => <div>Something went wrong.</div>;
/**
* 点位背景插件
* Point background plugin
*/
export const createViewPlugin = definePluginCreator<ViewPluginOptions>({
onBind: ({ bind }, opts) => {
@@ -167,9 +167,9 @@ export const createViewPlugin = definePluginCreator<ViewPluginOptions>({
const viewManager = ctx.get<ViewManager>(ViewManager);
await viewManager.init(opts);
},
// 页面渲染完成后 attach dom
// After the page is rendered, attach dom
onLayoutInit: async (ctx, opts) => {
// 预设 contextmenu
// contextmenu
if (!opts.presetConfig?.disableContextMenu) {
const menuService = ctx.container.get<MenuService>(MenuService);
menuService.addMenuItem({
@@ -197,14 +197,14 @@ export const createViewPlugin = definePluginCreator<ViewPluginOptions>({
await viewManager.attach(opts);
const eventService = ctx.container.get<EventService>(EventService);
const menuService = ctx.container.get<MenuService>(MenuService);
// 劫持全局的 contextmenu
// Hijack the global contextmenu
eventService.listenGlobalEvent('contextmenu', (e: React.MouseEvent) => {
if (domEditable(e.target as HTMLElement)) {
return;
}
const hasMenu = menuService.open(e);
if (!opts.presetConfig?.disableContextMenu || hasMenu) {
// 在 ide 内部永远阻塞右键
// Always block right button inside IDE
e.stopPropagation();
e.preventDefault();
}

View File

@@ -593,8 +593,8 @@ export namespace Drag {
*/
export interface IOptions {
/**
* 由于有一个 lm-cursor-backdrop 元素,用于阻止拖拽分屏过程中触发的 hover 事件
* 因此引入一个额外的配置,配置这个元素的边界位置
* Due to the lm-cursor-backdrop element, it is used to prevent the hover event from being triggered during dragging and dropping the split screen.
* Therefore, an additional configuration is introduced to configure the boundary position of this element
*/
backdropTransform?: BackDropTransform;

View File

@@ -623,7 +623,7 @@ export class DockPanel extends Widget {
const widgets = await factory();
let replaceRef: Widget;
widgets.forEach((widget: Widget, idx: number) => {
// 第一个执行分屏,后续都是 widget-all
// The first one executes the split screen, and the follow-up is widget-all.
if (idx === 0) {
this.bindWidget(event, widget, zone, target);
replaceRef = widget;
@@ -1128,7 +1128,7 @@ export namespace DockPanel {
*/
export interface IOptions {
/**
* 最大分屏数量限制
* Maximum number of split screens
*/
splitOptions?: SplitOptions;
/**
@@ -1630,15 +1630,15 @@ namespace Private {
}
/**
* 递归遍历布局树,计算 tab-area 的数量
* Recursively traverse the layout tree to count the number of tab-areas
* @param area DockLayout.Area
* @returns number 分屏数量
* @returns number number of split screens
*/
function countTabAreas(area: DockLayout.AreaConfig | null): number {
if (area?.type === 'tab-area') {
return 1; // 找到一个 tab 区域
return 1; // Find a tab area
} else if (area?.type === 'split-area') {
// 遍历子区域,递归计算每个区域的数量
// Traverse the subregions and recursively calculate the number of each region
return area.children.reduce(
(count, child) => count + countTabAreas(child),
0,
@@ -1698,7 +1698,7 @@ namespace Private {
// Hit test the dock layout at the given client position.
const target = layout.hitTestTabAreas(clientX, clientY);
// 最大分屏数量限制
// Maximum number of split screens
if (splitOptions?.maxSplitCount) {
const layoutConfig = layout.saveLayout();
const currentScreens = countTabAreas(layoutConfig.main);
@@ -1706,10 +1706,10 @@ namespace Private {
return { zone: 'invalid', target: null };
}
if (currentScreens >= splitOptions.maxSplitCount) {
// 如果数量超出最大屏幕数,此时只能充满屏幕,不能分屏
// If the number exceeds the maximum number of screens, the screen can only be filled at this time, not split-screen.
return { zone: 'widget-all', target };
}
// 限制只能左右分屏
// Limit can only split screen left and right
if (splitOptions?.splitOrientation === 'horizontal') {
if (target && target.x < target.width / 4) {
return { zone: 'widget-left', target };
@@ -1719,7 +1719,7 @@ namespace Private {
}
return { zone: 'widget-all', target };
}
// 限制只能上下分屏
// Restriction can only be split screen up and down
if (splitOptions?.splitOrientation === 'vertical') {
if (target && target.y < target.height / 4) {
return { zone: 'widget-top', target };
@@ -1732,7 +1732,7 @@ namespace Private {
}
// Test the edge zones when in multiple document mode.
// 分屏方向限制的时候,禁用 root 层的区域判断
// When the split-screen orientation is restricted, disable the area judgment of the root layer
if (panel.mode === 'multiple-document') {
// Get the client rect for the dock panel.
const panelRect = panel.node.getBoundingClientRect();

View File

@@ -21,7 +21,7 @@ import { createPortal } from '../utils';
import { ApplicationShell } from '../shell/application-shell';
import { ViewOptions } from '../constants/view-options';
// 控制 debug
// Control debugging
@injectable()
export class DebugService {
@inject(ViewOptions) viewOptions: ViewOptions;

View File

@@ -26,22 +26,22 @@ import { MimeData } from '../lumino/coreutils';
export interface DragPropsType {
/**
* 拖拽打开分屏的 URI
* Drag and drop to open the split-screen URI.
*/
uris: URI[];
/**
* startDrag event 位置数据
* StartDrag event location data
*/
position: {
clientX: number;
clientY: number;
};
/**
* 拖拽元素回显,不传不展示
* Drag and drop elements to echo, no transmission or display
*/
dragImage?: HTMLElement;
/**
* 拖拽完成后回调
* Callback after dragging is complete
* action: 'move' | 'copy' | 'link' | 'none'
*/
callback: (action: Drag.DropAction) => void;
@@ -49,7 +49,7 @@ export interface DragPropsType {
}
/**
* DragService 主要用于分屏操作
* DragService is mainly used for split-screen operation
*/
@injectable()
export class DragService {
@@ -60,7 +60,7 @@ export class DragService {
@inject(ViewRenderer) viewRenderer: ViewRenderer;
/**
* 业务侧手动拖拽触发分屏(侧边栏文件树拖拽进入开始分屏)
* Manually drag and drop on the business side to trigger the split screen (drag the sidebar file tree into the start split screen)
*/
startDrag({
uris,
@@ -94,7 +94,7 @@ export class DragService {
proposedAction: 'move',
supportedActions: 'move',
/**
* 仅支持在主面板区域分屏
* Only supports split screen in the main panel area
*/
source: this.shell.mainPanel,
backdropTransform,

View File

@@ -100,7 +100,7 @@ export interface HoverRequest {
position: HoverPosition;
cssClasses?: string[];
visualPreview?: (width: number) => HTMLElement | undefined;
/** hover 位置偏移 */
/** Hover position offset */
offset?: number;
}

View File

@@ -41,21 +41,21 @@ export class ViewService {
private prevPanelMap = new Map<LayoutPanelType, boolean>();
/**
* 唤起底部面板
* Evoke the bottom panel
*/
toggleBottomLayout() {
this.shell.bottomSplitLayout.setRelativeSizes([0.7, 0.3]);
}
/**
* 隐藏底部面板
* Hide bottom panel
*/
hideBottomLayout() {
this.shell.bottomSplitLayout.setRelativeSizes([1, 0]);
}
/**
* 获取所有打开的 tab title
* Get all open tab titles
*/
getOpenTitles() {
let titles: CustomTitleType[] = [];
@@ -69,7 +69,7 @@ export class ViewService {
}
/**
* 获取当前 panel 打开的所有 tab
* Get all tabs currently open in the panel
*/
getAllTabsFromArea(
area: LayoutPanelType.MAIN_PANEL | LayoutPanelType.BOTTOM_PANEL,
@@ -86,7 +86,7 @@ export class ViewService {
}
/**
* 关闭除了当前 tab 以外的所有 tab
* Close all tabs except the current tab
*/
closeOtherTabs(dispose = true) {
try {
@@ -111,7 +111,7 @@ export class ViewService {
}
/**
* 打开主面板的下一个 tab
* Open the next tab in the main panel
*/
openNextTab() {
const tabBars = (
@@ -135,7 +135,7 @@ export class ViewService {
}
/**
* 打开主面板的上一个 tab
* Open the previous tab of the main panel
*/
openLastTab() {
const tabBars = (
@@ -160,7 +160,7 @@ export class ViewService {
}
/**
* 开启全屏模式
* Enable full screen mode
*/
enableFullScreenMode() {
if (this.isFullScreenMode) {
@@ -178,7 +178,7 @@ export class ViewService {
}
/**
* 关闭全屏模式
* Turn off full screen mode
*/
disableFullScreenMode() {
if (!this.isFullScreenMode) {
@@ -196,7 +196,7 @@ export class ViewService {
}
/**
* 全屏模式切换
* full screen mode toggle
*/
switchFullScreenMode() {
if (!this.isFullScreenMode) {
@@ -207,14 +207,14 @@ export class ViewService {
}
/**
* 设置当前 activityBar 激活 item
* Set the current activityBar item
*/
setActivityBarUri(uri: URI) {
this.shell.activityBarWidget.setCurrentUri(uri);
}
/**
* 获取当前 activityBar 激活的 item
* Get the current activityBar active item
*/
get activityBarUri() {
return this.shell.activityBarWidget.currentUri;

View File

@@ -124,7 +124,7 @@ export class ApplicationShell extends Widget {
closeWidgetUriStack: URI[] = [];
/**
* 当前 focus widget 变化
* Current focus widget change
*/
protected readonly onCurrentWidgetChangeEmitter = new Emitter<
AbstractWidget | undefined
@@ -146,15 +146,15 @@ export class ApplicationShell extends Widget {
this.bottomPanel.hide();
this.topPanel = this.createPanel(LayoutPanelType.TOP_BAR);
// 扩展,目前暂时未用到。
// Extension, not currently in use.
this.rightToolbar = this.createPanel(LayoutPanelType.RIGHT_BAR);
// 默认模式下 rightToolbar 隐藏
// Default mode rightToolbar hide
this.rightToolbar.hide();
this.statusBar = this.createPanel(LayoutPanelType.STATUS_BAR);
this.activityBar = this.createPanel(LayoutPanelType.ACTIVITY_BAR);
this.secondarySidebar = this.createPanel(LayoutPanelType.SECONDARY_SIDEBAR);
// 创建左侧面板
// Create left panel
this.leftPanelHandler = this.sidePanelHandlerFactory();
this.leftPanelHandler.create('left');
this.leftPanelHandler.expand();
@@ -163,7 +163,7 @@ export class ApplicationShell extends Widget {
this.primarySidebar.id = uri.displayName;
this.widgetManager.setWidget(uri.toString(), this.primarySidebar);
// 默认右侧隐藏
// Default right side hide
this.secondarySidebar.hide();
this.layout = createLayout?.(this) || this.createLayout();
@@ -219,7 +219,7 @@ export class ApplicationShell extends Widget {
default:
throw new Error(`Unexpected area: ${options?.area}`);
}
// topBar statusbar 不监听
// topBar and statusbar do not listen
if (
area !== LayoutPanelType.STATUS_BAR &&
area !== LayoutPanelType.TOP_BAR
@@ -270,7 +270,7 @@ export class ApplicationShell extends Widget {
}
}
// 给本地持久化消费使用的方法
// Methods for local persistent consumption
setCurrentWidget(widget?: ReactWidget) {
this._currentWidget = widget;
this._currentWidgetParent = widget?.parent;
@@ -311,10 +311,10 @@ export class ApplicationShell extends Widget {
const leftRightSplitLayout = createSplitLayout(
[
// 左边的不可伸缩 bar
// Unretractable bar on the left
this.primarySidebar,
middleContentPanel,
// 右边的不可伸缩 bar
// Non-retractable bar on the right
this.secondarySidebar,
],
[0, 1, 0],
@@ -325,10 +325,10 @@ export class ApplicationShell extends Widget {
const centerLayout = createBoxLayout(
[
// 左边的不可伸缩 bar
// Unretractable bar on the left
this.activityBar,
mainDockPanel,
// 右边的不可伸缩 bar
// Non-retractable bar on the right
this.rightToolbar,
],
[0, 1, 0],
@@ -395,7 +395,7 @@ export class ApplicationShell extends Widget {
}
/**
* 将当前选中的 widget 的 tab 滚动到视区内
* Scroll the tab of the currently selected widget to the viewport
*/
tabbarIntoView(behavior?: boolean) {
const { mainPanel } = this;
@@ -435,7 +435,7 @@ export class ApplicationShell extends Widget {
const index = this.closeWidgetUriStack.findIndex(p =>
isURIMatch(p, uri),
);
// 有重复的先删除,再 push
// If there are duplicates, delete them first, and then push them.
if (index !== -1) {
this.closeWidgetUriStack.splice(index, 1);
}
@@ -458,11 +458,11 @@ export class ApplicationShell extends Widget {
}
/***********************************************************************
* layout 相关
* Layout related
*/
getLayoutData(): LayoutData {
// 记录子分屏 layout 数据
// Record subscreen layout data
const widgets: Widget[] = [];
this.primarySidebar.widgets.forEach(_widget => {
widgets.push(_widget);
@@ -518,7 +518,7 @@ export class ApplicationShell extends Widget {
}
}
// 下边是 tabs 切换,等 mainPanel 切换成 dockpanel 的时候启用
// Below is tabs switching, which will be enabled when mainPanel switches to dockpanel.
// activateWithLabel(widget: Widget) {
// this.mainPanel.activateWidget(widget);
// }

View File

@@ -33,16 +33,16 @@ import { type LayoutData } from './types';
import { ApplicationShell } from './application-shell';
/**
* 在会话之间存储和恢复 widget 其内部状态的接口
* Interface for storing and restoring the internal state of widgets between sessions
*/
interface StatefulWidget {
/**
* widget 内部的状态,返回 undefined 将不会保存
* The internal state of the widget, returning undefined will not save
*/
storeState(): object | undefined;
/**
* 复原存储的状态
* Restore the stored state
*/
restoreState(state: object): void;
}
@@ -57,30 +57,30 @@ const CustomPreferenceContribution = Symbol('CustomPreferenceContribution');
interface CustomPreferenceContribution {
/**
* 注册 command
* Registration command
*/
registerCustomPreferences(restorer: LayoutRestorer): void;
}
export interface CustomPreferenceConfig {
/**
* 该配置唯一 key
* Unique key for this configuration
*/
key: string;
/**
* 标题
* title
*/
title: string;
/**
* 描述
* describe
*/
descprition?: string;
/**
* 顺序
* order
*/
order: number;
/**
* 值设置器配置
* value setter configuration
*/
setting:
| {
@@ -100,7 +100,7 @@ export interface CustomPreferenceConfig {
}>;
};
/**
* 默认值
* default value
*/
default: any;
}
@@ -125,29 +125,29 @@ type RestoreState = LayoutData & {
};
/**
* 整个 restore 的流程:
* The entire restore process:
*
* -------------------- 初始化 --------------------
* 1. 读取 options 配置,等待 DockPanelSplitLayout 实例化完成
* 2. 从数据源 (目前是 localStorage) 读取持久化数据,包含 layoutData innerState
* 3. 遍历 layoutData 中的 widget uri 根据保存的 uri 线索重新创建 widget
* 3.1. 根据 uri 找到 Factory根据 uri 和 Factory 创建 widget
* 3.2. 用 portal 挂载,这是本 ide widget 的挂载方式决定的
* 3.3. 运行 widget.init,这是 ReactWidget 决定的
* 3.4. shell.stack(widget),持久化的 widget 全部都需要被 stack
* 4. 依次 restore 各个 panel layout
* -------------------- initialization --------------------
* 1. Read the options configuration and wait for the DockPanel and SplitLayout instantiation to complete
* 2. Read persistent data from a data source (currently localStorage), including layoutData and innerState
* 3. Traverse the widget URIs in layoutData and recreate the widget according to the saved URI clues.
* 3.1. Find Factory according to URI, create widget according to URI and Factory
* 3.2. Mount with portal, which is determined by the mounting method of this ide widget
* 3.3. Run widget.init, which is determined by ReactWidget
* 3.4. Shell.stack (widget), all persistent widgets need to be stacked
* 4. Sequentially restore panels and layouts
*
* -------------------- 运行中 --------------------
* 5. widget dispose 时,将 state 存于 innerState
* 6. widget create 时,从 innerState 中取数据回填
* (注意,这里都是和内存交互,和持久化数据源无关)
* -------------------- running --------------------
* 5. widget disposed, save state in innerState
* 6. When the widget is created, backfill the data from innerState
* (Note that this is all about interacting with memory and has nothing to do with persistent data sources.)
*
* -------------------- 销毁 --------------------
* 7. 应用销毁前读取 layoutData,和 innerState 一起存入持久化数据源
* 7.1. layoutData 中的 widget 对象仅保留它的 uri并且会转化为 string 的形式存储
* -------------------- destroy --------------------
* 7. Read the layoutData before the application is destroyed, and store it in the persistent data source together with innerState
* 7.1. A widget object in layoutData only retains its URI and is stored as a string
*
* Q:为什么 innerState 作为内存 state 也需要被存储?
* A:被打开又被关闭的 widget state 只存在 inner 中,没有被 layoutData 囊括
* Q: Why does innerState need to be stored as memory state?
* A: The widget state that is opened and closed only exists in inner, not included by layoutData
*/
@injectable()
@@ -170,7 +170,7 @@ class LayoutRestorer {
protected readonly widgetManager: WidgetManager;
/**
* 维护在内存中的持久化数据,在应用初始化时从源读取,但不会用于持久化初始化
* Maintains persistent data in memory that is read from the source during application initialization, but not used for persistent initialization
*/
innerState: Record<string, any> = {};
@@ -200,7 +200,7 @@ class LayoutRestorer {
private unloadEvent: undefined | Disposable;
public init(options: ViewPluginOptions) {
/** 没地方放,暂时放这里 */
/** No place to put it, put it here for now */
this.windowService.onStart();
this.viewOptions = options;
const { getStorageKey } = options || {};
@@ -394,7 +394,7 @@ class LayoutRestorer {
}
/**
* 持久化布局数据
* persistent layout data
*/
storeLayout() {
if (this.disabled) {
@@ -413,7 +413,7 @@ class LayoutRestorer {
}
/**
* 取出布局数据
* Retrieve layout data
*/
async restoreLayout() {
if (this.disabled) {

View File

@@ -17,10 +17,10 @@
import { type DockPanel, type Widget } from '../lumino/widgets';
/**
* 版本号控制向下不兼容问题
* Version number control backward incompatibility issue
*/
export type ApplicationShellLayoutVersion =
/** 初始化版本 */
/** initialization version */
0.2;
export const applicationShellLayoutVersion: ApplicationShellLayoutVersion = 0.2;
@@ -51,7 +51,7 @@ export interface LayoutData {
widgets?: Widget[];
};
bottomPanel?: DockPanel.ILayoutConfig & {
// 是否折叠
// Whether to fold
expanded?: boolean;
};
split?: {

View File

@@ -34,7 +34,7 @@ export enum LayoutPanelType {
SECONDARY_SIDEBAR = 'secondarySidebar',
BOTTOM_PANEL = 'bottomPanel',
STATUS_BAR = 'statusBar',
// 暂时未用到,留作扩展
// Not used yet, reserved for expansion
RIGHT_BAR = 'rightBar',
}
@@ -50,34 +50,34 @@ export const allLayoutEnums = [
];
/**
* widget 描述数据
* Widget description data
*/
interface WidgetDescription {
uri: URI;
innerState: string;
}
interface TabPanelData {
/** 固定值 */
/** fixed value */
type: 'tab-area';
/** 当前激活的 tab */
/** Currently active tab */
currentIndex?: number;
widgets?: WidgetDescription[];
}
/**
* main panel 的数据结构
* Main panel data structure
*/
interface MainPanelData {
main?: TabPanelData;
}
interface BottomPanelData {
main?: TabPanelData;
/** 是否默认折叠 */
/** Whether to fold by default */
expanded?: boolean;
}
export interface ActivityBarItem {
/**
* menu 位置
* Menu location
*/
position: 'top' | 'bottom';
/**
@@ -85,11 +85,11 @@ export interface ActivityBarItem {
*/
uri: URI;
/**
* tooltip 提示文案
* Tooltip Copywriting
*/
tooltip?: string;
/**
* 业务侧劫持实现 item 点击
* Business side hijacking implementation item click
*/
onClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
}
@@ -100,15 +100,15 @@ export interface StatusBarItem {
}
/**
* 支持传入 DockPanel options
* Support for incoming DockPanel options
*/
export interface SplitOptions {
/**
* 最大分屏数量限制
* Maximum number of split screens
*/
maxSplitCount: number;
/**
* 分屏方向限制,不传则不限制
* Split screen direction limit, no limit if not transmitted
*/
splitOrientation?: 'horizontal' | 'vertical';
}
@@ -123,7 +123,7 @@ export interface SplitScreenConfig {
bottom?: DockPanelConfig;
}
/** 预设数据 */
/** default data */
export interface LayoutData {
debugBar?: {
render: () => ReactElementType;
@@ -138,63 +138,63 @@ export interface LayoutData {
statusBarItems?: StatusBarItem[];
defaultWidgets?: URI[];
/** 持久化数据 */
/** persistent data */
mainPanel?: MainPanelData;
bottomPanel?: BottomPanelData;
}
export interface PresetConfigType {
/**
* 自定义分屏规则配置
* Custom split-screen rule configuration
*/
splitScreenConfig?: SplitScreenConfig;
/**
* 禁用预置右键菜单
* Disable preset right-click menu
*/
disableContextMenu?: boolean;
/**
* 禁用全屏
* Disable full screen
*/
disableFullScreen?: boolean;
}
export interface ViewPluginOptions {
// 预置配置
// preset configuration
presetConfig?: PresetConfigType;
/**
* 所有自定义 widget 工厂
* All custom widget factories
*/
widgetFactories?: WidgetFactory[];
/**
* widget 报错渲染
* Widget error rendering
*/
widgetFallbackRender?: React.FC<{ widget: ReactWidget } & FallbackProps>;
/**
* 默认布局信息
* Default layout information
*/
defaultLayoutData?: LayoutData;
/**
* 持久化数据存储的 key
* The key to persistent data storage
*/
getStorageKey?: () => string;
/**
* 关闭持久化逻辑
* Turn off persistence logic
*/
restoreDisabled?: boolean;
/**
* 自定义设置
* custom settings
*/
customPreferenceConfigs?: CustomPreferenceConfig[];
/**
* 自定义 IDE 布局
* Custom IDE layout
*/
customLayout?: (shell: ApplicationShell) => BoxLayout;
}
/**
* 菜单路径
* menu path
*/
export type MenuPath = string[];

View File

@@ -33,7 +33,7 @@ export class ViewManager {
@named(ViewContribution)
viewContributions: ContributionProvider<ViewContribution>;
// 通过 widgetManager 进行注入
// Injection via widgetManager
@inject(WidgetManager) widgetManager: WidgetManager;
@inject(ViewOptions) options: ViewOptions;
@@ -69,7 +69,7 @@ export class ViewManager {
viewOptions.defaultLayoutData?.defaultWidgets?.forEach(uri => {
this.openerService.open(uri);
});
// activityBar 由内部自定义,比较特殊
// activityBar is customized internally and is special.
const activityBar = this.shell.activityBarWidget;
this.viewRenderer.addReactPortal(activityBar);
activityBar?.initView?.(

View File

@@ -50,7 +50,7 @@ export class ViewRenderer {
comp: React.FunctionComponent;
}[] = [];
// 全局挂载,进入画布只会执行一次。
// Global mount, entering the canvas will only be executed once.
globalReactPortals: {
key?: string;
comp: React.FunctionComponent;
@@ -86,8 +86,8 @@ export class ViewRenderer {
}, 0);
/**
* 转成 react
* 注入 shell避免 inject cycle
* To react
* Inject shell to avoid injection cycle
*/
toReactComponent(shell: ApplicationShell): React.FC {
if (this.reactComp) {

View File

@@ -134,7 +134,7 @@ export class WidgetManager {
}
/**
* 使用工厂模式注册
* Register with factory mode
*/
async getOrCreateWidgetFromURI<T extends ReactWidget>(
uri: URI,

View File

@@ -156,7 +156,7 @@ export class FlowDockPanel extends DockPanel {
}
handleEvent(event: Event): void {
// 避免不同 dock-panel 之间的 tab 相互拖拽
// Avoid dragging tabs between different dock-panels
const dragSourceId = (event as Event & { source?: HTMLElement }).source?.id;
const targetArea = (event.target as HTMLElement)?.closest?.(
`#${dragSourceId}`,
@@ -165,7 +165,7 @@ export class FlowDockPanel extends DockPanel {
return;
}
// 禁止分屏
// Disable split screen
if (this._options?.disabledSplitScreen) {
return;
}

View File

@@ -22,7 +22,7 @@ import { Panel, BoxLayout, BoxPanel, PanelLayout } from '../../lumino/widgets';
export const SidePanelHandlerFactory = Symbol('SidePanelHandlerFactory');
/**
* 侧边栏分级面板 handler
* Sidebar grading panel handler
*/
@injectable()
export class SidePanelHandler {

View File

@@ -35,8 +35,8 @@ export abstract class ReactWidget extends AbstractWidget {
uri?: URI;
/**
* 容器 widget
* 该属性只会在子面板内存在。方便通过父容器访问属性。
* Container widget
* This property only exists in the child panel. It is convenient to access the property through the parent container.
*/
wrapperWidget?: ReactWidget;
@@ -71,8 +71,8 @@ export abstract class ReactWidget extends AbstractWidget {
/**
*
* @param uri 初始化的 uri
* @param childContainer view props 传入 widget 属性的时候才会有 childContainer
* @Param uri Initialized uri
* @param childContainer view props will only have childContainer when the widget property is passed in
*/
init(uri: URI, childContainer?: interfaces.Container): void {
this.uri = uri;

View File

@@ -176,7 +176,7 @@ export class DebugBarWidget extends ReactWidget {
render() {
return (
// 不走 lumino widget 逻辑,通过 css 控制显隐
// Do not use the lumino widget logic, control the hidden through css
<div
className="debug-bar-widget-container"
ref={this.ref}

View File

@@ -36,9 +36,9 @@ import {
import { type Message } from '../../lumino/messaging';
import { SPLIT_PANEL_CLASSNAME } from '../../constants/view';
// 展开状态 className
// Expand state className
const EXPAND_CLASSNAME = 'expand';
// 关闭状态 className
// Close state className
const CLOSE_CLASSNAME = 'close';
export interface SplitPanelType {
@@ -64,14 +64,14 @@ export abstract class SplitWidget
@inject(LayoutRestorer) protected layoutRestorer: LayoutRestorer;
/**
* 存在表示启用内部分区
* 使用 Orientation 标明布局分割方向
* 水平 - horizontal
* 垂直 - vertical
* Presence indicates that internal partitioning is enabled
* Use Orientation to indicate the layout split direction
* Horizontal - horizontal
* Vertical - vertical
*/
private _orientation: SplitLayout.Orientation | undefined;
/** 默认布局,初始化子面板的时候使用该布局 */
/** Default layout, used when initializing subpanels */
private _defaultStretch?: number[];
get defaultStretch() {
@@ -113,7 +113,7 @@ export abstract class SplitWidget
}
/**
* 所有分区面板
* All partition panels
*/
protected panels: Panel[] = [];
@@ -122,19 +122,19 @@ export abstract class SplitWidget
splitPanels: SplitPanelType[] = [];
/**
* 方向
* direction
*/
direction?: BoxLayout.Direction = 'left-to-right';
protected onFitRequest(msg: Message): void {
super.onFitRequest(msg);
// 水平布局生效
// Horizontal layout takes effect
if (!this.panels?.length || this.orientation !== 'horizontal') {
return;
}
/**
* 修复 lumino 原生问题
* 劫持 fit 方法,当面板 close 的时候移除前一个 handler
* Fix lumino native issues
* Hijack the fit method, remove the previous handler when the panel is closed
*/
this.panels.forEach(panel => {
const panelDom = panel?.node;
@@ -169,16 +169,16 @@ export abstract class SplitWidget
}
/**
* 初始化 panel node className
* Initialize panel node className
*/
addClassNames() {
// 数据不存在的时候不执行 classname 逻辑
// Does not execute classname logic when data does not exist
if (!this.storeData?.panelClose) {
return;
}
this.panels.forEach((_, idx) => {
// 1. 默认 expand 状态
// 2. storeData 存储状态为 close 时初始化为 close
// 1. Default expand state
// 2. storeData is initialized to close when the storage state is closed
const isExpand = !this.storeData?.panelClose?.[idx];
if (!isExpand) {
this.closePanel(idx);
@@ -189,7 +189,7 @@ export abstract class SplitWidget
}
/**
* 根据 uri 获取 widget
* Get widget by URI
*/
getWidget(uri: URI) {
const id = this.widgetManager.uriToWidgetID(uri);
@@ -197,7 +197,7 @@ export abstract class SplitWidget
}
/**
* 根据 widget uri 获取 expand 状态
* Get expanded state according to widget uri
*/
getWidgetExpand(uri?: URI): boolean {
if (!uri) {
@@ -209,7 +209,7 @@ export abstract class SplitWidget
}
/**
* 创建 panel
* Create panel
*/
protected async createPanels(stretch: number[]) {
this.splitPanels.sort(
@@ -218,11 +218,11 @@ export abstract class SplitWidget
return Promise.all(
this.splitPanels.map(async ({ widgetUri, widget }, idx) => {
const panel = this.createPanel(widgetUri);
// 面板关闭状态
// Panel closed status
if (stretch?.[idx] === 0) {
panel.node.classList.add(CLOSE_CLASSNAME);
} else {
// 默认 expand
// Default expand
panel.node.classList.add(EXPAND_CLASSNAME);
}
let panelWidget;
@@ -246,7 +246,7 @@ export abstract class SplitWidget
}
/**
* 通过 uri 展开 / 收起子面板
* Expand/retract subpanels via URI
*/
toggleSubWidget(uri?: URI) {
if (!uri || !this.layout) {
@@ -261,8 +261,8 @@ export abstract class SplitWidget
// const currentHandler = handlers[idx];
const isExpand = panel.node.classList.contains(EXPAND_CLASSNAME);
if (idx === expandIdx && isExpand) {
// 执行 close panel
// 隐藏 handler,避免关闭 panel 调整。
// Execute close panel
// Hide handlers to avoid closing panel adjustments.
// currentHandler.classList.add('lm-mod-hidden');
relativeSizes[idx] = 0;
panel.node.classList.remove(EXPAND_CLASSNAME);
@@ -308,10 +308,10 @@ export abstract class SplitWidget
panel.node.classList.add(EXPAND_CLASSNAME);
}
/** 通过 relativeSizes 直接控制面板开关 */
/** Direct control panel switches via relativeSizes */
/**
* 为什么 RelativeSizes 不直接和 expand 状态绑定:
* 面板关闭状态下可能默认展示标题高度,无法根据 relativeSizes 直接判断
* Why RelativeSizes is not directly bound to the expand state:
* When the panel is closed, the title height may be displayed by default, which cannot be directly judged according to relativeSizes.
*/
syncPanelRelativeSizes(sizes: number[]) {
this.contentPanel.setRelativeSizes(sizes);
@@ -331,9 +331,9 @@ export abstract class SplitWidget
this.contentPanel.setRelativeSizes(sizes);
}
/** 默认初始化分区布局 */
/** Default initialization of partition layout */
protected getDefaultStretch() {
// 从默认配置中取
// From the default configuration
if (this.defaultStretch) {
return this.defaultStretch;
}
@@ -343,7 +343,7 @@ export abstract class SplitWidget
}
/**
* 创建 container
* Create container
*/
protected async createContainer() {
const stretch = this.getDefaultStretch();
@@ -363,7 +363,7 @@ export abstract class SplitWidget
}
/**
* 默认不渲染
* Default does not render
*/
render(): ReactElementType {
return null;

View File

@@ -79,7 +79,7 @@ export class CustomTabBar extends TabBar<Widget> {
this.scrollBarFactory = () =>
new PerfectScrollbar(this.scrollContainer, {
// 兼容鼠标模式下的滚动
// Compatible scrolling in mouse mode
useBothWheelAxes: true,
suppressScrollY: true,
});
@@ -106,7 +106,7 @@ export class CustomTabBar extends TabBar<Widget> {
handleEvent(event: Event): void {
const canSuperHandle = this.getHandleEvent(event.target as HTMLElement);
// 不能阻塞 pointerup否则 toolbar 展示会触发分屏拖拽
// Cannot block pointerup, otherwise the toolbar display will trigger split-screen drag
if (canSuperHandle || event.type === 'pointerup') {
super.handleEvent(event);
}

View File

@@ -224,7 +224,7 @@ export class TabBarRenderer extends TabBar.Renderer {
data.title.label,
);
} else {
// 业务侧自己的 react 组件
// The business side's own react component
const virtualIconDOM = {
render: (host: HTMLElement) => {
const currentRoot = this.labelNodeRoot.get(host);
@@ -264,10 +264,10 @@ export class TabBarRenderer extends TabBar.Renderer {
const baseClassName = this.createIconClass(data);
if (typeof data.title.iconLabel === 'string') {
// 使用 vscode iconClass
// Using vscode iconClass
return h.i({ className: codicon(data.title.iconLabel) });
} else {
// 业务侧自己的 react 组件
// The business side's own react component
const virtualIconDOM = {
render: (host: HTMLElement) => {
const currentRoot = this.iconNodeRoot.get(host);
@@ -303,7 +303,7 @@ export class TabBarRenderer extends TabBar.Renderer {
if (title) {
const label = title.label || title.caption;
if (this.tabBar.orientation === 'horizontal') {
// 老的 preview
// Old preview
// this.hoverService.requestHover({
// content: this.renderEnhancedPreview(title),
// target: event.currentTarget,
@@ -311,7 +311,7 @@ export class TabBarRenderer extends TabBar.Renderer {
// cssClasses: ['extended-tab-preview'],
// visualPreview: width => this.renderVisualPreview(width, title),
// });
// 使用外部的 tooltip 组件
// Using an external tooltip component
label &&
this.hoverService.requestHover({
content: label,
@@ -342,7 +342,7 @@ export class TabBarRenderer extends TabBar.Renderer {
Command.Default.VIEW_SAVING_WIDGET_CLOSE_CONFIRM,
[title],
);
// 保存关闭提示
// Save close prompt
} else {
title?.owner.close();
}
@@ -353,12 +353,12 @@ export class TabBarRenderer extends TabBar.Renderer {
event: MouseEvent,
title?: CustomTitleType,
) => {
// 禁用全屏时禁止 tab 双击触发全屏
// Disable full screen when disabling tab double-clicking to trigger full screen
if (this.shell.disableFullScreen) {
return;
}
const isMainPanel = title?.owner?.parent?.id === MAIN_PANEL_ID;
// 主编辑区才会触发全屏
// The main editing area will only trigger full screen.
if (
this.tabBar &&
event.currentTarget instanceof HTMLElement &&

View File

@@ -84,7 +84,7 @@ export class TabBarToolbar extends ReactWidget {
) as ReactWidget;
return (factory?.toolbarItems || [])
.filter(item => {
// 默认是 ToolbarAlign.TRAILING
// Default is ToolbarAlign. TRAILING
if (!this.align) {
return !item.align || item.align === ToolbarAlign.TRAILING;
}

View File

@@ -23,49 +23,49 @@ import { type ReactWidget } from './react-widget';
export const WidgetFactory = Symbol('WidgetFactory');
export interface ToolbarItem {
// 1. 携带 commandId 走命令模式
// 1. Carry the commandId into command mode
commandId?: string;
tooltip?: string;
// 2. 携带 render 走直接渲染的模式
// 2. Carry the render to the direct rendering mode
render?: (widget: ReactWidget) => React.ReactElement<any, any> | null;
/**
* toolbar 对齐位置,默认是 ToolbarAlign.TRAILING
* Toolbar alignment position, the default is ToolbarAlign. TRAILING
*/
align?: ToolbarAlign;
}
export interface WidgetFactory {
/**
* widget 面板所在的区域
* The area where the widget panel is located
*/
area: LayoutPanelType;
/**
* widget 面板的 toolbar只有 dockpanel 才会渲染
* The toolbar of the widget panel, only dockpanel will render
*/
toolbarItems?: ToolbarItem[];
/**
* 通过 render 方法注入
* Injection via render method
*/
render?: () => React.ReactElement<any, any> | null;
/**
* 通过 widget 方式注入
* Inject via widget
*/
createWidget?: (uri: URI) => MaybePromise<ReactWidget>;
/**
* 指定 widget class
* Specify the widget class
*/
widget?: AsClass<ReactWidget>;
/**
* 根据 uri 进行面板匹配
* Panel matching based on URI
*/
canHandle?: (uri: URI) => boolean;
/**
* 通过 uri 生成 widget id
* Generate widget id by URI
*/
getId?: (uri: URI) => string;
/**
* 业务侧通过 uri 正则匹配
* Business side regular matching through URI
*/
match?: RegExp;
}

View File

@@ -72,14 +72,14 @@ export class WidgetOpenHandler implements OpenHandler {
...options,
area,
});
/** 创建 widget 时尝试从内存中恢复状态 */
/** Attempt to restore state from memory when creating a widget */
this.layoutRestorer.restoreWidget(widget);
/** 监听销毁时尝试保存状态到内存中 */
/** Attempt to save state to memory while listening for destruction */
widget.onDispose(() => this.layoutRestorer.storeWidget(widget));
}
widget.parent?.show();
/**
* 如果打开的是 bottom并且底部比较打开的不够高则自动打开一定高度
* If the bottom is opened, and the bottom is not high enough compared to the open one, it will automatically open a certain height.
*/
if (
area === LayoutPanelType.BOTTOM_PANEL &&
@@ -118,7 +118,7 @@ export class WidgetOpenHandler implements OpenHandler {
widget.uri = uri;
widget.onOpenRequest?.(uri, options);
// 区域唯一展示
// The only display in the region
widget.show();
}
}