Skip to content

Commit 8504a50

Browse files
Refactor tools
1 parent 2172767 commit 8504a50

File tree

3 files changed

+120
-114
lines changed

3 files changed

+120
-114
lines changed

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
export { default as registerDrag } from './drag.js';
77
export { default as logger, LogLevel } from './logger.js';
88
export { default as Cubism2Model } from './cubism2/index.js';
9-
export { default as tools, Tools } from './tools.js';
109

10+
export * from './tools.js';
1111
export * from './message.js';
1212
export * from './model.js';
1313
export * from './utils.js';

src/tools.ts

Lines changed: 117 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
fa_xmark
1414
} from './icons.js';
1515
import { showMessage, i18n } from './message.js';
16+
import type { Config, ModelManager } from './model.js';
17+
import type { Tips } from './widget.js';
1618

1719
interface Tools {
1820
/**
@@ -34,86 +36,122 @@ interface Tools {
3436
}
3537

3638
/**
37-
* Waifu tools configuration.
38-
* @type {Tools}
39+
* Waifu tools manager.
3940
*/
40-
const tools: Tools = {
41-
hitokoto: {
42-
icon: fa_comment,
43-
callback: async (template: string) => {
44-
// Add hitokoto.cn API
45-
const response = await fetch('https://v1.hitokoto.cn');
46-
const result = await response.json();
47-
const text = i18n(template, result.from, result.creator);
48-
showMessage(result.hitokoto, 6000, 9);
49-
setTimeout(() => {
50-
showMessage(text, 4000, 9);
51-
}, 6000);
52-
},
53-
},
54-
asteroids: {
55-
icon: fa_paper_plane,
56-
callback: () => {
57-
if (window.Asteroids) {
58-
if (!window.ASTEROIDSPLAYERS) window.ASTEROIDSPLAYERS = [];
59-
window.ASTEROIDSPLAYERS.push(new window.Asteroids());
60-
} else {
61-
const script = document.createElement('script');
62-
script.src =
63-
'https://fastly.jsdelivr.net/gh/stevenjoezhang/asteroids/asteroids.js';
64-
document.head.appendChild(script);
65-
}
66-
},
67-
},
68-
'switch-model': {
69-
icon: fa_user_circle,
70-
callback: () => {},
71-
},
72-
'switch-texture': {
73-
icon: fa_street_view,
74-
callback: () => {},
75-
},
76-
photo: {
77-
icon: fa_camera_retro,
78-
callback: (message: string | string[]) => {
79-
showMessage(message, 6000, 9);
80-
const canvas = document.getElementById('live2d') as HTMLCanvasElement;
81-
if (!canvas) return;
82-
const imageUrl = canvas.toDataURL();
41+
class ToolsManager {
42+
tools: Tools;
43+
config: Config;
44+
45+
constructor(model: ModelManager, config: Config, tips: Tips) {
46+
this.config = config;
47+
this.tools = {
48+
hitokoto: {
49+
icon: fa_comment,
50+
callback: async () => {
51+
// Add hitokoto.cn API
52+
const response = await fetch('https://v1.hitokoto.cn');
53+
const result = await response.json();
54+
const template = tips.message.hitokoto;
55+
const text = i18n(template, result.from, result.creator);
56+
showMessage(result.hitokoto, 6000, 9);
57+
setTimeout(() => {
58+
showMessage(text, 4000, 9);
59+
}, 6000);
60+
}
61+
},
62+
asteroids: {
63+
icon: fa_paper_plane,
64+
callback: () => {
65+
if (window.Asteroids) {
66+
if (!window.ASTEROIDSPLAYERS) window.ASTEROIDSPLAYERS = [];
67+
window.ASTEROIDSPLAYERS.push(new window.Asteroids());
68+
} else {
69+
const script = document.createElement('script');
70+
script.src =
71+
'https://fastly.jsdelivr.net/gh/stevenjoezhang/asteroids/asteroids.js';
72+
document.head.appendChild(script);
73+
}
74+
}
75+
},
76+
'switch-model': {
77+
icon: fa_user_circle,
78+
callback: () => model.loadNextModel()
79+
},
80+
'switch-texture': {
81+
icon: fa_street_view,
82+
callback: () => {
83+
let successMessage = '', failMessage = '';
84+
if (tips) {
85+
successMessage = tips.message.changeSuccess;
86+
failMessage = tips.message.changeFail;
87+
}
88+
model.loadRandTexture(successMessage, failMessage);
89+
}
90+
},
91+
photo: {
92+
icon: fa_camera_retro,
93+
callback: () => {
94+
const message = tips.message.photo;
95+
showMessage(message, 6000, 9);
96+
const canvas = document.getElementById('live2d') as HTMLCanvasElement;
97+
if (!canvas) return;
98+
const imageUrl = canvas.toDataURL();
99+
100+
const link = document.createElement('a');
101+
link.style.display = 'none';
102+
link.href = imageUrl;
103+
link.download = 'live2d-photo.png';
83104

84-
const link = document.createElement('a');
85-
link.style.display = 'none';
86-
link.href = imageUrl;
87-
link.download = 'live2d-photo.png';
105+
document.body.appendChild(link);
106+
link.click();
107+
document.body.removeChild(link);
108+
}
109+
},
110+
info: {
111+
icon: fa_info_circle,
112+
callback: () => {
113+
open('https://github.com/stevenjoezhang/live2d-widget');
114+
}
115+
},
116+
quit: {
117+
icon: fa_xmark,
118+
callback: () => {
119+
localStorage.setItem('waifu-display', Date.now().toString());
120+
const message = tips.message.goodbye;
121+
showMessage(message, 2000, 11);
122+
const waifu = document.getElementById('waifu');
123+
if (!waifu) return;
124+
waifu.style.bottom = '-500px';
125+
setTimeout(() => {
126+
waifu.style.display = 'none';
127+
const waifuToggle = document.getElementById('waifu-toggle');
128+
if (!waifuToggle) return;
129+
waifuToggle.classList.add('waifu-toggle-active');
130+
}, 3000);
131+
}
132+
}
133+
};
134+
}
88135

89-
document.body.appendChild(link);
90-
link.click();
91-
document.body.removeChild(link);
92-
},
93-
},
94-
info: {
95-
icon: fa_info_circle,
96-
callback: () => {
97-
open('https://github.com/stevenjoezhang/live2d-widget');
98-
},
99-
},
100-
quit: {
101-
icon: fa_xmark,
102-
callback: (message: string | string[]) => {
103-
localStorage.setItem('waifu-display', Date.now().toString());
104-
showMessage(message, 2000, 11);
105-
const waifu = document.getElementById('waifu');
106-
if (!waifu) return;
107-
waifu.style.bottom = '-500px';
108-
setTimeout(() => {
109-
waifu.style.display = 'none';
110-
const waifuToggle = document.getElementById('waifu-toggle');
111-
if (!waifuToggle) return;
112-
waifuToggle.classList.add('waifu-toggle-active');
113-
}, 3000);
114-
},
115-
},
116-
};
136+
registerTools() {
137+
if (!Array.isArray(this.config.tools)) {
138+
this.config.tools = Object.keys(this.tools);
139+
}
140+
for (const toolName of this.config.tools!) {
141+
if (this.tools[toolName]) {
142+
const { icon, callback } = this.tools[toolName];
143+
document
144+
.getElementById('waifu-tool')!
145+
.insertAdjacentHTML(
146+
'beforeend',
147+
`<span id="waifu-tool-${toolName}">${icon}</span>`,
148+
);
149+
document
150+
.getElementById(`waifu-tool-${toolName}`)!
151+
.addEventListener('click', callback);
152+
}
153+
}
154+
}
155+
}
117156

118-
export default tools;
119-
export { Tools };
157+
export { ToolsManager, Tools };

src/widget.ts

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import { ModelManager, Config, ModelList } from './model.js';
77
import { showMessage, welcomeMessage, Time } from './message.js';
88
import { randomSelection } from './utils.js';
9-
import tools from './tools.js';
9+
import { ToolsManager } from './tools.js';
1010
import logger from './logger.js';
1111
import registerDrag from './drag.js';
1212
import { fa_child } from './icons.js';
@@ -75,38 +75,6 @@ interface Tips {
7575
models: ModelList[];
7676
}
7777

78-
function registerTools(model: ModelManager, config: Config, tips: Tips) {
79-
tools['switch-model'].callback = () => model.loadNextModel();
80-
tools['switch-texture'].callback = () => {
81-
let successMessage = '', failMessage = '';
82-
if (tips) {
83-
successMessage = tips.message.changeSuccess;
84-
failMessage = tips.message.changeFail;
85-
}
86-
model.loadRandTexture(successMessage, failMessage);
87-
};
88-
tools.hitokoto.callback = tools.hitokoto.callback.bind(null, tips.message.hitokoto);
89-
tools.photo.callback = tools.photo.callback.bind(null, tips.message.photo);
90-
tools.quit.callback = tools.quit.callback.bind(null, tips.message.goodbye);
91-
if (!Array.isArray(config.tools)) {
92-
config.tools = Object.keys(tools);
93-
}
94-
for (const toolName of config.tools!) {
95-
if (tools[toolName]) {
96-
const { icon, callback } = tools[toolName];
97-
document
98-
.getElementById('waifu-tool')!
99-
.insertAdjacentHTML(
100-
'beforeend',
101-
`<span id="waifu-tool-${toolName}">${icon}</span>`,
102-
);
103-
document
104-
.getElementById(`waifu-tool-${toolName}`)!
105-
.addEventListener('click', callback);
106-
}
107-
}
108-
}
109-
11078
/**
11179
* Register event listeners.
11280
* @param {Tips} tips - Result configuration.
@@ -216,7 +184,7 @@ async function loadWidget(config: Config) {
216184
}
217185
const model = await ModelManager.initCheck(config, models);
218186
await model.loadModel('');
219-
registerTools(model, config, tips);
187+
new ToolsManager(model, config, tips).registerTools();
220188
if (config.drag) registerDrag();
221189
document.getElementById('waifu')!.style.bottom = '0';
222190
}

0 commit comments

Comments
 (0)