Skip to content

Commit d3e293a

Browse files
committed
refactor: use webview
1 parent e921c3d commit d3e293a

33 files changed

+1644
-326
lines changed

.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ module.exports = {
1616
'@typescript-eslint/no-explicit-any': 0,
1717
'@typescript-eslint/explicit-module-boundary-types': 0,
1818
'@typescript-eslint/no-non-null-assertion': 0,
19+
'@typescript-eslint/no-empty-function': 0,
20+
'no-case-declarations': 0
1921
}
2022
};

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@
9797
"type": "string",
9898
"description": "请勿修改"
9999
}
100-
101100
}
102101
}
103102
},
@@ -128,13 +127,15 @@
128127
"isomorphic-git": "^1.8.0",
129128
"querystring": "^0.2.0",
130129
"react": "^17.0.1",
131-
"react-dom": "^17.0.1"
130+
"react-dom": "^17.0.1",
131+
"react-select": "^3.1.1"
132132
},
133133
"devDependencies": {
134134
"@types/classnames": "^2.2.11",
135135
"@types/node": "^14.14.7",
136136
"@types/react": "^16.9.56",
137137
"@types/react-dom": "^16.9.9",
138+
"@types/react-select": "^3.0.26",
138139
"@typescript-eslint/eslint-plugin": "^4.7.0",
139140
"@typescript-eslint/parser": "^4.7.0",
140141
"css-loader": "^5.0.1",

src/extension.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import initialize from './initialize';
22
import CodingServer from './services/codingServer';
3-
import WebviewProvider from './webviews';
43
import ACTIONS, { dispatch } from './utils/actions';
54
import { proxyCtx } from './utils/proxy';
65
import toast from './utils/toast';
76
import { readConfig } from './services/dcloud';
87

98
async function activate(context: IContext) {
10-
const webviewProvider = new WebviewProvider(context);
119
const codingServer = new CodingServer(context);
1210
const repoInfo = await CodingServer.getRepoParams();
1311
console.warn('repoInfo: ', repoInfo);
@@ -16,7 +14,7 @@ async function activate(context: IContext) {
1614
dispatch(ACTIONS.SET_CTX, {
1715
context,
1816
value: {
19-
webviewProvider,
17+
webviewProvider: null,
2018
codingServer,
2119
depots: [],
2220
selectedDepot: null,

src/init/createWebview.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import WebviewProvider from '../webviews/depot';
2+
import ACTIONS, { dispatch } from '../utils/actions';
3+
4+
function createWebview(context: IContext) {
5+
const webviewProvider = new WebviewProvider(context);
6+
dispatch(ACTIONS.SET_WEBVIEW, {
7+
context,
8+
value: webviewProvider,
9+
});
10+
}
11+
12+
export default createWebview;

src/init/initCredentials.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import hx from 'hbuilderx';
22
import * as DCloudService from '../services/dcloud';
33
import toast from '../utils/toast';
44
import { refreshTree } from './registerCommands';
5+
import ACTIONS, { dispatch } from '../utils/actions';
56

67
const { executeCommand } = hx.commands;
78

@@ -29,12 +30,18 @@ export async function initCredentials(context: IContext) {
2930
if (accessToken) {
3031
const userData = await codingServer.getUserInfo(accessToken);
3132
toast.info(`logged in as CODING user: ${userData.name} @ ${userData.team}`);
33+
34+
dispatch(ACTIONS.SET_USER_INFO, {
35+
context: context,
36+
value: userData,
37+
});
3238
}
3339
} catch (err) {
3440
if (Number(err) === 1) {
3541
toast.warn(`请先登录 DCloud`);
3642
}
3743
} finally {
3844
refreshTree();
45+
context.webviewProvider.refresh();
3946
}
4047
}

src/init/initLoginLogout.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export default function initLoginLogout(context: IContext) {
77
onUserLogin(() => {
88
console.warn('login');
99
refreshTree();
10+
context.webviewProvider.refresh();
1011
});
1112

1213
onUserLogout(() => {

src/init/registerCommands.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export default function registerCommands(context: IContext) {
7272
);
7373

7474
context.subscriptions.push(
75-
registerCommand('codingPlugin.createDepot', async function (param: any) {
75+
registerCommand('codingPlugin.createDepot', async function (callback: any) {
7676
const depot = await showInputBox({
7777
prompt: '请输入仓库名',
7878
});
@@ -84,13 +84,22 @@ export default function registerCommands(context: IContext) {
8484

8585
const team = context.userInfo.team;
8686
const result = await codingServer.createDepot(team, depot, depot);
87+
const webview = context.webviewProvider?.panel.webView;
8788
if (result) {
89+
webview.postMessage({
90+
command: 'create.depot.success',
91+
data: result,
92+
});
8893
const res = await toast.info('仓库创建成功,是否切换到该仓库?', ['是', '否']);
8994
if (res === '是') {
9095
dispatch(ACTIONS.SET_SELECTED_DEPOT, {
9196
context,
9297
value: result,
9398
});
99+
webview.postMessage({
100+
command: 'create.depot.switch',
101+
data: result,
102+
});
94103
}
95104
refreshTree();
96105
}
@@ -122,6 +131,7 @@ export default function registerCommands(context: IContext) {
122131
value: newToken,
123132
});
124133
refreshTree();
134+
context.webviewProvider.refresh();
125135
}
126136
} catch {
127137
toast.error(`个人令牌无效`);
@@ -166,6 +176,7 @@ export default function registerCommands(context: IContext) {
166176
value: result.Token,
167177
});
168178
refreshTree();
179+
context.webviewProvider.refresh();
169180
}
170181
} catch (err) {
171182
toast.error(`创建团队失败`);

src/initialize.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import createTreeViews from './init/createTreeViews';
2+
import createWebview from './init/createWebview';
23
import initWorkspace from './init/initWorkspace';
34
import { initCredentials } from './init/initCredentials';
45
import registerCommands from './init/registerCommands';
@@ -13,5 +14,6 @@ export default function initialize(context: IContext) {
1314
initCredentials(context);
1415
registerCommands(context);
1516
createTreeViews(context);
17+
createWebview(context);
1618
initWorkspace(context);
1719
}

src/utils/actions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const enum ACTIONS {
99
SET_CTX = 'SET_CTX',
1010
SET_MR_CUSTOM_EDITOR = 'SET_MR_CUSTOM_EDITOR',
1111
SET_TOKEN = 'SET_TOKEN',
12+
SET_WEBVIEW = 'SET_WEBVIEW',
1213
}
1314

1415
interface IPayload {
@@ -43,6 +44,9 @@ export const dispatch = (type: ACTIONS, { context, value }: IPayload) => {
4344
context.token = value;
4445
setConfig(`token`, value);
4546
break;
47+
case ACTIONS.SET_WEBVIEW:
48+
context.webviewProvider = value;
49+
break;
4650
default:
4751
return;
4852
}

src/webviews/depot.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import hx from 'hbuilderx';
2+
import path from 'path';
3+
import toast from '../utils/toast';
4+
import ACTIONS, { dispatch } from '../utils/actions';
5+
6+
interface IMessage {
7+
command: string;
8+
data?: any;
9+
callback?: (...args: any[]) => void;
10+
}
11+
12+
export default class WebviewProvider {
13+
context: IContext;
14+
panel: IWebviewPanel;
15+
16+
constructor(context: IContext) {
17+
this.context = context;
18+
this.panel = this.createPanel();
19+
this.listen();
20+
this.refresh();
21+
}
22+
23+
refresh() {
24+
this.update({
25+
token: this.context.token,
26+
userInfo: this.context.userInfo,
27+
});
28+
}
29+
30+
listen() {
31+
this.panel.webView.onDidReceiveMessage(async (message: IMessage) => {
32+
console.log('webview receive message => ', message);
33+
const { command, data } = message;
34+
35+
switch (command) {
36+
case 'webview.mrDetail':
37+
hx.env.openExternal(data);
38+
break;
39+
case 'webview.toast':
40+
toast.error(data);
41+
break;
42+
case 'webview.refresh':
43+
this.refresh();
44+
break;
45+
default:
46+
hx.commands.executeCommand(command);
47+
return;
48+
}
49+
});
50+
}
51+
52+
createPanel() {
53+
const webviewPanel: IWebviewPanel = hx.window.createWebView('codingPlugin.webview', {
54+
enableScripts: true,
55+
});
56+
57+
return webviewPanel;
58+
}
59+
60+
async update(data: any) {
61+
const webview = this.panel.webView;
62+
const fileInfo = hx.Uri.file(path.resolve(__dirname, '../../out/webviews/main.js'));
63+
64+
const config = hx.workspace.getConfiguration();
65+
const colorScheme = config.get('editor.colorScheme');
66+
67+
const COLORS: Record<string, string> = {
68+
Monokai: 'themeDark',
69+
'Atom One Dark': 'themeDarkBlue',
70+
Default: 'themeLight',
71+
};
72+
73+
if (data.token && !data.userInfo) {
74+
try {
75+
const userInfo = await this.context.codingServer.getUserInfo(data.token);
76+
data.userInfo = userInfo;
77+
dispatch(ACTIONS.SET_USER_INFO, {
78+
context: this.context,
79+
value: userInfo,
80+
});
81+
} catch (err) {
82+
console.warn('个人令牌出错了');
83+
}
84+
}
85+
86+
webview.html = `
87+
<html>
88+
<body class='${COLORS[colorScheme]}'>
89+
<div>
90+
<div id='root'></div>
91+
</div>
92+
<script>
93+
window.__CODING__ = '${JSON.stringify(data)}'
94+
</script>
95+
<script src='${fileInfo}'></script>
96+
</body>
97+
</html>
98+
`;
99+
}
100+
}

0 commit comments

Comments
 (0)