Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion packages/core-browser/src/react-providers/config-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import React from 'react';

import type { Injector } from '@opensumi/di';
import type { ExtensionCandidate, ExtensionConnectOption, UrlProvider } from '@opensumi/ide-core-common';
import type {
ExtensionBrowserStyleSheet,
ExtensionCandidate,
ExtensionConnectOption,
UrlProvider,
} from '@opensumi/ide-core-common';

import type { IPreferences, LayoutConfig } from '../bootstrap';

Expand Down Expand Up @@ -223,6 +228,10 @@ export interface AppConfig {
* 默认值为 false
*/
devtools?: boolean;
/**
* 配置插件 browser 层的 component 样式文件和 iconfont 样式文件
*/
extensionBrowserStyleSheet?: ExtensionBrowserStyleSheet;
}

export const ConfigContext = React.createContext<AppConfig>({
Expand Down
8 changes: 8 additions & 0 deletions packages/core-common/src/types/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ export interface ExtensionConnectOption {
host?: string;
}

/**
* 插件 browser 层的样式表配置项
*/
export interface ExtensionBrowserStyleSheet {
componentUri: string;
Comment thread
erha19 marked this conversation as resolved.
iconfontUri: string;
}

/**
* 将插件路径转换为 ExtensionCandidate 对象
* @param extensionPath 插件路径
Expand Down
21 changes: 19 additions & 2 deletions packages/extension/src/browser/extension-view.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ export class ViewExtProcessService implements AbstractViewExtProcessService {
action.popoverComponent,
proxiedHead,
this.appConfig.componentCDNType,
this.appConfig.extensionBrowserStyleSheet,
);
this.toolbarPopoverRegistry.registerComponent(
`${extension.id}:${action.popoverComponent}`,
Expand Down Expand Up @@ -437,7 +438,15 @@ export class ViewExtProcessService implements AbstractViewExtProcessService {
}
if (this.appConfig.useExperimentalShadowDom) {
return (props) =>
getShadowRoot(moduleExports[id], extension, props, id, proxiedHead, this.appConfig.componentCDNType);
getShadowRoot(
moduleExports[id],
extension,
props,
id,
proxiedHead,
this.appConfig.componentCDNType,
this.appConfig.extensionBrowserStyleSheet,
);
}
return moduleExports[id];
}
Expand Down Expand Up @@ -525,7 +534,15 @@ export class ViewExtProcessService implements AbstractViewExtProcessService {
...other,
id,
component: (props) =>
getShadowRoot(panel, extension, props, id, proxiedHead, this.appConfig.componentCDNType),
getShadowRoot(
panel,
extension,
props,
id,
proxiedHead,
this.appConfig.componentCDNType,
this.appConfig.extensionBrowserStyleSheet,
),
})),
};
return pre;
Expand Down
45 changes: 35 additions & 10 deletions packages/extension/src/browser/shadowRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import ReactDOM from 'react-dom';

import { ComponentContextProvider, IconContext, IIconResourceOptions } from '@opensumi/ide-components';
import { DisposableCollection, LabelService, useInjectable } from '@opensumi/ide-core-browser';
import { localize, URI } from '@opensumi/ide-core-common';
import { ExtensionBrowserStyleSheet, localize, URI } from '@opensumi/ide-core-common';
import { getThemeTypeSelector, IIconService, IThemeService, ThemeType } from '@opensumi/ide-theme';

import { IExtension } from '../common';
Expand Down Expand Up @@ -74,14 +74,16 @@ function useMutationObserver(from: HTMLHeadElement, target: HTMLHeadElement) {

const packageName = '@opensumi/ide-components';

function getStyleSheet(filePath: string, version: string, cdnType: CDNType = 'alipay') {
const link = document.createElement('link');
let href = '';
function getCdnHref(filePath: string, version: string, cdnType: CDNType = 'alipay') {
if (cdnType === 'alipay') {
href = `${CDN_TYPE_MAP['alipay']}/${packageName.slice(1)}/${version}/${filePath}`;
return `${CDN_TYPE_MAP['alipay']}/${packageName.slice(1)}/${version}/${filePath}`;
} else {
href = `${CDN_TYPE_MAP[cdnType]}/${packageName}@${version}/${filePath}`;
return `${CDN_TYPE_MAP[cdnType]}/${packageName}@${version}/${filePath}`;
}
}

function getStyleSheet(href: string) {
const link = document.createElement('link');
link.setAttribute('href', href);
link.setAttribute('rel', 'stylesheet');
return link;
Expand All @@ -93,12 +95,14 @@ const ShadowRoot = ({
children,
proxiedHead,
cdnType,
styleSheet,
}: {
id: string;
extensionId: string;
children: any;
proxiedHead: HTMLHeadElement;
cdnType?: CDNType;
styleSheet?: ExtensionBrowserStyleSheet;
}) => {
const shadowRootRef = useRef<HTMLDivElement | null>(null);
const [shadowRoot, setShadowRoot] = React.useState<ShadowRoot | null>(null);
Expand All @@ -112,8 +116,15 @@ const ShadowRoot = ({
if (shadowRootRef.current) {
const shadowRootElement = shadowRootRef.current.attachShadow({ mode: 'open' });
if (proxiedHead) {
proxiedHead.appendChild(getStyleSheet('dist/index.css', pkgJson.version, cdnType));
proxiedHead.appendChild(getStyleSheet('lib/icon/iconfont/iconfont.css', pkgJson.version, cdnType));
if (styleSheet) {
proxiedHead.appendChild(getStyleSheet(styleSheet.componentUri));
proxiedHead.appendChild(getStyleSheet(styleSheet.iconfontUri));
} else {
proxiedHead.appendChild(getStyleSheet(getCdnHref('dist/index.css', pkgJson.version, cdnType)));
proxiedHead.appendChild(
getStyleSheet(getCdnHref('lib/icon/iconfont/iconfont.css', pkgJson.version, cdnType)),
);
}

// 如果是一个插件注册了多个视图,节点需要被 clone 才能生效,否则第一个视图 appendChild 之后节点就没了
const newHead = cloneNode<HTMLHeadElement>(proxiedHead);
Expand Down Expand Up @@ -166,7 +177,15 @@ const ShadowRoot = ({
);
};

export function getShadowRoot(panel, extension: IExtension, props, id, proxiedHead, type?: CDNType) {
export function getShadowRoot(
panel,
extension: IExtension,
props,
id,
proxiedHead,
type?: CDNType,
extensionBrowserStyleSheet?: ExtensionBrowserStyleSheet,
) {
const Component = panel;
const { getIcon } = React.useContext(IconContext);
const labelService = useInjectable<LabelService>(LabelService);
Expand All @@ -177,7 +196,13 @@ export function getShadowRoot(panel, extension: IExtension, props, id, proxiedHe

return (
<ComponentContextProvider value={{ getIcon, localize, getResourceIcon }}>
<ShadowRoot id={`${extension.id}-${id}`} extensionId={extension.id} proxiedHead={proxiedHead} cdnType={type}>
<ShadowRoot
id={`${extension.id}-${id}`}
extensionId={extension.id}
proxiedHead={proxiedHead}
cdnType={type}
styleSheet={extensionBrowserStyleSheet}
>
<Component {...props} />
</ShadowRoot>
</ComponentContextProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Injectable, Autowired } from '@opensumi/di';
import {
ClientAppContribution,
Domain,
getIcon,
IStatusBarService,
StatusBarAlignment,
StatusBarEntryAccessor,
Expand Down Expand Up @@ -53,11 +54,7 @@ export class StatusBarContribution extends WithEventBus implements ClientAppCont
color: '#FFFFFF',
tooltip: 'OpenSumi',
alignment: StatusBarAlignment.LEFT,
iconClass: this.iconService.fromIcon(
'',
'https://img.alicdn.com/imgextra/i1/O1CN01I0fKZ51PTgHByjznG_!!6000000001842-2-tps-40-40.png',
IconType.Mask,
),
iconClass: getIcon('code'),
priority: Infinity,
});
}
Expand Down